diff --git a/src/argparse.cpp b/src/argparse.cpp index 147c50b..c1dc151 100644 --- a/src/argparse.cpp +++ b/src/argparse.cpp @@ -4,7 +4,7 @@ void print_help(const char *argv0) fprintf(stderr, "rntviewer v" V_MAJOR "." V_MINOR " by silverweed" "\n" - "\nUsage: %s [-ehknRtv] [-s START] [-l LEN] [-w WIDTH] <ntuple_file.root> [ntuple_name]" + "\nUsage: %s [-ehknRtv] [-s START] [-l LEN] [-w WIDTH] <ntuple_file.root> [ntuple_name[;cycle]]" "\n\t-R: disable highlighting of non-RNTuple ROOT objects" "\n\t-e: display some extended info(*) (may slow down the startup)" "\n\t-h: display this help and exit" diff --git a/src/hover.cpp b/src/hover.cpp index c61ea0e..862de0b 100644 --- a/src/hover.cpp +++ b/src/hover.cpp @@ -385,7 +385,7 @@ struct Sec_Hover_Fn { return push_str8_node_child(arena, prev, fmt, name); }); range("Envelope size: %s", 6, [] (Arena *arena, String8_Node *prev, const char *fmt, const u8 *payload, u64) { - u64 size; + u64 size = 0; memcpy(&size, payload, 6); return push_str8_node_child(arena, prev, fmt, to_pretty_size(arena, size).c()); }); diff --git a/src/render.cpp b/src/render.cpp index 3be6513..6b18a95 100644 --- a/src/render.cpp +++ b/src/render.cpp @@ -154,17 +154,19 @@ void init_viewer(Arena *arena, App_State &app, u16 n_cols) String8 ntpl_desc = rntuple_description(scratch.arena, anchor->anchor); if (rntuple_is_old_version(anchor->anchor)) { viewer.col_title[0] = 1.f; - viewer.title = push_str8f(arena, "\"%s\" (%s) from file \"%s\" ** old version, some data missing! **", - anchor->name.c(), ntpl_desc.c(), app.inspected_file.name.c()); + viewer.title = push_str8f(arena, "\"%s;%u\" (%s) from file \"%s\" ** old version, some data missing! **", + anchor->name.c(), anchor->cycle, ntpl_desc.c(), app.inspected_file.name.c()); } else { viewer.col_title[0] = viewer.col_title[1] = viewer.col_title[2] = 1.f; - viewer.title = push_str8f(arena, "\"%s\" (%s) from file \"%s\"", anchor->name.c(), ntpl_desc.c(), app.inspected_file.name.c()); + viewer.title = push_str8f(arena, "\"%s;%u\" (%s) from file \"%s\"", anchor->name.c(), anchor->cycle, + ntpl_desc.c(), app.inspected_file.name.c()); } } else { String8 title = str8("RNTuples"); for (Section *sec = app.tfile_data.sections[Sec_RNTuple_Anchor].head; sec; sec = sec->next) { const RNTuple_Anchor_Info *anchor = (const RNTuple_Anchor_Info *)sec->info; - title = str8_concat(scratch.arena, title, push_str8f(scratch.arena, " \"%s\",", anchor->name)); + String8 s = push_str8f(scratch.arena, " \"%s;%hu\",", anchor->name, anchor->cycle); + title = str8_concat(scratch.arena, title, s); } title.size -= 1; // strip trailing comma title = str8_concat(scratch.arena, title, push_str8f(scratch.arena, " from file \"%s\"", app.inspected_file.name.c())); diff --git a/src/rntuple.cpp b/src/rntuple.cpp index 754999a..b16e8e2 100644 --- a/src/rntuple.cpp +++ b/src/rntuple.cpp @@ -242,7 +242,8 @@ RNTuple_Data get_rntuple_data(Arena *arena, const Inspected_File &file, const TF tot_page_list_size += plist_locator.GetNBytesOnStorage(); } - fprintf(stderr, "Loading pages from %s...\n", descriptor.GetName().c_str()); + const RNTuple_Anchor_Info *ntuple_info = (const RNTuple_Anchor_Info *)sec_anchor->info; + fprintf(stderr, "Loading pages from \"%s;%u\"...\n", ntuple_info->name.c(), ntuple_info->cycle); u64 clusters_first_idx = n_clusters; diff --git a/src/rntuple.h b/src/rntuple.h index fb804a5..3146e08 100644 --- a/src/rntuple.h +++ b/src/rntuple.h @@ -120,6 +120,7 @@ struct Byte_Range_Node { struct RNTuple_Anchor_Info { String8 name; + u16 cycle; u64 offset_in_file; ROOT::RNTuple anchor; }; diff --git a/src/tfile.cpp b/src/tfile.cpp index c3ece5b..b0a37a9 100644 --- a/src/tfile.cpp +++ b/src/tfile.cpp @@ -148,6 +148,7 @@ b8 walk_tkeys(Arena *arena, const u8 *data, u64 data_len, u32 flags, TFile_Data const u64 key_version_off = 4; const u64 keylen_off = 14; + const u64 cycle_off = 16; // Store information about where we will start walking through the tkeys. u32 tfile_obj_nbytes = read_be<u32>(data + cur); @@ -271,12 +272,35 @@ b8 walk_tkeys(Arena *arena, const u8 *data, u64 data_len, u32 flags, TFile_Data u64 name_off = cname_off + cname_len + 1; u8 name_len = data[name_off]; const char *rntuple_name = (const char *)data + name_off + 1; - if (!ntpl_name.size || strncmp((const char *)ntpl_name.str, rntuple_name, name_len) == 0) { + u16 cycle_on_disk = read_be<u16>(data + cur + cycle_off); + // Check if this needs to be filtered out (i.e. if `ntpl_name` is non-empty and doesn't match it. + // The cycle may also be included in the criteria if the name ends with `;N`) + b8 consider_ntuple = true; + if (ntpl_name.size) { + if (ntpl_name.size) { + i32 semicolon_idx = -1; + for (i64 i = ntpl_name.size - 1; i >= 0; --i) { + if (ntpl_name.str[i] == ';') { + semicolon_idx = i; + break; + } + } + if (semicolon_idx >= 0) { + // compare cycle + u16 cycle_wanted = atoi(ntpl_name.c() + semicolon_idx + 1); + consider_ntuple = (cycle_on_disk == cycle_wanted); + name_len = semicolon_idx; + } + consider_ntuple = consider_ntuple && strncmp((const char *)ntpl_name.str, rntuple_name, name_len) == 0; + } + } + if (consider_ntuple) { RNTuple_Anchor_Info *rntuple_info = arena_push<RNTuple_Anchor_Info>(arena); rntuple_info->offset_in_file = cur; if (name_len) { rntuple_info->name = str8_from_buf(arena, data + name_off + 1, name_len); } + rntuple_info->cycle = cycle_on_disk; u64 anchor_seek = cur + keylen; RNTuple_Anchor_On_Disk anchor;