35
36
ROLLBACK_NORMAL = 1
36
37
ROLLBACK_WITH_DELETE = 2
38
def __init__(self, path, overwrite=True, wait=True, timeout=10, delay=0.5):
39
def __init__(self, path, wait=True, timeout=10, delay=0.5):
41
self.overwrite = overwrite
43
44
self.timeout = timeout
48
49
self.lock = self._make_lock()
49
50
self.readers_sem = self._make_readers_semaphore()
51
def open(self, mode="r", wait=True):
52
def open(self, mode="r", overwrite=True, wait=True):
54
self.overwrite = overwrite
54
56
self.lock.acquire(wait=wait)
229
230
raise SharedFileException("must be in read mode, not '%s'" %
233
def _unsafe_delete(self):
237
if e.errno != errno.ENOENT:
239
raise SharedFileNotFound("'%s' not found" % self.path)
232
241
def _commit(self):
233
242
# the parent directory may have been deleted out from under us; if
234
243
# that has happened we probably can't avoid a race condition
268
278
return FileSemaphore(self._make_hidden_file_with_suffix('readers_sem'))
280
class SharedFileDict(object):
281
""" Provide a key-value store backed by a SharedFile """
282
def __init__(self, path, serializer=None):
283
self.file = SharedFile(path)
284
self.serializer = serializer or pickle
286
def __getitem__(self, key):
288
self.file.open(mode='r')
289
except SharedFileNotFound:
290
raise KeyError("key '%s' not found" % key)
292
return self.serializer.load(self.file)[key]
296
#TODO: get should support default value
299
def __setitem__(self, key, value):
300
self.file.open(mode='rw')
302
d = self.serializer.load(self.file)
304
self.serializer.dump(d, self.file)
306
self.file.request_rollback()
311
def __delitem__(self, key):
312
self.file.open(mode='rw')
314
d = self.serializer.load(self.file)
317
# Delete the file if the last key was deleted
318
raise SharedFileRollbackWithDelete
319
self.serializer.dump(d, self.file)
320
except SharedFileRollbackWithDelete:
321
self.file.request_rollback(delete=True)
323
self.file.request_rollback()
328
def update(self, data):
329
self.file.open(mode='rw')
331
d = self.serializer.load(self.file)
333
self.serializer.dump(d, self.file)
335
self.file.request_rollback()
341
# N.B. this is not part of the dictionary protocol, is there a more
343
self.file.open(mode='w', overwrite=True)
345
self.serializer.dump(data, self.file)
347
self.file.request_rollback()
353
return self.to_dict().items()
356
return self.to_dict().keys()
359
return len(self.keys())
362
return bool(self.keys())
365
return self.to_dict().values()
367
def has_key(self, key):
368
return key in self.to_dict().keys()
370
__contains__ = has_key
372
def clear(self, wait=True):
374
self.file.delete(wait=wait)
375
except SharedFileNotFound:
380
self.file.open(mode='r')
381
except SharedFileNotFound:
384
return self.serializer.load(self.file)
388
def _unsafe_delete(self):
390
self.file._unsafe_delete()
391
except SharedFileNotFound: