|
1 | 1 | from ethereum import utils
|
2 | 2 | from ethereum.slogging import get_logger
|
3 | 3 | from rlp.utils import str_to_bytes
|
| 4 | +import sys |
| 5 | +if sys.version_info.major == 2: |
| 6 | + from repoze.lru import lru_cache |
| 7 | +else: |
| 8 | + from functools import lru_cache |
| 9 | + |
4 | 10 | log = get_logger('db')
|
5 | 11 |
|
6 | 12 |
|
@@ -41,25 +47,6 @@ def __eq__(self, other):
|
41 | 47 | def __hash__(self):
|
42 | 48 | return utils.big_endian_to_int(str_to_bytes(self.__repr__()))
|
43 | 49 |
|
44 |
| - def inc_refcount(self, key, value): |
45 |
| - self.put(key, value) |
46 |
| - |
47 |
| - def dec_refcount(self, key): |
48 |
| - pass |
49 |
| - |
50 |
| - def revert_refcount_changes(self, epoch): |
51 |
| - pass |
52 |
| - |
53 |
| - def commit_refcount_changes(self, epoch): |
54 |
| - pass |
55 |
| - |
56 |
| - def cleanup(self, epoch): |
57 |
| - pass |
58 |
| - |
59 |
| - def put_temporarily(self, key, value): |
60 |
| - self.inc_refcount(key, value) |
61 |
| - self.dec_refcount(key) |
62 |
| - |
63 | 50 |
|
64 | 51 | DB = EphemDB = _EphemDB
|
65 | 52 |
|
@@ -136,21 +123,62 @@ def __eq__(self, other):
|
136 | 123 | def __hash__(self):
|
137 | 124 | return utils.big_endian_to_int(str_to_bytes(self.__repr__()))
|
138 | 125 |
|
139 |
| - def inc_refcount(self, key, value): |
140 |
| - self.put(key, value) |
| 126 | +@lru_cache(128) |
| 127 | +def add1(b): |
| 128 | + v = utils.big_endian_to_int(b) |
| 129 | + return utils.zpad(utils.encode_int(v + 1), 4) |
141 | 130 |
|
142 |
| - def dec_refcount(self, key): |
143 |
| - pass |
| 131 | +@lru_cache(128) |
| 132 | +def sub1(b): |
| 133 | + v = utils.big_endian_to_int(b) |
| 134 | + return utils.zpad(utils.encode_int(v - 1), 4) |
144 | 135 |
|
145 |
| - def revert_refcount_changes(self, epoch): |
146 |
| - pass |
| 136 | +class RefcountDB(BaseDB): |
147 | 137 |
|
148 |
| - def commit_refcount_changes(self, epoch): |
149 |
| - pass |
| 138 | + def __init__(self, db): |
| 139 | + self.db = db |
| 140 | + self.kv = None |
| 141 | + |
| 142 | + def get(self, key): |
| 143 | + return self.db.get(key)[4:] |
150 | 144 |
|
151 |
| - def cleanup(self, epoch): |
| 145 | + def get_refcount(self, key): |
| 146 | + try: |
| 147 | + return utils.big_endian_to_int(self.db.get(key)[:4]) |
| 148 | + except KeyError: |
| 149 | + return 0 |
| 150 | + |
| 151 | + def put(self, key, value): |
| 152 | + try: |
| 153 | + existing = self.db.get(key) |
| 154 | + assert existing[4:] == value |
| 155 | + self.db.put(key, add1(existing[:4]) + value) |
| 156 | + # print('putin', key, utils.big_endian_to_int(existing[:4]) + 1) |
| 157 | + except KeyError: |
| 158 | + self.db.put(key, b'\x00\x00\x00\x01' + value) |
| 159 | + # print('putin', key, 1) |
| 160 | + |
| 161 | + def delete(self, key): |
| 162 | + existing = self.db.get(key) |
| 163 | + if existing[:4] == b'\x00\x00\x00\x01': |
| 164 | + # print('deletung') |
| 165 | + self.db.delete(key) |
| 166 | + else: |
| 167 | + # print(repr(existing[:4])) |
| 168 | + self.db.put(key, sub1(existing[:4]) + existing[4:]) |
| 169 | + |
| 170 | + def commit(self): |
152 | 171 | pass
|
153 | 172 |
|
154 |
| - def put_temporarily(self, key, value): |
155 |
| - self.inc_refcount(key, value) |
156 |
| - self.dec_refcount(key) |
| 173 | + def _has_key(self, key): |
| 174 | + return key in self.db |
| 175 | + |
| 176 | + def __contains__(self, key): |
| 177 | + return self._has_key(key) |
| 178 | + |
| 179 | + def __eq__(self, other): |
| 180 | + return isinstance(other, self.__class__) and self.db == other.db |
| 181 | + |
| 182 | + def __hash__(self): |
| 183 | + return utils.big_endian_to_int(str_to_bytes(self.__repr__())) |
| 184 | + |
0 commit comments