@@ -647,12 +647,14 @@ static void ExtendDestinationModel(std::span<const ROOT::RFieldDescriptor *> new
647
647
}
648
648
649
649
// Generates default (zero) values for the given columns
650
- static void GenerateZeroPagesForColumns (size_t nEntriesToGenerate, std::span<const RColumnMergeInfo> columns,
651
- RSealedPageMergeData &sealedPageData, ROOT::Internal::RPageAllocator &pageAlloc,
652
- const ROOT::RNTupleDescriptor &dstDescriptor, const RNTupleMergeData &mergeData)
650
+ [[nodiscard]]
651
+ static ROOT::RResult<void >
652
+ GenerateZeroPagesForColumns (size_t nEntriesToGenerate, std::span<const RColumnMergeInfo> columns,
653
+ RSealedPageMergeData &sealedPageData, ROOT::Internal::RPageAllocator &pageAlloc,
654
+ const ROOT::RNTupleDescriptor &dstDescriptor, const RNTupleMergeData &mergeData)
653
655
{
654
656
if (!nEntriesToGenerate)
655
- return ;
657
+ return ROOT::RResult< void >:: Success () ;
656
658
657
659
for (const auto &column : columns) {
658
660
const ROOT::RFieldDescriptor *field = column.fParentFieldDescriptor ;
@@ -682,12 +684,10 @@ static void GenerateZeroPagesForColumns(size_t nEntriesToGenerate, std::span<con
682
684
const auto structure = field->GetStructure ();
683
685
684
686
if (structure == ROOT::ENTupleStructure::kStreamer ) {
685
- R__LOG_FATAL (NTupleMergeLog ())
686
- << " RNTuple::Merge"
687
- " Destination RNTuple contains a streamer field (%s) that is not present in one of the sources. "
688
- " Creating a default value for a streamer field is ill-defined, therefore the merging process will abort."
689
- << field->GetFieldName ();
690
- continue ;
687
+ return R__FAIL (
688
+ " Destination RNTuple contains a streamer field (" + field->GetFieldName () +
689
+ " ) that is not present in one of the sources. "
690
+ " Creating a default value for a streamer field is ill-defined, therefore the merging process will abort." );
691
691
}
692
692
693
693
// NOTE: we cannot have a Record here because it has no associated columns.
@@ -726,21 +726,23 @@ static void GenerateZeroPagesForColumns(size_t nEntriesToGenerate, std::span<con
726
726
sealedPageData.fPagesV .back ().cend ());
727
727
}
728
728
}
729
+ return ROOT::RResult<void >::Success ();
729
730
}
730
731
731
732
// Merges all columns appearing both in the source and destination RNTuples, just copying them if their
732
733
// compression matches ("fast merge") or by unsealing and resealing them with the proper compression.
733
- void RNTupleMerger::MergeCommonColumns (ROOT::Internal::RClusterPool &clusterPool,
734
- const ROOT::RClusterDescriptor &clusterDesc,
735
- std::span<const RColumnMergeInfo> commonColumns,
736
- const RCluster::ColumnSet_t &commonColumnSet,
737
- std::size_t nCommonColumnsInCluster, RSealedPageMergeData &sealedPageData,
738
- const RNTupleMergeData &mergeData, ROOT::Internal::RPageAllocator &pageAlloc)
734
+ ROOT::RResult<void >
735
+ RNTupleMerger::MergeCommonColumns (ROOT::Internal::RClusterPool &clusterPool,
736
+ const ROOT::RClusterDescriptor &clusterDesc,
737
+ std::span<const RColumnMergeInfo> commonColumns,
738
+ const RCluster::ColumnSet_t &commonColumnSet, std::size_t nCommonColumnsInCluster,
739
+ RSealedPageMergeData &sealedPageData, const RNTupleMergeData &mergeData,
740
+ ROOT::Internal::RPageAllocator &pageAlloc)
739
741
{
740
742
assert (nCommonColumnsInCluster == commonColumnSet.size ());
741
743
assert (nCommonColumnsInCluster <= commonColumns.size ());
742
744
if (nCommonColumnsInCluster == 0 )
743
- return ;
745
+ return ROOT::RResult< void >:: Success () ;
744
746
745
747
const RCluster *cluster = clusterPool.GetCluster (clusterDesc.GetId (), commonColumnSet);
746
748
// we expect the cluster pool to contain the requested set of columns, since they were
@@ -795,8 +797,10 @@ void RNTupleMerger::MergeCommonColumns(ROOT::Internal::RClusterPool &clusterPool
795
797
// TODO: also avoid doing this if we added no real page of this column to the destination yet.
796
798
if (columnDesc.GetFirstElementIndex () > clusterDesc.GetFirstEntryIndex () && mergeData.fNumDstEntries > 0 ) {
797
799
const auto nMissingEntries = columnDesc.GetFirstElementIndex () - clusterDesc.GetFirstEntryIndex ();
798
- GenerateZeroPagesForColumns (nMissingEntries, {&column, 1 }, sealedPageData, pageAlloc, mergeData.fDstDescriptor ,
799
- mergeData);
800
+ auto res = GenerateZeroPagesForColumns (nMissingEntries, {&column, 1 }, sealedPageData, pageAlloc,
801
+ mergeData.fDstDescriptor , mergeData);
802
+ if (!res)
803
+ return R__FORWARD_ERROR (res);
800
804
}
801
805
802
806
// Loop over the pages
@@ -844,15 +848,18 @@ void RNTupleMerger::MergeCommonColumns(ROOT::Internal::RClusterPool &clusterPool
844
848
sealedPageData.fGroups .emplace_back (column.fOutputId , sealedPageData.fPagesV .back ().cbegin (),
845
849
sealedPageData.fPagesV .back ().cend ());
846
850
} // end loop over common columns
851
+
852
+ return ROOT::RResult<void >::Success ();
847
853
}
848
854
849
855
// Iterates over all clusters of `source` and merges their pages into `destination`.
850
856
// It is assumed that all columns in `commonColumns` are present (and compatible) in both the source and
851
857
// the destination's schemas.
852
858
// The pages may be "fast-merged" (i.e. simply copied with no decompression/recompression) if the target
853
859
// compression is unspecified or matches the original compression settings.
854
- void RNTupleMerger::MergeSourceClusters (RPageSource &source, std::span<const RColumnMergeInfo> commonColumns,
855
- std::span<const RColumnMergeInfo> extraDstColumns, RNTupleMergeData &mergeData)
860
+ ROOT::RResult<void >
861
+ RNTupleMerger::MergeSourceClusters (RPageSource &source, std::span<const RColumnMergeInfo> commonColumns,
862
+ std::span<const RColumnMergeInfo> extraDstColumns, RNTupleMergeData &mergeData)
856
863
{
857
864
ROOT::Internal::RClusterPool clusterPool{source};
858
865
@@ -894,10 +901,15 @@ void RNTupleMerger::MergeSourceClusters(RPageSource &source, std::span<const RCo
894
901
missingColumns.push_back (commonColumns[i]);
895
902
896
903
RSealedPageMergeData sealedPageData;
897
- MergeCommonColumns (clusterPool, clusterDesc, commonColumns, commonColumnSet, nCommonColumnsInCluster,
898
- sealedPageData, mergeData, *fPageAlloc );
899
- GenerateZeroPagesForColumns (nClusterEntries, missingColumns, sealedPageData, *fPageAlloc ,
900
- mergeData.fDstDescriptor , mergeData);
904
+ auto res = MergeCommonColumns (clusterPool, clusterDesc, commonColumns, commonColumnSet, nCommonColumnsInCluster,
905
+ sealedPageData, mergeData, *fPageAlloc );
906
+ if (!res)
907
+ return R__FORWARD_ERROR (res);
908
+
909
+ res = GenerateZeroPagesForColumns (nClusterEntries, missingColumns, sealedPageData, *fPageAlloc ,
910
+ mergeData.fDstDescriptor , mergeData);
911
+ if (!res)
912
+ return R__FORWARD_ERROR (res);
901
913
902
914
// Commit the pages and the clusters
903
915
mergeData.fDestination .CommitSealedPageV (sealedPageData.fGroups );
@@ -914,6 +926,7 @@ void RNTupleMerger::MergeSourceClusters(RPageSource &source, std::span<const RCo
914
926
// However, as of today, we aren't really handling such huge files, and even relatively big ones
915
927
// such as the CMS dataset have a page list size of about only 2 MB.
916
928
// So currently we simply merge all cluster groups into one.
929
+ return ROOT::RResult<void >::Success ();
917
930
}
918
931
919
932
static std::optional<std::type_index> ColumnInMemoryType (std::string_view fieldType, ENTupleColumnType onDiskType)
@@ -977,7 +990,8 @@ static void AddColumnsFromField(std::vector<RColumnMergeInfo> &columns, const RO
977
990
// 2. when merging a deferred column into an existing column (in which case we need to fill the "hole" with
978
991
// zeroes). For the first case srcFieldDesc and dstFieldDesc are the same (see the calling site of this function),
979
992
// but for the second case they're not, and we need to pick the source field because we will then check the
980
- // column's *input* id inside fParentFieldDescriptor to see if it's a suppressed column (see GenerateZeroPagesForColumns()).
993
+ // column's *input* id inside fParentFieldDescriptor to see if it's a suppressed column (see
994
+ // GenerateZeroPagesForColumns()).
981
995
info.fParentFieldDescriptor = &srcFieldDesc;
982
996
// Save the parent field descriptor since this may be either the source or destination descriptor depending on
983
997
// whether this is an extraDstField or a commonField. We will need this in GenerateZeroPagesForColumns() to
@@ -1183,7 +1197,9 @@ ROOT::RResult<void> RNTupleMerger::Merge(std::span<RPageSource *> sources, const
1183
1197
1184
1198
// handle extra dst fields & common fields
1185
1199
auto columnInfos = GatherColumnInfos (descCmp, srcDescriptor.GetRef (), mergeData);
1186
- MergeSourceClusters (*source, columnInfos.fCommonColumns , columnInfos.fExtraDstColumns , mergeData);
1200
+ auto res = MergeSourceClusters (*source, columnInfos.fCommonColumns , columnInfos.fExtraDstColumns , mergeData);
1201
+ if (!res)
1202
+ return R__FORWARD_ERROR (res);
1187
1203
} // end loop over sources
1188
1204
1189
1205
if (fDestination ->GetNEntries () == 0 )
0 commit comments