Statistics
| Branch: | Tag: | Revision:

root / snf-pithos-backend / pithos / backends / lib / hashfiler / blocker.py @ 401777e9

History | View | Annotate | Download (4.9 kB)

1
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
from pithos.api.settings import PITHOS_BACKEND_STORAGE
35
from store_helpers import get_blocker
36

    
37

    
38
class Blocker(object):
39
    """Blocker.
40
       Required constructor parameters: blocksize, blockpath, hashtype.
41
       Optional blockpool.
42
    """
43

    
44
    def __init__(self, **params):
45
        fblocker, rblocker, hashlen, blocksize = \
46
                        get_blocker(PITHOS_BACKEND_STORAGE, **params)
47
        self.fblocker = fblocker
48
        self.rblocker = rblocker
49
        self.hashlen = hashlen
50
        self.blocksize = blocksize
51

    
52
    def block_hash(self, data):
53
        """Hash a block of data"""
54
        if self.fblocker:
55
            return self.fblocker.block_hash(data)
56
        elif self.rblocker:
57
            return self.rblocker.block_hash(data)
58

    
59
    def block_ping(self, hashes):
60
        """Check hashes for existence and
61
           return those missing from block storage.
62
        """
63
        if self.fblocker:
64
            return self.fblocker.block_ping(hashes)
65
        elif self.rblocker:
66
            return self.rblocker.block_ping(hashes)
67

    
68
    def block_retr(self, hashes):
69
        """Retrieve blocks from storage by their hashes."""
70
        if self.fblocker:
71
            return self.fblocker.block_retr(hashes)
72
        elif self.rblocker:
73
            return self.rblocker.block_retr(hashes)
74

    
75
    def block_stor(self, blocklist):
76
        """Store a bunch of blocks and return (hashes, missing).
77
           Hashes is a list of the hashes of the blocks,
78
           missing is a list of indices in that list indicating
79
           which blocks were missing from the store.
80
        """
81
        if self.fblocker:
82
            (hashes, missing) = self.fblocker.block_stor(blocklist)
83
        elif self.rblocker:
84
            (hashes, missing) = self.rblocker.block_stor(blocklist)
85
        return (hashes, missing)
86

    
87
    def block_delta(self, blkhash, offset, data):
88
        """Construct and store a new block from a given block
89
           and a data 'patch' applied at offset. Return:
90
           (the hash of the new block, if the block already existed)
91
        """
92
        blocksize = self.blocksize
93
        if self.fblocker:
94
            (hash, existed) = self.fblocker.block_delta(blkhash, offset, data)
95
        elif self.rblocker:
96
            (hash, existed) = self.rblocker.block_delta(blkhash, offset,
97
                                                            data)
98
        if not hash:
99
            return None, None
100
        if self.rblocker and not hash:
101
            block = self.rblocker.block_retr((blkhash,))
102
            if not block:
103
                return None, None
104
            block = block[0]
105
            newblock = block[:offset] + data
106
            if len(newblock) > blocksize:
107
                newblock = newblock[:blocksize]
108
            elif len(newblock) < blocksize:
109
                newblock += block[len(newblock):]
110
            hash, existed = self.rblocker.block_stor((newblock,))
111
        elif self.fblocker and not hash:
112
            block = self.fblocker.block_retr((blkhash,))
113
            if not block:
114
                return None, None
115
            block = block[0]
116
            newblock = block[:offset] + data
117
            if len(newblock) > blocksize:
118
                newblock = newblock[:blocksize]
119
            elif len(newblock) < blocksize:
120
                newblock += block[len(newblock):]
121
            hash, existed = self.fblocker.block_stor((newblock,))
122

    
123
        return hash, 1 if existed else 0