Revision b3155065

b/snf-pithos-app/README
43 43
PITHOS_UPDATE_MD5                True                                              Update object checksums when using hashmaps
44 44
===============================  ================================================  ============================================================
45 45

  
46
To update checksums asynchronously, enable the queue, install snf-pithos-tools and use ``pithos-dispatcher``::
47

  
48
    pithos-dispatcher --exchange=pithos --callback=pithos.api.dispatch.update_md5
49

  
46 50
Administrator functions
47 51
-----------------------
48 52

  
b/snf-pithos-app/pithos/api/dispatch.py
1
from pithos.api.settings import (BACKEND_DB_MODULE, BACKEND_DB_CONNECTION,
2
                                    BACKEND_BLOCK_MODULE, BACKEND_BLOCK_PATH,
3
                                    BACKEND_QUEUE_MODULE, BACKEND_QUEUE_CONNECTION,
4
                                    BACKEND_QUOTA, BACKEND_VERSIONING)
5
from pithos.backends import connect_backend
6
from pithos.api.util import hashmap_md5
7

  
8
def update_md5(m):
9
    if m['resource'] != 'object' or m['details']['action'] != 'object update':
10
        return
11
    
12
    backend = connect_backend(db_module=BACKEND_DB_MODULE,
13
                              db_connection=BACKEND_DB_CONNECTION,
14
                              block_module=BACKEND_BLOCK_MODULE,
15
                              block_path=BACKEND_BLOCK_PATH,
16
                              queue_module=BACKEND_QUEUE_MODULE,
17
                              queue_connection=BACKEND_QUEUE_CONNECTION)
18
    backend.default_policy['quota'] = BACKEND_QUOTA
19
    backend.default_policy['versioning'] = BACKEND_VERSIONING
20
    
21
    path = m['value']
22
    account, container, name = path.split('/', 2)
23
    version = m['details']['version']
24
    meta = None
25
    try:
26
        meta = backend.get_object_meta(account, account, container, name, 'pithos', version)
27
        if meta['checksum'] == '':
28
            size, hashmap = backend.get_object_hashmap(account, account, container, name, version)
29
            checksum = hashmap_md5(backend, hashmap, size)
30
            backend.update_object_checksum(account, account, container, name, version, checksum)
31
            print 'INFO: Updated checksum for path "%s"' % (path,)
32
    except Exception, e:
33
        print 'WARNING: Can not update checksum for path "%s" (%s)' % (path, e)
34
    
35
    backend.close()
b/snf-pithos-app/pithos/api/functions.py
886 886
        raise RequestEntityTooLarge('Quota exceeded')
887 887
    if not checksum and UPDATE_MD5:
888 888
        # Update the MD5 after the hashmap, as there may be missing hashes.
889
        checksum = hashmap_md5(request, hashmap, size)
889
        checksum = hashmap_md5(request.backend, hashmap, size)
890 890
        try:
891
            version_id = request.backend.update_object_checksum(request.user_uniq,
892
                            v_account, v_container, v_object, version_id, checksum)
891
            request.backend.update_object_checksum(request.user_uniq,
892
              v_account, v_container, v_object, version_id, checksum)
893 893
        except NotAllowedError:
894 894
            raise Forbidden('Not allowed')
895 895
    if public is not None:
......
1187 1187
    if dest_bytes is not None and dest_bytes < size:
1188 1188
        size = dest_bytes
1189 1189
        hashmap = hashmap[:(int((size - 1) / request.backend.block_size) + 1)]
1190
    checksum = hashmap_md5(request, hashmap, size) if UPDATE_MD5 else ''
1190
    checksum = hashmap_md5(request.backend, hashmap, size) if UPDATE_MD5 else ''
1191 1191
    try:
1192 1192
        version_id = request.backend.update_object_hashmap(request.user_uniq,
1193 1193
                        v_account, v_container, v_object, size, prev_meta['type'],
b/snf-pithos-app/pithos/api/util.py
761 761
        hashmap.append(request.backend.put_block(('\x00' * bo) + data[:bl]))
762 762
    return bl # Return ammount of data written.
763 763

  
764
def hashmap_md5(request, hashmap, size):
764
def hashmap_md5(backend, hashmap, size):
765 765
    """Produce the MD5 sum from the data in the hashmap."""
766 766
    
767 767
    # TODO: Search backend for the MD5 of another object with the same hashmap and size...
768 768
    md5 = hashlib.md5()
769
    bs = request.backend.block_size
769
    bs = backend.block_size
770 770
    for bi, hash in enumerate(hashmap):
771
        data = request.backend.get_block(hash) # Blocks come in padded.
771
        data = backend.get_block(hash) # Blocks come in padded.
772 772
        if bi == len(hashmap) - 1:
773 773
            data = data[:size % bs]
774 774
        md5.update(data)

Also available in: Unified diff