diff mbox series

[v2] hashserv: Fix read-only mode

Message ID 20231003065625.3111543-1-karim.benhoucine@landisgyr.com
State New
Headers show
Series [v2] hashserv: Fix read-only mode | expand

Commit Message

Karim Ben Houcine Oct. 3, 2023, 6:56 a.m. UTC
TCP read-only hash equivalence server is not working: the connection is prematurely closed without even notifying the value of the unihash.
Expected behaviour is:
    1. the client sends a ‘report’ message indicating the 'taskhash', 'method', 'outhash' and a proposed value of 'unihash'.
    2.the server sends back the 'taskhash', 'method' and actual value of 'unihash' to use.
The problem is that in read-only mode, the server rejects 'report' messages (connexion is closed).
hashserv.tests.TestHashEquivalenceUnixServer.test_ro_server test modified accordingly

Signed-off-by: Karim Ben Houcine <karim.benhoucine@landisgyr.com>
---
 lib/hashserv/server.py | 45 +++++++++++++++++++++++++++++++++++++++++-
 lib/hashserv/tests.py  |  5 ++---
 2 files changed, 46 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/lib/hashserv/server.py b/lib/hashserv/server.py
index d40a2ab8..1f198af4 100644
--- a/lib/hashserv/server.py
+++ b/lib/hashserv/server.py
@@ -180,7 +180,11 @@  class ServerClient(bb.asyncrpc.AsyncServerConnection):
             'get-stats': self.handle_get_stats,
         })
 
-        if not read_only:
+        if read_only:
+            self.handlers.update({
+                'report': self.handle_readonly_report,
+            })
+        else:
             self.handlers.update({
                 'report': self.handle_report,
                 'report-equiv': self.handle_equivreport,
@@ -453,6 +457,45 @@  class ServerClient(bb.asyncrpc.AsyncServerConnection):
 
         self.write_message(d)
 
+
+    async def handle_readonly_report(self, data):
+        with closing(self.db.cursor()) as cursor:
+
+            # Check if outhash is known
+            cursor.execute(
+                '''
+                SELECT outhashes_v2.taskhash AS taskhash, unihashes_v2.unihash AS unihash FROM outhashes_v2
+                INNER JOIN unihashes_v2 ON unihashes_v2.method=outhashes_v2.method AND unihashes_v2.taskhash=outhashes_v2.taskhash
+                -- Select any matching output hash
+                WHERE outhashes_v2.method=:method AND outhashes_v2.outhash=:outhash
+                -- Pick the oldest hash
+                ORDER BY outhashes_v2.created ASC
+                LIMIT 1
+                ''',
+                {
+                    'method': data['method'],
+                    'outhash': data['outhash'],
+                    'taskhash': data['taskhash'],
+                }
+            )
+            row = cursor.fetchone()
+            if row is not None:
+                # outhash is known => corrects unihash
+                unihash = row['unihash']
+            else:
+                # outhash is unknown => nothing to do
+                unihash = data['taskhash']
+
+
+            d = {
+                'taskhash': data['taskhash'],
+                'method': data['method'],
+                'unihash': unihash,
+            }
+
+        self.write_message(d)
+
+
     async def handle_equivreport(self, data):
         with closing(self.db.cursor()) as cursor:
             insert_data = {
diff --git a/lib/hashserv/tests.py b/lib/hashserv/tests.py
index f6b85aed..5bf88092 100644
--- a/lib/hashserv/tests.py
+++ b/lib/hashserv/tests.py
@@ -312,13 +312,12 @@  class HashEquivalenceCommonTests(object):
         # Check the hash via the read-only server
         self.assertClientGetHash(ro_client, taskhash, unihash)
 
-        # Ensure that reporting via the read-only server fails
+        # Ensure that reporting via the read-only server doesn't modify the database
         taskhash2 = 'c665584ee6817aa99edfc77a44dd853828279370'
         outhash2 = '3c979c3db45c569f51ab7626a4651074be3a9d11a84b1db076f5b14f7d39db44'
         unihash2 = '90e9bc1d1f094c51824adca7f8ea79a048d68824'
 
-        with self.assertRaises(ConnectionError):
-            ro_client.report_unihash(taskhash2, self.METHOD, outhash2, unihash2)
+        ro_client.report_unihash(taskhash2, self.METHOD, outhash2, unihash2)
 
         # Ensure that the database was not modified
         self.assertClientGetHash(self.client, taskhash2, None)