diff --git a/Makefile b/Makefile index 3ec3682..ab926eb 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ else ROOTLIBDIR = $(shell root-config --libdir) endif -CFLAGS = -Wall -Wextra -pedantic +CFLAGS = -Wall -Wextra -pedantic -fcolor-diagnostics INC = -Ithird_party -Ithird_party/imgui LIBS = -lglfw diff --git a/src/hover.cpp b/src/hover.cpp index 113543e..ff8426c 100644 --- a/src/hover.cpp +++ b/src/hover.cpp @@ -1080,8 +1080,13 @@ struct Sec_Hover_Fn { void free_slot() { titled_section("Free Slot", [this] { - u32 keylen = tkey(); - range("Freed Data", section.range.len - section.post_size - keylen); + // Sometimes a free slot has a leading TKey, but in general the only bytes that are + // guaranteed to be valid are the first 4. + field<i32>("NBytes: %d", [] (Arena *arena, String8_Node *prev, const char *fmt, i32 x) { + x = bswap(x); + return push_str8_node_child(arena, prev, fmt, abs(x)); + }); + range("Freed Data", section.range.len - sizeof(i32)); }); } }; diff --git a/src/render.cpp b/src/render.cpp index c0e7d75..2b3f547 100644 --- a/src/render.cpp +++ b/src/render.cpp @@ -236,14 +236,19 @@ void viewer_jump_to_page_list(App_State &app, u64 page_list_idx) internal void viewer_jump_to_free_slot(App_State &app, u64 free_slot_idx) { - assert(app.tfile_data.n_free_slots > 0); + u64 n_free_slots = app.tfile_data.sections[Sec_Free_Slot].count; + assert(n_free_slots > 0); - u64 idx = (free_slot_idx + app.tfile_data.n_free_slots) % app.tfile_data.n_free_slots; + u64 idx = (free_slot_idx + n_free_slots) % n_free_slots; - Byte_Range free_slot = app.tfile_data.free_slots[idx]; + Section *sec = app.tfile_data.sections[Sec_Free_Slot].head; + for (u64 i = 0; i < idx; ++i) { + sec = sec->next; + assert(sec); + } app.viewer.latest_section_gone_to[Sec_Free_Slot] = idx; - viewer_jump_to(app, free_slot.start); + viewer_jump_to(app, sec->range.start); } internal @@ -479,7 +484,7 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms) } } - if (app.tfile_data.n_free_slots) { + if (app.tfile_data.sections[Sec_Free_Slot].count) { ImGui::ColorEdit3("_Free Slot", app.viewer.col_section[Sec_Free_Slot], edit_flags); ImGui::SameLine(); if (ImGui::Button("Free Slot")) diff --git a/src/rntuple.cpp b/src/rntuple.cpp index 1612111..8c06040 100644 --- a/src/rntuple.cpp +++ b/src/rntuple.cpp @@ -4,6 +4,7 @@ Section *push_section(Arena *arena, TFile_Data &tdata, Section_Id id) Section *sec = arena_push<Section>(arena); sec->id = id; push_to_sll(tdata.sections[id].head, tdata.sections[id].tail, sec); + tdata.sections[id].count += 1; return sec; } @@ -194,7 +195,8 @@ RNTuple_Data get_rntuple_data(Arena *arena, const Inspected_File &file, const TF Page_Info_Node *pinfo_head = nullptr, *pinfo_tail = nullptr; Page_Info_Node *last_inserted_pinfo = nullptr; - RNTupleDescriptor *descriptors = arena_push_array_nozero<RNTupleDescriptor>(arena, tfile_data.n_anchors); + u64 n_anchors = tfile_data.sections[Sec_RNTuple_Anchor].count; + RNTupleDescriptor *descriptors = arena_push_array_nozero<RNTupleDescriptor>(arena, n_anchors); u32 anchor_idx = 0; u64 n_tot_cluster_groups = 0; u64 n_tot_clusters = 0; @@ -205,7 +207,7 @@ RNTuple_Data get_rntuple_data(Arena *arena, const Inspected_File &file, const TF n_tot_cluster_groups += desc.GetNClusterGroups(); n_tot_clusters += desc.GetNActiveClusters(); } - assert(anchor_idx == tfile_data.n_anchors); + assert(anchor_idx == n_anchors); // Allocate space for clusters/cluster groups infos Cluster_Info *clusters = arena_push_array<Cluster_Info>(arena, n_tot_clusters); @@ -217,7 +219,6 @@ RNTuple_Data get_rntuple_data(Arena *arena, const Inspected_File &file, const TF /// Load all RNTuple data /// anchor_idx = 0; - printf("%p\n", tfile_data.sections[Sec_RNTuple_Anchor].head); for (Section *sec_anchor = tfile_data.sections[Sec_RNTuple_Anchor].head; sec_anchor; sec_anchor = sec_anchor->next, ++anchor_idx) { const ROOT::RNTuple &anchor = *(const ROOT::RNTuple *)sec_anchor->info; if (!anchor.GetNBytesHeader()) @@ -362,14 +363,14 @@ RNTuple_Data get_rntuple_data(Arena *arena, const Inspected_File &file, const TF } // destruct all descriptors - for (u64 i = 0; i < tfile_data.n_anchors; ++i) + for (u64 i = 0; i < n_anchors; ++i) descriptors[i].~RNTupleDescriptor(); chr::time_point end_t = chr::high_resolution_clock::now(); u64 time_spent_ms = chr::duration_cast<chr::milliseconds>(end_t - start_t).count(); - fprintf(stderr, "Loaded %" PRIu64 " pages from %u anchors in %" PRIu64 " ms (%" PRIu64 " duplicates).\nGenerating groups...\n", - n_pages, tfile_data.n_anchors, time_spent_ms, n_duplicate_page_ranges); + fprintf(stderr, "Loaded %" PRIu64 " pages from %" PRIu64 " anchors in %" PRIu64 " ms (%" PRIu64 " duplicates).\nGenerating groups...\n", + n_pages, n_anchors, time_spent_ms, n_duplicate_page_ranges); // Create page groups and chunks. // Each page group is a grouping of GROUP_SIZE page infos whose range is equal to the combined ranges @@ -479,15 +480,6 @@ Section find_section(App_State &app, u64 off, i64 hilite_cluster = -1) const RNTuple_Data &rdata = app.rndata; Section sec {}; - // Check free slots - for (u64 i = 0; i < app.tfile_data.n_free_slots; ++i) { - Byte_Range rng = app.tfile_data.free_slots[i]; - if (rng.start <= off && off < rng.end()) { - sec.id = Sec_Free_Slot; - sec.range = rng; - return sec; - } - } for (u32 i = 1; i < Sec_COUNT; ++i) { for (Section *sec = app.tfile_data.sections[i].head; sec; sec = sec->next) { diff --git a/src/rntuple.h b/src/rntuple.h index 075772f..cb2b0e9 100644 --- a/src/rntuple.h +++ b/src/rntuple.h @@ -65,13 +65,7 @@ enum Section_Id { Sec_RNTuple_Header, Sec_RNTuple_Footer, Sec_Page_List, - - // By 'Unique' we mean that we only highlight one section of that type. - // In the future we might want to improve this and support properly highlighting - // multiple RNTuples (in which case anchor/header/footer/page list would become non-unique) - Sec_COUNT_UNIQUE, - Sec_FIRST_NON_UNIQUE = Sec_COUNT_UNIQUE, - Sec_Page = Sec_FIRST_NON_UNIQUE, + Sec_Page, Sec_RNTuple_Anchor, Sec_Free_Slot, // any other object stored in a TKey @@ -150,12 +144,7 @@ struct TFile_Data { u32 compression; Sections sections[Sec_COUNT]; - TKeys_Data tkeys_data; - // Sorted list of free slots in the TFile - Byte_Range *free_slots; - u64 n_free_slots; - u32 n_anchors; // XXX: remove me? }; // @Volatile: when changed, remember to update merge_rntuple_data() @@ -167,10 +156,6 @@ struct RNTuple_Data { u64 tot_page_comp_size; u64 tot_page_uncomp_size; - // TODO - Range_Seq *checksums; - u64 n_checksums; - Cluster_Group_Info *cluster_groups; u64 n_cluster_groups; u64 tot_page_list_size; diff --git a/src/tfile.cpp b/src/tfile.cpp index b82edb0..9d6ff61 100644 --- a/src/tfile.cpp +++ b/src/tfile.cpp @@ -239,12 +239,9 @@ b8 walk_tkeys(Arena *arena, const u8 *data, u64 data_len, u32 flags, TFile_Data ++n_keys; } - printf("cur: 0x%lX\n", cur); - if (is_free_slot) { // don't try to read the rest of the data cur += n_bytes; - printf("skipping %u bytes\n", n_bytes); continue; } @@ -308,8 +305,6 @@ b8 walk_tkeys(Arena *arena, const u8 *data, u64 data_len, u32 flags, TFile_Data sec_anchor->range.len = n_bytes - keylen; sec_anchor->pre_size = keylen; sec_anchor->post_size = 8; - - ++tfile_data.n_anchors; } else if (key_has_class_name("RBlob")) { if (!sections[Sec_Page].head) { @@ -361,37 +356,25 @@ b8 walk_tkeys(Arena *arena, const u8 *data, u64 data_len, u32 flags, TFile_Data u64 free_slots_start = sec_tfile_freelist->range.start; u64 free_slots_end = sec_tfile_freelist->range.end(); u64 n_free_slots = (free_slots_end - free_slots_start) / free_slot_size; - if (n_free_slots) { - tfile_data.free_slots = arena_push_array_nozero<Byte_Range>(arena, n_free_slots); - u64 cur = free_slots_start; - for (u64 i = 0; i < n_free_slots; ) { - memcpy(&fs, data + cur, free_slot_size); - Byte_Range *free_slot = &tfile_data.free_slots[i]; - u64 start, end; - if (is_big_file) { - start = bswap(fs.rng.rng_long.start); - end = min(data_len, bswap(fs.rng.rng_long.end)); - } else { - start = bswap(fs.rng.rng_short.start); - end = min(data_len, bswap(fs.rng.rng_short.end)); - } - - cur += free_slot_size; - - printf("0x%lX - 0x%lX\n", start, end); - - // The free slot might not be a "real" slot (if its end is lower than its start or if it starts past the end of - // the file): in this case, don't add it to the list. - if (end >= start && start < data_len) { - free_slot->start = start; - free_slot->len = end - start + 1; // +1 because `end` is inclusive - ++i; - } else { - assert(n_free_slots > 0); - --n_free_slots; - } + for (u64 i = 0; i < n_free_slots; ++i) { + u64 cur = free_slots_start + i * free_slot_size; + memcpy(&fs, data + cur, free_slot_size); + u64 start, end; + if (is_big_file) { + start = bswap(fs.rng.rng_long.start); + end = min(data_len, bswap(fs.rng.rng_long.end)); + } else { + start = bswap(fs.rng.rng_short.start); + end = min(data_len, bswap(fs.rng.rng_short.end)); + } + + // The free slot might not be a "real" slot (if its end is lower than its start or if it starts past the end of + // the file): in this case, don't add it to the list. + if (end >= start && start < data_len) { + Section *sec_free_slot = push_section(arena, tfile_data, Sec_Free_Slot); + sec_free_slot->range.start = start; + sec_free_slot->range.len = end - start + 1; // +1 because `end` is inclusive } - tfile_data.n_free_slots = n_free_slots; } return true; @@ -404,11 +387,12 @@ void map_rntuple_rblobs(Arena *arena, TFile_Data &tfile_data) defer { scratch_end(scratch); }; TKeys_Data &tkeys_data = tfile_data.tkeys_data; + u64 n_anchors = tfile_data.sections[Sec_RNTuple_Anchor].count; // 0: header, 1: footer b8 *found[2] = { - arena_push_array<b8>(scratch.arena, tfile_data.n_anchors), - arena_push_array<b8>(scratch.arena, tfile_data.n_anchors) + arena_push_array<b8>(scratch.arena, n_anchors), + arena_push_array<b8>(scratch.arena, n_anchors) }; for (Byte_Range_Node *tkey = tkeys_data.rblob_keys; tkey; tkey = tkey->next) { @@ -444,7 +428,7 @@ void map_rntuple_rblobs(Arena *arena, TFile_Data &tfile_data) } } - for (u64 i = 0; i < tfile_data.n_anchors; ++i) { + for (u64 i = 0; i < n_anchors; ++i) { if (!found[0][i]) { fprintf(stderr, "Didn't found header for RNTuple %" PRIu64 "\n", i); }