dummy.py 9.86 KB
Newer Older
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
1
2
3
import os
import sqlite3
import json
4
import logging
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
5
import types
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
6

7
8
9
10
11
12
13
class BackEnd:
    def __init__(self, basepath, log_file='backend.out', log_level=logging.DEBUG):
        self.basepath = basepath
        logging.basicConfig(filename=log_file,level=log_level,)
        if not os.path.exists(basepath):
            os.makedirs(basepath)
        db = '/'.join([basepath, 'db'])
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
14
        self.con = sqlite3.connect(db)
15
16
        # Create tables
        sql = '''create table if not exists objects(name text)'''
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
17
18
        self.con.execute(sql)
        self.con.commit()
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
19

20
    def get_account_meta(self, account):
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
21
22
23
        """
        returns a dictionary with the container metadata
        """
24
        logging.info("get_account_meta: %s", account)
25
26
27
28
29
30
        fullname = '/'.join([self.basepath, account])
        if not os.path.exists(fullname):
            raise NameError('Account does not exist')
        contents = os.listdir(fullname) 
        count = len(contents)
        size = sum(os.path.getsize('/'.join([self.basepath, account, objectname])) for objectname in contents)
31
        return {'name': account, 'count': count, 'bytes': size}
32
33
        
    def create_container(self, account, name):
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
34
35
36
37
        """
        creates a new container with the given name
        if it doesn't exists under the basepath
        """
38
        logging.info("create_container: %s %s", account, name)
39
40
        fullname = '/'.join([self.basepath, account, name])    
        if not os.path.exists(fullname):
41
            os.makedirs(fullname)
42
43
44
        else:
            raise NameError('Container already exists')
        return
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
45

46
    def delete_container(self, account, name):
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
47
48
        """
        deletes the container with the given name
49
        if it exists under the basepath
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
50
51
        and it's empty
        """
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
52
        logging.debug("delete_container: %s %s", account, name)
53
54
55
        fullname = '/'.join([self.basepath, account, name])    
        if not os.path.exists(fullname):
            raise NameError('Container does not exist')
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
56
57
        if os.listdir(fullname):
            raise Exception('Container is not empty')
58
        else:
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
59
            os.rmdir(fullname)
60
        return
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
61
    
62
    def get_container_meta(self, account, name):
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
63
64
65
        """
        returns a dictionary with the container metadata
        """
66
67
68
69
70
71
72
73
74
75
76
77
        fullname = '/'.join([self.basepath, account, name])
        if not os.path.exists(fullname):
            raise NameError('Container does not exist')
        contents = os.listdir(fullname) 
        count = len(contents)
        size = sum(os.path.getsize('/'.join([self.basepath, account, name, objectname])) for objectname in contents)
        return {'name': name, 'count': count, 'bytes': size}
    
    def list_containers(self, marker = None, limit = 10000):
        return os.listdir(self.basepath)[:limit]
    
    def list_objects(self, account, container, prefix='', delimiter=None, marker = None, limit = 10000):
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
78
        logging.info("list_objects: %s %s %s %s %s %s", account, container, prefix, delimiter, marker, limit)
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
79
80
81
        dir = '/'.join([self.basepath, account, container])
        if not os.path.exists(dir):
            raise NameError('Container does not exist')
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
        p1 = '/'.join(['%', prefix, '%'])
        p2 = '/'.join([account, container, '%'])
        search_str = (prefix and [p1] or [p2])[0]
        c = self.con.execute('select * from objects where name like ''?'' order by name', (search_str,))
        objects = c.fetchall()
        if delimiter:
            pseudo_objects = {}
            for x in objects:
                pseudo_name = x[0][len(prefix):]
                i = pseudo_name.find(delimiter)
                if i != -1:
                    pseudo_name = pseudo_name[:i]
                #TODO: Virtual directories.
                pseudo_objects[pseudo_name] = x
            objects = pseudo_objects.keys()
        start = 0
        if marker:
            try:
                start = objects.index(marker)
            except ValueError:
                pass
        if not limit or limit > 10000:
            limit = 10000
        return objects[start:start + limit]
106
    
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
107
    def get_object_meta(self, account, container, name, keys=None):
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
        dir = '/'.join([self.basepath, account, container])
        if not os.path.exists(dir):
            raise NameError('Container does not exist')
        else:
            os.chdir(dir)
        location = self.__get_object_linkinfo('/'.join([account, container, name]))
        location = '.'.join([location, 'meta'])
        f = open(location, 'r')
        data = json.load(f)
        f.close()
        return data
    
    def get_object_data(self, account, container, name, offset=0, length=-1):
        dir = '/'.join([self.basepath, account, container])
        if not os.path.exists(dir):
            raise NameError('Container does not exist')
        else:
            os.chdir(dir)
        location = self.__get_object_linkinfo('/'.join([account, container, name]))
        f = open(location, 'r')
        if offset:
            f.seek(offset)
        data = f.read(length)
        f.close()
        return data
    
    def update_object(self, account, container, name, data):
        dir = '/'.join([self.basepath, account, container])
        if not os.path.exists(dir):
            raise NameError('Container does not exist')
        try:
            location = self.__get_object_linkinfo('/'.join([account, container, name]))
        except NameError:
            # new object
            location = str(self.__save_linkinfo('/'.join([account, container, name])))
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
143
        self.__store_data(location, account, container, data)
144
        return
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
145
    
146
147
148
149
150
151
152
153
154
    def update_object_meta(self, account, container, name, meta):
        dir = '/'.join([self.basepath, account, container])
        if not os.path.exists(dir):
            raise NameError('Container does not exist')
        try:
            location = self.__get_object_linkinfo('/'.join([account, container, name]))
        except NameError:
            # new object
            location = str(self.__save_linkinfo('/'.join([account, container, name])))
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
155
        self.__store_metadata(location, account, container, meta)
156
        return
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
157
    
158
159
160
161
    def copy_object(self, account, src_container, src_name, dest_container, dest_name, meta):
        fullname = '/'.join([self.basepath, account, dest_container])    
        if not os.path.exists(fullname):
            raise NameError('Destination container does not exist')
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
162
163
        data = self.get_object_data(account, src_container, src_name)
        self.update_object(account, dest_container, dest_name, data)
164
165
166
167
168
169
170
171
172
        src_object_meta = self.get_object_meta(account, src_container, src_name)
        if (type(src_object_meta) == types.DictType):
            distinct_keys = [k for k in src_object_meta.keys() if k not in meta.keys()]
            for k in distinct_keys:
                meta[k] = src_object_meta[k]
                self.update_object_meta(account, dest_container, dest_name, meta)
        else:
            self.update_object_meta(account, dest_container, dest_name, meta)
        return
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
173
    
174
175
176
177
178
179
180
181
182
183
184
185
186
    def delete_object(self, account, container, name):
        dir = '/'.join([self.basepath, account, container])
        if not os.path.exists(dir):
            raise NameError('Container does not exist')
        else:
            os.chdir(dir)
        location = self.__get_object_linkinfo('/'.join([account, container, name]))
        # delete object data
        self.__delete_data(location, account, container)
        # delete object metadata
        location = '.'.join([location, 'meta'])
        self.__delete_data(location, account, container)
        return
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
187
    
188
189
190
191
192
193
194
195
196
197
198
    def __store_metadata(self, location, account, container, meta):
        dir = '/'.join([self.basepath, account, container])
        if not os.path.exists(dir):
            raise NameError('Container does not exist')
        else:
            os.chdir(dir)
        location = '.'.join([location, 'meta'])
        f = open(location, 'w')
        data = json.dumps(meta)
        f.write(data)
        f.close()
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
199
    
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
    def __store_data(self, location, account, container, data):
        dir = '/'.join([self.basepath, account, container])
        if not os.path.exists(dir):
            raise NameError('Container does not exist')
        else:
            os.chdir(dir)
        f = open(location, 'w')
        f.write(data)
        f.close()
        
    def __delete_data(self, location, account, container):
        file = '/'.join([self.basepath, account, container, location])
        if not os.path.exists(dir):
            raise NameError('Container does not exist')
        else:
            os.remove(file)
        
    def __get_object_linkinfo(self, name):
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
218
        c = self.con.execute('select rowid from objects where name=''?''', (name,))
219
220
221
222
223
        row = c.fetchone()
        if row:
            return str(row[0])
        else:
            raise NameError('Object not found')
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
224
    
225
    def __save_linkinfo(self, name):
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
226
227
        id = self.con.execute('insert into objects(name) values(?)', (name,)).lastrowid
        self.con.commit()
228
        return id
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
229
    
230
    def __delete_linkinfo(self, name):
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
231
232
        self.con.execute('delete from objects where name = ?', (name,))
        self.cont.commit()
Sofia Papagiannaki's avatar
Sofia Papagiannaki committed
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
        return
    
#def binary_search_name(a, x, lo = 0, hi = None):
#    """
#    Search a sorted array of dicts for the value of the key 'name'.
#    Raises ValueError if the value is not found.
#    a -- the array
#    x -- the value to search for
#    """
#    if hi is None:
#            hi = len(a)
#    while lo < hi:
#        mid = (lo + hi) // 2
#        midval = a[mid][0]
#        if midval < x:
#            lo = mid + 1
#        elif midval > x: 
#            hi = mid
#        else:
#            return mid
#    raise ValueError()