Statistics
| Branch: | Tag: | Revision:

root / snf-pithos-backend / pithos / backends / lib / hashfiler / context_file.py @ 4a7b190f

History | View | Annotate | Download (5.5 kB)

1 2e662088 Antony Chazapis
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2 2715ade4 Sofia Papagiannaki
#
3 a9b3f29d Antony Chazapis
# Redistribution and use in source and binary forms, with or
4 a9b3f29d Antony Chazapis
# without modification, are permitted provided that the following
5 a9b3f29d Antony Chazapis
# conditions are met:
6 2715ade4 Sofia Papagiannaki
#
7 a9b3f29d Antony Chazapis
#   1. Redistributions of source code must retain the above
8 a9b3f29d Antony Chazapis
#      copyright notice, this list of conditions and the following
9 a9b3f29d Antony Chazapis
#      disclaimer.
10 2715ade4 Sofia Papagiannaki
#
11 a9b3f29d Antony Chazapis
#   2. Redistributions in binary form must reproduce the above
12 a9b3f29d Antony Chazapis
#      copyright notice, this list of conditions and the following
13 a9b3f29d Antony Chazapis
#      disclaimer in the documentation and/or other materials
14 a9b3f29d Antony Chazapis
#      provided with the distribution.
15 2715ade4 Sofia Papagiannaki
#
16 a9b3f29d Antony Chazapis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 a9b3f29d Antony Chazapis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 a9b3f29d Antony Chazapis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 a9b3f29d Antony Chazapis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 a9b3f29d Antony Chazapis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 a9b3f29d Antony Chazapis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 a9b3f29d Antony Chazapis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 a9b3f29d Antony Chazapis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 a9b3f29d Antony Chazapis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 a9b3f29d Antony Chazapis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 a9b3f29d Antony Chazapis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 a9b3f29d Antony Chazapis
# POSSIBILITY OF SUCH DAMAGE.
28 2715ade4 Sofia Papagiannaki
#
29 a9b3f29d Antony Chazapis
# The views and conclusions contained in the software and
30 a9b3f29d Antony Chazapis
# documentation are those of the authors and should not be
31 a9b3f29d Antony Chazapis
# interpreted as representing official policies, either expressed
32 a9b3f29d Antony Chazapis
# or implied, of GRNET S.A.
33 a9b3f29d Antony Chazapis
34 29148653 Sofia Papagiannaki
from os import SEEK_CUR, SEEK_SET
35 5b20c402 Antony Chazapis
from errno import ENOENT, EROFS
36 a9b3f29d Antony Chazapis
37 a9b3f29d Antony Chazapis
38 a9b3f29d Antony Chazapis
_zeros = ''
39 a9b3f29d Antony Chazapis
40 a9b3f29d Antony Chazapis
41 a9b3f29d Antony Chazapis
def zeros(nr):
42 a9b3f29d Antony Chazapis
    global _zeros
43 a9b3f29d Antony Chazapis
    size = len(_zeros)
44 a9b3f29d Antony Chazapis
    if nr == size:
45 a9b3f29d Antony Chazapis
        return _zeros
46 a9b3f29d Antony Chazapis
47 a9b3f29d Antony Chazapis
    if nr > size:
48 a9b3f29d Antony Chazapis
        _zeros += '\0' * (nr - size)
49 a9b3f29d Antony Chazapis
        return _zeros
50 a9b3f29d Antony Chazapis
51 a9b3f29d Antony Chazapis
    if nr < size:
52 a9b3f29d Antony Chazapis
        _zeros = _zeros[:nr]
53 a9b3f29d Antony Chazapis
        return _zeros
54 a9b3f29d Antony Chazapis
55 a9b3f29d Antony Chazapis
56 a9b3f29d Antony Chazapis
def file_sync_write_chunks(openfile, chunksize, offset, chunks, size=None):
57 a9b3f29d Antony Chazapis
    """Write given chunks to the given buffered file object.
58 a9b3f29d Antony Chazapis
       Writes never span across chunk boundaries.
59 a9b3f29d Antony Chazapis
       If size is given stop after or pad until size bytes have been written.
60 a9b3f29d Antony Chazapis
    """
61 a9b3f29d Antony Chazapis
    fwrite = openfile.write
62 a9b3f29d Antony Chazapis
    seek = openfile.seek
63 a9b3f29d Antony Chazapis
    padding = 0
64 a9b3f29d Antony Chazapis
65 a9b3f29d Antony Chazapis
    try:
66 a9b3f29d Antony Chazapis
        seek(offset * chunksize)
67 29148653 Sofia Papagiannaki
    except IOError:
68 a9b3f29d Antony Chazapis
        seek = None
69 a9b3f29d Antony Chazapis
        for x in xrange(offset):
70 a9b3f29d Antony Chazapis
            fwrite(zeros(chunksize))
71 a9b3f29d Antony Chazapis
72 a9b3f29d Antony Chazapis
    cursize = offset * chunksize
73 a9b3f29d Antony Chazapis
74 a9b3f29d Antony Chazapis
    for chunk in chunks:
75 a9b3f29d Antony Chazapis
        if padding:
76 a9b3f29d Antony Chazapis
            if seek:
77 2715ade4 Sofia Papagiannaki
                seek(padding - 1, SEEK_CUR)
78 a9b3f29d Antony Chazapis
                fwrite("\x00")
79 a9b3f29d Antony Chazapis
            else:
80 a9b3f29d Antony Chazapis
                fwrite(buffer(zeros(chunksize), 0, padding))
81 a9b3f29d Antony Chazapis
        if size is not None and cursize + chunksize >= size:
82 a9b3f29d Antony Chazapis
            chunk = chunk[:chunksize - (cursize - size)]
83 a9b3f29d Antony Chazapis
            fwrite(chunk)
84 a9b3f29d Antony Chazapis
            cursize += len(chunk)
85 a9b3f29d Antony Chazapis
            break
86 a9b3f29d Antony Chazapis
        fwrite(chunk)
87 a9b3f29d Antony Chazapis
        padding = chunksize - len(chunk)
88 a9b3f29d Antony Chazapis
89 a9b3f29d Antony Chazapis
    padding = size - cursize if size is not None else 0
90 a9b3f29d Antony Chazapis
    if padding <= 0:
91 a9b3f29d Antony Chazapis
        return
92 a9b3f29d Antony Chazapis
93 a9b3f29d Antony Chazapis
    q, r = divmod(padding, chunksize)
94 a9b3f29d Antony Chazapis
    for x in xrange(q):
95 a9b3f29d Antony Chazapis
        fwrite(zeros(chunksize))
96 a9b3f29d Antony Chazapis
    fwrite(buffer(zeros(chunksize), 0, r))
97 a9b3f29d Antony Chazapis
98 a9b3f29d Antony Chazapis
99 a9b3f29d Antony Chazapis
def file_sync_read_chunks(openfile, chunksize, nr, offset=0):
100 a9b3f29d Antony Chazapis
    """Read and yield groups of chunks from a buffered file object at offset.
101 a9b3f29d Antony Chazapis
       Reads never span accros chunksize boundaries.
102 a9b3f29d Antony Chazapis
    """
103 a9b3f29d Antony Chazapis
    fread = openfile.read
104 a9b3f29d Antony Chazapis
    remains = offset * chunksize
105 a9b3f29d Antony Chazapis
    seek = openfile.seek
106 a9b3f29d Antony Chazapis
    try:
107 a9b3f29d Antony Chazapis
        seek(remains)
108 29148653 Sofia Papagiannaki
    except IOError:
109 a9b3f29d Antony Chazapis
        seek = None
110 a9b3f29d Antony Chazapis
        while 1:
111 a9b3f29d Antony Chazapis
            s = fread(remains)
112 a9b3f29d Antony Chazapis
            remains -= len(s)
113 a9b3f29d Antony Chazapis
            if remains <= 0:
114 a9b3f29d Antony Chazapis
                break
115 a9b3f29d Antony Chazapis
116 a9b3f29d Antony Chazapis
    while nr:
117 a9b3f29d Antony Chazapis
        remains = chunksize
118 a9b3f29d Antony Chazapis
        chunk = ''
119 a9b3f29d Antony Chazapis
        while 1:
120 a9b3f29d Antony Chazapis
            s = fread(remains)
121 a9b3f29d Antony Chazapis
            if not s:
122 a9b3f29d Antony Chazapis
                if chunk:
123 a9b3f29d Antony Chazapis
                    yield chunk
124 a9b3f29d Antony Chazapis
                return
125 a9b3f29d Antony Chazapis
            chunk += s
126 a9b3f29d Antony Chazapis
            remains -= len(s)
127 a9b3f29d Antony Chazapis
            if remains <= 0:
128 a9b3f29d Antony Chazapis
                break
129 a9b3f29d Antony Chazapis
        yield chunk
130 a9b3f29d Antony Chazapis
        nr -= 1
131 a9b3f29d Antony Chazapis
132 a9b3f29d Antony Chazapis
133 a9b3f29d Antony Chazapis
class ContextFile(object):
134 a9b3f29d Antony Chazapis
    __slots__ = ("name", "fdesc", "create")
135 a9b3f29d Antony Chazapis
136 a9b3f29d Antony Chazapis
    def __init__(self, name, create=0):
137 a9b3f29d Antony Chazapis
        self.name = name
138 a9b3f29d Antony Chazapis
        self.fdesc = None
139 a9b3f29d Antony Chazapis
        self.create = create
140 a9b3f29d Antony Chazapis
        #self.dirty = 0
141 a9b3f29d Antony Chazapis
142 a9b3f29d Antony Chazapis
    def __enter__(self):
143 a9b3f29d Antony Chazapis
        name = self.name
144 a9b3f29d Antony Chazapis
        try:
145 a9b3f29d Antony Chazapis
            fdesc = open(name, 'rb+')
146 a9b3f29d Antony Chazapis
        except IOError, e:
147 5b20c402 Antony Chazapis
            if self.create and e.errno == ENOENT:
148 5b20c402 Antony Chazapis
                fdesc = open(name, 'w+')
149 5b20c402 Antony Chazapis
            elif not self.create and e.errno == EROFS:
150 5b20c402 Antony Chazapis
                fdesc = open(name, 'rb')
151 5b20c402 Antony Chazapis
            else:
152 a9b3f29d Antony Chazapis
                raise
153 a9b3f29d Antony Chazapis
154 a9b3f29d Antony Chazapis
        self.fdesc = fdesc
155 a9b3f29d Antony Chazapis
        return self
156 a9b3f29d Antony Chazapis
157 a9b3f29d Antony Chazapis
    def __exit__(self, exc, arg, trace):
158 a9b3f29d Antony Chazapis
        fdesc = self.fdesc
159 a9b3f29d Antony Chazapis
        if fdesc is not None:
160 a9b3f29d Antony Chazapis
            #if self.dirty:
161 a9b3f29d Antony Chazapis
            #    fsync(fdesc.fileno())
162 a9b3f29d Antony Chazapis
            fdesc.close()
163 2715ade4 Sofia Papagiannaki
        return False  # propagate exceptions
164 a9b3f29d Antony Chazapis
165 a9b3f29d Antony Chazapis
    def seek(self, offset, whence=SEEK_SET):
166 a9b3f29d Antony Chazapis
        return self.fdesc.seek(offset, whence)
167 a9b3f29d Antony Chazapis
168 a9b3f29d Antony Chazapis
    def tell(self):
169 a9b3f29d Antony Chazapis
        return self.fdesc.tell()
170 a9b3f29d Antony Chazapis
171 a9b3f29d Antony Chazapis
    def truncate(self, size):
172 a9b3f29d Antony Chazapis
        self.fdesc.truncate(size)
173 a9b3f29d Antony Chazapis
174 a9b3f29d Antony Chazapis
    def sync_write(self, data):
175 a9b3f29d Antony Chazapis
        #self.dirty = 1
176 a9b3f29d Antony Chazapis
        self.fdesc.write(data)
177 a9b3f29d Antony Chazapis
178 a9b3f29d Antony Chazapis
    def sync_write_chunks(self, chunksize, offset, chunks, size=None):
179 a9b3f29d Antony Chazapis
        #self.dirty = 1
180 29148653 Sofia Papagiannaki
        return file_sync_write_chunks(self.fdesc, chunksize, offset, chunks,
181 29148653 Sofia Papagiannaki
                                      size)
182 a9b3f29d Antony Chazapis
183 a9b3f29d Antony Chazapis
    def sync_read(self, size):
184 a9b3f29d Antony Chazapis
        read = self.fdesc.read
185 a9b3f29d Antony Chazapis
        data = ''
186 a9b3f29d Antony Chazapis
        while 1:
187 a9b3f29d Antony Chazapis
            s = read(size)
188 a9b3f29d Antony Chazapis
            if not s:
189 a9b3f29d Antony Chazapis
                break
190 a9b3f29d Antony Chazapis
            data += s
191 a9b3f29d Antony Chazapis
        return data
192 a9b3f29d Antony Chazapis
193 a9b3f29d Antony Chazapis
    def sync_read_chunks(self, chunksize, nr, offset=0):
194 a9b3f29d Antony Chazapis
        return file_sync_read_chunks(self.fdesc, chunksize, nr, offset)