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) |