##// END OF EJS Templates
lock: turn prepinherit/reacquire into a single context manager...
Siddharth Agarwal -
r26473:5f94e64f default
parent child Browse files
Show More
@@ -7,6 +7,7 b''
7 7
8 8 from __future__ import absolute_import
9 9
10 import contextlib
10 11 import errno
11 12 import os
12 13 import socket
@@ -171,19 +172,20 b' class lock(object):'
171 172 locker = self._readlock()
172 173 return self._testlock(locker)
173 174
174 def prepinherit(self):
175 """prepare for the lock to be inherited by a Mercurial subprocess
175 @contextlib.contextmanager
176 def inherit(self):
177 """context for the lock to be inherited by a Mercurial subprocess.
176 178
177 Returns a string that will be recognized by the lock in the
178 subprocess. Communicating this string to the subprocess needs to be done
179 separately -- typically by an environment variable.
179 Yields a string that will be recognized by the lock in the subprocess.
180 Communicating this string to the subprocess needs to be done separately
181 -- typically by an environment variable.
180 182 """
181 183 if not self.held:
182 184 raise error.LockInheritanceContractViolation(
183 'prepinherit can only be called while lock is held')
185 'inherit can only be called while lock is held')
184 186 if self._inherited:
185 187 raise error.LockInheritanceContractViolation(
186 'prepinherit cannot be called while lock is already inherited')
188 'inherit cannot be called while lock is already inherited')
187 189 if self.releasefn:
188 190 self.releasefn()
189 191 if self._parentheld:
@@ -191,15 +193,12 b' class lock(object):'
191 193 else:
192 194 lockname = '%s:%s' % (lock._host, self.pid)
193 195 self._inherited = True
194 return lockname
195
196 def reacquire(self):
197 if not self._inherited:
198 raise error.LockInheritanceContractViolation(
199 'reacquire can only be called after prepinherit')
200 if self.acquirefn:
201 self.acquirefn()
202 self._inherited = False
196 try:
197 yield lockname
198 finally:
199 if self.acquirefn:
200 self.acquirefn()
201 self._inherited = False
203 202
204 203 def release(self):
205 204 """release the lock and execute callback function if any
@@ -158,23 +158,22 b' class testlock(unittest.TestCase):'
158 158 parentstate.assertacquirecalled(True)
159 159
160 160 # set up lock inheritance
161 lockname = parentlock.prepinherit()
162 parentstate.assertreleasecalled(True)
163 parentstate.assertpostreleasecalled(False)
164 parentstate.assertlockexists(True)
165
166 childstate = teststate(self, d, pidoffset=1)
167 childlock = childstate.makelock(parentlock=lockname)
168 childstate.assertacquirecalled(True)
161 with parentlock.inherit() as lockname:
162 parentstate.assertreleasecalled(True)
163 parentstate.assertpostreleasecalled(False)
164 parentstate.assertlockexists(True)
169 165
170 # release the child lock -- the lock file should still exist on disk
171 childlock.release()
172 childstate.assertreleasecalled(True)
173 childstate.assertpostreleasecalled(True)
174 childstate.assertlockexists(True)
166 childstate = teststate(self, d, pidoffset=1)
167 childlock = childstate.makelock(parentlock=lockname)
168 childstate.assertacquirecalled(True)
175 169
176 parentstate.resetacquirefn()
177 parentlock.reacquire()
170 childlock.release()
171 childstate.assertreleasecalled(True)
172 childstate.assertpostreleasecalled(True)
173 childstate.assertlockexists(True)
174
175 parentstate.resetacquirefn()
176
178 177 parentstate.assertacquirecalled(True)
179 178
180 179 parentlock.release()
@@ -188,39 +187,39 b' class testlock(unittest.TestCase):'
188 187 lock0 = state0.makelock()
189 188 state0.assertacquirecalled(True)
190 189
191 lock0name = lock0.prepinherit()
192 state0.assertreleasecalled(True)
193 state0.assertpostreleasecalled(False)
194 state0.assertlockexists(True)
190 with lock0.inherit() as lock0name:
191 state0.assertreleasecalled(True)
192 state0.assertpostreleasecalled(False)
193 state0.assertlockexists(True)
195 194
196 state1 = teststate(self, d, pidoffset=1)
197 lock1 = state1.makelock(parentlock=lock0name)
198 state1.assertacquirecalled(True)
195 state1 = teststate(self, d, pidoffset=1)
196 lock1 = state1.makelock(parentlock=lock0name)
197 state1.assertacquirecalled(True)
199 198
200 # from within lock1, acquire another lock
201 lock1name = lock1.prepinherit()
202 # since the file on disk is lock0's this should have the same name
203 self.assertEqual(lock0name, lock1name)
199 # from within lock1, acquire another lock
200 with lock1.inherit() as lock1name:
201 # since the file on disk is lock0's this should have the same
202 # name
203 self.assertEqual(lock0name, lock1name)
204 204
205 state2 = teststate(self, d, pidoffset=2)
206 lock2 = state2.makelock(parentlock=lock1name)
207 state2.assertacquirecalled(True)
205 state2 = teststate(self, d, pidoffset=2)
206 lock2 = state2.makelock(parentlock=lock1name)
207 state2.assertacquirecalled(True)
208 208
209 lock2.release()
210 state2.assertreleasecalled(True)
211 state2.assertpostreleasecalled(True)
212 state2.assertlockexists(True)
209 lock2.release()
210 state2.assertreleasecalled(True)
211 state2.assertpostreleasecalled(True)
212 state2.assertlockexists(True)
213 213
214 state1.resetacquirefn()
215 lock1.reacquire()
216 state1.assertacquirecalled(True)
214 state1.resetacquirefn()
215
216 state1.assertacquirecalled(True)
217 217
218 lock1.release()
219 state1.assertreleasecalled(True)
220 state1.assertpostreleasecalled(True)
221 state1.assertlockexists(True)
218 lock1.release()
219 state1.assertreleasecalled(True)
220 state1.assertpostreleasecalled(True)
221 state1.assertlockexists(True)
222 222
223 lock0.reacquire()
224 223 lock0.release()
225 224
226 225 def testinheritlockfork(self):
@@ -230,26 +229,25 b' class testlock(unittest.TestCase):'
230 229 parentstate.assertacquirecalled(True)
231 230
232 231 # set up lock inheritance
233 lockname = parentlock.prepinherit()
234 childstate = teststate(self, d, pidoffset=1)
235 childlock = childstate.makelock(parentlock=lockname)
236 childstate.assertacquirecalled(True)
232 with parentlock.inherit() as lockname:
233 childstate = teststate(self, d, pidoffset=1)
234 childlock = childstate.makelock(parentlock=lockname)
235 childstate.assertacquirecalled(True)
237 236
238 # fork the child lock
239 forkchildlock = copy.deepcopy(childlock)
240 forkchildlock._pidoffset += 1
241 forkchildlock.release()
242 childstate.assertreleasecalled(False)
243 childstate.assertpostreleasecalled(False)
244 childstate.assertlockexists(True)
237 # fork the child lock
238 forkchildlock = copy.deepcopy(childlock)
239 forkchildlock._pidoffset += 1
240 forkchildlock.release()
241 childstate.assertreleasecalled(False)
242 childstate.assertpostreleasecalled(False)
243 childstate.assertlockexists(True)
245 244
246 # release the child lock
247 childlock.release()
248 childstate.assertreleasecalled(True)
249 childstate.assertpostreleasecalled(True)
250 childstate.assertlockexists(True)
245 # release the child lock
246 childlock.release()
247 childstate.assertreleasecalled(True)
248 childstate.assertpostreleasecalled(True)
249 childstate.assertlockexists(True)
251 250
252 parentlock.reacquire()
253 251 parentlock.release()
254 252
255 253 if __name__ == '__main__':
General Comments 0
You need to be logged in to leave comments. Login now