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 |
|
|
|
178 |
|
|
|
179 |
|
|
|
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 |
' |
|
|
185 | 'inherit can only be called while lock is held') | |
|
184 | 186 | if self._inherited: |
|
185 | 187 | raise error.LockInheritanceContractViolation( |
|
186 |
' |
|
|
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 |
|
|
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 |
|
|
|
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.assert |
|
|
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 |
|
|
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 |
|
|
|
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