Revision c4399e62 snf-pithos-backend/pithos/backends/lib/hashfiler/context_file.py
b/snf-pithos-backend/pithos/backends/lib/hashfiler/context_file.py | ||
---|---|---|
31 | 31 |
# interpreted as representing official policies, either expressed |
32 | 32 |
# or implied, of GRNET S.A. |
33 | 33 |
|
34 |
from os import SEEK_CUR, SEEK_SET, fsync, makedirs |
|
34 |
from os import SEEK_CUR, SEEK_SET, fsync, makedirs, rename
|
|
35 | 35 |
from os.path import dirname |
36 |
from errno import ENOENT, EROFS
|
|
36 |
from errno import ENOENT, ESPIPE
|
|
37 | 37 |
|
38 | 38 |
|
39 | 39 |
_zeros = '' |
40 |
fsync # get used |
|
40 | 41 |
|
41 | 42 |
|
42 | 43 |
def zeros(nr): |
... | ... | |
65 | 66 |
|
66 | 67 |
try: |
67 | 68 |
seek(offset * chunksize) |
68 |
except IOError, e: |
|
69 |
except IOError as e: |
|
70 |
if e.errno != ESPIPE: |
|
71 |
raise |
|
72 |
|
|
73 |
# substitute seeking in a non-seekable file (e.g. pipe) |
|
69 | 74 |
seek = None |
70 | 75 |
for x in xrange(offset): |
71 | 76 |
fwrite(zeros(chunksize)) |
... | ... | |
106 | 111 |
seek = openfile.seek |
107 | 112 |
try: |
108 | 113 |
seek(remains) |
109 |
except IOError, e: |
|
114 |
except IOError as e: |
|
115 |
if e.errno != ESPIPE: |
|
116 |
raise |
|
117 |
|
|
118 |
# substitute seeking in a non-seekable file (e.g. pipe) |
|
110 | 119 |
seek = None |
111 | 120 |
while 1: |
112 | 121 |
s = fread(remains) |
... | ... | |
132 | 141 |
|
133 | 142 |
|
134 | 143 |
class ContextFile(object): |
135 |
__slots__ = ("name", "fdesc", "create") |
|
136 | 144 |
|
137 |
def __init__(self, name, create=0):
|
|
145 |
def __init__(self, name, create=True, write=False, temp=''):
|
|
138 | 146 |
self.name = name |
139 | 147 |
self.fdesc = None |
140 |
self.create = create |
|
148 |
self._create = create |
|
149 |
self._write = write |
|
150 |
self._mode = 'rb+' if write else 'rb' |
|
151 |
self._temp = temp |
|
152 |
self._rename = False |
|
141 | 153 |
#self.dirty = 0 |
142 | 154 |
|
143 | 155 |
def __enter__(self): |
144 | 156 |
name = self.name |
145 | 157 |
try: |
146 |
fdesc = open(name, 'rb+')
|
|
158 |
fdesc = open(name, self._mode)
|
|
147 | 159 |
except IOError, e: |
148 |
if self.create and e.errno == ENOENT: |
|
149 |
try: |
|
150 |
fdesc = open(name, 'w+') |
|
151 |
except IOError as e: |
|
152 |
if e.errno != ENOENT: |
|
153 |
raise |
|
154 |
|
|
155 |
# ENOENT means parent dirs do not exist. |
|
156 |
# Create them. |
|
157 |
makedirs(dirname(name)) |
|
158 |
fdesc = open(name, 'w+') |
|
159 |
elif not self.create and e.errno == EROFS: |
|
160 |
fdesc = open(name, 'rb') |
|
161 |
else: |
|
160 |
if not (self._create and e.errno == ENOENT): |
|
162 | 161 |
raise |
163 | 162 |
|
163 |
# File does not exist. Create it, |
|
164 |
# optionally under a temporary filename. |
|
165 |
temp = self._temp |
|
166 |
self._rename = False |
|
167 |
if temp: |
|
168 |
name += '_' + temp |
|
169 |
self._rename = name |
|
170 |
|
|
171 |
try: |
|
172 |
fdesc = open(name, 'w+') |
|
173 |
except IOError as e: |
|
174 |
if e.errno != ENOENT: |
|
175 |
raise |
|
176 |
|
|
177 |
# ENOENT means parent dirs do not exist. |
|
178 |
# Create them. |
|
179 |
makedirs(dirname(name)) |
|
180 |
fdesc = open(name, 'w+') |
|
181 |
|
|
164 | 182 |
self.fdesc = fdesc |
165 | 183 |
return self |
166 | 184 |
|
... | ... | |
170 | 188 |
#if self.dirty: |
171 | 189 |
# fsync(fdesc.fileno()) |
172 | 190 |
fdesc.close() |
191 |
|
|
192 |
tempname = self._rename |
|
193 |
if tempname: |
|
194 |
# Temporary file needs to be moved into proper place |
|
195 |
# This is usually an atomic filesystem operation. |
|
196 |
rename(tempname, self.name) |
|
197 |
|
|
173 | 198 |
return False # propagate exceptions |
174 | 199 |
|
175 | 200 |
def seek(self, offset, whence=SEEK_SET): |
Also available in: Unified diff