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