abc57447813d0bef0f779bd4565a05529d5b6d80
[iotcloud.git] / PyORAM / src / pyoram / storage / block_storage_mmap.py
1 __all__ = ('BlockStorageMMap',)
2
3 import logging
4 import mmap
5
6 from pyoram.storage.block_storage import \
7     BlockStorageTypeFactory
8 from pyoram.storage.block_storage_file import \
9     BlockStorageFile
10
11 log = logging.getLogger("pyoram")
12
13 class _BlockStorageMemoryImpl(object):
14     """
15     This class implementents the BlockStorageInterface read/write
16     methods for classes with a private attribute _f that can be
17     accessed using __getslice__/__setslice__ notation.
18     """
19
20     def read_blocks(self, indices):
21         blocks = []
22         for i in indices:
23             assert 0 <= i < self.block_count
24             self._bytes_received += self.block_size
25             pos_start = self._header_offset + i * self.block_size
26             pos_stop = pos_start + self.block_size
27             blocks.append(self._f[pos_start:pos_stop])
28         return blocks
29
30     def yield_blocks(self, indices):
31         for i in indices:
32             assert 0 <= i < self.block_count
33             self._bytes_received += self.block_size
34             pos_start = self._header_offset + i * self.block_size
35             pos_stop = pos_start + self.block_size
36             yield self._f[pos_start:pos_stop]
37
38     def read_block(self, i):
39         assert 0 <= i < self.block_count
40         self._bytes_received += self.block_size
41         pos_start = self._header_offset + i * self.block_size
42         pos_stop = pos_start + self.block_size
43         return self._f[pos_start:pos_stop]
44
45     def write_blocks(self, indices, blocks, callback=None):
46         for i, block in zip(indices, blocks):
47             assert 0 <= i < self.block_count
48             self._bytes_sent += self.block_size
49             pos_start = self._header_offset + i * self.block_size
50             pos_stop = pos_start + self.block_size
51             self._f[pos_start:pos_stop] = block
52             if callback is not None:
53                 callback(i)
54
55     def write_block(self, i, block):
56         assert 0 <= i < self.block_count
57         self._bytes_sent += self.block_size
58         pos_start = self._header_offset + i * self.block_size
59         pos_stop = pos_start + self.block_size
60         self._f[pos_start:pos_stop] = block
61
62 class BlockStorageMMap(_BlockStorageMemoryImpl,
63                        BlockStorageFile):
64     """
65     A class implementing the block storage interface by creating a
66     memory map over a local file. This class uses the same storage
67     format as BlockStorageFile. Thus, a block storage space can be
68     created using this class and then, after saving the raw storage
69     data to disk, reopened with any other class compatible with
70     BlockStorageFile (and visa versa).
71     """
72
73     def __init__(self, *args, **kwds):
74         mm = kwds.pop('mm', None)
75         self._mmap_owned = True
76         super(BlockStorageMMap, self).__init__(*args, **kwds)
77         if mm is None:
78             self._f.flush()
79             mm = mmap.mmap(self._f.fileno(), 0)
80         else:
81             self._mmap_owned = False
82         self._f.close()
83         self._f = mm
84
85     #
86     # Define BlockStorageInterface Methods
87     # (override what is defined on BlockStorageFile)
88     #
89
90     #@classmethod
91     #def compute_storage_size(...)
92
93     def clone_device(self):
94         f =  BlockStorageMMap(self.storage_name,
95                               threadpool_size=0,
96                               mm=self._f,
97                               ignore_lock=True)
98         f._pool = self._pool
99         f._close_pool = False
100         return f
101
102     @classmethod
103     def setup(cls,
104               storage_name,
105               block_size,
106               block_count,
107               **kwds):
108         f = BlockStorageFile.setup(storage_name,
109                                    block_size,
110                                    block_count,
111                                    **kwds)
112         f.close()
113         return BlockStorageMMap(storage_name)
114
115     #def update_header_data(...)
116
117     def close(self):
118         self._prep_for_close()
119         if self._f is not None:
120             if self._mmap_owned:
121                 try:
122                     self._f.close()
123                 except OSError:                        # pragma: no cover
124                     pass                               # pragma: no cover
125             self._f = None
126
127     #def read_blocks(...)
128
129     #def yield_blocks(...)
130
131     #def read_block(...)
132
133     #def write_blocks(...)
134
135     #def write_block(...)
136
137     #@property
138     #def bytes_sent(...)
139
140     #@property
141     #def bytes_received(...)
142
143 BlockStorageTypeFactory.register_device("mmap", BlockStorageMMap)