|
@@ -1,7 +1,7 @@
|
|
from __future__ import with_statement
|
|
from __future__ import with_statement
|
|
from datetime import datetime, timedelta
|
|
from datetime import datetime, timedelta
|
|
from getpass import getuser
|
|
from getpass import getuser
|
|
-from itertools import izip
|
|
|
|
|
|
+from itertools import izip_longest
|
|
import msgpack
|
|
import msgpack
|
|
import os
|
|
import os
|
|
import socket
|
|
import socket
|
|
@@ -29,6 +29,7 @@ class ItemIter(object):
|
|
self.unpacker = iter(unpacker)
|
|
self.unpacker = iter(unpacker)
|
|
self.filter = filter
|
|
self.filter = filter
|
|
self.stack = []
|
|
self.stack = []
|
|
|
|
+ self.peeks = 0
|
|
self._peek = None
|
|
self._peek = None
|
|
self._peek_iter = None
|
|
self._peek_iter = None
|
|
global foo
|
|
global foo
|
|
@@ -39,9 +40,12 @@ class ItemIter(object):
|
|
|
|
|
|
def next(self):
|
|
def next(self):
|
|
if self.stack:
|
|
if self.stack:
|
|
- return self.stack.pop(0)
|
|
|
|
- self._peek = None
|
|
|
|
- return self.get_next()
|
|
|
|
|
|
+ item = self.stack.pop(0)
|
|
|
|
+ else:
|
|
|
|
+ self._peek = None
|
|
|
|
+ item = self.get_next()
|
|
|
|
+ self.peeks = max(0, self.peeks - len(item.get('chunks', [])))
|
|
|
|
+ return item
|
|
|
|
|
|
def get_next(self):
|
|
def get_next(self):
|
|
next = self.unpacker.next()
|
|
next = self.unpacker.next()
|
|
@@ -52,7 +56,7 @@ class ItemIter(object):
|
|
def peek(self):
|
|
def peek(self):
|
|
while True:
|
|
while True:
|
|
while not self._peek or not self._peek_iter:
|
|
while not self._peek or not self._peek_iter:
|
|
- if len(self.stack) > 100:
|
|
|
|
|
|
+ if self.peeks > 100:
|
|
raise StopIteration
|
|
raise StopIteration
|
|
self._peek = self.get_next()
|
|
self._peek = self.get_next()
|
|
self.stack.append(self._peek)
|
|
self.stack.append(self._peek)
|
|
@@ -61,7 +65,9 @@ class ItemIter(object):
|
|
else:
|
|
else:
|
|
self._peek_iter = None
|
|
self._peek_iter = None
|
|
try:
|
|
try:
|
|
- return self._peek_iter.next()
|
|
|
|
|
|
+ item = self._peek_iter.next()
|
|
|
|
+ self.peeks += 1
|
|
|
|
+ return item
|
|
except StopIteration:
|
|
except StopIteration:
|
|
self._peek = None
|
|
self._peek = None
|
|
|
|
|
|
@@ -186,25 +192,26 @@ class Archive(object):
|
|
self.cache.commit()
|
|
self.cache.commit()
|
|
|
|
|
|
def calc_stats(self, cache):
|
|
def calc_stats(self, cache):
|
|
|
|
+ def add(id):
|
|
|
|
+ count, size, csize = self.cache.chunks[id]
|
|
|
|
+ stats.update(size, csize, count == 1)
|
|
|
|
+ self.cache.chunks[id] = count - 1, size, csize
|
|
# This function is a bit evil since it abuses the cache to calculate
|
|
# This function is a bit evil since it abuses the cache to calculate
|
|
# the stats. The cache transaction must be rolled back afterwards
|
|
# the stats. The cache transaction must be rolled back afterwards
|
|
unpacker = msgpack.Unpacker()
|
|
unpacker = msgpack.Unpacker()
|
|
cache.begin_txn()
|
|
cache.begin_txn()
|
|
stats = Statistics()
|
|
stats = Statistics()
|
|
- for id in self.metadata['items']:
|
|
|
|
- unpacker.feed(self.key.decrypt(id, self.store.get(id)))
|
|
|
|
|
|
+ add(self.id)
|
|
|
|
+ for id, chunk in izip_longest(self.metadata['items'], self.store.get_many(self.metadata['items'])):
|
|
|
|
+ unpacker.feed(self.key.decrypt(id, chunk))
|
|
for item in unpacker:
|
|
for item in unpacker:
|
|
try:
|
|
try:
|
|
for id, size, csize in item['chunks']:
|
|
for id, size, csize in item['chunks']:
|
|
- count, _, _ = self.cache.chunks[id]
|
|
|
|
- stats.update(size, csize, count == 1)
|
|
|
|
- stats.nfiles += 1
|
|
|
|
- self.cache.chunks[id] = count - 1, size, csize
|
|
|
|
|
|
+ add(id)
|
|
|
|
+ stats.nfiles += 1
|
|
except KeyError:
|
|
except KeyError:
|
|
pass
|
|
pass
|
|
- count, size, csize = self.cache.chunks[id]
|
|
|
|
- stats.update(size, csize, count == 1)
|
|
|
|
- self.cache.chunks[id] = count - 1, size, csize
|
|
|
|
|
|
+ add(id)
|
|
cache.rollback()
|
|
cache.rollback()
|
|
return stats
|
|
return stats
|
|
|
|
|
|
@@ -237,7 +244,7 @@ class Archive(object):
|
|
fd = open(path, 'wb')
|
|
fd = open(path, 'wb')
|
|
start_cb(item)
|
|
start_cb(item)
|
|
ids = [id for id, size, csize in item['chunks']]
|
|
ids = [id for id, size, csize in item['chunks']]
|
|
- for id, chunk in izip(ids, self.store.get_many(ids, peek)):
|
|
|
|
|
|
+ for id, chunk in izip_longest(ids, self.store.get_many(ids, peek)):
|
|
data = self.key.decrypt(id, chunk)
|
|
data = self.key.decrypt(id, chunk)
|
|
fd.write(data)
|
|
fd.write(data)
|
|
fd.close()
|
|
fd.close()
|
|
@@ -296,9 +303,8 @@ class Archive(object):
|
|
start(item)
|
|
start(item)
|
|
ids = [id for id, size, csize in item['chunks']]
|
|
ids = [id for id, size, csize in item['chunks']]
|
|
try:
|
|
try:
|
|
- for id, chunk in izip(ids, self.store.get_many(ids, peek)):
|
|
|
|
- if chunk:
|
|
|
|
- self.key.decrypt(id, chunk)
|
|
|
|
|
|
+ for id, chunk in izip_longest(ids, self.store.get_many(ids, peek)):
|
|
|
|
+ self.key.decrypt(id, chunk)
|
|
except Exception, e:
|
|
except Exception, e:
|
|
result(item, False)
|
|
result(item, False)
|
|
return
|
|
return
|