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