Comparison

util/datamanager.lua @ 13183:33b114fbb5de

util.datamanager: Add way to efficiently remove first items in a list Copying data without parsing it should be more performant than parsing it serializing back.
author Kim Alvefur <zash@zash.se>
date Wed, 12 Jul 2023 11:42:41 +0200
parent 13182:c48ae06e24d6
child 13185:b57f45165e1e
comparison
equal deleted inserted replaced
13182:c48ae06e24d6 13183:33b114fbb5de
504 return index, err; 504 return index, err;
505 end 505 end
506 return setmetatable({ file = file; index = index }, indexed_list_mt); 506 return setmetatable({ file = file; index = index }, indexed_list_mt);
507 end 507 end
508 508
509 local function shift_index(index_filename, index, trim_to, offset)
510 local index_scratch = index_filename .. "~";
511 local new_index, err = io_open(index_scratch, "w");
512 if not new_index then
513 os_remove(index_filename);
514 return "deleted", err;
515 end
516
517 local ok, err = new_index:write(index_magic);
518 if not ok then
519 new_index:close();
520 os_remove(index_filename);
521 os_remove(index_scratch);
522 return "deleted", err;
523 end
524
525 if not index.file or not index.file:seek("set", index_item_size * trim_to) then
526 new_index:close();
527 os_remove(index_filename);
528 os_remove(index_scratch);
529 return "deleted";
530 else
531 local pack, unpack = string.pack, string.unpack;
532 for item in index.file:lines(index_item_size) do
533 local ok, err = new_index:write(pack(index_fmt, unpack(index_fmt, item) - offset));
534 if not ok then
535 os_remove(index_filename);
536 os_remove(index_scratch);
537 return "deleted", err;
538 end
539 end
540 local ok, err = new_index:close();
541 if not ok then
542 os_remove(index_filename);
543 os_remove(index_scratch);
544 return "deleted", err;
545 end
546 return os_rename(index_scratch, index_filename);
547 end
548 end
549
550 local function list_shift(username, host, datastore, trim_to)
551 if trim_to == 1 then
552 return true
553 end
554 if type(trim_to) ~= "number" or trim_to < 1 then
555 return nil, "invalid-argument";
556 end
557 local list_filename = getpath(username, host, datastore, "list");
558 local index_filename = getpath(username, host, datastore, "lidx");
559 local index, err = get_list_index(username, host, datastore);
560 if not index then
561 return nil, err;
562 end
563
564 local new_first = index[trim_to];
565 if not new_first then
566 os_remove(index_filename);
567 return os_remove(list_filename);
568 end
569
570 local offset = new_first.start;
571 if offset == 0 then
572 return true;
573 end
574
575 local r, err = io_open(list_filename, "r");
576 if not r then
577 return nil, err;
578 end
579 local w, err = io_open(list_filename .. "~", "w");
580 if not w then
581 return nil, err;
582 end
583 r:seek("set", offset);
584 for block in r:lines(0x1000) do
585 local ok, err = w:write(block);
586 if not ok then
587 return nil, err;
588 end
589 end
590 r:close();
591 local ok, err = w:close();
592 if not ok then
593 return nil, err;
594 end
595 shift_index(index_filename, index, trim_to, offset)
596 return os_rename(list_filename .. "~", list_filename);
597 end
598
599
509 local type_map = { 600 local type_map = {
510 keyval = "dat"; 601 keyval = "dat";
511 list = "list"; 602 list = "list";
512 } 603 }
513 604
607 path_decode = decode; 698 path_decode = decode;
608 path_encode = encode; 699 path_encode = encode;
609 700
610 build_list_index = build_list_index; 701 build_list_index = build_list_index;
611 list_open = list_open; 702 list_open = list_open;
703 list_shift = list_shift;
612 }; 704 };