parse root version
This commit is contained in:
parent
d177ea66a8
commit
5923ac4360
10 changed files with 90 additions and 24 deletions
|
@ -10,7 +10,7 @@ struct Inspected_File {
|
||||||
u8 *mem;
|
u8 *mem;
|
||||||
u64 size;
|
u64 size;
|
||||||
|
|
||||||
const char *name;
|
String8 name;
|
||||||
|
|
||||||
// @Platform: inotify file descriptor
|
// @Platform: inotify file descriptor
|
||||||
int inot;
|
int inot;
|
||||||
|
@ -20,10 +20,11 @@ struct App_State {
|
||||||
Window_Data win_data;
|
Window_Data win_data;
|
||||||
User_Input user_input;
|
User_Input user_input;
|
||||||
RNTuple_Data rndata;
|
RNTuple_Data rndata;
|
||||||
|
TFile_Data tfile_data;
|
||||||
Viewer viewer;
|
Viewer viewer;
|
||||||
Inspected_File inspected_file;
|
Inspected_File inspected_file;
|
||||||
|
|
||||||
const char *ntpl_name;
|
String8 ntpl_name;
|
||||||
|
|
||||||
Delta_Time_Accum delta_time_accum;
|
Delta_Time_Accum delta_time_accum;
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ bool os_open_and_map_file(const char *fname, App_State &app)
|
||||||
if (!fmem)
|
if (!fmem)
|
||||||
fprintf(stderr, "Failed to open file %s\n", fname);
|
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.stream = file;
|
||||||
app.inspected_file.size = fsize;
|
app.inspected_file.size = fsize;
|
||||||
app.inspected_file.mem = reinterpret_cast<u8*>(fmem);
|
app.inspected_file.mem = reinterpret_cast<u8*>(fmem);
|
||||||
|
|
|
@ -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);
|
App_State *app = reinterpret_cast<App_State *>(user_data);
|
||||||
const RNTuple_Data &rdata = app->rndata;
|
const RNTuple_Data &rdata = app->rndata;
|
||||||
|
const TFile_Data &tdata = app->tfile_data;
|
||||||
u64 rblob_sz = rdata.rblob_header_size; // @Incomplete
|
u64 rblob_sz = rdata.rblob_header_size; // @Incomplete
|
||||||
|
|
||||||
off += app->viewer.base_display_addr;
|
off += app->viewer.base_display_addr;
|
||||||
|
|
||||||
#define COL(c) (ImColor((c)[0], (c)[1], (c)[2]))
|
#define COL(c) (ImColor((c)[0], (c)[1], (c)[2]))
|
||||||
// TFile start
|
// 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
|
// Handle pages
|
||||||
// fast case: `off` is in the same page info as previous `off`.
|
// 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_header, 150, 0, 50);
|
||||||
COL(col_footer, 50, 0, 150);
|
COL(col_footer, 50, 0, 150);
|
||||||
COL(col_key, 0, 100, 50);
|
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, 125, 0, 125);
|
||||||
COL(col_page_start, 200, 0, 200);
|
COL(col_page_start, 200, 0, 200);
|
||||||
COL(col_checksum, 134, 65, 25);
|
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)) {
|
if (ImGui::Begin("main", nullptr, main_win_flags)) {
|
||||||
|
|
||||||
String8 ntpl_desc = rntuple_description(scratch.arena, app.rndata);
|
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
|
// Draw stats
|
||||||
{
|
{
|
||||||
|
@ -222,9 +225,13 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms)
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGuiColorEditFlags flags = ImGuiColorEditFlags_NoInputs|ImGuiColorEditFlags_NoLabel;
|
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();
|
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::ColorEdit3("_RNTuple Anchor", app.viewer.col_anchor, flags);
|
||||||
ImGui::SameLine();
|
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::Text("%s", to_pretty_size(scratch.arena, app.rndata.tot_page_list_size).c());
|
||||||
|
|
||||||
ImGui::Separator();
|
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 pages: %lu", app.rndata.n_pages);
|
||||||
ImGui::Text("Num elements: %lu", app.rndata.n_elems);
|
ImGui::Text("Num elements: %lu", app.rndata.n_elems);
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@ struct Viewer {
|
||||||
f32 col_header[3];
|
f32 col_header[3];
|
||||||
f32 col_footer[3];
|
f32 col_footer[3];
|
||||||
f32 col_key[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[3];
|
||||||
f32 col_page_start[3];
|
f32 col_page_start[3];
|
||||||
f32 col_checksum[3];
|
f32 col_checksum[3];
|
||||||
|
|
|
@ -63,7 +63,7 @@ ROOT::Experimental::RNTupleDescriptor create_descriptor(Arena *arena, RMicroFile
|
||||||
}
|
}
|
||||||
|
|
||||||
internal
|
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;
|
||||||
using namespace ROOT::Experimental::Internal;
|
using namespace ROOT::Experimental::Internal;
|
||||||
|
@ -230,13 +230,39 @@ void gather_metadata(Arena *arena, RMicroFileReader &reader, const RNTuple_File_
|
||||||
}
|
}
|
||||||
|
|
||||||
internal
|
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
|
// TODO: proper error handling
|
||||||
RMicroFileReader file_reader { fname };
|
RMicroFileReader file_reader { file.name.c() };
|
||||||
RNTuple_File_Info file_info = file_reader.GetNTupleProper(ntpl_name);
|
RNTuple_File_Info file_info = file_reader.GetNTupleProper(ntpl_name.c());
|
||||||
if (!file_info.failed) {
|
if (!file_info.failed) {
|
||||||
rndata.version.epoch = file_info.anchor.fVersionEpoch;
|
rndata.version.epoch = file_info.anchor.fVersionEpoch;
|
||||||
rndata.version.major = file_info.anchor.fVersionMajor;
|
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.start = file_info.anchor_key_seek;
|
||||||
rndata.rng_anchor_key.len = file_info.anchor_key_nbytes;
|
rndata.rng_anchor_key.len = file_info.anchor_key_nbytes;
|
||||||
rndata.rblob_header_size = file_info.rblob_key_header_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;
|
return rndata;
|
||||||
|
|
|
@ -37,12 +37,19 @@ struct Cluster_Group_Info {
|
||||||
Byte_Range rng_page_list;
|
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 RNTuple_Data {
|
||||||
struct {
|
struct {
|
||||||
u16 epoch, major, minor, patch;
|
u16 epoch, major, minor, patch;
|
||||||
} version;
|
} version;
|
||||||
|
|
||||||
u64 root_file_header_size;
|
|
||||||
u64 rblob_header_size;
|
u64 rblob_header_size;
|
||||||
Byte_Range rng_anchor;
|
Byte_Range rng_anchor;
|
||||||
Byte_Range rng_anchor_key;
|
Byte_Range rng_anchor_key;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <byteswap.h>
|
||||||
#include <utility> // for std::forward
|
#include <utility> // for std::forward
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
|
@ -124,8 +125,9 @@ int main(int argc, char **argv)
|
||||||
os_start_file_watch(fname, app);
|
os_start_file_watch(fname, app);
|
||||||
}
|
}
|
||||||
|
|
||||||
app.ntpl_name = ntpl_name;
|
app.ntpl_name = str8(ntpl_name);
|
||||||
app.rndata = get_rntuple_data(arena, fname, 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);
|
make_viewer(app);
|
||||||
|
|
||||||
// Start main loop
|
// Start main loop
|
||||||
|
|
|
@ -1068,17 +1068,29 @@ static size_t ComputeNumChunks(size_t nbytes, size_t maxChunkSize)
|
||||||
// PUBLIC INTERFACE
|
// 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 {
|
struct RMicroFileReader::Impl {
|
||||||
std::unique_ptr<ROOT::Internal::RRawFile> fRawFile;
|
std::unique_ptr<ROOT::Internal::RRawFile> fRawFile;
|
||||||
std::uint64_t fMaxBlobSize = 0;
|
std::uint64_t fMaxBlobSize = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
RMicroFileReader::RMicroFileReader(const char *fname) {
|
RMicroFileReader::RMicroFileReader(const char *fname)
|
||||||
|
{
|
||||||
impl = new Impl;
|
impl = new Impl;
|
||||||
impl->fRawFile = ROOT::Internal::RRawFile::Create(fname);
|
impl->fRawFile = ROOT::Internal::RRawFile::Create(fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
RMicroFileReader::~RMicroFileReader() {
|
RMicroFileReader::~RMicroFileReader()
|
||||||
|
{
|
||||||
delete impl;
|
delete impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1183,7 +1195,6 @@ RMicroFileReader::GetNTupleProper(const char *ntupleName)
|
||||||
dummy.MakeBigKey();
|
dummy.MakeBigKey();
|
||||||
fileInfo.rblob_key_header_nbytes = dummy.GetHeaderSize();
|
fileInfo.rblob_key_header_nbytes = dummy.GetHeaderSize();
|
||||||
}
|
}
|
||||||
fileInfo.tfile_header_nbytes = RTFHeader{}.GetSize();
|
|
||||||
// @----
|
// @----
|
||||||
ReadBuffer(ntuple, objNbytes, offset);
|
ReadBuffer(ntuple, objNbytes, offset);
|
||||||
if (objNbytes != key.fObjLen) {
|
if (objNbytes != key.fObjLen) {
|
||||||
|
|
|
@ -38,9 +38,16 @@ struct RNTuple_File_Info {
|
||||||
std::uint64_t anchor_key_seek;
|
std::uint64_t anchor_key_seek;
|
||||||
std::uint64_t anchor_key_nbytes;
|
std::uint64_t anchor_key_nbytes;
|
||||||
std::uint64_t rblob_key_header_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 {
|
class RMicroFileReader final {
|
||||||
public:
|
public:
|
||||||
explicit RMicroFileReader(const char *fname);
|
explicit RMicroFileReader(const char *fname);
|
||||||
|
|
|
@ -5,6 +5,6 @@ struct String8 {
|
||||||
const char *c() const { return reinterpret_cast<const char *>(str); }
|
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, ...);
|
String8 push_str8f(Arena *arena, char *fmt, ...);
|
||||||
|
|
Loading…
Reference in a new issue