66 |
66 |
sql = '''create table if not exists versions (
|
67 |
67 |
version_id integer primary key,
|
68 |
68 |
name text,
|
|
69 |
user text,
|
69 |
70 |
tstamp datetime default current_timestamp,
|
70 |
71 |
size integer default 0,
|
71 |
72 |
hide integer default 0)'''
|
... | ... | |
137 |
138 |
logger.debug("update_account_meta: %s %s %s", account, meta, replace)
|
138 |
139 |
if user != account:
|
139 |
140 |
raise NotAllowedError
|
140 |
|
self._put_metadata(account, meta, replace)
|
|
141 |
self._put_metadata(user, account, meta, replace)
|
141 |
142 |
|
142 |
143 |
def list_containers(self, user, account, marker=None, limit=10000, until=None):
|
143 |
144 |
"""Return a list of containers existing under an account."""
|
... | ... | |
157 |
158 |
path, version_id, mtime = self._get_containerinfo(account, container)
|
158 |
159 |
except NameError:
|
159 |
160 |
path = os.path.join(account, container)
|
160 |
|
version_id = self._put_version(path)
|
|
161 |
version_id = self._put_version(path, user)
|
161 |
162 |
else:
|
162 |
163 |
raise NameError('Container already exists')
|
163 |
164 |
|
... | ... | |
172 |
173 |
if count > 0:
|
173 |
174 |
raise IndexError('Container is not empty')
|
174 |
175 |
self._del_path(path) # Point of no return.
|
175 |
|
self._copy_version(account, account, True, True) # New account version.
|
|
176 |
self._copy_version(user, account, account, True, True) # New account version.
|
176 |
177 |
|
177 |
178 |
def get_container_meta(self, user, account, container, until=None):
|
178 |
179 |
"""Return a dictionary with the container metadata."""
|
... | ... | |
204 |
205 |
if user != account:
|
205 |
206 |
raise NotAllowedError
|
206 |
207 |
path, version_id, mtime = self._get_containerinfo(account, container)
|
207 |
|
self._put_metadata(path, meta, replace)
|
|
208 |
self._put_metadata(user, path, meta, replace)
|
208 |
209 |
|
209 |
210 |
def list_objects(self, user, account, container, prefix='', delimiter=None, marker=None, limit=10000, virtual=True, keys=[], until=None):
|
210 |
211 |
"""Return a list of objects existing under a container."""
|
... | ... | |
233 |
234 |
|
234 |
235 |
logger.debug("get_object_meta: %s %s %s %s", account, container, name, version)
|
235 |
236 |
self._can_read(user, account, container, name)
|
236 |
|
path, version_id, mtime, size = self._get_objectinfo(account, container, name, version)
|
|
237 |
path, version_id, muser, mtime, size = self._get_objectinfo(account, container, name, version)
|
237 |
238 |
if version is None:
|
238 |
239 |
modified = mtime
|
239 |
240 |
else:
|
240 |
|
modified = self._get_version(path, version)[1] # Overall last modification
|
|
241 |
modified = self._get_version(path, version)[2] # Overall last modification
|
241 |
242 |
|
242 |
243 |
meta = self._get_metadata(path, version_id)
|
243 |
|
meta.update({'name': name, 'bytes': size, 'version': version_id, 'version_timestamp': mtime, 'modified': modified})
|
|
244 |
meta.update({'name': name, 'bytes': size})
|
|
245 |
meta.update({'version': version_id, 'version_timestamp': mtime})
|
|
246 |
meta.update({'modified': modified, 'modified_by': muser})
|
244 |
247 |
return meta
|
245 |
248 |
|
246 |
249 |
def update_object_meta(self, user, account, container, name, meta, replace=False):
|
... | ... | |
248 |
251 |
|
249 |
252 |
logger.debug("update_object_meta: %s %s %s %s %s", account, container, name, meta, replace)
|
250 |
253 |
self._can_write(user, account, container, name)
|
251 |
|
path, version_id, mtime, size = self._get_objectinfo(account, container, name)
|
252 |
|
self._put_metadata(path, meta, replace)
|
|
254 |
path, version_id, muser, mtime, size = self._get_objectinfo(account, container, name)
|
|
255 |
self._put_metadata(user, path, meta, replace)
|
253 |
256 |
|
254 |
257 |
def get_object_permissions(self, user, account, container, name):
|
255 |
258 |
"""Return the path from which this object gets its permissions from,\
|
... | ... | |
275 |
278 |
|
276 |
279 |
logger.debug("get_object_hashmap: %s %s %s %s", account, container, name, version)
|
277 |
280 |
self._can_read(user, account, container, name)
|
278 |
|
path, version_id, mtime, size = self._get_objectinfo(account, container, name, version)
|
|
281 |
path, version_id, muser, mtime, size = self._get_objectinfo(account, container, name, version)
|
279 |
282 |
sql = 'select block_id from hashmaps where version_id = ? order by pos asc'
|
280 |
283 |
c = self.con.execute(sql, (version_id,))
|
281 |
284 |
hashmap = [x[0] for x in c.fetchall()]
|
... | ... | |
292 |
295 |
path = os.path.join(path, name)
|
293 |
296 |
if permissions is not None:
|
294 |
297 |
r, w = self._check_permissions(path, permissions)
|
295 |
|
src_version_id, dest_version_id = self._copy_version(path, path, not replace_meta, False)
|
|
298 |
src_version_id, dest_version_id = self._copy_version(user, path, path, not replace_meta, False)
|
296 |
299 |
sql = 'update versions set size = ? where version_id = ?'
|
297 |
300 |
self.con.execute(sql, (size, dest_version_id))
|
298 |
301 |
# TODO: Check for block_id existence.
|
... | ... | |
324 |
327 |
dest_path = os.path.join(dest_path, dest_name)
|
325 |
328 |
if permissions is not None:
|
326 |
329 |
r, w = self._check_permissions(dest_path, permissions)
|
327 |
|
src_version_id, dest_version_id = self._copy_version(src_path, dest_path, not replace_meta, True, src_version)
|
|
330 |
src_version_id, dest_version_id = self._copy_version(user, src_path, dest_path, not replace_meta, True, src_version)
|
328 |
331 |
for k, v in dest_meta.iteritems():
|
329 |
332 |
sql = 'insert or replace into metadata (version_id, key, value) values (?, ?, ?)'
|
330 |
333 |
self.con.execute(sql, (dest_version_id, k, v))
|
... | ... | |
346 |
349 |
logger.debug("delete_object: %s %s %s", account, container, name)
|
347 |
350 |
if user != account:
|
348 |
351 |
raise NotAllowedError
|
349 |
|
path, version_id, mtime, size = self._get_objectinfo(account, container, name)
|
350 |
|
self._put_version(path, 0, 1)
|
|
352 |
path = self._get_objectinfo(account, container, name)[0]
|
|
353 |
self._put_version(path, user, 0, 1)
|
351 |
354 |
sql = 'delete from permissions where name = ?'
|
352 |
355 |
self.con.execute(sql, (path,))
|
353 |
356 |
self.con.commit()
|
... | ... | |
421 |
424 |
|
422 |
425 |
def _get_version(self, path, version=None):
|
423 |
426 |
if version is None:
|
424 |
|
sql = '''select version_id, strftime('%s', tstamp), size, hide from versions where name = ?
|
|
427 |
sql = '''select version_id, user, strftime('%s', tstamp), size, hide from versions where name = ?
|
425 |
428 |
order by version_id desc limit 1'''
|
426 |
429 |
c = self.con.execute(sql, (path,))
|
427 |
430 |
row = c.fetchone()
|
428 |
|
if not row or int(row[3]):
|
|
431 |
if not row or int(row[4]):
|
429 |
432 |
raise NameError('Object does not exist')
|
430 |
433 |
else:
|
431 |
|
sql = '''select version_id, strftime('%s', tstamp), size from versions where name = ?
|
|
434 |
# The database (sqlite) will not complain if the version is not an integer.
|
|
435 |
sql = '''select version_id, user, strftime('%s', tstamp), size from versions where name = ?
|
432 |
436 |
and version_id = ?'''
|
433 |
437 |
c = self.con.execute(sql, (path, version))
|
434 |
438 |
row = c.fetchone()
|
435 |
439 |
if not row:
|
436 |
440 |
raise IndexError('Version does not exist')
|
437 |
|
return str(row[0]), int(row[1]), int(row[2])
|
|
441 |
return str(row[0]), str(row[1]), int(row[2]), int(row[3])
|
438 |
442 |
|
439 |
|
def _put_version(self, path, size=0, hide=0):
|
440 |
|
sql = 'insert into versions (name, size, hide) values (?, ?, ?)'
|
441 |
|
id = self.con.execute(sql, (path, size, hide)).lastrowid
|
|
443 |
def _put_version(self, path, user, size=0, hide=0):
|
|
444 |
sql = 'insert into versions (name, user, size, hide) values (?, ?, ?, ?)'
|
|
445 |
id = self.con.execute(sql, (path, user, size, hide)).lastrowid
|
442 |
446 |
self.con.commit()
|
443 |
447 |
return str(id)
|
444 |
448 |
|
445 |
|
def _copy_version(self, src_path, dest_path, copy_meta=True, copy_data=True, src_version=None):
|
|
449 |
def _copy_version(self, user, src_path, dest_path, copy_meta=True, copy_data=True, src_version=None):
|
446 |
450 |
if src_version is not None:
|
447 |
|
src_version_id, mtime, size = self._get_version(src_path, src_version)
|
|
451 |
src_version_id, muser, mtime, size = self._get_version(src_path, src_version)
|
448 |
452 |
else:
|
449 |
453 |
# Latest or create from scratch.
|
450 |
454 |
try:
|
451 |
|
src_version_id, mtime, size = self._get_version(src_path)
|
|
455 |
src_version_id, muser, mtime, size = self._get_version(src_path)
|
452 |
456 |
except NameError:
|
453 |
457 |
src_version_id = None
|
454 |
458 |
size = 0
|
455 |
459 |
if not copy_data:
|
456 |
460 |
size = 0
|
457 |
|
dest_version_id = self._put_version(dest_path, size)
|
|
461 |
dest_version_id = self._put_version(dest_path, user, size)
|
458 |
462 |
if copy_meta and src_version_id is not None:
|
459 |
463 |
sql = 'insert into metadata select %s, key, value from metadata where version_id = ?'
|
460 |
464 |
sql = sql % dest_version_id
|
... | ... | |
499 |
503 |
|
500 |
504 |
def _get_objectinfo(self, account, container, name, version=None):
|
501 |
505 |
path = os.path.join(account, container, name)
|
502 |
|
version_id, mtime, size = self._get_version(path, version)
|
503 |
|
return path, version_id, mtime, size
|
|
506 |
version_id, muser, mtime, size = self._get_version(path, version)
|
|
507 |
return path, version_id, muser, mtime, size
|
504 |
508 |
|
505 |
509 |
def _get_metadata(self, path, version):
|
506 |
510 |
sql = 'select key, value from metadata where version_id = ?'
|
507 |
511 |
c = self.con.execute(sql, (version,))
|
508 |
512 |
return dict(c.fetchall())
|
509 |
513 |
|
510 |
|
def _put_metadata(self, path, meta, replace=False):
|
|
514 |
def _put_metadata(self, user, path, meta, replace=False):
|
511 |
515 |
"""Create a new version and store metadata."""
|
512 |
516 |
|
513 |
|
src_version_id, dest_version_id = self._copy_version(path, path, not replace, True)
|
|
517 |
src_version_id, dest_version_id = self._copy_version(user, path, path, not replace, True)
|
514 |
518 |
for k, v in meta.iteritems():
|
515 |
519 |
if not replace and v == '':
|
516 |
520 |
sql = 'delete from metadata where version_id = ? and key = ?'
|