Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomeu Vizoso <tomeu@tomeuvizoso.net>2008-09-25 15:44:23 (GMT)
committer Tomeu Vizoso <tomeu@tomeuvizoso.net>2008-09-25 15:44:23 (GMT)
commit96564f6bb56079cc1eccd0230057f753fce7f6f4 (patch)
treee24343e673540caee59486d5e1ddf40f62a3a216
parent2faab951dc6030dd97386eedb092bc1e03df4499 (diff)
Store each metadata property in its own file
-rw-r--r--src/olpc/datastore/metadatastore.py135
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