1 __all__ = ('HeapStorage',)
5 from pyoram.util.virtual_heap import SizedVirtualHeap
6 from pyoram.storage.block_storage import (BlockStorageInterface,
7 BlockStorageTypeFactory)
9 class HeapStorageInterface(object):
13 def __exit__(self, *args):
20 def clone_device(self, *args, **kwds):
21 raise NotImplementedError # pragma: no cover
24 def compute_storage_size(cls, *args, **kwds):
25 raise NotImplementedError # pragma: no cover
27 def setup(cls, *args, **kwds):
28 raise NotImplementedError # pragma: no cover
31 def header_data(self, *args, **kwds):
32 raise NotImplementedError # pragma: no cover
34 def bucket_count(self, *args, **kwds):
35 raise NotImplementedError # pragma: no cover
37 def bucket_size(self, *args, **kwds):
38 raise NotImplementedError # pragma: no cover
40 def blocks_per_bucket(self, *args, **kwds):
41 raise NotImplementedError # pragma: no cover
43 def storage_name(self, *args, **kwds):
44 raise NotImplementedError # pragma: no cover
46 def virtual_heap(self, *args, **kwds):
47 raise NotImplementedError # pragma: no cover
49 def bucket_storage(self, *args, **kwds):
50 raise NotImplementedError # pragma: no cover
52 def update_header_data(self, *args, **kwds):
53 raise NotImplementedError # pragma: no cover
54 def close(self, *args, **kwds):
55 raise NotImplementedError # pragma: no cover
56 def read_path(self, *args, **kwds):
57 raise NotImplementedError # pragma: no cover
58 def write_path(self, *args, **kwds):
59 raise NotImplementedError # pragma: no cover
63 raise NotImplementedError # pragma: no cover
65 def bytes_received(self):
66 raise NotImplementedError # pragma: no cover
68 class HeapStorage(HeapStorageInterface):
70 _header_struct_string = "!LLL"
71 _header_offset = struct.calcsize(_header_struct_string)
73 def _new_storage(self, storage, **kwds):
74 storage_type = kwds.pop('storage_type', 'file')
77 def __init__(self, storage, **kwds):
78 if isinstance(storage, BlockStorageInterface):
79 self._storage = storage
82 "Keywords not used when initializing "
83 "with a storage device: %s"
86 storage_type = kwds.pop('storage_type', 'file')
87 self._storage = BlockStorageTypeFactory(storage_type)\
90 heap_base, heap_height, blocks_per_bucket = \
92 self._header_struct_string,
93 self._storage.header_data[:self._header_offset])
94 self._vheap = SizedVirtualHeap(
97 blocks_per_bucket=blocks_per_bucket)
100 # Define HeapStorageInterface Methods
103 def clone_device(self):
104 return HeapStorage(self._storage.clone_device())
107 def compute_storage_size(cls,
115 assert (block_size > 0) and (block_size == int(block_size))
116 assert heap_height >= 0
117 assert blocks_per_bucket >= 1
118 assert heap_base >= 2
119 assert 'block_count' not in kwds
120 vheap = SizedVirtualHeap(
123 blocks_per_bucket=blocks_per_bucket)
125 return BlockStorageTypeFactory(storage_type).\
126 compute_storage_size(
127 vheap.blocks_per_bucket * block_size,
128 vheap.bucket_count(),
132 return cls._header_offset + \
133 BlockStorageTypeFactory(storage_type).\
134 compute_storage_size(
135 vheap.blocks_per_bucket * block_size,
136 vheap.bucket_count(),
149 if 'block_count' in kwds:
150 raise ValueError("'block_count' keyword is not accepted")
153 "heap height must be 0 or greater. Invalid value: %s"
155 if blocks_per_bucket < 1:
157 "blocks_per_bucket must be 1 or greater. "
158 "Invalid value: %s" % (blocks_per_bucket))
161 "heap base must be 2 or greater. Invalid value: %s"
164 vheap = SizedVirtualHeap(
167 blocks_per_bucket=blocks_per_bucket)
169 user_header_data = kwds.pop('header_data', bytes())
170 if type(user_header_data) is not bytes:
172 "'header_data' must be of type bytes. "
173 "Invalid type: %s" % (type(user_header_data)))
174 kwds['header_data'] = \
175 struct.pack(cls._header_struct_string,
178 blocks_per_bucket) + \
182 BlockStorageTypeFactory(storage_type).setup(
184 vheap.blocks_per_bucket * block_size,
185 vheap.bucket_count(),
189 def header_data(self):
190 return self._storage.header_data[self._header_offset:]
193 def bucket_count(self):
194 return self._storage.block_count
197 def bucket_size(self):
198 return self._storage.block_size
201 def blocks_per_bucket(self):
202 return self._vheap.blocks_per_bucket
205 def storage_name(self):
206 return self._storage.storage_name
209 def virtual_heap(self):
213 def bucket_storage(self):
216 def update_header_data(self, new_header_data):
217 self._storage.update_header_data(
218 self._storage.header_data[:self._header_offset] + \
222 print("Non enc heap close 1")
223 self._storage.close()
224 print("Non enc heap close 2")
226 def read_path(self, b, level_start=0):
227 assert 0 <= b < self._vheap.bucket_count()
228 bucket_list = self._vheap.Node(b).bucket_path_from_root()
229 assert 0 <= level_start < len(bucket_list)
230 return self._storage.read_blocks(bucket_list[level_start:])
232 def write_path(self, b, buckets, level_start=0):
233 assert 0 <= b < self._vheap.bucket_count()
234 bucket_list = self._vheap.Node(b).bucket_path_from_root()
235 assert 0 <= level_start < len(bucket_list)
236 self._storage.write_blocks(bucket_list[level_start:],
240 def bytes_sent(self):
241 return self._storage.bytes_sent
244 def bytes_received(self):
245 return self._storage.bytes_received