Comparison

util/datamanager.lua @ 13185:b57f45165e1e

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.
author Kim Alvefur <zash@zash.se>
date Wed, 12 Jul 2023 11:45:12 +0200
parent 13183:33b114fbb5de
child 13186:affaf6d08d26
comparison
equal deleted inserted replaced
13184:d16845afb3e2 13185:b57f45165e1e
32 32
33 local prosody = prosody; 33 local prosody = prosody;
34 34
35 local raw_mkdir = lfs.mkdir; 35 local raw_mkdir = lfs.mkdir;
36 local atomic_append; 36 local atomic_append;
37 local remove_blocks;
37 local ENOENT = 2; 38 local ENOENT = 2;
38 pcall(function() 39 pcall(function()
39 local pposix = require "prosody.util.pposix"; 40 local pposix = require "prosody.util.pposix";
40 raw_mkdir = pposix.mkdir or raw_mkdir; -- Doesn't trample on umask 41 raw_mkdir = pposix.mkdir or raw_mkdir; -- Doesn't trample on umask
41 atomic_append = pposix.atomic_append; 42 atomic_append = pposix.atomic_append;
43 remove_blocks = pposix.remove_blocks;
42 ENOENT = pposix.ENOENT or ENOENT; 44 ENOENT = pposix.ENOENT or ENOENT;
43 end); 45 end);
44 46
45 local _ENV = nil; 47 local _ENV = nil;
46 -- luacheck: std none 48 -- luacheck: std none
568 end 570 end
569 571
570 local offset = new_first.start; 572 local offset = new_first.start;
571 if offset == 0 then 573 if offset == 0 then
572 return true; 574 return true;
575 end
576
577 if remove_blocks then
578 local f, err = io_open(list_filename, "r+");
579 if not f then
580 return f, err;
581 end
582
583 local diff = 0;
584 local block_offset = 0;
585 if offset % 0x1000 ~= 0 then
586 -- Not an even block boundary, we will have to overwrite
587 diff = offset % 0x1000;
588 block_offset = offset - diff;
589 end
590
591 if block_offset == 0 then
592 log("debug", "")
593 else
594 local ok, err = remove_blocks(f, 0, block_offset);
595 log("debug", "remove_blocks(%s, 0, %d)", f, block_offset);
596 if not ok then
597 log("warn", "Could not remove blocks from %q[%d, %d]: %s", list_filename, 0, block_offset, err);
598 else
599 if diff ~= 0 then
600 -- overwrite unaligned leftovers
601 if f:seek("set", 0) then
602 local wrote, err = f:write(string.rep("\n", diff));
603 if not wrote then
604 log("error", "Could not blank out %q[%d, %d]: %s", list_filename, 0, diff, err);
605 end
606 end
607 end
608 local ok, err = f:close();
609 shift_index(index_filename, index, trim_to, offset); -- Shift or delete the index
610 return ok, err;
611 end
612 end
573 end 613 end
574 614
575 local r, err = io_open(list_filename, "r"); 615 local r, err = io_open(list_filename, "r");
576 if not r then 616 if not r then
577 return nil, err; 617 return nil, err;