inotify: change protocol so that different query types can be supported.
authorNicolas Dumazet <nicdumz.commits@gmail.com>
Fri, 17 Apr 2009 20:10:47 +0900
changeset 8553 e387ecd7a6ed
parent 8552 06561793778e
child 8554 47d7347484f5
inotify: change protocol so that different query types can be supported.
hgext/inotify/client.py
hgext/inotify/common.py
hgext/inotify/server.py
--- a/hgext/inotify/client.py	Tue Apr 07 19:30:01 2009 +0900
+++ b/hgext/inotify/client.py	Fri Apr 17 20:10:47 2009 +0900
@@ -78,13 +78,13 @@
             else:
                 raise
 
-    def _send(self, data):
+    def _send(self, type, data):
         """Sends protocol version number, and the data"""
-        self.sock.sendall(chr(common.version) + data)
+        self.sock.sendall(chr(common.version) + type + data)
 
         self.sock.shutdown(socket.SHUT_WR)
 
-    def _receive(self):
+    def _receive(self, type):
         """
         Read data, check version number, extract headers,
         and returns a tuple (data descriptor, header)
@@ -97,8 +97,12 @@
                       'server version %d)\n') % version)
             raise QueryFailed('incompatible server version')
 
-        # only one type of request is supported for now
-        type = 'STAT'
+        readtype = cs.read(4)
+        if readtype != type:
+            self.ui.warn(_('(inotify: received \'%s\' response when expecting'
+                       ' \'%s\')\n') % (readtype, type))
+            raise QueryFailed('wrong response type')
+
         hdrfmt = common.resphdrfmts[type]
         hdrsize = common.resphdrsizes[type]
         try:
@@ -108,12 +112,12 @@
 
         return cs, resphdr
 
-    def query(self, req):
+    def query(self, type, req):
         self._connect()
 
-        self._send(req)
+        self._send(type, req)
 
-        return self._receive()
+        return self._receive(type)
 
     @start_server
     def statusquery(self, names, match, ignored, clean, unknown=True):
@@ -130,7 +134,7 @@
 
         req = '\0'.join(genquery())
 
-        cs, resphdr = self.query(req)
+        cs, resphdr = self.query('STAT', req)
 
         def readnames(nbytes):
             if nbytes:
--- a/hgext/inotify/common.py	Tue Apr 07 19:30:01 2009 +0900
+++ b/hgext/inotify/common.py	Fri Apr 17 20:10:47 2009 +0900
@@ -8,7 +8,27 @@
 
 import cStringIO, socket, struct
 
-version = 1
+"""
+  Protocol between inotify clients and server:
+
+  Client sending query:
+  1) send protocol version number
+  2) send query type (string, 4 letters long)
+  3) send query parameters:
+     - For STAT, N+1 \0-separated strings:
+        1) N different names that need checking
+        2) 1 string containing all the status types to match
+
+  Server sending query answer:
+  1) send protocol version number
+  2) send query type
+  3) send struct.pack'ed headers describing the length of the content:
+      e.g. for STAT, receive 8 integers describing the length of the
+      8 \0-separated string lists ( one list for each lmar!?ic status type )
+
+"""
+
+version = 2
 
 resphdrfmts = {
     'STAT': '>llllllll' # status requests
--- a/hgext/inotify/server.py	Tue Apr 07 19:30:01 2009 +0900
+++ b/hgext/inotify/server.py	Fri Apr 17 20:10:47 2009 +0900
@@ -594,6 +594,8 @@
                            'version %d\n') % version)
             return
 
+        type = cs.read(4)
+
         names = cs.read().split('\0')
 
         states = names.pop()
@@ -638,8 +640,8 @@
             try:
                 v = chr(common.version)
 
-                sock.sendall(v + struct.pack(common.resphdrfmts['STAT'],
-                                         *map(len, results)))
+                sock.sendall(v + type + struct.pack(common.resphdrfmts[type],
+                                            *map(len, results)))
                 sock.sendall(''.join(results))
             finally:
                 sock.shutdown(socket.SHUT_WR)