# HG changeset patch # User Kim Alvefur # Date 1689155112 -7200 # Node ID b57f45165e1e5831218805cc3b0f037448a0d1aa # Parent d16845afb3e23f3c3488125e79d0802aba70aec2 util.datamanager: Efficiently remove whole blocks to shift lists Using the new pposix.remove_blocks() it should be very performant to delete whole sections of a file, given a supporting file system. diff -r d16845afb3e2 -r b57f45165e1e util/datamanager.lua --- a/util/datamanager.lua Wed Jun 07 05:07:03 2023 +0200 +++ b/util/datamanager.lua Wed Jul 12 11:45:12 2023 +0200 @@ -34,11 +34,13 @@ local raw_mkdir = lfs.mkdir; local atomic_append; +local remove_blocks; local ENOENT = 2; pcall(function() local pposix = require "prosody.util.pposix"; raw_mkdir = pposix.mkdir or raw_mkdir; -- Doesn't trample on umask atomic_append = pposix.atomic_append; + remove_blocks = pposix.remove_blocks; ENOENT = pposix.ENOENT or ENOENT; end); @@ -572,6 +574,44 @@ return true; end + if remove_blocks then + local f, err = io_open(list_filename, "r+"); + if not f then + return f, err; + end + + local diff = 0; + local block_offset = 0; + if offset % 0x1000 ~= 0 then + -- Not an even block boundary, we will have to overwrite + diff = offset % 0x1000; + block_offset = offset - diff; + end + + if block_offset == 0 then + log("debug", "") + else + local ok, err = remove_blocks(f, 0, block_offset); + log("debug", "remove_blocks(%s, 0, %d)", f, block_offset); + if not ok then + log("warn", "Could not remove blocks from %q[%d, %d]: %s", list_filename, 0, block_offset, err); + else + if diff ~= 0 then + -- overwrite unaligned leftovers + if f:seek("set", 0) then + local wrote, err = f:write(string.rep("\n", diff)); + if not wrote then + log("error", "Could not blank out %q[%d, %d]: %s", list_filename, 0, diff, err); + end + end + end + local ok, err = f:close(); + shift_index(index_filename, index, trim_to, offset); -- Shift or delete the index + return ok, err; + end + end + end + local r, err = io_open(list_filename, "r"); if not r then return nil, err;