7 from binascii import hexlify, unhexlify
8 from cStringIO import StringIO
10 from lib.client import Pithos_Client, Fault
11 from lib.util import get_user, get_auth, get_server, get_api
14 # XXX Get these from container...
15 BLOCK_SIZE = 4 * 1024 * 1024
19 def file_read_iterator(fp, size=1024):
29 def __init__(self, f):
30 super(HashMap, self).__init__()
33 def _hash_raw(self, v):
34 h = hashlib.new(BLOCK_HASH)
38 def _hash_block(self, v):
39 return self._hash_raw(v.rstrip('\x00'))
43 return self._hash_raw('')
45 return self.__getitem__(0)
51 h += [('\x00' * len(h[0]))] * (s - len(h))
53 h = [self._hash_raw(h[x] + h[x + 1]) for x in range(0, len(h), 2)]
58 for block in file_read_iterator(fp, BLOCK_SIZE):
59 self.append(self._hash_block(block))
62 def smart_upload(client, file):
63 dest_container = 'pithos'
64 dest_object = os.path.split(file)[-1]
66 size = os.path.getsize(file)
67 hashes = HashMap(sys.argv[1])
68 map = {'bytes': size, 'hashes': [hexlify(x) for x in hashes]}
71 client.create_object_by_hashmap(dest_container, dest_object, map)
73 if fault.status != 409:
78 missing = fault.data.split('\n')
80 del missing[missing.index(''):]
82 with open(file) as fp:
84 offset = hashes.index(unhexlify(hash)) * BLOCK_SIZE
86 block = fp.read(BLOCK_SIZE)
87 client.create_object('pithos', '.upload', StringIO(block))
89 client.create_object_by_hashmap(dest_container, dest_object, map)
92 if __name__ == '__main__':
93 if len(sys.argv) != 2 or not os.path.isfile(sys.argv[1]):
94 print 'syntax: %s <file>' % sys.argv[0]
97 client = Pithos_Client(get_server(), get_auth(), get_user())
98 smart_upload(client, sys.argv[1])