Statistics
| Branch: | Tag: | Revision:

root / pithos / backends / dummy.py @ 24484999

History | View | Annotate | Download (10.5 kB)

1
import os
2
import sqlite3
3
import json
4
import logging
5

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

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

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