Open only recently changed files to conserve file descriptors
This commit is contained in:
parent
411939468b
commit
c619e74e15
58
kitsune
58
kitsune
|
@ -12,14 +12,19 @@ class WatchedFile:
|
|||
def __init__(self, path, seek_to_end):
|
||||
self.path = path
|
||||
self.seek_to_end = seek_to_end
|
||||
self.reopen()
|
||||
stf = os.stat(self.path)
|
||||
self.st_ctime_ns = stf.st_ctime_ns
|
||||
self.st_size = stf.st_size
|
||||
self.fileno = None
|
||||
if stf.st_ctime_ns >= time.time_ns() - 1E9:
|
||||
self.reopen()
|
||||
|
||||
def reopen(self):
|
||||
self.fd = open(self.path, errors='replace')
|
||||
self.fileno = self.fd.fileno()
|
||||
self.last_ts = 0
|
||||
if self.seek_to_end:
|
||||
self.fd.seek(0, 2)
|
||||
self.fd.seek(self.st_size, 0)
|
||||
self.seek_to_end = False
|
||||
|
||||
def format_ts(ts_ns):
|
||||
|
@ -59,30 +64,35 @@ def watch(args):
|
|||
# has any of the files changed
|
||||
for f in watched_files.values():
|
||||
# XXX - we should also detect replaced files.
|
||||
st = os.stat(f.fileno)
|
||||
try:
|
||||
if f.fileno:
|
||||
st = os.stat(f.fileno)
|
||||
try:
|
||||
stf = os.stat(f.path)
|
||||
if stf.st_ino != st.st_ino:
|
||||
f.reopen()
|
||||
st = os.stat(f.fileno)
|
||||
except FileNotFoundError:
|
||||
# ignore,
|
||||
# or maybe remove from watched_files?
|
||||
# or just mark as deleted?
|
||||
pass
|
||||
if st.st_mtime_ns > f.last_ts:
|
||||
if st.st_size < f.fd.tell():
|
||||
# We are beyond the end of the file, so it has probably
|
||||
# been truncated and rewritten - read from beginning
|
||||
f.fd.seek(0, 0)
|
||||
dead = "✝" if st.st_nlink == 0 else " "
|
||||
f.last_ts = st.st_mtime_ns
|
||||
new_content = f.fd.read()
|
||||
lines = new_content.split("\n")
|
||||
if lines[-1] == "":
|
||||
lines.pop()
|
||||
for ln in lines:
|
||||
print(f"{f.path:{filename_length}}", format_ts(f.last_ts), dead, ln)
|
||||
else:
|
||||
stf = os.stat(f.path)
|
||||
if stf.st_ino != st.st_ino:
|
||||
if stf.st_ctime_ns != f.st_ctime_ns:
|
||||
f.reopen()
|
||||
st = os.stat(f.fileno)
|
||||
except FileNotFoundError:
|
||||
# ignore,
|
||||
# or maybe remove from watched_files?
|
||||
# or just mark as deleted?
|
||||
pass
|
||||
if st.st_mtime_ns > f.last_ts:
|
||||
if st.st_size < f.fd.tell():
|
||||
# We are beyond the end of the file, so it has probably
|
||||
# been truncated and rewritten - read from beginning
|
||||
f.fd.seek(0, 0)
|
||||
dead = "✝" if st.st_nlink == 0 else " "
|
||||
f.last_ts = st.st_mtime_ns
|
||||
new_content = f.fd.read()
|
||||
lines = new_content.split("\n")
|
||||
if lines[-1] == "":
|
||||
lines.pop()
|
||||
for ln in lines:
|
||||
print(f"{f.path:{filename_length}}", format_ts(f.last_ts), dead, ln)
|
||||
time.sleep(0.1)
|
||||
seek_to_end = False
|
||||
|
||||
|
|
Loading…
Reference in New Issue