diff options
Diffstat (limited to 'fs.py')
-rw-r--r-- | fs.py | 143 |
1 files changed, 0 insertions, 143 deletions
@@ -1,143 +0,0 @@ -import re -import tor_utils - - -class VFS: - def __init__(self, data_size=800, replica_factor=3): - assert data_size / 8 == data_size // 8 - self.fs = dict() - self.re_slash = re.compile('/+') - self.block_size = data_size // 8 - self.replica_factor = replica_factor - - def open(self, path): - path = self.re_slash.sub('/', path) - tokens = path.split('/') - handle = self.fs - - for tk in tokens[:-1]: - if not tk: - raise ValueError('Invalid path %s' % path) - handle = handle.get(tk, dict()) - if not isinstance(handle, dict): - raise ValueError('%s is not valid' % path) - - default_file_handle = FileHandle( - block_size=self.block_size, - replica_factor=self.replica_factor, - ) - file_handle = handle.get(tokens[-1], default_file_handle) - return file_handle - - -class FileHandle: - def __init__(self, block_size, replica_factor): - self.block_size = block_size - self.replica_factor = replica_factor - self.block_store = dict() - - def load_block(self, index, check_boundary=True): - assert index >= 0 - - if index in self.block_store: - # Load from one of its replica - for addr in self.block_store[index]: - block = tor_utils.load_block(addr) - if block is not None: - return block - - # Fail - raise ValueError("Fail to load block at index %d" % index) - - elif check_boundary: - raise ValueError("Index out of bound") - - else: - return b'\x00' * self.block_size - - def store_block(self, index, block): - assert index >= 0 - - addresses = list() - for _ in range(self.replica_factor): - addr = tor_utils.store_block(block, self.block_size) - addresses.append(addr) - - self.block_store[index] = addresses - - def read(self, offset, length): - begin_offset = offset - end_offset = offset + length - - begin_index = begin_offset // self.block_size - end_index = end_offset // self.block_size - - # Load first block - if begin_offset / self.block_size != begin_index: - block = self.load_block(begin_index) - front_length = self.block_size * (begin_index + 1) - begin_offset - assert front_length > 0 - front_block = block[:-front_length] - begin_index += 1 - else: - front_length = 0 - front_block = b'' - - # Load last block - if end_offset / self.block_size != end_index: - block = self.load_block(end_index) - tail_length = self.block_size * (end_index) - end_offset - assert tail_length > 0 - tail_block = block[:tail_length] - else: - tail_length = 0 - tail_block = b'' - - # Load intermediate blocks - data = front_block - - for index in range(begin_index, end_index): - block = self.load_block(index) - data += block - - data += tail_block - return data - - def write(self, offset, data): - length = len(data) - begin_offset = offset - end_offset = offset + length - - begin_index = begin_offset // self.block_size - end_index = end_offset // self.block_size - - # Update first block - if begin_offset / self.block_size != begin_index: - block = self.load_block(begin_index) - front_length = self.block_size * (begin_index + 1) - begin_offset - assert front_length > 0 - - new_block = block[:-front_length] + data[:front_length] - self.store_block(begin_index, new_block) - begin_index += 1 - else: - front_length = 0 - - # Update last block - if end_offset / self.block_size != end_index: - block = self.load_block(end_index) - tail_length = self.block_size * (end_index) - end_offset - assert tail_length > 0 - - new_block = data[-tail_length:] + block[:tail_length] - self.store_block(end_index, new_block) - else: - tail_length = 0 - - # Update intermediate blocks - for index in range(begin_index, end_index): - begin_data_offset = front_length + self.block_size * (index - begin_index) - end_data_offset = begin_data_offset + self.block_size - - new_block = data[begin_data_offset:end_data_offset] - self.store_block(index, new_block) |