15#include <ROOT/RCurlConnection.hxx>
23#include <nlohmann/json.hpp>
54 jsonAnchor[
"formatVersionEpoch"] = fVersionEpoch;
55 jsonAnchor[
"formatVersionMajor"] = fVersionMajor;
56 jsonAnchor[
"formatVersionMinor"] = fVersionMinor;
57 jsonAnchor[
"formatVersionPatch"] = fVersionPatch;
80 }
catch (
const nlohmann::json::parse_error &
e) {
81 return R__FAIL(
"cannot parse S3 anchor JSON: " + std::string(
e.what()));
88 }
catch (
const nlohmann::json::exception &
e) {
89 return R__FAIL(
"missing or invalid 'anchorVersion' in S3 anchor: " + std::string(
e.what()));
93 return R__FAIL(
"unsupported S3 anchor version: " + std::to_string(
anchor.fVersionAnchor));
96 anchor.fVersionEpoch =
jsonAnchor.at(
"formatVersionEpoch").get<std::uint16_t>();
97 anchor.fVersionMajor =
jsonAnchor.at(
"formatVersionMajor").get<std::uint16_t>();
98 anchor.fVersionMinor =
jsonAnchor.at(
"formatVersionMinor").get<std::uint16_t>();
99 anchor.fVersionPatch =
jsonAnchor.at(
"formatVersionPatch").get<std::uint16_t>();
109 }
catch (
const nlohmann::json::exception &
e) {
110 return R__FAIL(
"missing or invalid field in S3 anchor: " + std::string(
e.what()));
120 const std::string
uriStr(uri);
125 if (
uriStr.find_first_of(
"@?#") != std::string::npos)
126 return R__FAIL(
"S3 URI must not contain userinfo ('@'), a query ('?') or a fragment ('#'): " +
uriStr);
134 for (std::size_t i = 0; i <
uriStr.size() && i < std::strlen(
"ntpl+s3+https://"); ++i)
135 schemeLower.push_back(
static_cast<char>(std::tolower(
static_cast<unsigned char>(
uriStr[i]))));
141 schemeLen = std::strlen(
"ntpl+s3+https://");
144 schemeLen = std::strlen(
"ntpl+s3+http://");
146 return R__FAIL(
"invalid S3 URI (expected ntpl+s3+http:// or ntpl+s3+https://): " +
uriStr);
175 static std::once_flag
once;
176 std::call_once(
once, []() {
178 <<
"Do not store real data with this version of RNTuple!";
188 return fBaseUrl +
"/" + std::to_string(
objId);
196 fConnection.SetUrl(
url).ThrowOnError();
197 auto status = fConnection.SendPutReq(
data,
size);
217 fAnchor.fHeaderOffset = 0;
219 fAnchor.fLenHeader =
length;
230 PutObject(MakeObjectUrl(
pageObjId),
reinterpret_cast<const unsigned char *
>(
sealedPage.GetBuffer()),
238 fCounters->fNPageCommitted.Inc();
239 fCounters->fSzWritePayload.Add(
sealedPage.GetBufferSize());
240 fNBytesCurrentCluster +=
sealedPage.GetBufferSize();
246 return std::exchange(fNBytesCurrentCluster, 0);
257 const auto objId = fObjectId++;
267 fCounters->fSzWritePayload.Add(
static_cast<std::int64_t
>(
szPageListZip));
285 fAnchor.fFooterOffset = 0;
287 fAnchor.fLenFooter =
length;
292 PutObject(fBaseUrl,
reinterpret_cast<const unsigned char *
>(
anchorJson.data()),
anchorJson.size());
299std::unique_ptr<ROOT::Internal::RPageSink>
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
#define R__LOG_WARNING(...)
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h length
Storage provider that writes ntuple pages into S3-compatible object storage.
ROOT::Internal::RCurlConnection fConnection
One HTTP connection reused for every upload, so curl keeps it alive across objects on the same host i...
void InitImpl(unsigned char *serializedHeader, std::uint32_t length) final
std::uint64_t StageClusterImpl() final
Returns the number of bytes written to storage (excluding metadata)
RNTupleLocator CommitClusterGroupImpl(unsigned char *serializedPageList, std::uint32_t length) final
Returns the locator of the page list envelope of the given buffer that contains the serialized page l...
std::unique_ptr< ROOT::Internal::RPageSink > CloneAsHidden(std::string_view name, const ROOT::RNTupleWriteOptions &opts) const final
Creates a new sink with the same underlying storage as this but writing to a different RNTuple named ...
std::string MakeObjectUrl(std::uint64_t objId) const
Resolve a numeric object ID to its full HTTP URL.
RNTupleLocator CommitSealedPageImpl(ROOT::DescriptorId_t physicalColumnId, const RPageStorage::RSealedPage &sealedPage) final
RPageSinkS3(std::string_view ntupleName, std::string_view baseUrl, const ROOT::RNTupleWriteOptions &options, RFromBaseUrl)
Internal constructor used by CloneAsHidden: the public constructor derives the base URL by parsing an...
RNTupleLink CommitDatasetImpl() final
void PutObject(const std::string &url, const unsigned char *data, std::size_t size)
Upload raw bytes to the given S3 URL via an HTTP PUT request.
Helper class to compress data blocks in the ROOT compression frame format.
static std::size_t Zip(const void *from, std::size_t nbytes, int compression, void *to)
Returns the size of the compressed data, written into the provided output buffer.
Base class for a sink with a physical storage backend.
void EnableDefaultMetrics(const std::string &prefix)
Enables the default set of metrics provided by RPageSink.
Base class for all ROOT issued exceptions.
RNTupleLocator payload that is common for object stores using 64bit location information.
Generic information about the physical location of data.
Common user-tunable settings for storing RNTuples.
The class is used as a return type for operations that can fail; wraps a value of type T or an RError...
RResult< std::string > ParseS3Url(std::string_view uri)
Translate an ntpl+s3 URI into its plain HTTP(S) equivalent.
ROOT::RLogChannel & NTupleLog()
Log channel for RNTuple diagnostics.
std::unique_ptr< T[]> MakeUninitArray(std::size_t size)
Make an array of default-initialized elements.
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
bool StartsWith(std::string_view string, std::string_view prefix)
Entry point for an RNTuple stored in S3-compatible object storage.
std::uint16_t fVersionMinor
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 fVersionPatch
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 fHeaderOffset
std::uint64_t fFooterOffset
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.
std::uint16_t fVersionMajor
Tag to select the internal constructor that takes an already-resolved base URL.
A sealed page contains the bytes of a page as written to storage (packed & compressed).