| ... | ... | @@ -86,17 +86,7 @@ pub const Node = struct { |
| 86 | 86 | name: [max_name_len]u8, |
| 87 | 87 | |
| 88 | 88 | fn getIpcFd(s: Storage) ?posix.fd_t { |
| 89 | | if (s.estimated_total_count != std.math.maxInt(u32)) |
| 90 | | return null; |
| 91 | | |
| 92 | | const low: u16 = @truncate(s.completed_count); |
| 93 | | return low; |
| 94 | | } |
| 95 | | |
| 96 | | fn getMainStorageIndex(s: Storage) Node.Index { |
| 97 | | assert(s.estimated_total_count == std.math.maxInt(u32)); |
| 98 | | const i: u16 = @truncate(s.completed_count >> 16); |
| 99 | | return @enumFromInt(i); |
| 89 | return if (s.estimated_total_count != std.math.maxInt(u32)) null else @bitCast(s.completed_count); |
| 100 | 90 | } |
| 101 | 91 | |
| 102 | 92 | fn setIpcFd(s: *Storage, fd: posix.fd_t) void { |
| ... | ... | @@ -538,14 +528,9 @@ fn serialize() Serialized { |
| 538 | 528 | @memcpy(&dest_storage.name, &storage_ptr.name); |
| 539 | 529 | dest_storage.completed_count = @atomicLoad(u32, &storage_ptr.completed_count, .monotonic); |
| 540 | 530 | dest_storage.estimated_total_count = @atomicLoad(u32, &storage_ptr.estimated_total_count, .monotonic); |
| 541 | | |
| 542 | | if (dest_storage.getIpcFd() != null) { |
| 543 | | any_ipc = true; |
| 544 | | dest_storage.completed_count |= @as(u32, @intCast(i)) << 16; |
| 545 | | } |
| 546 | | |
| 547 | 531 | const end_parent = @atomicLoad(Node.Parent, parent_ptr, .seq_cst); |
| 548 | 532 | if (begin_parent == end_parent) { |
| 533 | any_ipc = any_ipc or (dest_storage.getIpcFd() != null); |
| 549 | 534 | serialized_node_parents_buffer[serialized_len] = begin_parent; |
| 550 | 535 | serialized_node_map_buffer[i] = @enumFromInt(serialized_len); |
| 551 | 536 | serialized_len += 1; |
| ... | ... | @@ -577,23 +562,25 @@ fn serialize() Serialized { |
| 577 | 562 | |
| 578 | 563 | var parents_copy: [default_node_storage_buffer_len]Node.Parent = undefined; |
| 579 | 564 | var storage_copy: [default_node_storage_buffer_len]Node.Storage = undefined; |
| 565 | var ipc_metadata_copy: [default_node_storage_buffer_len]SavedMetadata = undefined; |
| 580 | 566 | |
| 581 | | const SavedMetadata = extern struct { |
| 567 | var ipc_metadata: [default_node_storage_buffer_len]SavedMetadata = undefined; |
| 568 | var ipc_metadata_len: u16 = 0; |
| 569 | |
| 570 | const SavedMetadata = struct { |
| 571 | ipc_fd: u16, |
| 572 | main_index: u16, |
| 582 | 573 | start_index: u16, |
| 583 | 574 | nodes_len: u16, |
| 584 | | main_index: u16, |
| 585 | | flags: Flags, |
| 586 | | |
| 587 | | const Flags = enum(u16) { |
| 588 | | saved = std.math.maxInt(u16), |
| 589 | | _, |
| 590 | | }; |
| 591 | 575 | }; |
| 592 | 576 | |
| 593 | 577 | fn serializeIpc(start_serialized_len: usize) usize { |
| 594 | 578 | var serialized_len = start_serialized_len; |
| 595 | 579 | var pipe_buf: [2 * 4096]u8 align(4) = undefined; |
| 596 | 580 | |
| 581 | const old_ipc_metadata = ipc_metadata_copy[0..ipc_metadata_len]; |
| 582 | ipc_metadata_len = 0; |
| 583 | |
| 597 | 584 | main_loop: for ( |
| 598 | 585 | serialized_node_parents_buffer[0..serialized_len], |
| 599 | 586 | serialized_node_storage_buffer[0..serialized_len], |
| ... | ... | @@ -618,7 +605,7 @@ fn serializeIpc(start_serialized_len: usize) usize { |
| 618 | 605 | // Ignore all but the last message on the pipe. |
| 619 | 606 | var input: []align(2) u8 = pipe_buf[0..bytes_read]; |
| 620 | 607 | if (input.len == 0) { |
| 621 | | serialized_len = useSavedIpcData(serialized_len, main_storage, main_index); |
| 608 | serialized_len = useSavedIpcData(serialized_len, main_storage, main_index, old_ipc_metadata); |
| 622 | 609 | continue; |
| 623 | 610 | } |
| 624 | 611 | |
| ... | ... | @@ -626,7 +613,7 @@ fn serializeIpc(start_serialized_len: usize) usize { |
| 626 | 613 | if (input.len < 4) { |
| 627 | 614 | std.log.warn("short read: {d} out of 4 header bytes", .{input.len}); |
| 628 | 615 | // TODO keep track of the short read to trash odd bytes with the next read |
| 629 | | serialized_len = useSavedIpcData(serialized_len, main_storage, main_index); |
| 616 | serialized_len = useSavedIpcData(serialized_len, main_storage, main_index, old_ipc_metadata); |
| 630 | 617 | continue :main_loop; |
| 631 | 618 | } |
| 632 | 619 | const subtree_len = std.mem.readInt(u32, input[0..4], .little); |
| ... | ... | @@ -634,7 +621,7 @@ fn serializeIpc(start_serialized_len: usize) usize { |
| 634 | 621 | if (input.len < expected_bytes) { |
| 635 | 622 | std.log.warn("short read: {d} out of {d} ({d} nodes)", .{ input.len, expected_bytes, subtree_len }); |
| 636 | 623 | // TODO keep track of the short read to trash odd bytes with the next read |
| 637 | | serialized_len = useSavedIpcData(serialized_len, main_storage, main_index); |
| 624 | serialized_len = useSavedIpcData(serialized_len, main_storage, main_index, old_ipc_metadata); |
| 638 | 625 | continue :main_loop; |
| 639 | 626 | } |
| 640 | 627 | if (input.len > expected_bytes) { |
| ... | ... | @@ -650,16 +637,16 @@ fn serializeIpc(start_serialized_len: usize) usize { |
| 650 | 637 | }; |
| 651 | 638 | |
| 652 | 639 | // Remember in case the pipe is empty on next update. |
| 653 | | const real_storage: *Node.Storage = Node.storageByIndex(main_storage.getMainStorageIndex()); |
| 654 | | @as(*SavedMetadata, @ptrCast(&real_storage.name)).* = .{ |
| 640 | ipc_metadata[ipc_metadata_len] = .{ |
| 641 | .ipc_fd = @intCast(fd), |
| 655 | 642 | .start_index = @intCast(serialized_len), |
| 656 | 643 | .nodes_len = @intCast(parents.len), |
| 657 | 644 | .main_index = @intCast(main_index), |
| 658 | | .flags = .saved, |
| 659 | 645 | }; |
| 646 | ipc_metadata_len += 1; |
| 660 | 647 | |
| 661 | 648 | // Mount the root here. |
| 662 | | main_storage.* = storage[0]; |
| 649 | copyRoot(main_storage, &storage[0]); |
| 663 | 650 | |
| 664 | 651 | // Copy the rest of the tree to the end. |
| 665 | 652 | @memcpy(serialized_node_storage_buffer[serialized_len..][0 .. storage.len - 1], storage[1..]); |
| ... | ... | @@ -685,34 +672,56 @@ fn serializeIpc(start_serialized_len: usize) usize { |
| 685 | 672 | // Save a copy in case any pipes are empty on the next update. |
| 686 | 673 | @memcpy(parents_copy[0..serialized_len], serialized_node_parents_buffer[0..serialized_len]); |
| 687 | 674 | @memcpy(storage_copy[0..serialized_len], serialized_node_storage_buffer[0..serialized_len]); |
| 675 | @memcpy(ipc_metadata_copy[0..ipc_metadata_len], ipc_metadata[0..ipc_metadata_len]); |
| 688 | 676 | |
| 689 | 677 | return serialized_len; |
| 690 | 678 | } |
| 691 | 679 | |
| 692 | | fn useSavedIpcData(start_serialized_len: usize, main_storage: *Node.Storage, main_index: usize) usize { |
| 693 | | const saved_metadata: *SavedMetadata = @ptrCast(&main_storage.name); |
| 694 | | if (saved_metadata.flags != .saved) { |
| 680 | fn copyRoot(dest: *Node.Storage, src: *align(2) Node.Storage) void { |
| 681 | dest.* = .{ |
| 682 | .completed_count = src.completed_count, |
| 683 | .estimated_total_count = src.estimated_total_count, |
| 684 | .name = if (src.name[0] == 0) dest.name else src.name, |
| 685 | }; |
| 686 | } |
| 687 | |
| 688 | fn findOld(ipc_fd: posix.fd_t, old_metadata: []const SavedMetadata) ?*const SavedMetadata { |
| 689 | for (old_metadata) |*m| { |
| 690 | if (m.ipc_fd == ipc_fd) |
| 691 | return m; |
| 692 | } |
| 693 | return null; |
| 694 | } |
| 695 | |
| 696 | fn useSavedIpcData( |
| 697 | start_serialized_len: usize, |
| 698 | main_storage: *Node.Storage, |
| 699 | main_index: usize, |
| 700 | old_metadata: []const SavedMetadata, |
| 701 | ) usize { |
| 702 | const ipc_fd = main_storage.getIpcFd().?; |
| 703 | const saved_metadata = findOld(ipc_fd, old_metadata) orelse { |
| 695 | 704 | main_storage.completed_count = 0; |
| 696 | 705 | main_storage.estimated_total_count = 0; |
| 697 | 706 | return start_serialized_len; |
| 698 | | } |
| 707 | }; |
| 699 | 708 | |
| 700 | 709 | const start_index = saved_metadata.start_index; |
| 701 | 710 | const nodes_len = saved_metadata.nodes_len; |
| 702 | 711 | const old_main_index = saved_metadata.main_index; |
| 703 | 712 | |
| 704 | | const real_storage: *Node.Storage = Node.storageByIndex(main_storage.getMainStorageIndex()); |
| 705 | | @as(*SavedMetadata, @ptrCast(&real_storage.name)).* = .{ |
| 713 | ipc_metadata[ipc_metadata_len] = .{ |
| 714 | .ipc_fd = @intCast(ipc_fd), |
| 706 | 715 | .start_index = @intCast(start_serialized_len), |
| 707 | 716 | .nodes_len = nodes_len, |
| 708 | 717 | .main_index = @intCast(main_index), |
| 709 | | .flags = .saved, |
| 710 | 718 | }; |
| 719 | ipc_metadata_len += 1; |
| 711 | 720 | |
| 712 | 721 | const parents = parents_copy[start_index..][0 .. nodes_len - 1]; |
| 713 | 722 | const storage = storage_copy[start_index..][0 .. nodes_len - 1]; |
| 714 | 723 | |
| 715 | | main_storage.* = storage_copy[old_main_index]; |
| 724 | copyRoot(main_storage, &storage_copy[old_main_index]); |
| 716 | 725 | |
| 717 | 726 | @memcpy(serialized_node_storage_buffer[start_serialized_len..][0..storage.len], storage); |
| 718 | 727 | |