Logo Search packages:      
Sourcecode: ubuntuone-client version File versions

file_shelf.py

# ubuntuone.storagefs.diskcache - disk-backed filesystem cache
#
# Authors: Facundo Batista <facundo@canonical.com>
#          Guillermo Gonzalez  <guillermo.gonzalez@canonical.com>
#
# Copyright 2009 Canonical Ltd.
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 3, as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranties of
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
# PURPOSE.  See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program.  If not, see <http://www.gnu.org/licenses/>.
"""storage shelf using a files tree."""

from __future__ import with_statement
from UserDict import DictMixin
import cPickle
import os

00026 class FileShelf(object, DictMixin):
    """ File based shelf.

    It support arbritary python objects as values (anything accepted by
    cPickle).  And support any valid file name as key.
    """

00033     def __init__(self, path, depth=3):
        """ Create a FileShelf.

        @param path: the path to use as the root of the shelf
        @param depth: the directory depth to use, can't be < 0. default is 3
        """
        self._path = path
        if depth < 0:
            raise ValueError("depth must be >= 0")
        self._depth = depth
        self._check_and_create_dirs(self._path)

00045     def _check_and_create_dirs(self, path):
        """ check if the path isn't a file and in case it don't exists,
        creates it
        """
        if os.path.exists(path) and os.path.isfile(path):
            os.unlink(path)
        if not os.path.exists(path):
            os.makedirs(path)

00054     def key_file(self, key):
        """ get the real key used by the storage from a key """
        # cannot use None to create files in the disk
        if key is None:
            raise ValueError("Invalid key: %r" % key)

        # length always needs to be longer (we have a uuid after all)
        if len(key) < self._depth:
            raise ValueError("The key (%r) needs to be longer!" % key)

        letters = [key[i] for i in xrange(0, self._depth)]
        path = os.path.join(self._path, *letters)
        self._check_and_create_dirs(path)
        return os.path.join(path, key)

00069     def has_key(self, key):
        """ True if the the shelf has the key """
        return os.path.exists(self.key_file(key))

00073     def keys(self):
        """ returns a iterator over the keys """
        for dirpath, dirnames, filenames in os.walk(self._path):
            for filename in filenames:
                yield filename

00079     def pop(self, key):
        """ returns the key and deletes the entry """
        k = self[key]
        del self[key]
        return k

00085     def __contains__(self, key):
        """ returns if the file storage has that key """
        # this method surely has some effect! pylint: disable-msg=W0104
        try:
            self[key]
        except KeyError:
            return False
        else:
            return True

00095     def __getitem__(self, key):
        """ getitem backed by the file storage """
        try:
            with open(self.key_file(key), "rb") as fd:
                data = cPickle.load(fd)
        except (IOError, OSError, EOFError):
            raise KeyError
        else:
            return data

00105     def __setitem__(self, key, value):
        """ setitem backed by the file storage """
        with open(self.key_file(key), "wb") as fh:
            cPickle.dump(value, fh, protocol=2)
            fh.flush()
            os.fsync(fh.fileno())

00112     def __delitem__(self, key):
        """ delitem backed by the file storage """
        os.remove(self.key_file(key))

00116     def __len__(self):
        """ The len of the shelf.
        To get len(keys) we need to iterate over the full key set.
        """
        counter = 0
        for key in self.keys():
            counter += 1
        return counter


Generated by  Doxygen 1.6.0   Back to index