open files with O_NOATIME if possible

This commit is contained in:
Carlo Teubner 2014-08-30 14:10:41 +01:00
parent 21e03af56b
commit f4804c07ca
1 changed files with 41 additions and 2 deletions

View File

@ -82,7 +82,7 @@ class ChunkBuffer:
chunks = list(bytes(s) for s in self.chunker.chunkify(self.buffer))
self.buffer.seek(0)
self.buffer.truncate(0)
# Leave the last parital chunk in the buffer unless flush is True
# Leave the last partial chunk in the buffer unless flush is True
end = None if flush or len(chunks) == 1 else -1
for chunk in chunks[:end]:
self.chunks.append(self.write_chunk(chunk))
@ -399,7 +399,7 @@ class Archive:
chunks = [cache.chunk_incref(id_, self.stats) for id_ in ids]
# Only chunkify the file if needed
if chunks is None:
with open(path, 'rb') as fd:
with Archive._open_rb(path, st) as fd:
chunks = []
for chunk in self.chunker.chunkify(fd):
chunks.append(cache.add_chunk(self.key.id_hash(chunk), chunk, self.stats))
@ -414,6 +414,45 @@ class Archive:
for name, info in manifest.archives.items():
yield Archive(repository, key, manifest, name, cache=cache)
@staticmethod
def _open_rb(path, st):
flags_noatime = None
euid = None
def open_simple(p, s):
return open(p, 'rb')
def open_noatime_if_owner(p, s):
if s.st_uid == euid:
return os.fdopen(os.open(p, flags_noatime), 'rb')
else:
return open(p, 'rb')
def open_noatime(p, s):
try:
fd = os.open(p, flags_noatime)
except PermissionError:
# Was this EPERM due to the O_NOATIME flag?
fo = open(p, 'rb')
# Yes, it was -- otherwise the above line would have thrown
# another exception.
euid = os.geteuid()
# So in future, let's check whether the file is owned by us
# before attempting to use O_NOATIME.
Archive._open_rb = open_noatime_if_owner
return fo
return os.fdopen(fd, 'rb')
o_noatime = getattr(os, 'O_NOATIME', None)
if o_noatime is not None:
flags_noatime = os.O_RDONLY | getattr(os, 'O_BINARY', 0) | o_noatime
# Always use O_NOATIME version.
Archive._open_rb = open_noatime
else:
# Always use non-O_NOATIME version.
Archive._open_rb = open_simple
return Archive._open_rb(path, st)
class RobustUnpacker():
"""A restartable/robust version of the streaming msgpack unpacker