##// END OF EJS Templates
inotify: Separate query sending logic from Server starting....
Nicolas Dumazet -
r8552:06561793 default
parent child Browse files
Show More
@@ -13,9 +13,9 b''
13
13
14 from mercurial.i18n import _
14 from mercurial.i18n import _
15 from mercurial import cmdutil, util
15 from mercurial import cmdutil, util
16 import errno, os, server, socket
16 import os, server
17 from weakref import proxy
17 from weakref import proxy
18 from client import client
18 from client import client, QueryFailed
19
19
20 def serve(ui, repo, **opts):
20 def serve(ui, repo, **opts):
21 '''start an inotify server for this repository'''
21 '''start an inotify server for this repository'''
@@ -55,12 +55,16 b' def reposetup(ui, repo):'
55 files = match.files()
55 files = match.files()
56 if '.' in files:
56 if '.' in files:
57 files = []
57 files = []
58 if not ignored and not self.inotifyserver:
58 cli = client(ui, repo)
59 cli = client(ui, repo)
59 try:
60 try:
60 if not ignored and not self.inotifyserver:
61 result = cli.statusquery(files, match, False,
61 result = cli.statusquery(files, match, False,
62 clean, unknown)
62 clean, unknown)
63 if result and ui.config('inotify', 'debug'):
63 except QueryFailed, instr:
64 ui.debug(str(instr))
65 pass
66 else:
67 if ui.config('inotify', 'debug'):
64 r2 = super(inotifydirstate, self).status(
68 r2 = super(inotifydirstate, self).status(
65 match, False, clean, unknown)
69 match, False, clean, unknown)
66 for c,a,b in zip('LMARDUIC', result, r2):
70 for c,a,b in zip('LMARDUIC', result, r2):
@@ -71,46 +75,7 b' def reposetup(ui, repo):'
71 if f not in a:
75 if f not in a:
72 ui.warn('*** inotify: %s -%s\n' % (c, f))
76 ui.warn('*** inotify: %s -%s\n' % (c, f))
73 result = r2
77 result = r2
74
75 if result is not None:
76 return result
78 return result
77 except (OSError, socket.error), err:
78 autostart = ui.configbool('inotify', 'autostart', True)
79
80 if err[0] == errno.ECONNREFUSED:
81 ui.warn(_('(found dead inotify server socket; '
82 'removing it)\n'))
83 os.unlink(repo.join('inotify.sock'))
84 if err[0] in (errno.ECONNREFUSED, errno.ENOENT) and autostart:
85 ui.debug(_('(starting inotify server)\n'))
86 try:
87 try:
88 server.start(ui, repo)
89 except server.AlreadyStartedException, inst:
90 # another process may have started its own
91 # inotify server while this one was starting.
92 ui.debug(str(inst))
93 except Exception, inst:
94 ui.warn(_('could not start inotify server: '
95 '%s\n') % inst)
96 else:
97 # server is started, send query again
98 try:
99 return cli.statusquery(files, match, ignored,
100 clean, unknown)
101 except socket.error, err:
102 ui.warn(_('could not talk to new inotify '
103 'server: %s\n') % err[-1])
104 elif err[0] in (errno.ECONNREFUSED, errno.ENOENT):
105 # silently ignore normal errors if autostart is False
106 ui.debug(_('(inotify server not running)\n'))
107 else:
108 ui.warn(_('failed to contact inotify server: %s\n')
109 % err[-1])
110 ui.traceback()
111 # replace by old status function
112 self.status = super(inotifydirstate, self).status
113
114 return super(inotifydirstate, self).status(
79 return super(inotifydirstate, self).status(
115 match, ignored, clean, unknown)
80 match, ignored, clean, unknown)
116
81
@@ -8,8 +8,58 b''
8 # GNU General Public License version 2, incorporated herein by reference.
8 # GNU General Public License version 2, incorporated herein by reference.
9
9
10 from mercurial.i18n import _
10 from mercurial.i18n import _
11 import common
11 import common, server
12 import os, socket, struct
12 import errno, os, socket, struct
13
14 class QueryFailed(Exception): pass
15
16 def start_server(function):
17 """
18 Decorator.
19 Tries to call function, if it fails, try to (re)start inotify server.
20 Raise QueryFailed if something went wrong
21 """
22 def decorated_function(self, *args):
23 result = None
24 try:
25 return function(self, *args)
26 except (OSError, socket.error), err:
27 autostart = self.ui.configbool('inotify', 'autostart', True)
28
29 if err[0] == errno.ECONNREFUSED:
30 self.ui.warn(_('(found dead inotify server socket; '
31 'removing it)\n'))
32 os.unlink(self.repo.join('inotify.sock'))
33 if err[0] in (errno.ECONNREFUSED, errno.ENOENT) and autostart:
34 self.ui.debug(_('(starting inotify server)\n'))
35 try:
36 try:
37 server.start(self.ui, self.repo)
38 except server.AlreadyStartedException, inst:
39 # another process may have started its own
40 # inotify server while this one was starting.
41 self.ui.debug(str(inst))
42 except Exception, inst:
43 self.ui.warn(_('could not start inotify server: '
44 '%s\n') % inst)
45 else:
46 try:
47 return function(self, *args)
48 except socket.error, err:
49 self.ui.warn(_('could not talk to new inotify '
50 'server: %s\n') % err[-1])
51 elif err[0] in (errno.ECONNREFUSED, errno.ENOENT):
52 # silently ignore normal errors if autostart is False
53 self.ui.debug(_('(inotify server not running)\n'))
54 else:
55 self.ui.warn(_('failed to contact inotify server: %s\n')
56 % err[-1])
57
58 self.ui.traceback()
59 raise QueryFailed('inotify query failed')
60
61 return decorated_function
62
13
63
14 class client(object):
64 class client(object):
15 def __init__(self, ui, repo):
65 def __init__(self, ui, repo):
@@ -38,14 +88,14 b' class client(object):'
38 """
88 """
39 Read data, check version number, extract headers,
89 Read data, check version number, extract headers,
40 and returns a tuple (data descriptor, header)
90 and returns a tuple (data descriptor, header)
41 Returns (None, None) on error
91 Raises QueryFailed on error
42 """
92 """
43 cs = common.recvcs(self.sock)
93 cs = common.recvcs(self.sock)
44 version = ord(cs.read(1))
94 version = ord(cs.read(1))
45 if version != common.version:
95 if version != common.version:
46 self.ui.warn(_('(inotify: received response from incompatible '
96 self.ui.warn(_('(inotify: received response from incompatible '
47 'server version %d)\n') % version)
97 'server version %d)\n') % version)
48 return None, None
98 raise QueryFailed('incompatible server version')
49
99
50 # only one type of request is supported for now
100 # only one type of request is supported for now
51 type = 'STAT'
101 type = 'STAT'
@@ -54,7 +104,7 b' class client(object):'
54 try:
104 try:
55 resphdr = struct.unpack(hdrfmt, cs.read(hdrsize))
105 resphdr = struct.unpack(hdrfmt, cs.read(hdrsize))
56 except struct.error:
106 except struct.error:
57 return None, None
107 raise QueryFailed('unable to retrieve query response headers')
58
108
59 return cs, resphdr
109 return cs, resphdr
60
110
@@ -65,6 +115,7 b' class client(object):'
65
115
66 return self._receive()
116 return self._receive()
67
117
118 @start_server
68 def statusquery(self, names, match, ignored, clean, unknown=True):
119 def statusquery(self, names, match, ignored, clean, unknown=True):
69
120
70 def genquery():
121 def genquery():
@@ -81,9 +132,6 b' class client(object):'
81
132
82 cs, resphdr = self.query(req)
133 cs, resphdr = self.query(req)
83
134
84 if not cs:
85 return None
86
87 def readnames(nbytes):
135 def readnames(nbytes):
88 if nbytes:
136 if nbytes:
89 names = cs.read(nbytes)
137 names = cs.read(nbytes)
General Comments 0
You need to be logged in to leave comments. Login now