MCPcopy
hub / github.com/borgbackup/borg / SaveFile

Class SaveFile

src/borg/platform/base.py:222–272  ·  view source on GitHub ↗

Update file contents atomically. Must be used as a context manager (defining the scope of the transaction). On a journaling filesystem the file contents are always updated atomically and won't become corrupted, even on power failures or crashes (for caveats see SyncFile).

Source from the content-addressed store, hash-verified

220
221
222class SaveFile:
223 """
224 Update file contents atomically.
225
226 Must be used as a context manager (defining the scope of the transaction).
227
228 On a journaling filesystem the file contents are always updated
229 atomically and won't become corrupted, even on power failures or
230 crashes (for caveats see SyncFile).
231
232 SaveFile can safely be used in parallel (e.g., by multiple processes) to write
233 to the same target path. Whatever writer finishes last (executes the os.replace
234 last) "wins" and has successfully written its content to the target path.
235 Internally used temporary files are created in the target directory and are
236 named <BASENAME>-<RANDOMCHARS>.tmp and cleaned up in normal and error conditions.
237 """
238
239 def __init__(self, path, binary=False):
240 self.binary = binary
241 self.path = path
242 path_obj = Path(path)
243 self.dir = str(path_obj.parent)
244 self.tmp_prefix = path_obj.name + "-"
245 self.tmp_fd = None # OS-level fd
246 self.tmp_fname = None # full path/filename corresponding to self.tmp_fd
247 self.f = None # Python file-like SyncFile
248
249 def __enter__(self):
250 from .. import platform
251 from ..helpers.fs import mkstemp_mode
252
253 self.tmp_fd, self.tmp_fname = mkstemp_mode(prefix=self.tmp_prefix, suffix=".tmp", dir=self.dir, mode=0o666)
254 self.f = platform.SyncFile(self.tmp_fname, fd=self.tmp_fd, binary=self.binary)
255 return self.f
256
257 def __exit__(self, exc_type, exc_val, exc_tb):
258 from .. import platform
259
260 self.f.close() # this indirectly also closes self.tmp_fd
261 self.tmp_fd = None
262 if exc_type is not None:
263 safe_unlink(self.tmp_fname) # with-body has failed, clean up tmp file
264 return # continue processing the exception normally
265
266 try:
267 os.replace(self.tmp_fname, self.path) # POSIX: atomic rename
268 except OSError:
269 safe_unlink(self.tmp_fname) # rename has failed, clean up tmp file
270 raise
271 finally:
272 platform.sync_dir(self.dir)
273
274
275def swidth(s):

Callers 9

saveMethod · 0.85
createMethod · 0.85
saveMethod · 0.85
_write_files_cacheMethod · 0.85
save_configMethod · 0.85
recover_segmentMethod · 0.85
saveMethod · 0.85
get_cache_dirFunction · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected