data.py 3.44 KB
Newer Older
Gerion Entrup's avatar
Gerion Entrup committed
1
import llfuse
2
from sqlfuse.model import FuseDir, Special
3
import logging
4

Gerion Entrup's avatar
Gerion Entrup committed
5
6

class Data:
Gerion Entrup's avatar
Gerion Entrup committed
7
8
    """Manages the building of the filetree and the allocated inodes"""

9
    def __init__(self, session, fs):
Gerion Entrup's avatar
Gerion Entrup committed
10
11
12
13
14
15
16
        """Construct a Data object.

        Arguments:
        session -- a sqlalchemy session
        fs      -- a list of *Path objects, that describe a filesystem
        """

17
        self.logger = logging.getLogger('sqlfuse.data')
Gerion Entrup's avatar
Gerion Entrup committed
18
        self._cache = llfuse.ROOT_INODE * [None]
19
        self._session = session
20
21
22
23
        self._tree = FuseDir(None, llfuse.ROOT_INODE, None, "/", self,
                             root=True)
        self._cache.append(self._tree)
        self._create_tree(fs)
24
25
        self.logger.debug("created tree")
        self.logger.debug(self.print_tree())
Gerion Entrup's avatar
Gerion Entrup committed
26

27
    def _create_tree(self, fs):
Gerion Entrup's avatar
Gerion Entrup committed
28
        """Creates a tree based on the description filesystem 'fs'"""
29
        dtree = [{}, None]
30
        # build tree as dict
31
32
33
34
35
36
        for cpath in fs:
            path = cpath.path.split('/')
            t = dtree
            if path[0] == '':
                path = path[1:]
            for f in path:
37
38
                if f not in t[0]:
                    t[0][f] = [{}, None]
39
                t = t[0][f]
40
            t[1] = cpath
Gerion Entrup's avatar
Gerion Entrup committed
41

42
43
44
45
        # build real objects
        queue = [(dtree[0], self._tree)]
        for (dnode, node) in queue:
            for filename in dnode:
46
47
48
49
50
51
                (subdnode, qpath) = dnode[filename]
                nnode = self._create_tree_node(node, qpath, filename)
                if len(subdnode) > 0:
                    queue.append((subdnode, nnode))

    def _create_tree_node(self, node, qpath, filename):
Gerion Entrup's avatar
Gerion Entrup committed
52
53
54
55
56
57
58
        """Creates an individual node of the filesystem.

        Arguments:
        node     -- the parent node
        qpath    -- the path object that holds the attributes and functions
        filename -- the filename of the new node
        """
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
        # if self defined
        if qpath is not None:
            if qpath.fuse_io:
                ndir = node.add_fuseio(
                    qpath.get(node, self._session, filename))
            else:
                ndir = node.add_special(
                    Special(qpath.query, qpath.functions, qpath.where,
                            self._session, node, filename, self,
                            qpath.fileattr))
        else:
            ndir = FuseDir(None, -1, node, filename, self)
            if not node.is_special():
                self.pin_inode(ndir)
            node.add_fuseio(ndir, filename)
        return ndir
Gerion Entrup's avatar
Gerion Entrup committed
75

76
    def get(self, inode):
Gerion Entrup's avatar
Gerion Entrup committed
77
        """Returns the FuseIO object that belongs to the given inode."""
78
79
80
81
82
        try:
            return self._cache[inode]
        except KeyError:
            return None

83
    def pin_inode(self, fuseio):
Gerion Entrup's avatar
Gerion Entrup committed
84
        """Find a free inode and assign it to the FuseIO object."""
85
86
87
        ino = len(self._cache)
        fuseio.set_inode(ino)
        self._cache.append(fuseio)
Gerion Entrup's avatar
Gerion Entrup committed
88

89
    def print_tree(self):
Gerion Entrup's avatar
Gerion Entrup committed
90
        """Returns a string representation of the filesystem tree."""
91
        res = ''
92
93
94
        queue = [('/', self._tree, 0)]
        while len(queue) > 0:
            (name, elem, indent) = queue.pop()
95
            res += ''.join([' ' * indent, name, ': ', elem.__repr__(), '\n'])
96
97
98
99
100
            for (name, child) in elem.get_children().items():
                queue.append((name, child, indent + 2))
            for special in elem.get_specials():
                queue.append(
                    ('special', special, indent + 2))
101
        return res