32 static RLogChannel sLog(
"ROOT.RNTupleExporter");
36struct RColumnExportInfo {
47 fQualifiedName(desc.GetQualifiedFieldName(fieldDesc.GetId()) +
'-' + std::to_string(colDesc.GetIndex()))
52struct RAddColumnsResult {
55 RAddColumnsResult &
operator+=(
const RAddColumnsResult &other)
63bool ItemIsFilteredOut(
const RNTupleExporter::RFilter<T> &filter,
const T &item)
65 bool filterHasType = filter.fSet.find(item) != filter.fSet.end();
72 const RNTupleExporter::RPagesOptions &options)
77 RAddColumnsResult res{};
79 for (
const auto &subfieldDesc : desc.GetFieldIterable(fieldDesc)) {
80 if (subfieldDesc.IsProjectedField())
83 for (
const auto &colDesc : desc.GetColumnIterable(subfieldDesc)) {
85 bool typeIsFiltered = ItemIsFilteredOut(options.fColumnTypeFilter, colDesc.GetType());
87 vec.emplace_back(desc, colDesc, subfieldDesc);
100 for (
const auto &clusterDesc : desc.GetActiveClusterIterable()) {
101 for (
const auto &colInfo : columns) {
102 const auto &pages = clusterDesc.GetPageRange(colInfo.fColDesc->GetPhysicalId());
103 nPages += pages.GetPageInfos().size();
111RNTupleExporter::RPagesResult
126 std::vector<RColumnExportInfo> columnInfos;
131 columnSet.reserve(columnInfos.size());
132 for (
const auto &colInfo : columnInfos) {
133 columnSet.emplace(colInfo.fColDesc->GetPhysicalId());
136 const auto nPages = CountPages(desc.GetRef(), columnInfos);
143 int pagesExported = 0;
144 int prevIntPercent = 0;
145 std::vector<char> unzipBuf;
147 const auto clusterId = clusterDesc.GetId();
149 for (
const auto &colInfo : columnInfos) {
150 auto columnId = colInfo.fColDesc->GetPhysicalId();
151 const auto &pages = clusterDesc.GetPageRange(columnId);
152 const auto &colRange = clusterDesc.GetColumnRange(columnId);
153 auto colElement = ROOT::Internal::RColumnElementBase::Generate<void>(colInfo.fColDesc->GetType());
154 colElement->SetBitsOnStorage(colInfo.fColDesc->GetBitsOnStorage());
156 std::uint64_t pageIdx = 0;
159 <<
"exporting column \"" << colInfo.fQualifiedName <<
"\" (" << pages.GetPageInfos().size() <<
" pages)";
162 assert(!colRange.IsSuppressed() || pages.GetPageInfos().empty());
164 for (
const auto &pageInfo : pages.GetPageInfos()) {
169 std::ostringstream ss{options.
fOutputPath, std::ios_base::ate};
170 assert(colRange.GetCompressionSettings());
171 ss <<
"/cluster_" << clusterDesc.GetId() <<
"_" << colInfo.fQualifiedName <<
"_page_" << pageIdx
172 <<
"_elems_" << pageInfo.GetNElements() <<
"_comp_" << *colRange.GetCompressionSettings() <<
".page";
173 const auto outFileName = ss.str();
174 std::ofstream outFile{outFileName, std::ios_base::binary};
177 R__FAIL(std::string(
"output path ") + options.
fOutputPath +
" does not exist or is not writable!"));
181 const auto *pageBuf =
static_cast<const char *
>(onDiskPage->
GetAddress());
183 const auto nbytesPacked = colElement->GetPackedSize(pageInfo.GetNElements());
184 const auto nbytesData = pageInfo.GetLocator().GetNBytesOnStorage();
185 if (unzipBuf.size() < nbytesPacked)
186 unzipBuf.resize(nbytesPacked);
188 outFile.write(unzipBuf.data(), nbytesPacked);
190 const bool includeChecksum =
192 const std::size_t maybeChecksumSize = includeChecksum * 8;
193 const auto nbytesData = pageInfo.GetLocator().GetNBytesOnStorage() + maybeChecksumSize;
194 outFile.write(pageBuf, nbytesData);
199 ++pageIdx, ++pagesExported;
202 int intPercent =
static_cast<int>(100.f * pagesExported / res.
fExportedFileNames.size());
203 if (intPercent != prevIntPercent) {
204 fprintf(stderr,
"\rExport progress: %02d%%", intPercent);
205 if (intPercent == 100)
206 fprintf(stderr,
"\n");
207 prevIntPercent = intPercent;
215 std::ostringstream ss;
218 ss << addColRes.fNColsTotal <<
" columns)";
220 auto nColsFilteredOut = addColRes.fNColsTotal - columnInfos.size();
221 ss << nColsFilteredOut <<
"/" << addColRes.fNColsTotal <<
" columns filtered out)";
#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_DEBUG(DEBUGLEVEL,...)
const ROOT::RFieldDescriptor * fFieldDesc
std::string fQualifiedName
const ROOT::RColumnDescriptor * fColDesc
static void AddColumnsFromField(std::vector< RColumnMergeInfo > &columns, const ROOT::RNTupleDescriptor &srcDesc, const FieldCollectionMap_t< RColReprMapping > &colReprMappings, RNTupleMergeData &mergeData, const ROOT::RFieldDescriptor &srcFieldDesc, const ROOT::RFieldDescriptor &dstFieldDesc, const std::string &prefix="")
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
std::string & operator+=(std::string &left, const TString &right)
@ kBlacklist
Don't export items contained in the filter's set.
static RPagesResult ExportPages(ROOT::Internal::RPageSource &source, const RPagesOptions &options={})
Given a page source, writes all its pages to individual files (1 per page).
Managed a set of clusters containing compressed and packed pages.
An in-memory subset of the packed and compressed pages of a cluster.
std::unordered_set< ROOT::DescriptorId_t > ColumnSet_t
const ROnDiskPage * GetOnDiskPage(const ROnDiskPage::Key &key) const
static void Unzip(const void *from, size_t nbytes, size_t dataLen, void *to)
The nbytes parameter provides the size ls of the from buffer.
A page as being stored on disk, that is packed and compressed.
const void * GetAddress() const
Abstract interface to read data from an ntuple.
void Attach(ROOT::Internal::RNTupleSerializer::EDescriptorDeserializeMode mode=ROOT::Internal::RNTupleSerializer::EDescriptorDeserializeMode::kForReading)
Open the physical storage container and deserialize header and footer.
RSharedDescriptorGuard GetSharedDescriptorGuard() const
Takes the read lock for the descriptor.
Metadata stored for every column of an RNTuple.
Base class for all ROOT issued exceptions.
Metadata stored for every field of an RNTuple.
ROOT::DescriptorId_t GetId() const
A log configuration for a channel, e.g.
The on-storage metadata of an RNTuple.
RClusterDescriptorIterable GetActiveClusterIterable() const
std::size_t GetNActiveClusters() const
std::size_t GetNClusters() const
ROOT::DescriptorId_t R__DEPRECATED(6, 46, "This function is ill-defined in the descriptor " "as not all cluster descriptors may be present. This interface is no longer exposed.") FindClusterId(ROOT ROOT::DescriptorId_t R__DEPRECATED(6, 46, "This function is ill-defined in the descriptor " "as not all cluster descriptors may be present. This interface is no longer exposed.") FindNextClusterId(ROOT ROOT::DescriptorId_t R__DEPRECATED(6, 46, "This function is ill-defined in the descriptor " "as not all cluster descriptors may be present. This interface is no longer exposed.") FindPrevClusterId(ROOT std::string GetQualifiedFieldName(ROOT::DescriptorId_t fieldId) const
Walks up the parents of the field ID and returns a field name of the form a.b.c.d In case of invalid ...
const RFieldDescriptor & GetFieldZero() const
std::unordered_set< T > fSet
RFilter< ENTupleColumnType > fColumnTypeFilter
Optional filter that determines which columns are included or excluded from being exported.
@ kDecompress
If enabled, uncompress (but don't unpack) the page (mutually exclusive with kIncludeChecksums)
@ kShowProgressBar
If enabled, the exporter will report the current progress on the stderr.
std::vector< std::string > fExportedFileNames
On-disk pages within a page source are identified by the column and page number.