|
|
@@ -410,8 +410,16 @@ class Table(object): |
|
|
|
|
|
|
|
def _remove_rows(self, subdir, filename, start, stop): |
|
|
|
"""Helper to mark specific rows as being removed from a |
|
|
|
file, and potentially removing or truncating the file itself.""" |
|
|
|
# Import an existing list of deleted rows for this file |
|
|
|
file, and potentially remove or truncate the file itself.""" |
|
|
|
# Close potentially open file in file_open LRU cache |
|
|
|
self.file_open.cache_remove(self, subdir, filename) |
|
|
|
|
|
|
|
# We keep a file like 0000.removed that contains a list of |
|
|
|
# which rows have been "removed". Note that we never have to |
|
|
|
# remove entries from this list, because we never decrease |
|
|
|
# self.nrows, and so we will never overwrite those locations in the |
|
|
|
# file. Only when the list covers the entire extent of the |
|
|
|
# file will that file be removed. |
|
|
|
datafile = os.path.join(self.root, subdir, filename) |
|
|
|
cachefile = datafile + ".removed" |
|
|
|
try: |
|
|
@@ -465,6 +473,14 @@ class Table(object): |
|
|
|
except: |
|
|
|
pass |
|
|
|
else: |
|
|
|
# File needs to stick around. This means we can get |
|
|
|
# degenerate cases where we have large files containing as |
|
|
|
# little as one row. Try to punch a hole in the file, |
|
|
|
# so that this region doesn't take up filesystem space. |
|
|
|
offset = start * self.packer.size |
|
|
|
count = (stop - start) * self.packer.size |
|
|
|
nilmdb.utils.fallocate.punch_hole(datafile, offset, count) |
|
|
|
|
|
|
|
# Update cache. Try to do it atomically. |
|
|
|
nilmdb.utils.atomic.replace_file(cachefile, |
|
|
|
pickle.dumps(merged, 2)) |
|
|
|