parse root version

This commit is contained in:
silverweed 2024-07-18 15:32:32 +02:00
parent d177ea66a8
commit 5923ac4360
10 changed files with 90 additions and 24 deletions

View file

@ -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;

View file

@ -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<u8*>(fmem);

View file

@ -35,13 +35,15 @@ u32 mem_edit_bg_color_fn(const u8 *, u64 off, void *user_data)
{
App_State *app = reinterpret_cast<App_State *>(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);

View file

@ -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];

View file

@ -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)
{
RNTuple_Data rndata = {};
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 {};
// 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;

View file

@ -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;

View file

@ -13,6 +13,7 @@
#include <cstdio>
#include <cstdint>
#include <byteswap.h>
#include <utility> // for std::forward
#include <chrono>
@ -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

View file

@ -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<ROOT::Internal::RRawFile> 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) {

View file

@ -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);

View file

@ -5,6 +5,6 @@ struct String8 {
const char *c() const { return reinterpret_cast<const char *>(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, ...);