diff options
author | Tomeu Vizoso <tomeu@tomeuvizoso.net> | 2008-09-25 15:44:23 (GMT) |
---|---|---|
committer | Tomeu Vizoso <tomeu@tomeuvizoso.net> | 2008-09-25 15:44:23 (GMT) |
commit | 96564f6bb56079cc1eccd0230057f753fce7f6f4 (patch) | |
tree | e24343e673540caee59486d5e1ddf40f62a3a216 | |
parent | 2faab951dc6030dd97386eedb092bc1e03df4499 (diff) |
Store each metadata property in its own file
-rw-r--r-- | src/olpc/datastore/metadatastore.py | 135 |
1 files changed, 31 insertions, 104 deletions
diff --git a/src/olpc/datastore/metadatastore.py b/src/olpc/datastore/metadatastore.py index 5b607be..810ccb8 100644 --- a/src/olpc/datastore/metadatastore.py +++ b/src/olpc/datastore/metadatastore.py @@ -1,5 +1,6 @@ import os import logging +import errno from olpc.datastore import layoutmanager @@ -7,25 +8,21 @@ MAX_SIZE = 256 class MetadataStore(object): def store(self, uid, metadata): - metadata = metadata.copy() - - for key in metadata.keys(): - if ' ' in key: - raise ValueError('Property names cannot include spaces. ' - 'Wrong name: %r' % key) - dir_path = layoutmanager.get_instance().get_entry_path(uid) if not os.path.exists(dir_path): os.makedirs(dir_path) - for key, value in metadata.items(): - if isinstance(value, str) and \ - (len(value) > MAX_SIZE or not self._is_unicode(value)): - self._write_external(key, value, dir_path) - del metadata[key] + metadata_path = os.path.join(dir_path, 'metadata') + if not os.path.exists(metadata_path): + os.makedirs(metadata_path) metadata['uid'] = uid - self._encode(metadata, os.path.join(dir_path, 'metadata')) + for key, value in metadata.items(): + f = open(os.path.join(metadata_path, key), 'w+') + try: + f.write(str(value)) + finally: + f.close() def retrieve(self, uid, properties=None): dir_path = layoutmanager.get_instance().get_entry_path(uid) @@ -33,103 +30,33 @@ class MetadataStore(object): raise ValueError('Unknown object: %r' % uid) metadata_path = os.path.join(dir_path, 'metadata') - metadata = self._decode(metadata_path, properties) + metadata = {} + if properties is None or not properties: + properties = os.listdir(metadata_path) - if properties is None or len(properties) != len(metadata): - extra_metadata_dir = os.path.join(dir_path, 'extra_metadata') - if os.path.exists(extra_metadata_dir): - for key in os.listdir(extra_metadata_dir): - if properties is not None and key not in properties: - continue - file_path = os.path.join(extra_metadata_dir, key) - if os.path.exists(file_path): - # TODO: This class shouldn't know anything about dbus. - import dbus - metadata[key] = dbus.ByteArray(open(file_path).read()) + for key in properties: + property_path = metadata_path + '/' + key + try: + value = open(property_path, 'r').read() + except IOError, e: + if e.errno != errno.ENOENT: + raise + else: + if not value: + metadata[key] = '' + else: + # TODO: This class shouldn't know anything about dbus. + import dbus + metadata[key] = dbus.ByteArray(value) + return metadata def delete(self, uid): dir_path = layoutmanager.get_instance().get_entry_path(uid) metadata_path = os.path.join(dir_path, 'metadata') - if os.path.isfile(metadata_path): - os.remove(os.path.join(dir_path, 'metadata')) - else: - logging.warning('%s is not a valid path' % metadata_path) - - extra_metadata_path = os.path.join(dir_path, 'extra_metadata') - if os.path.isdir(extra_metadata_path): - for key in os.listdir(extra_metadata_path): - os.remove(os.path.join(extra_metadata_path, key)) - os.rmdir(os.path.join(dir_path, 'extra_metadata')) - else: - logging.warning('%s is not a valid path' % extra_metadata_path) - - def _write_external(self, key, value, dir_path): - extra_metadata_dir = os.path.join(dir_path, 'extra_metadata') - if not os.path.exists(extra_metadata_dir): - os.makedirs(extra_metadata_dir) - f = open(os.path.join(extra_metadata_dir, key), 'w') - f.write(value) - f.close() - - def _is_unicode(self, string): - try: - string.decode('utf-8') - return True - except UnicodeDecodeError: - return False - - def _encode(self, metadata, file_path): - f = open(file_path, 'w') - f.write('v1\n') - for key, value in metadata.items(): - if not key: - raise ValueError('Property keys cannot be empty') - if (' ' in key) or ('\t' in key): - raise ValueError('Property keys cannot contain tabulators: %r' \ - % key) - if value is None: - value = '' - else: - value = str(value) - f.write('%s\t%d\t%s\n' % (key, len(value), value)) - f.close() - - def _decode(self, file_path, properties): - f = open(file_path, 'r') - version_line = f.readline() - try: - version = int(version_line[1:-1]) - if version != 1: - raise ValueError('Incompatible version %r' % version) - except: - logging.error('Invalid version line: %s' % version_line) - raise - - metadata = {} - while True: - line = f.readline() - if not line: - break - - key, value_len, value = line.split('\t', 2) - value_len = int(value_len) - - if len(value) == value_len + 1: - value = value[:-1] # skip the newline - else: - value += f.read(value_len - len(value)) - f.seek(1, 1) # skip the newline - - if properties is None: - metadata[key] = value - elif key in properties: - metadata[key] = value - if len(properties) == len(metadata): - break - - f.close() - return metadata + for key in os.listdir(metadata_path): + os.remove(os.path.join(metadata_path, key)) + os.rmdir(metadata_path) def _cast_for_journal(self, key, value): # Hack because the current journal expects these properties to have some |