From 5923ac4360274075586f70e1cba010dd0789f2c1 Mon Sep 17 00:00:00 2001 From: silverweed Date: Thu, 18 Jul 2024 15:32:32 +0200 Subject: [PATCH] parse root version --- src/app_state.h | 5 +++-- src/platform_linux.h | 2 +- src/render.cpp | 22 +++++++++++++++----- src/render.h | 3 ++- src/rntuple.cpp | 39 ++++++++++++++++++++++++++++------- src/rntuple.h | 9 +++++++- src/rntviewer.cpp | 6 ++++-- src/root/RMicroFileReader.cxx | 17 ++++++++++++--- src/root/RMicroFileReader.hxx | 9 +++++++- src/str.h | 2 +- 10 files changed, 90 insertions(+), 24 deletions(-) diff --git a/src/app_state.h b/src/app_state.h index 7329e2c..7b09dcb 100644 --- a/src/app_state.h +++ b/src/app_state.h @@ -10,7 +10,7 @@ struct Inspected_File { u8 *mem; u64 size; - const char *name; + String8 name; // @Platform: inotify file descriptor int inot; @@ -20,10 +20,11 @@ struct App_State { Window_Data win_data; User_Input user_input; RNTuple_Data rndata; + TFile_Data tfile_data; Viewer viewer; Inspected_File inspected_file; - const char *ntpl_name; + String8 ntpl_name; Delta_Time_Accum delta_time_accum; diff --git a/src/platform_linux.h b/src/platform_linux.h index d4282c9..364b40e 100644 --- a/src/platform_linux.h +++ b/src/platform_linux.h @@ -25,7 +25,7 @@ bool os_open_and_map_file(const char *fname, App_State &app) if (!fmem) fprintf(stderr, "Failed to open file %s\n", fname); - app.inspected_file.name = fname; + app.inspected_file.name = str8(fname); app.inspected_file.stream = file; app.inspected_file.size = fsize; app.inspected_file.mem = reinterpret_cast(fmem); diff --git a/src/render.cpp b/src/render.cpp index 0fa8b8c..afdfa82 100644 --- a/src/render.cpp +++ b/src/render.cpp @@ -35,13 +35,15 @@ u32 mem_edit_bg_color_fn(const u8 *, u64 off, void *user_data) { App_State *app = reinterpret_cast(user_data); const RNTuple_Data &rdata = app->rndata; + const TFile_Data &tdata = app->tfile_data; u64 rblob_sz = rdata.rblob_header_size; // @Incomplete off += app->viewer.base_display_addr; #define COL(c) (ImColor((c)[0], (c)[1], (c)[2])) // TFile start - if (off <= rdata.root_file_header_size) return COL(app->viewer.col_tfile); + if (off <= tdata.root_file_header_size) return COL(app->viewer.col_tfile_header); + if (tdata.rng_root_file_obj.start <= off && off < tdata.rng_root_file_obj.end()) return COL(app->viewer.col_tfile_obj); // Handle pages // fast case: `off` is in the same page info as previous `off`. @@ -135,7 +137,8 @@ void make_viewer(App_State &app) COL(col_header, 150, 0, 50); COL(col_footer, 50, 0, 150); COL(col_key, 0, 100, 50); - COL(col_tfile, 90, 90, 90); + COL(col_tfile_header, 90, 90, 90); + COL(col_tfile_obj, 120, 120, 120); COL(col_page, 125, 0, 125); COL(col_page_start, 200, 0, 200); COL(col_checksum, 134, 65, 25); @@ -184,7 +187,7 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms) if (ImGui::Begin("main", nullptr, main_win_flags)) { String8 ntpl_desc = rntuple_description(scratch.arena, app.rndata); - ImGui::Text("RNTuple '%s' (%s) from file \"%s\"", app.ntpl_name, ntpl_desc.c(), app.inspected_file.name); + ImGui::Text("RNTuple '%s' (%s) from file \"%s\"", app.ntpl_name.c(), ntpl_desc.c(), app.inspected_file.name.c()); // Draw stats { @@ -222,9 +225,13 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms) ImGui::TableNextColumn(); ImGuiColorEditFlags flags = ImGuiColorEditFlags_NoInputs|ImGuiColorEditFlags_NoLabel; - ImGui::ColorEdit3("_TFile", app.viewer.col_tfile, flags); + ImGui::ColorEdit3("_TFile Header", app.viewer.col_tfile_header, flags); ImGui::SameLine(); - if (ImGui::Button("TFile")) viewer_jump_to(app.viewer, 0); + if (ImGui::Button("TFile Header")) viewer_jump_to(app.viewer, 0); + + ImGui::ColorEdit3("_TFile Object", app.viewer.col_tfile_obj, flags); + ImGui::SameLine(); + if (ImGui::Button("TFile Object")) viewer_jump_to(app.viewer, app.tfile_data.rng_root_file_obj.start); ImGui::ColorEdit3("_RNTuple Anchor", app.viewer.col_anchor, flags); ImGui::SameLine(); @@ -278,6 +285,11 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms) ImGui::Text("%s", to_pretty_size(scratch.arena, app.rndata.tot_page_list_size).c()); ImGui::Separator(); + String8 root_version_str = push_str8f(scratch.arena, "%u.%u.%u", + app.tfile_data.root_version_major, + app.tfile_data.root_version_minor, + app.tfile_data.root_version_patch); + ImGui::Text("ROOT version: %s", root_version_str.c()); ImGui::Text("Num pages: %lu", app.rndata.n_pages); ImGui::Text("Num elements: %lu", app.rndata.n_elems); diff --git a/src/render.h b/src/render.h index 664e2e6..7b0d7f2 100644 --- a/src/render.h +++ b/src/render.h @@ -5,7 +5,8 @@ struct Viewer { f32 col_header[3]; f32 col_footer[3]; f32 col_key[3]; - f32 col_tfile[3]; + f32 col_tfile_header[3]; + f32 col_tfile_obj[3]; f32 col_page[3]; f32 col_page_start[3]; f32 col_checksum[3]; diff --git a/src/rntuple.cpp b/src/rntuple.cpp index f0ab40c..594c4b8 100644 --- a/src/rntuple.cpp +++ b/src/rntuple.cpp @@ -63,7 +63,7 @@ ROOT::Experimental::RNTupleDescriptor create_descriptor(Arena *arena, RMicroFile } internal -void gather_metadata(Arena *arena, RMicroFileReader &reader, const RNTuple_File_Info &info, RNTuple_Data &rndata) +void gather_ntuple_metadata(Arena *arena, RMicroFileReader &reader, const RNTuple_File_Info &info, RNTuple_Data &rndata) { using namespace ROOT::Experimental; using namespace ROOT::Experimental::Internal; @@ -230,13 +230,39 @@ void gather_metadata(Arena *arena, RMicroFileReader &reader, const RNTuple_File_ } internal -RNTuple_Data get_rntuple_data(Arena *arena, const char *fname, const char *ntpl_name) +TFile_Data get_tfile_data(const Inspected_File &file) +{ + TFile_Data tfile_data{}; + + Root_File_Info root_file_info = get_root_file_info(file.name.c()); + tfile_data.root_file_header_size = root_file_info.tfile_header_nbytes; + tfile_data.rng_root_file_obj.start = root_file_info.tfile_obj_seek; + tfile_data.rng_root_file_obj.len = root_file_info.tfile_obj_nbytes; + + // parse root version + const u64 len_root_magic = 4; + assert(file.size > len_root_magic + sizeof(u32)); + u32 version_be; + memcpy(&version_be, file.mem + len_root_magic, sizeof(version_be)); + u32 version = bswap_32(version_be); + u32 version_major = version / 10000; + u32 version_minor = (version - version_major * 10000) / 100; + u32 version_patch = (version - version_major * 10000 - version_minor * 100); + tfile_data.root_version_major = (u16)version_major; + tfile_data.root_version_minor = (u16)version_minor; + tfile_data.root_version_patch = (u16)version_patch; + + return tfile_data; +} + +internal +RNTuple_Data get_rntuple_data(Arena *arena, const Inspected_File &file, String8 ntpl_name) { - RNTuple_Data rndata = {}; + RNTuple_Data rndata {}; // TODO: proper error handling - RMicroFileReader file_reader { fname }; - RNTuple_File_Info file_info = file_reader.GetNTupleProper(ntpl_name); + RMicroFileReader file_reader { file.name.c() }; + RNTuple_File_Info file_info = file_reader.GetNTupleProper(ntpl_name.c()); if (!file_info.failed) { rndata.version.epoch = file_info.anchor.fVersionEpoch; rndata.version.major = file_info.anchor.fVersionMajor; @@ -251,9 +277,8 @@ RNTuple_Data get_rntuple_data(Arena *arena, const char *fname, const char *ntpl_ rndata.rng_anchor_key.start = file_info.anchor_key_seek; rndata.rng_anchor_key.len = file_info.anchor_key_nbytes; rndata.rblob_header_size = file_info.rblob_key_header_nbytes; - rndata.root_file_header_size = file_info.tfile_header_nbytes; - gather_metadata(arena, file_reader, file_info, rndata); + gather_ntuple_metadata(arena, file_reader, file_info, rndata); } return rndata; diff --git a/src/rntuple.h b/src/rntuple.h index 5c4dce6..21dbb8a 100644 --- a/src/rntuple.h +++ b/src/rntuple.h @@ -37,12 +37,19 @@ struct Cluster_Group_Info { Byte_Range rng_page_list; }; +struct TFile_Data { + u64 root_file_header_size; + Byte_Range rng_root_file_obj; + u16 root_version_major; + u16 root_version_minor; + u16 root_version_patch; +}; + struct RNTuple_Data { struct { u16 epoch, major, minor, patch; } version; - u64 root_file_header_size; u64 rblob_header_size; Byte_Range rng_anchor; Byte_Range rng_anchor_key; diff --git a/src/rntviewer.cpp b/src/rntviewer.cpp index bdce714..4dd58c2 100644 --- a/src/rntviewer.cpp +++ b/src/rntviewer.cpp @@ -13,6 +13,7 @@ #include #include +#include #include // for std::forward #include @@ -124,8 +125,9 @@ int main(int argc, char **argv) os_start_file_watch(fname, app); } - app.ntpl_name = ntpl_name; - app.rndata = get_rntuple_data(arena, fname, ntpl_name); + app.ntpl_name = str8(ntpl_name); + app.tfile_data = get_tfile_data(app.inspected_file); + app.rndata = get_rntuple_data(arena, app.inspected_file, app.ntpl_name); make_viewer(app); // Start main loop diff --git a/src/root/RMicroFileReader.cxx b/src/root/RMicroFileReader.cxx index 9e92431..0e0ec11 100644 --- a/src/root/RMicroFileReader.cxx +++ b/src/root/RMicroFileReader.cxx @@ -1068,17 +1068,29 @@ static size_t ComputeNumChunks(size_t nbytes, size_t maxChunkSize) // PUBLIC INTERFACE // ========================================================================================= +Root_File_Info get_root_file_info(const char *fname) +{ + RTFString fileName { fname }; + Root_File_Info fileInfo {}; + fileInfo.tfile_header_nbytes = RTFHeader{}.GetSize(); + fileInfo.tfile_obj_seek = 100; // kBEGIN + fileInfo.tfile_obj_nbytes = sizeof(RTFFile) + fileName.GetSize() + RTFString{}.GetSize() + RTFUUID{}.GetSize(); + return fileInfo; +} + struct RMicroFileReader::Impl { std::unique_ptr fRawFile; std::uint64_t fMaxBlobSize = 0; }; -RMicroFileReader::RMicroFileReader(const char *fname) { +RMicroFileReader::RMicroFileReader(const char *fname) +{ impl = new Impl; impl->fRawFile = ROOT::Internal::RRawFile::Create(fname); } -RMicroFileReader::~RMicroFileReader() { +RMicroFileReader::~RMicroFileReader() +{ delete impl; } @@ -1183,7 +1195,6 @@ RMicroFileReader::GetNTupleProper(const char *ntupleName) dummy.MakeBigKey(); fileInfo.rblob_key_header_nbytes = dummy.GetHeaderSize(); } - fileInfo.tfile_header_nbytes = RTFHeader{}.GetSize(); // @---- ReadBuffer(ntuple, objNbytes, offset); if (objNbytes != key.fObjLen) { diff --git a/src/root/RMicroFileReader.hxx b/src/root/RMicroFileReader.hxx index db802b8..67a8331 100644 --- a/src/root/RMicroFileReader.hxx +++ b/src/root/RMicroFileReader.hxx @@ -38,9 +38,16 @@ struct RNTuple_File_Info { std::uint64_t anchor_key_seek; std::uint64_t anchor_key_nbytes; std::uint64_t rblob_key_header_nbytes; - std::uint64_t tfile_header_nbytes; }; +struct Root_File_Info { + std::uint64_t tfile_header_nbytes; + std::uint64_t tfile_obj_seek; + std::uint64_t tfile_obj_nbytes; +}; + +Root_File_Info get_root_file_info(const char *fname); + class RMicroFileReader final { public: explicit RMicroFileReader(const char *fname); diff --git a/src/str.h b/src/str.h index fd81c54..8c88a4d 100644 --- a/src/str.h +++ b/src/str.h @@ -5,6 +5,6 @@ struct String8 { const char *c() const { return reinterpret_cast(str); } }; -#define str8(s) String8((u8*)(s), sizeof(s) - 1) +#define str8(s) String8 { (u8*)(s), sizeof(s) - 1 } String8 push_str8f(Arena *arena, char *fmt, ...);