refactor sections to allow multiple of any type
This commit is contained in:
parent
a1caf3951c
commit
2d4862c234
5 changed files with 172 additions and 126 deletions
|
@ -323,7 +323,7 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms)
|
|||
if (ImGui::Begin("main", nullptr, main_win_flags)) {
|
||||
|
||||
// FIXME :multiple_anchors:
|
||||
const ROOT::RNTuple &anchor = app.tfile_data.anchors_head->anchor;
|
||||
const ROOT::RNTuple &anchor = *(const ROOT::RNTuple *)app.tfile_data.tkeys_data.sections[Sec_RNTuple_Anchor].head->info;
|
||||
String8 ntpl_desc = rntuple_description(scratch.arena, anchor);
|
||||
if (rntuple_is_old_version(anchor)) {
|
||||
ImGui::TextColored(ImColor(1.f, 0.f, 0.f), "\"%s\" (%s) from file \"%s\" ** old version, some data missing! **",
|
||||
|
@ -388,17 +388,18 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms)
|
|||
|
||||
// Unique sections: just display a button that jumps to the start of it and show their size
|
||||
for (u32 i = 0; i < Sec_COUNT; ++i) {
|
||||
Byte_Range range = get_section_range(app, static_cast<Section_Id>(i));
|
||||
if (!range.len) continue;
|
||||
for (Section *sec = app.tfile_data.tkeys_data.sections[i].head; sec; sec = sec->next) {
|
||||
if (!sec->range.len) continue;
|
||||
|
||||
String8 sec_name = section_names[i];
|
||||
String8 col_label = push_str8f(scratch.arena, "_%s", sec_name.c());
|
||||
ImGui::ColorEdit3(col_label.c(), app.viewer.col_section[i], edit_flags);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button(sec_name.c()))
|
||||
viewer_jump_to(app, range.start);
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("%s", to_pretty_size(scratch.arena, range.len).c());
|
||||
String8 sec_name = section_names[i];
|
||||
String8 col_label = push_str8f(scratch.arena, "_%s", sec_name.c());
|
||||
ImGui::ColorEdit3(col_label.c(), app.viewer.col_section[i], edit_flags);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button(sec_name.c()))
|
||||
viewer_jump_to(app, sec->range.start);
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("%s", to_pretty_size(scratch.arena, sec->range.len).c());
|
||||
}
|
||||
}
|
||||
|
||||
// Repeated sections: allow jumping to the N-th
|
||||
|
|
|
@ -48,7 +48,7 @@ String8_Node *render_legend_to_string(Arena *arena, const Term_Viewer &viewer, c
|
|||
Ansi_Color color = viewer.col_section[section];
|
||||
String8 color_str = ansi_color_table[color];
|
||||
String8 sec_name = section_names[section];
|
||||
Byte_Range range = get_section_range(app, static_cast<Section_Id>(section));
|
||||
Byte_Range range = { 0, 0 }; // TODO get_section_range(app, static_cast<Section_Id>(section));
|
||||
if (range.len)
|
||||
tail = push_str8_node(arena, tail, "%s%20s %s0x%lX - 0x%lX [%s]\n",
|
||||
color_str.c(), sec_name.c(), color_none.c(),
|
||||
|
@ -217,7 +217,7 @@ String8_Node *render_range_to_string(Arena *arena, App_State &app, u64 len, u64
|
|||
defer { scratch_end(scratch); };
|
||||
|
||||
// Header
|
||||
String8 ntpl_desc = rntuple_description(scratch.arena, app.tfile_data.anchors_head->anchor); // FIXME :multiple_anchors:
|
||||
String8 ntpl_desc = rntuple_description(scratch.arena, *(const ROOT::RNTuple *)app.tfile_data.tkeys_data.sections[Sec_RNTuple_Anchor].head->info); // FIXME :multiple_anchors:
|
||||
String8_Node *result = push_str8_node(arena, nullptr, "RNTuple '%s' (%s) from file \"%s\"\n",
|
||||
app.ntpl_name.c(), ntpl_desc.c(), app.inspected_file.name.c());
|
||||
String8_Node *result_tail = result;
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
internal
|
||||
Section *push_section(Arena *arena, TFile_Data &tdata, Section_Id id)
|
||||
{
|
||||
Section *sec = arena_push<Section>(arena);
|
||||
sec->id = id;
|
||||
push_to_sll(tdata.tkeys_data.sections[id].head, tdata.tkeys_data.sections[id].tail, sec);
|
||||
return sec;
|
||||
}
|
||||
|
||||
internal
|
||||
b8 rntuple_is_old_version(const ROOT::RNTuple &ntuple)
|
||||
{
|
||||
|
@ -189,10 +198,10 @@ RNTuple_Data get_rntuple_data(Arena *arena, const Inspected_File &file, const TF
|
|||
u32 anchor_idx = 0;
|
||||
u64 n_tot_cluster_groups = 0;
|
||||
u64 n_tot_clusters = 0;
|
||||
for (RNTuple_Anchor_Node *anchor_node = tfile_data.anchors_head; anchor_node; anchor_node = anchor_node->next, ++anchor_idx) {
|
||||
for (Section *sec_anchor = tfile_data.tkeys_data.sections[Sec_RNTuple_Anchor].head; sec_anchor; sec_anchor = sec_anchor->next, ++anchor_idx) {
|
||||
RNTupleDescriptor &desc = descriptors[anchor_idx];
|
||||
new (&desc) RNTupleDescriptor();
|
||||
desc = create_descriptor(arena, anchor_node->anchor, reader);
|
||||
desc = create_descriptor(arena, *(const ROOT::RNTuple *)sec_anchor->info, reader);
|
||||
n_tot_cluster_groups += desc.GetNClusterGroups();
|
||||
n_tot_clusters += desc.GetNActiveClusters();
|
||||
}
|
||||
|
@ -208,8 +217,8 @@ RNTuple_Data get_rntuple_data(Arena *arena, const Inspected_File &file, const TF
|
|||
|
||||
/// Load all RNTuple data ///
|
||||
anchor_idx = 0;
|
||||
for (RNTuple_Anchor_Node *anchor_node = tfile_data.anchors_head; anchor_node; anchor_node = anchor_node->next, ++anchor_idx) {
|
||||
const ROOT::RNTuple &anchor = anchor_node->anchor;
|
||||
for (Section *sec_anchor = tfile_data.tkeys_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())
|
||||
continue;
|
||||
|
||||
|
@ -459,12 +468,6 @@ RNTuple_Data get_rntuple_data(Arena *arena, const Inspected_File &file, const TF
|
|||
return rndata;
|
||||
}
|
||||
|
||||
internal
|
||||
Byte_Range get_section_range(const App_State &app, Section_Id sec)
|
||||
{
|
||||
return app.tfile_data.tkeys_data.sections[sec].range;
|
||||
}
|
||||
|
||||
internal
|
||||
Section find_section(App_State &app, u64 off, i64 hilite_cluster = -1)
|
||||
{
|
||||
|
@ -486,22 +489,15 @@ Section find_section(App_State &app, u64 off, i64 hilite_cluster = -1)
|
|||
}
|
||||
}
|
||||
|
||||
for (u32 i = 1; i < Sec_COUNT_UNIQUE; ++i) {
|
||||
const Section &sec = tdata.sections[i];
|
||||
if (sec.range.start - sec.pre_size <= off && off < sec.range.end()) {
|
||||
return sec;
|
||||
for (u32 i = 1; i < Sec_COUNT; ++i) {
|
||||
for (Section *sec = tdata.sections[i].head; sec; sec = sec->next) {
|
||||
if (sec->range.start - sec->pre_size <= off && off < sec->range.end()) {
|
||||
return *sec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check anchors
|
||||
for (RNTuple_Anchor_Node *node = app.tfile_data.anchors_head; node; node = node->next) {
|
||||
const Section &sec = node->section;
|
||||
if (sec.range.start - sec.pre_size <= off && off < sec.range.end()) {
|
||||
return sec;
|
||||
}
|
||||
}
|
||||
|
||||
u64 rblob_sz = tdata.sections[Sec_Page].pre_size;
|
||||
u64 rblob_sz = tdata.sections[Sec_Page].head->pre_size;
|
||||
|
||||
/// Page fast lookup (relative to app.last_pinfo)
|
||||
{
|
||||
|
|
|
@ -81,6 +81,8 @@ enum Section_Id {
|
|||
};
|
||||
|
||||
struct Section {
|
||||
Section *next;
|
||||
|
||||
Section_Id id;
|
||||
Byte_Range range;
|
||||
u64 pre_size; // usually the TKey header, excluded from `range`
|
||||
|
@ -128,8 +130,13 @@ struct Other_Root_Obj_Info {
|
|||
};
|
||||
static const Other_Root_Obj_Info invalid_other_root_obj_info {};
|
||||
|
||||
struct Sections {
|
||||
Section *head, *tail;
|
||||
u32 count;
|
||||
};
|
||||
|
||||
struct TKeys_Data {
|
||||
Section sections[Sec_COUNT];
|
||||
Sections sections[Sec_COUNT];
|
||||
|
||||
RNTuple_Anchor_Info *rntuples;
|
||||
Byte_Range_Node *rblob_keys;
|
||||
|
@ -154,8 +161,7 @@ struct TFile_Data {
|
|||
// Sorted list of free slots in the TFile
|
||||
Byte_Range *free_slots;
|
||||
u64 n_free_slots;
|
||||
RNTuple_Anchor_Node *anchors_head, *anchors_tail;
|
||||
u32 n_anchors;
|
||||
u32 n_anchors; // XXX: remove me?
|
||||
};
|
||||
|
||||
// @Volatile: when changed, remember to update merge_rntuple_data()
|
||||
|
@ -187,3 +193,6 @@ struct RNTuple_Data {
|
|||
Page_Info_Chunk *page_chunks;
|
||||
u64 n_page_chunks;
|
||||
};
|
||||
|
||||
internal
|
||||
Section *push_section(Arena *arena, TFile_Data &tdata, Section_Id id);
|
||||
|
|
214
src/tfile.cpp
214
src/tfile.cpp
|
@ -110,19 +110,33 @@ b8 walk_tkeys(Arena *arena, const u8 *data, u64 data_len, u32 flags, TFile_Data
|
|||
|
||||
if (is_big_file) {
|
||||
tfile_data.compression = bswap(header.info.info_long.compress_be);
|
||||
// NOTE: the + 18 is the UUID
|
||||
tkeys_data.sections[Sec_TFile_Header].range.len = 4 + sizeof(header_version) + sizeof(begin) + sizeof(TFile_Header::Info::Long) + 18;
|
||||
tkeys_data.sections[Sec_TFile_Info].range.start = bswap(header.info.info_long.seek_info_be);
|
||||
tkeys_data.sections[Sec_TFile_Info].range.len = bswap(header.info.info_long.nbytes_info_be);
|
||||
tkeys_data.sections[Sec_TFile_FreeList].range.start = bswap(header.info.info_long.seek_free_be);
|
||||
tkeys_data.sections[Sec_TFile_FreeList].range.len = bswap(header.info.info_long.nbytes_free_be);
|
||||
push_section(arena, tfile_data, Sec_TFile_Header)->range = {
|
||||
0,
|
||||
// NOTE: the + 18 is the UUID
|
||||
4 + sizeof(header_version) + sizeof(begin) + sizeof(TFile_Header::Info::Long) + 18
|
||||
};
|
||||
push_section(arena, tfile_data, Sec_TFile_Info)->range = {
|
||||
bswap(header.info.info_long.seek_info_be),
|
||||
bswap(header.info.info_long.nbytes_info_be)
|
||||
};
|
||||
push_section(arena, tfile_data, Sec_TFile_FreeList)->range = {
|
||||
bswap(header.info.info_long.seek_free_be),
|
||||
bswap(header.info.info_long.nbytes_free_be)
|
||||
};
|
||||
} else {
|
||||
tfile_data.compression = bswap(header.info.info_short.compress_be);
|
||||
tkeys_data.sections[Sec_TFile_Header].range.len = 4 + sizeof(header_version) + sizeof(begin) + sizeof(TFile_Header::Info::Short) + 18;
|
||||
tkeys_data.sections[Sec_TFile_Info].range.start = bswap(header.info.info_short.seek_info_be);
|
||||
tkeys_data.sections[Sec_TFile_Info].range.len = bswap(header.info.info_short.nbytes_info_be);
|
||||
tkeys_data.sections[Sec_TFile_FreeList].range.start = bswap(header.info.info_short.seek_free_be);
|
||||
tkeys_data.sections[Sec_TFile_FreeList].range.len = bswap(header.info.info_short.nbytes_free_be);
|
||||
push_section(arena, tfile_data, Sec_TFile_Header)->range = {
|
||||
0,
|
||||
4 + sizeof(header_version) + sizeof(begin) + sizeof(TFile_Header::Info::Short) + 18
|
||||
};
|
||||
push_section(arena, tfile_data, Sec_TFile_Info)->range = {
|
||||
bswap(header.info.info_short.seek_info_be),
|
||||
bswap(header.info.info_short.nbytes_info_be)
|
||||
};
|
||||
push_section(arena, tfile_data, Sec_TFile_FreeList)->range = {
|
||||
bswap(header.info.info_short.seek_free_be),
|
||||
bswap(header.info.info_short.nbytes_free_be)
|
||||
};
|
||||
}
|
||||
|
||||
// Jump to the TFile object
|
||||
|
@ -144,9 +158,10 @@ b8 walk_tkeys(Arena *arena, const u8 *data, u64 data_len, u32 flags, TFile_Data
|
|||
{
|
||||
u16 tfile_obj_keylen = read_be<u16>(data + cur + keylen_off);
|
||||
|
||||
tkeys_data.sections[Sec_TFile_Object].range.start = cur + tfile_obj_keylen;
|
||||
tkeys_data.sections[Sec_TFile_Object].range.len = tfile_obj_nbytes - tfile_obj_keylen;
|
||||
tkeys_data.sections[Sec_TFile_Object].pre_size = tfile_obj_keylen;
|
||||
Section *sec_tfile_obj = push_section(arena, tfile_data, Sec_TFile_Object);
|
||||
sec_tfile_obj->range.start = cur + tfile_obj_keylen;
|
||||
sec_tfile_obj->range.len = tfile_obj_nbytes - tfile_obj_keylen;
|
||||
sec_tfile_obj->pre_size = tfile_obj_keylen;
|
||||
|
||||
cur += tfile_obj_keylen; // advance to the tfile object payload
|
||||
|
||||
|
@ -169,17 +184,18 @@ b8 walk_tkeys(Arena *arena, const u8 *data, u64 data_len, u32 flags, TFile_Data
|
|||
memcpy(&seek_keys_be, data + cur + 18 + 8, sizeof(seek_keys_be));
|
||||
cur += 18 + 8 + sizeof(seek_keys_be);
|
||||
seek_keys = bswap(seek_keys_be);
|
||||
tkeys_data.sections[Sec_TFile_Object].post_size = 12; // small TFile has padding at the end of the TFile obj section
|
||||
sec_tfile_obj->post_size = 12; // small TFile has padding at the end of the TFile obj section
|
||||
}
|
||||
|
||||
tkeys_data.sections[Sec_TKey_List].range.start = seek_keys;
|
||||
Section *sec_tkey_list = push_section(arena, tfile_data, Sec_TKey_List);
|
||||
sec_tkey_list->range.start = seek_keys;
|
||||
|
||||
// Read right away the tkey list information, so we have it even if the key walk fails to find it
|
||||
u32 seek_keys_nbytes = read_be<u32>(data + seek_keys);
|
||||
u16 seek_keys_keylen = read_be<u16>(data + seek_keys + keylen_off);
|
||||
tkeys_data.sections[Sec_TKey_List].pre_size = seek_keys_keylen;
|
||||
tkeys_data.sections[Sec_TKey_List].range.start += seek_keys_keylen;
|
||||
tkeys_data.sections[Sec_TKey_List].range.len = seek_keys_nbytes - seek_keys_keylen;
|
||||
sec_tkey_list->pre_size = seek_keys_keylen;
|
||||
sec_tkey_list->range.start += seek_keys_keylen;
|
||||
sec_tkey_list->range.len = seek_keys_nbytes - seek_keys_keylen;
|
||||
}
|
||||
|
||||
cur = pre + tfile_obj_nbytes;
|
||||
|
@ -230,23 +246,23 @@ b8 walk_tkeys(Arena *arena, const u8 *data, u64 data_len, u32 flags, TFile_Data
|
|||
continue;
|
||||
}
|
||||
|
||||
if (cur == tkeys_data.sections[Sec_TKey_List].range.start - tkeys_data.sections[Sec_TKey_List].pre_size) {
|
||||
if (keylen != tkeys_data.sections[Sec_TKey_List].pre_size ||
|
||||
(u64)(n_bytes - keylen) != tkeys_data.sections[Sec_TKey_List].range.len)
|
||||
if (cur == tkeys_data.sections[Sec_TKey_List].head->range.start - tkeys_data.sections[Sec_TKey_List].head->pre_size) {
|
||||
if (keylen != tkeys_data.sections[Sec_TKey_List].head->pre_size ||
|
||||
(u64)(n_bytes - keylen) != tkeys_data.sections[Sec_TKey_List].head->range.len)
|
||||
{
|
||||
fprintf(stderr, "Warning: inconsistent key list data, the file may have not parsed properly.\n");
|
||||
fprintf(stderr, " (keylen: %u vs %lu, nbytes: %u vs %lu)\n",
|
||||
keylen, tkeys_data.sections[Sec_TKey_List].pre_size,
|
||||
n_bytes, tkeys_data.sections[Sec_TKey_List].range.len);
|
||||
keylen, tkeys_data.sections[Sec_TKey_List].head->pre_size,
|
||||
n_bytes, tkeys_data.sections[Sec_TKey_List].head->range.len);
|
||||
}
|
||||
} else if (cur == tkeys_data.sections[Sec_TFile_Info].range.start) {
|
||||
tkeys_data.sections[Sec_TFile_Info].pre_size = keylen;
|
||||
tkeys_data.sections[Sec_TFile_Info].range.start += keylen;
|
||||
tkeys_data.sections[Sec_TFile_Info].range.len = n_bytes - keylen;
|
||||
} else if (cur == tkeys_data.sections[Sec_TFile_FreeList].range.start) {
|
||||
tkeys_data.sections[Sec_TFile_FreeList].pre_size = keylen;
|
||||
tkeys_data.sections[Sec_TFile_FreeList].range.start += keylen;
|
||||
tkeys_data.sections[Sec_TFile_FreeList].range.len = n_bytes - keylen;
|
||||
} else if (cur == tkeys_data.sections[Sec_TFile_Info].head->range.start) {
|
||||
tkeys_data.sections[Sec_TFile_Info].head->pre_size = keylen;
|
||||
tkeys_data.sections[Sec_TFile_Info].head->range.start += keylen;
|
||||
tkeys_data.sections[Sec_TFile_Info].head->range.len = n_bytes - keylen;
|
||||
} else if (cur == tkeys_data.sections[Sec_TFile_FreeList].head->range.start) {
|
||||
tkeys_data.sections[Sec_TFile_FreeList].head->pre_size = keylen;
|
||||
tkeys_data.sections[Sec_TFile_FreeList].head->range.start += keylen;
|
||||
tkeys_data.sections[Sec_TFile_FreeList].head->range.len = n_bytes - keylen;
|
||||
} else {
|
||||
// Check if this is a RNTuple anchor
|
||||
u64 key_header_size = (key_version >= 1000) ? 18 + 16 : 18 + 8;
|
||||
|
@ -271,31 +287,34 @@ b8 walk_tkeys(Arena *arena, const u8 *data, u64 data_len, u32 flags, TFile_Data
|
|||
tkeys_data.rntuples = rntuple_info;
|
||||
rntuple_info_tail = rntuple_info;
|
||||
|
||||
if (!tkeys_data.sections[Sec_RNTuple_Anchor].range.start) {
|
||||
u64 anchor_seek = cur + keylen;
|
||||
RNTuple_Anchor_On_Disk anchor;
|
||||
memcpy(&anchor, data + anchor_seek, sizeof(anchor));
|
||||
u64 anchor_seek = cur + keylen;
|
||||
RNTuple_Anchor_On_Disk anchor;
|
||||
memcpy(&anchor, data + anchor_seek, sizeof(anchor));
|
||||
|
||||
RNTuple_Anchor_Node *anchor_node = arena_push<RNTuple_Anchor_Node>(arena);
|
||||
anchor_node->anchor = ROOT::Experimental::Internal::CreateAnchor(
|
||||
bswap(anchor.epoch_be), bswap(anchor.major_be), bswap(anchor.minor_be), bswap(anchor.patch_be),
|
||||
bswap(anchor.seek_header_be), bswap(anchor.nbytes_header_be), bswap(anchor.len_header_be),
|
||||
bswap(anchor.seek_footer_be), bswap(anchor.nbytes_footer_be), bswap(anchor.len_footer_be),
|
||||
bswap(anchor.max_key_size_be));
|
||||
anchor_node->section.id = Sec_RNTuple_Anchor;
|
||||
anchor_node->section.range.start = anchor_seek;
|
||||
anchor_node->section.range.len = n_bytes - keylen;
|
||||
anchor_node->section.pre_size = keylen;
|
||||
anchor_node->section.post_size = 8;
|
||||
push_to_sll(tfile_data.anchors_head, tfile_data.anchors_tail, anchor_node);
|
||||
++tfile_data.n_anchors;
|
||||
}
|
||||
ROOT::RNTuple *rntuple = arena_push<ROOT::RNTuple>(arena);
|
||||
new (rntuple) ROOT::RNTuple();
|
||||
*rntuple = ROOT::Experimental::Internal::CreateAnchor(
|
||||
bswap(anchor.epoch_be), bswap(anchor.major_be), bswap(anchor.minor_be), bswap(anchor.patch_be),
|
||||
bswap(anchor.seek_header_be), bswap(anchor.nbytes_header_be), bswap(anchor.len_header_be),
|
||||
bswap(anchor.seek_footer_be), bswap(anchor.nbytes_footer_be), bswap(anchor.len_footer_be),
|
||||
bswap(anchor.max_key_size_be));
|
||||
|
||||
Section *sec_anchor = push_section(arena, tfile_data, Sec_RNTuple_Anchor);
|
||||
sec_anchor->info = rntuple;
|
||||
sec_anchor->id = Sec_RNTuple_Anchor;
|
||||
sec_anchor->range.start = anchor_seek;
|
||||
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 (!tkeys_data.sections[Sec_Page].pre_size) {
|
||||
tkeys_data.sections[Sec_Page].pre_size = keylen;
|
||||
tkeys_data.sections[Sec_Page_List].pre_size = keylen;
|
||||
tkeys_data.sections[Sec_Page_List].post_size = 8;
|
||||
if (!tkeys_data.sections[Sec_Page].head) {
|
||||
push_section(arena, tfile_data, Sec_Page)->pre_size = keylen;
|
||||
Section *sec_page_list = push_section(arena, tfile_data, Sec_Page_List);
|
||||
sec_page_list->pre_size = keylen;
|
||||
sec_page_list->post_size = 8;
|
||||
}
|
||||
|
||||
Byte_Range_Node *rblob_key = arena_push<Byte_Range_Node>(arena);
|
||||
|
@ -325,13 +344,10 @@ b8 walk_tkeys(Arena *arena, const u8 *data, u64 data_len, u32 flags, TFile_Data
|
|||
if (flags & WTK_PRINT_KEYS_INFO)
|
||||
printf("Found %u TKeys.\n", n_keys);
|
||||
|
||||
for (u32 id = 1; id < Sec_COUNT_UNIQUE; ++id)
|
||||
tkeys_data.sections[id].id = (Section_Id)id;
|
||||
|
||||
// adjust header section padding
|
||||
{
|
||||
u64 padding_end = tkeys_data.sections[Sec_TFile_Object].range.start - tkeys_data.sections[Sec_TFile_Object].pre_size;
|
||||
Section &sec_header = tkeys_data.sections[Sec_TFile_Header];
|
||||
u64 padding_end = tkeys_data.sections[Sec_TFile_Object].head->range.start - tkeys_data.sections[Sec_TFile_Object].head->pre_size;
|
||||
Section &sec_header = *tkeys_data.sections[Sec_TFile_Header].head;
|
||||
sec_header.post_size = padding_end - sec_header.range.len;
|
||||
sec_header.range.len += sec_header.post_size;
|
||||
}
|
||||
|
@ -339,8 +355,9 @@ b8 walk_tkeys(Arena *arena, const u8 *data, u64 data_len, u32 flags, TFile_Data
|
|||
// collect free slots
|
||||
TFile_Free_Slot fs;
|
||||
u64 free_slot_size = sizeof(u16) + (is_big_file ? sizeof(fs.rng.rng_long) : sizeof(fs.rng.rng_short));
|
||||
u64 free_slots_start = tkeys_data.sections[Sec_TFile_FreeList].range.start;
|
||||
u64 free_slots_end = tkeys_data.sections[Sec_TFile_FreeList].range.end();
|
||||
Section *sec_tfile_freelist = tkeys_data.sections[Sec_TFile_FreeList].head;
|
||||
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);
|
||||
|
@ -379,26 +396,58 @@ b8 walk_tkeys(Arena *arena, const u8 *data, u64 data_len, u32 flags, TFile_Data
|
|||
}
|
||||
|
||||
internal
|
||||
void map_rntuple_rblobs(const ROOT::RNTuple &anchor, TKeys_Data &tkeys_data)
|
||||
void map_rntuple_rblobs(Arena *arena, TFile_Data &tfile_data)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
defer { scratch_end(scratch); };
|
||||
|
||||
TKeys_Data &tkeys_data = tfile_data.tkeys_data;
|
||||
|
||||
// 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)
|
||||
};
|
||||
|
||||
for (Byte_Range_Node *tkey = tkeys_data.rblob_keys; tkey; tkey = tkey->next) {
|
||||
// NOTE: since we know the rblob_keys list is sorted by decreasing address, as soon as we find an address that's
|
||||
// lower than the section we're looking for, we know it must be the closest one (therefore the correct one).
|
||||
if (!tkeys_data.sections[Sec_RNTuple_Header].range.start && tkey->rng.start < anchor.GetSeekHeader()) {
|
||||
tkeys_data.sections[Sec_RNTuple_Header].range.start = tkey->rng.start + tkey->rng.len;
|
||||
tkeys_data.sections[Sec_RNTuple_Header].range.len = anchor.GetNBytesHeader();
|
||||
tkeys_data.sections[Sec_RNTuple_Header].pre_size = tkey->rng.len;
|
||||
tkeys_data.sections[Sec_RNTuple_Header].post_size = 8;
|
||||
// NOTE: assuming the header's address is lower than the footer's
|
||||
break;
|
||||
}
|
||||
|
||||
if (!tkeys_data.sections[Sec_RNTuple_Footer].range.start && tkey->rng.start < anchor.GetSeekFooter()) {
|
||||
tkeys_data.sections[Sec_RNTuple_Footer].range.start = tkey->rng.start + tkey->rng.len;
|
||||
tkeys_data.sections[Sec_RNTuple_Footer].range.len = anchor.GetNBytesFooter();
|
||||
tkeys_data.sections[Sec_RNTuple_Footer].pre_size = tkey->rng.len;
|
||||
tkeys_data.sections[Sec_RNTuple_Footer].post_size = 8;
|
||||
continue;
|
||||
for (Section_Id sec_id : { Sec_RNTuple_Header, Sec_RNTuple_Footer }) {
|
||||
i64 best_anchor_idx = -1;
|
||||
const ROOT::RNTuple *best_anchor = nullptr;
|
||||
u64 i = 0;
|
||||
u64 best_anchor_diff = (u64)-1;
|
||||
b8 *found_sec = found[sec_id == Sec_RNTuple_Footer];
|
||||
for (Section *sec_anchor = tfile_data.tkeys_data.sections[Sec_RNTuple_Anchor].head; sec_anchor; sec_anchor = sec_anchor->next, ++i) {
|
||||
const ROOT::RNTuple &anchor = *(const ROOT::RNTuple *)sec_anchor->info;
|
||||
if (!found_sec[i]) {
|
||||
u64 seek = sec_id == Sec_RNTuple_Header ? anchor.GetSeekHeader() : anchor.GetSeekFooter();
|
||||
i64 diff = seek - tkey->rng.start;
|
||||
if (diff > 0 && (u64)diff < best_anchor_diff) {
|
||||
best_anchor_idx = i;
|
||||
best_anchor = &anchor;
|
||||
best_anchor_diff = diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (best_anchor_idx >= 0) {
|
||||
found_sec[best_anchor_idx] = true;
|
||||
Section *sec_header = push_section(arena, tfile_data, sec_id);
|
||||
sec_header->range.start = tkey->rng.start + tkey->rng.len;
|
||||
sec_header->range.len = sec_id == Sec_RNTuple_Header ? best_anchor->GetNBytesHeader() : best_anchor->GetNBytesFooter();
|
||||
sec_header->pre_size = tkey->rng.len;
|
||||
sec_header->post_size = 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (u64 i = 0; i < tfile_data.n_anchors; ++i) {
|
||||
if (!found[0][i]) {
|
||||
fprintf(stderr, "Didn't found header for RNTuple %" PRIu64 "\n", i);
|
||||
}
|
||||
if (!found[1][i]) {
|
||||
fprintf(stderr, "Didn't found footer for RNTuple %" PRIu64 "\n", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -408,17 +457,8 @@ b8 get_tfile_data(Arena *arena, const Inspected_File &file, u32 walk_tkeys_flags
|
|||
{
|
||||
b8 success = walk_tkeys(arena, file.mem, file.size, walk_tkeys_flags, tfile_data);
|
||||
if (success) {
|
||||
// If we weren't given a rntuple name, use the first one in the file (if any)
|
||||
if (!ntpl_name.size && tfile_data.tkeys_data.rntuples)
|
||||
ntpl_name = tfile_data.tkeys_data.rntuples->name;
|
||||
|
||||
if (ntpl_name.size) {
|
||||
// Since the RNTuple Header and Footer key headers are not pointed to by anything, nor is their size known,
|
||||
// the only way to robustly get their offset and len is to go through all RBlobs and see which ones are immediately
|
||||
// before the (known) Header and Footer payloads.
|
||||
// FIXME :multiple_anchors: should not use anchors_head->anchor!!! This assumes we have exactly 1 anchor!
|
||||
map_rntuple_rblobs(tfile_data.anchors_head->anchor, tfile_data.tkeys_data);
|
||||
}
|
||||
// TODO: if ntpl_name is non-empty, only pick the given RNTuple
|
||||
map_rntuple_rblobs(arena, tfile_data);
|
||||
} else {
|
||||
fprintf(stderr, "Error: failed to walk TFile keys.\n");
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue