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
|