Fix imports.
[pithos] / pithos / migrate-maps.py
1 #!/usr/bin/env python
2
3 import sys
4 import os
5 import time
6 import logging
7 import hashlib
8 import binascii
9
10 from os import makedirs, unlink
11 from os.path import isdir, realpath, exists, join
12 from binascii import hexlify
13
14 from backends.lib.hashfiler.context_file import ContextFile
15
16 class HashMap(list):
17     
18     def __init__(self, blocksize, blockhash):
19         super(HashMap, self).__init__()
20         self.blocksize = blocksize
21         self.blockhash = blockhash
22     
23     def _hash_raw(self, v):
24         h = hashlib.new(self.blockhash)
25         h.update(v)
26         return h.digest()
27     
28     def hash(self):
29         if len(self) == 0:
30             return self._hash_raw('')
31         if len(self) == 1:
32             return self.__getitem__(0)
33         
34         h = list(self)
35         s = 2
36         while s < len(h):
37             s = s * 2
38         h += [('\x00' * len(h[0]))] * (s - len(h))
39         while len(h) > 1:
40             h = [self._hash_raw(h[x] + h[x + 1]) for x in range(0, len(h), 2)]
41         return h[0]
42
43 class Mapper(object):
44     """Mapper.
45        Required contstructor parameters: mappath, namelen.
46     """
47
48     mappath = None
49     namelen = None
50
51     def __init__(self, **params):
52         self.params = params
53         self.namelen = params['namelen']
54         mappath = realpath(params['mappath'])
55         if not isdir(mappath):
56             if not exists(mappath):
57                 makedirs(mappath)
58             else:
59                 raise ValueError("Variable mappath '%s' is not a directory" % (mappath,))
60         self.mappath = mappath
61
62     def _get_rear_map(self, maphash, create=0):
63         filename = hexlify(maphash)
64         dir = join(self.mappath, filename[0:2], filename[2:4], filename[4:6])
65         if not exists(dir):
66             makedirs(dir)
67         name = join(dir, filename)
68         return ContextFile(name, create)
69
70     def _check_rear_map(self, maphash):
71         filename = hexlify(maphash)
72         dir = join(self.mappath, filename[0:2], filename[2:4], filename[4:6])
73         name = join(dir, filename)
74         return exists(name)
75
76     def map_retr(self, maphash, blkoff=0, nr=100000000000000):
77         """Return as a list, part of the hashes map of an object
78            at the given block offset.
79            By default, return the whole hashes map.
80         """
81         namelen = self.namelen
82         hashes = ()
83
84         with self._get_rear_map(maphash, 0) as rmap:
85             if rmap:
86                 hashes = list(rmap.sync_read_chunks(namelen, nr, blkoff))
87         return hashes
88
89     def map_stor(self, maphash, hashes=(), blkoff=0, create=1):
90         """Store hashes in the given hashes map."""
91         namelen = self.namelen
92         if self._check_rear_map(maphash):
93             return
94         with self._get_rear_map(maphash, 1) as rmap:
95             rmap.sync_write_chunks(namelen, blkoff, hashes, None)
96
97 if __name__ == "__main__":
98     map = HashMap(4 * 1024 * 1024, 'sha256')
99
100     namelen = len(map.hash())
101     params = {'mappath': os.path.join('data/pithos/maps-new'),
102               'namelen': namelen}
103     mapper = Mapper(**params)
104
105     files = os.listdir('data/pithos/maps')
106     for f in files:
107         with ContextFile(os.path.join('data/pithos/maps', f), 0) as rmap:
108             hashes = list(rmap.sync_read_chunks(namelen, 100000000000000, 0))
109             map[:] = hashes
110             hash = map.hash()
111             mapper.map_stor(hash, hashes)
112             print 'update versions set hash=\'%s\' where serial=%s;' % (hexlify(hash), int(f, 16))
113