-
Notifications
You must be signed in to change notification settings - Fork 0
/
berkeleydb_backend.py
77 lines (63 loc) · 2.45 KB
/
berkeleydb_backend.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import bsddb # BerkeleyDB bindings.
import os
# Backend that uses a local BerkeleyDB store. We assume single-threaded use
# of this backend. Since the python bindings only support string values in
# the DB, we encode reference counts as decimal strings prepended to the value
# string and separated by a tilde character.
class BerkeleyDBBackend:
# filename is a local file where this data will be persisted.
def __init__(self, filename):
self.bytesPut = 0
self.bytesGotten = 0
self.filename = filename
self.bytesPut = 0
self.bytesGotten = 0
try:
self.kvstore = bsddb.hashopen(self.filename)
except:
# The file failed to load, so delete it and try again.
try:
os.unlink(filename)
except:
pass
self.kvstore = bsddb.hashopen(self.filename)
def resetCounters(self):
self.bytesPut = 0
self.bytesGotten = 0
def __del__(self):
self.kvstore.close()
def put(self, key, value):
self.bytesPut += len(value)
try:
self.incRefCount(key)
except KeyError:
# This key does not exist yet, so create it with a reference count of 1.
self.kvstore[key] = '1~' + value
def get(self, key):
(_, _, value) = self.kvstore[key].partition('~')
self.bytesGotten += len(value)
return value
# Changes the reference count in a record string loaded from the DB.
def addToRefCount(self, record, delta):
# Parse out the reference count, increment it by the delta, and rebuild
# the record string.
(refCountStr, _, value) = record.partition('~')
return str(delta + int(refCountStr)) + '~' + value
def incRefCount(self, key):
self.kvstore[key] = self.addToRefCount(self.kvstore[key], 1)
def decRefCount(self, key):
record = self.addToRefCount(self.kvstore[key], -1)
if record.startswith('0~'):
# Delete this record from the store.
del self.kvstore[key]
else: # Save the updated record.
self.kvstore[key] = record
def nuke(self):
self.kvstore.close()
try:
os.unlink(self.filename)
except:
pass
self.kvstore = bsddb.hashopen(self.filename)
def flush(self):
self.kvstore.sync()