Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RPageStorageS3.cxx
Go to the documentation of this file.
1/// \file RPageStorageS3.cxx
2/// \author Jas Mehta <jasmehta805@gmail.com>
3/// \date 2026-06-01
4
5/*************************************************************************
6 * Copyright (C) 1995-2026, Rene Brun and Fons Rademakers. *
7 * All rights reserved. *
8 * *
9 * For the licensing terms see $ROOTSYS/LICENSE. *
10 * For the list of contributors see $ROOTSYS/README/CREDITS. *
11 *************************************************************************/
12
14
15#include <nlohmann/json.hpp>
16
17#include <string>
18
19/// Field-by-field equality check across all 14 anchor members.
20/// Used to verify round-trip correctness in tests.
22{
23 return fVersionAnchor == other.fVersionAnchor && fVersionEpoch == other.fVersionEpoch &&
24 fVersionMajor == other.fVersionMajor && fVersionMinor == other.fVersionMinor &&
25 fVersionPatch == other.fVersionPatch && fUrlTemplate == other.fUrlTemplate &&
26 fHeaderObjId == other.fHeaderObjId && fHeaderOffset == other.fHeaderOffset &&
27 fNBytesHeader == other.fNBytesHeader && fLenHeader == other.fLenHeader &&
28 fFooterObjId == other.fFooterObjId && fFooterOffset == other.fFooterOffset &&
29 fNBytesFooter == other.fNBytesFooter && fLenFooter == other.fLenFooter;
30}
31
32/// Serialize the anchor to a pretty-printed JSON string (2-space indent).
33/// nlohmann/json handles type conversion, string escaping, and uint64 precision.
34/// The output is suitable for direct upload to S3 as the anchor object.
36{
37 nlohmann::json jsonAnchor;
38 jsonAnchor["anchorVersion"] = fVersionAnchor;
39 jsonAnchor["formatVersionEpoch"] = fVersionEpoch;
40 jsonAnchor["formatVersionMajor"] = fVersionMajor;
41 jsonAnchor["formatVersionMinor"] = fVersionMinor;
42 jsonAnchor["formatVersionPatch"] = fVersionPatch;
43 jsonAnchor["urlTemplate"] = fUrlTemplate;
44 jsonAnchor["headerObjId"] = fHeaderObjId;
45 jsonAnchor["headerOffset"] = fHeaderOffset;
46 jsonAnchor["nBytesHeader"] = fNBytesHeader;
47 jsonAnchor["lenHeader"] = fLenHeader;
48 jsonAnchor["footerObjId"] = fFooterObjId;
49 jsonAnchor["footerOffset"] = fFooterOffset;
50 jsonAnchor["nBytesFooter"] = fNBytesFooter;
51 jsonAnchor["lenFooter"] = fLenFooter;
52 return jsonAnchor.dump(2);
53}
54
55/// Construct an anchor from a JSON string.
56/// The anchor version is checked first; if it does not match the current version,
57/// parsing fails immediately. All remaining fields are extracted with jsonAnchor.at()
58/// which throws on missing keys or type mismatches.
61{
62 nlohmann::json jsonAnchor;
63 try {
64 jsonAnchor = nlohmann::json::parse(json);
65 } catch (const nlohmann::json::parse_error &e) {
66 return R__FAIL("cannot parse S3 anchor JSON: " + std::string(e.what()));
67 }
68
70
71 try {
72 anchor.fVersionAnchor = jsonAnchor.at("anchorVersion").get<std::uint32_t>();
73 } catch (const nlohmann::json::exception &e) {
74 return R__FAIL("missing or invalid 'anchorVersion' in S3 anchor: " + std::string(e.what()));
75 }
76
77 if (anchor.fVersionAnchor != RNTupleAnchorS3().fVersionAnchor)
78 return R__FAIL("unsupported S3 anchor version: " + std::to_string(anchor.fVersionAnchor));
79
80 try {
81 anchor.fVersionEpoch = jsonAnchor.at("formatVersionEpoch").get<std::uint16_t>();
82 anchor.fVersionMajor = jsonAnchor.at("formatVersionMajor").get<std::uint16_t>();
83 anchor.fVersionMinor = jsonAnchor.at("formatVersionMinor").get<std::uint16_t>();
84 anchor.fVersionPatch = jsonAnchor.at("formatVersionPatch").get<std::uint16_t>();
85 anchor.fUrlTemplate = jsonAnchor.at("urlTemplate").get<std::string>();
86 anchor.fHeaderObjId = jsonAnchor.at("headerObjId").get<std::uint64_t>();
87 anchor.fHeaderOffset = jsonAnchor.at("headerOffset").get<std::uint64_t>();
88 anchor.fNBytesHeader = jsonAnchor.at("nBytesHeader").get<std::uint64_t>();
89 anchor.fLenHeader = jsonAnchor.at("lenHeader").get<std::uint64_t>();
90 anchor.fFooterObjId = jsonAnchor.at("footerObjId").get<std::uint64_t>();
91 anchor.fFooterOffset = jsonAnchor.at("footerOffset").get<std::uint64_t>();
92 anchor.fNBytesFooter = jsonAnchor.at("nBytesFooter").get<std::uint64_t>();
93 anchor.fLenFooter = jsonAnchor.at("lenFooter").get<std::uint64_t>();
94 } catch (const nlohmann::json::exception &e) {
95 return R__FAIL("missing or invalid field in S3 anchor: " + std::string(e.what()));
96 }
97
98 return anchor;
99}
nlohmann::json json
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
Definition RError.hxx:299
#define e(i)
Definition RSha256.hxx:103
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
The class is used as a return type for operations that can fail; wraps a value of type T or an RError...
Definition RError.hxx:197
Entry point for an RNTuple stored in S3-compatible object storage.
bool operator==(const RNTupleAnchorS3 &other) const
Field-by-field equality check across all 14 anchor members.
std::uint64_t fHeaderObjId
Object ID and byte offset of the compressed header within the S3 object.
std::string fUrlTemplate
Pattern for resolving object IDs to full S3 URLs.
std::uint32_t fVersionAnchor
Allows evolving the anchor JSON schema in future versions.
std::uint16_t fVersionEpoch
Version of the RNTuple binary format supported by the writer.
std::uint64_t fNBytesHeader
Compressed and uncompressed sizes of the header envelope.
std::string ToJSON() const
Serialize the anchor to a JSON string suitable for storage at the base URL.
std::uint64_t fNBytesFooter
Compressed and uncompressed sizes of the footer envelope.
static RResult< RNTupleAnchorS3 > CreateFromJSON(const std::string &json)
Deserialize the anchor from a JSON string. Returns an error on malformed or incompatible input.
std::uint64_t fFooterObjId
Object ID and byte offset of the compressed footer within the S3 object.