File indexing completed on 2025-01-18 10:10:37
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef ROOT7_RColumn
0017 #define ROOT7_RColumn
0018
0019 #include <ROOT/RConfig.hxx> // for R__likely
0020 #include <ROOT/RColumnElement.hxx>
0021 #include <ROOT/RColumnModel.hxx>
0022 #include <ROOT/RNTupleUtil.hxx>
0023 #include <ROOT/RPage.hxx>
0024 #include <ROOT/RPageStorage.hxx>
0025
0026 #include <TError.h>
0027
0028 #include <cstring> // for memcpy
0029 #include <memory>
0030 #include <utility>
0031
0032 namespace ROOT {
0033 namespace Experimental {
0034 namespace Internal {
0035
0036
0037
0038
0039
0040
0041
0042
0043 class RColumn {
0044 private:
0045 RColumnModel fModel;
0046
0047
0048
0049
0050 std::uint32_t fIndex;
0051 RPageSink *fPageSink = nullptr;
0052 RPageSource *fPageSource = nullptr;
0053 RPageStorage::ColumnHandle_t fHandleSink;
0054 RPageStorage::ColumnHandle_t fHandleSource;
0055
0056
0057
0058
0059
0060 RPage fWritePage[2];
0061
0062 int fWritePageIdx = 0;
0063
0064
0065
0066 std::uint32_t fApproxNElementsPerPage = 0;
0067
0068 NTupleSize_t fNElements = 0;
0069
0070 RPage fReadPage;
0071
0072 ColumnId_t fColumnIdSource = kInvalidColumnId;
0073
0074 NTupleSize_t fFirstElementIndex = 0;
0075
0076 std::unique_ptr<RColumnElementBase> fElement;
0077
0078 RColumn(const RColumnModel &model, std::uint32_t index);
0079
0080
0081
0082 void SwapWritePagesIfFull() {
0083 if (R__likely(fWritePage[fWritePageIdx].GetNElements() < fApproxNElementsPerPage))
0084 return;
0085
0086 fWritePageIdx = 1 - fWritePageIdx;
0087 R__ASSERT(fWritePage[fWritePageIdx].IsEmpty());
0088 fWritePage[fWritePageIdx].Reset(fNElements);
0089 }
0090
0091
0092 void FlushShadowWritePage() {
0093 auto otherIdx = 1 - fWritePageIdx;
0094 if (fWritePage[otherIdx].IsEmpty())
0095 return;
0096 fPageSink->CommitPage(fHandleSink, fWritePage[otherIdx]);
0097
0098
0099 fWritePage[otherIdx].Reset(0);
0100 }
0101
0102 public:
0103 template <typename CppT>
0104 static std::unique_ptr<RColumn> Create(const RColumnModel &model, std::uint32_t index)
0105 {
0106 auto column = std::unique_ptr<RColumn>(new RColumn(model, index));
0107 column->fElement = RColumnElementBase::Generate<CppT>(model.GetType());
0108 return column;
0109 }
0110
0111 RColumn(const RColumn&) = delete;
0112 RColumn &operator =(const RColumn&) = delete;
0113 ~RColumn();
0114
0115
0116
0117
0118 void ConnectPageSink(DescriptorId_t fieldId, RPageSink &pageSink, NTupleSize_t firstElementIndex = 0U);
0119
0120 void ConnectPageSource(DescriptorId_t fieldId, RPageSource &pageSource);
0121
0122 void Append(const void *from)
0123 {
0124 void *dst = fWritePage[fWritePageIdx].GrowUnchecked(1);
0125
0126 if (fWritePage[fWritePageIdx].GetNElements() == fApproxNElementsPerPage / 2) {
0127 FlushShadowWritePage();
0128 }
0129
0130 std::memcpy(dst, from, fElement->GetSize());
0131 fNElements++;
0132
0133 SwapWritePagesIfFull();
0134 }
0135
0136 void AppendV(const void *from, std::size_t count)
0137 {
0138
0139 if (fWritePage[fWritePageIdx].GetNElements() + count > fApproxNElementsPerPage) {
0140
0141 for (unsigned i = 0; i < count; ++i) {
0142 Append(static_cast<const unsigned char *>(from) + fElement->GetSize() * i);
0143 }
0144 return;
0145 }
0146
0147
0148
0149
0150
0151
0152 if ((fWritePage[fWritePageIdx].GetNElements() < fApproxNElementsPerPage / 2) &&
0153 (fWritePage[fWritePageIdx].GetNElements() + count >= fApproxNElementsPerPage / 2))
0154 {
0155 FlushShadowWritePage();
0156 }
0157
0158 void *dst = fWritePage[fWritePageIdx].GrowUnchecked(count);
0159
0160 std::memcpy(dst, from, fElement->GetSize() * count);
0161 fNElements += count;
0162
0163
0164 SwapWritePagesIfFull();
0165 }
0166
0167 void Read(const NTupleSize_t globalIndex, void *to)
0168 {
0169 if (!fReadPage.Contains(globalIndex)) {
0170 MapPage(globalIndex);
0171 }
0172 const auto elemSize = fElement->GetSize();
0173 void *from = static_cast<unsigned char *>(fReadPage.GetBuffer()) +
0174 (globalIndex - fReadPage.GetGlobalRangeFirst()) * elemSize;
0175 std::memcpy(to, from, elemSize);
0176 }
0177
0178 void Read(RClusterIndex clusterIndex, void *to)
0179 {
0180 if (!fReadPage.Contains(clusterIndex)) {
0181 MapPage(clusterIndex);
0182 }
0183 const auto elemSize = fElement->GetSize();
0184 void *from = static_cast<unsigned char *>(fReadPage.GetBuffer()) +
0185 (clusterIndex.GetIndex() - fReadPage.GetClusterRangeFirst()) * elemSize;
0186 std::memcpy(to, from, elemSize);
0187 }
0188
0189 void ReadV(const NTupleSize_t globalIndex, const ClusterSize_t::ValueType count, void *to)
0190 {
0191 if (!fReadPage.Contains(globalIndex)) {
0192 MapPage(globalIndex);
0193 }
0194 NTupleSize_t idxInPage = globalIndex - fReadPage.GetGlobalRangeFirst();
0195
0196 const auto elemSize = fElement->GetSize();
0197 const void *from = static_cast<unsigned char *>(fReadPage.GetBuffer()) + idxInPage * elemSize;
0198 if (globalIndex + count <= fReadPage.GetGlobalRangeLast() + 1) {
0199 std::memcpy(to, from, elemSize * count);
0200 } else {
0201 ClusterSize_t::ValueType nBatch = fReadPage.GetNElements() - idxInPage;
0202 std::memcpy(to, from, elemSize * nBatch);
0203 auto tail = static_cast<unsigned char *>(to) + nBatch * elemSize;
0204 ReadV(globalIndex + nBatch, count - nBatch, tail);
0205 }
0206 }
0207
0208 void ReadV(RClusterIndex clusterIndex, const ClusterSize_t::ValueType count, void *to)
0209 {
0210 if (!fReadPage.Contains(clusterIndex)) {
0211 MapPage(clusterIndex);
0212 }
0213 NTupleSize_t idxInPage = clusterIndex.GetIndex() - fReadPage.GetClusterRangeFirst();
0214
0215 const auto elemSize = fElement->GetSize();
0216 const void *from = static_cast<unsigned char *>(fReadPage.GetBuffer()) + idxInPage * elemSize;
0217 if (clusterIndex.GetIndex() + count <= fReadPage.GetClusterRangeLast() + 1) {
0218 std::memcpy(to, from, elemSize * count);
0219 } else {
0220 ClusterSize_t::ValueType nBatch = fReadPage.GetNElements() - idxInPage;
0221 std::memcpy(to, from, elemSize * nBatch);
0222 auto tail = static_cast<unsigned char *>(to) + nBatch * elemSize;
0223 ReadV(RClusterIndex(clusterIndex.GetClusterId(), clusterIndex.GetIndex() + nBatch), count - nBatch, tail);
0224 }
0225 }
0226
0227 template <typename CppT>
0228 CppT *Map(const NTupleSize_t globalIndex) {
0229 NTupleSize_t nItems;
0230 return MapV<CppT>(globalIndex, nItems);
0231 }
0232
0233 template <typename CppT>
0234 CppT *Map(RClusterIndex clusterIndex)
0235 {
0236 NTupleSize_t nItems;
0237 return MapV<CppT>(clusterIndex, nItems);
0238 }
0239
0240 template <typename CppT>
0241 CppT *MapV(const NTupleSize_t globalIndex, NTupleSize_t &nItems) {
0242 if (R__unlikely(!fReadPage.Contains(globalIndex))) {
0243 MapPage(globalIndex);
0244 }
0245
0246 nItems = fReadPage.GetGlobalRangeLast() - globalIndex + 1;
0247 return reinterpret_cast<CppT*>(
0248 static_cast<unsigned char *>(fReadPage.GetBuffer()) +
0249 (globalIndex - fReadPage.GetGlobalRangeFirst()) * RColumnElement<CppT>::kSize);
0250 }
0251
0252 template <typename CppT>
0253 CppT *MapV(RClusterIndex clusterIndex, NTupleSize_t &nItems)
0254 {
0255 if (!fReadPage.Contains(clusterIndex)) {
0256 MapPage(clusterIndex);
0257 }
0258
0259 nItems = fReadPage.GetClusterRangeLast() - clusterIndex.GetIndex() + 1;
0260 return reinterpret_cast<CppT*>(
0261 static_cast<unsigned char *>(fReadPage.GetBuffer()) +
0262 (clusterIndex.GetIndex() - fReadPage.GetClusterRangeFirst()) * RColumnElement<CppT>::kSize);
0263 }
0264
0265 NTupleSize_t GetGlobalIndex(RClusterIndex clusterIndex)
0266 {
0267 if (!fReadPage.Contains(clusterIndex)) {
0268 MapPage(clusterIndex);
0269 }
0270 return fReadPage.GetClusterInfo().GetIndexOffset() + clusterIndex.GetIndex();
0271 }
0272
0273 RClusterIndex GetClusterIndex(NTupleSize_t globalIndex) {
0274 if (!fReadPage.Contains(globalIndex)) {
0275 MapPage(globalIndex);
0276 }
0277 return RClusterIndex(fReadPage.GetClusterInfo().GetId(),
0278 globalIndex - fReadPage.GetClusterInfo().GetIndexOffset());
0279 }
0280
0281
0282 void GetCollectionInfo(const NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *collectionSize)
0283 {
0284 NTupleSize_t idxStart = 0;
0285 NTupleSize_t idxEnd;
0286
0287 if (R__likely(globalIndex > 0)) {
0288 if (R__likely(fReadPage.Contains(globalIndex - 1))) {
0289 idxStart = *Map<ClusterSize_t>(globalIndex - 1);
0290 idxEnd = *Map<ClusterSize_t>(globalIndex);
0291 if (R__unlikely(fReadPage.GetClusterInfo().GetIndexOffset() == globalIndex))
0292 idxStart = 0;
0293 } else {
0294 idxEnd = *Map<ClusterSize_t>(globalIndex);
0295 auto selfOffset = fReadPage.GetClusterInfo().GetIndexOffset();
0296 idxStart = (globalIndex == selfOffset) ? 0 : *Map<ClusterSize_t>(globalIndex - 1);
0297 }
0298 } else {
0299 idxEnd = *Map<ClusterSize_t>(globalIndex);
0300 }
0301 *collectionSize = idxEnd - idxStart;
0302 *collectionStart = RClusterIndex(fReadPage.GetClusterInfo().GetId(), idxStart);
0303 }
0304
0305 void GetCollectionInfo(RClusterIndex clusterIndex, RClusterIndex *collectionStart, ClusterSize_t *collectionSize)
0306 {
0307 auto index = clusterIndex.GetIndex();
0308 auto idxStart = (index == 0) ? 0 : *Map<ClusterSize_t>(clusterIndex - 1);
0309 auto idxEnd = *Map<ClusterSize_t>(clusterIndex);
0310 *collectionSize = idxEnd - idxStart;
0311 *collectionStart = RClusterIndex(clusterIndex.GetClusterId(), idxStart);
0312 }
0313
0314
0315 void GetSwitchInfo(NTupleSize_t globalIndex, RClusterIndex *varIndex, std::uint32_t *tag) {
0316 auto varSwitch = Map<RColumnSwitch>(globalIndex);
0317 *varIndex = RClusterIndex(fReadPage.GetClusterInfo().GetId(), varSwitch->GetIndex());
0318 *tag = varSwitch->GetTag();
0319 }
0320
0321 void Flush();
0322 void MapPage(const NTupleSize_t index);
0323 void MapPage(RClusterIndex clusterIndex);
0324 NTupleSize_t GetNElements() const { return fNElements; }
0325 RColumnElementBase *GetElement() const { return fElement.get(); }
0326 const RColumnModel &GetModel() const { return fModel; }
0327 std::uint32_t GetIndex() const { return fIndex; }
0328 ColumnId_t GetColumnIdSource() const { return fColumnIdSource; }
0329 NTupleSize_t GetFirstElementIndex() const { return fFirstElementIndex; }
0330 RPageSource *GetPageSource() const { return fPageSource; }
0331 RPageSink *GetPageSink() const { return fPageSink; }
0332 RPageStorage::ColumnHandle_t GetHandleSource() const { return fHandleSource; }
0333 RPageStorage::ColumnHandle_t GetHandleSink() const { return fHandleSink; }
0334 };
0335
0336 }
0337 }
0338 }
0339
0340 #endif