-
Notifications
You must be signed in to change notification settings - Fork 1.4k
[ntuple] add support for leaf count arrays in classes #20633
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -417,6 +417,51 @@ public: | |
| void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final; | ||
| }; | ||
|
|
||
| /** | ||
| \class ROOT::RLeafCountArrayField | ||
| \brief A field for an RVec field as a class member on disk that is represented as leaf count array` in memory. | ||
| \ingroup NTuple | ||
| */ | ||
| class RLeafCountArrayField final : public RFieldBase { | ||
| friend class RClassField; // only class fields are able to construct this | ||
|
|
||
| private: | ||
| std::size_t fItemSize{0}; ///< The size of a child field's item | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For better or worse, the leaf count is currently limited (hard coded) to 32bits. |
||
| ROOT::Internal::RColumnIndex fNWritten{0}; ///< Number of items written in the current cluster | ||
| std::ptrdiff_t fCountLeafDelta{0}; ///< Offset delta of the count leaf int member relative to the array | ||
| bool fHasPersistentCountLeaf{true}; ///< The count leaf may be only transient in RNTuple | ||
|
|
||
| RLeafCountArrayField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField, | ||
| std::ptrdiff_t countLeafDelta, bool hasPersistentCountLeaf); | ||
|
|
||
| protected: | ||
| std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final; | ||
|
|
||
| const RColumnRepresentations &GetColumnRepresentations() const final; | ||
| void GenerateColumns() final; | ||
| void GenerateColumns(const ROOT::RNTupleDescriptor &desc) final; | ||
|
|
||
| void ConstructValue(void *where) const final { *reinterpret_cast<void **>(where) = nullptr; } | ||
|
|
||
| std::size_t AppendImpl(const void *from) final; | ||
| void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final; | ||
|
|
||
| void ReconcileOnDiskField(const RNTupleDescriptor &desc) final; | ||
|
|
||
| void CommitClusterImpl() final { fNWritten = 0; } | ||
|
|
||
| public: | ||
| RLeafCountArrayField(RLeafCountArrayField &&other) = default; | ||
| RLeafCountArrayField &operator=(RLeafCountArrayField &&other) = default; | ||
| ~RLeafCountArrayField() final = default; | ||
|
|
||
| std::vector<RValue> SplitValue(const RValue &value) const final; | ||
|
|
||
| size_t GetValueSize() const final { return sizeof(void *); } | ||
| size_t GetAlignment() const final { return std::alignment_of<void *>(); } | ||
| void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final; | ||
| }; | ||
|
|
||
| } // namespace ROOT | ||
|
|
||
| #endif | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -205,7 +205,19 @@ ROOT::RClassField::RClassField(std::string_view fieldName, TClass *classp) | |||||
| } | ||||||
| } | ||||||
|
|
||||||
| auto subField = RFieldBase::Create(dataMember->GetName(), typeName).Unwrap(); | ||||||
| const auto memberName = dataMember->GetName(); | ||||||
| std::unique_ptr<RFieldBase> subField; | ||||||
|
|
||||||
| if (auto realMember = IsLeafCountArray(*dataMember)) { | ||||||
| assert(typeName.length() > 0); | ||||||
| assert(*typeName.rbegin() == '*'); | ||||||
| auto itemField = RFieldBase::Create("_0", typeName.substr(0, typeName.length() - 1)).Unwrap(); | ||||||
| const std::ptrdiff_t offsetDelta = realMember->GetThisOffset() - dataMember->GetOffset(); | ||||||
| subField = std::unique_ptr<RLeafCountArrayField>(new RLeafCountArrayField( | ||||||
| memberName, std::move(itemField), offsetDelta, true /* fHasPersistentCountLeaf */)); | ||||||
| } else { | ||||||
| subField = RFieldBase::Create(memberName, typeName).Unwrap(); | ||||||
| } | ||||||
|
|
||||||
| const auto normTypeName = ROOT::Internal::GetNormalizedUnresolvedTypeName(origTypeName); | ||||||
| if (normTypeName == subField->GetTypeName()) { | ||||||
|
|
@@ -239,6 +251,43 @@ void ROOT::RClassField::Attach(std::unique_ptr<RFieldBase> child, RSubFieldInfo | |||||
| RFieldBase::Attach(std::move(child)); | ||||||
| } | ||||||
|
|
||||||
| TRealData *ROOT::RClassField::IsLeafCountArray(const TDataMember &dm) const | ||||||
| { | ||||||
| if (!(dm.Property() & kIsPointer) || !dm.GetTitle()) | ||||||
| return nullptr; | ||||||
|
|
||||||
| std::string title = dm.GetTitle(); | ||||||
| if (title.length() == 0 || title[0] != '[') | ||||||
| return nullptr; | ||||||
|
|
||||||
| auto idxRight = title.find_first_of("]", 1); | ||||||
| if (idxRight == std::string::npos) | ||||||
| return nullptr; | ||||||
|
|
||||||
| auto countLeaf = title.substr(1, idxRight - 1); | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
(and subsequent change) |
||||||
| for (auto realMember : ROOT::Detail::TRangeStaticCast<TRealData>(*fClass->GetListOfRealData())) { | ||||||
| if (countLeaf != realMember->GetName()) | ||||||
| continue; | ||||||
|
|
||||||
| const auto dmCountLeaf = realMember->GetDataMember(); | ||||||
|
|
||||||
| const auto dtCountLeaf = dmCountLeaf->GetDataType(); | ||||||
| if (!dtCountLeaf || ((dtCountLeaf->GetType() != kInt_t) && (dtCountLeaf->GetType() != kUInt_t))) { | ||||||
| throw ROOT::RException( | ||||||
| R__FAIL(std::string("invalid count leaf type: ") + GetTypeName() + "." + realMember->GetName())); | ||||||
| } | ||||||
|
|
||||||
| if (realMember->GetThisOffset() >= dm.GetOffset()) { | ||||||
| throw ROOT::RException(R__FAIL(std::string("count leaf member defined after array: ") + GetTypeName() + "." + | ||||||
| realMember->GetName())); | ||||||
| } | ||||||
|
|
||||||
| return realMember; | ||||||
| } | ||||||
|
|
||||||
| throw ROOT::RException(R__FAIL(std::string("invalid count leaf name in: ") + GetTypeName() + "." + dm.GetName())); | ||||||
| } | ||||||
|
|
||||||
| std::vector<const ROOT::TSchemaRule *> ROOT::RClassField::FindRules(const ROOT::RFieldDescriptor *fieldDesc) | ||||||
| { | ||||||
| ROOT::Detail::TSchemaRuleSet::TMatches rules; | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -460,4 +460,28 @@ struct ExampleMC { | |
| }; | ||
| } // namespace v2 | ||
|
|
||
| struct LeafCountInClassBase { | ||
| Int_t fSize = 0; | ||
| }; | ||
|
|
||
| struct LeafCountInClass : public LeafCountInClassBase { | ||
| unsigned char *fPayload1 = nullptr; //[fSize]; | ||
| unsigned char *fPayload2 = nullptr; //[fSize]; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm probably missing the context behind this PR, but looking at this class makes me wonder if we're subtly introducing support for raw pointers in RNTuple on-disk format.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One could "emulate" a raw pointer by using
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also note that on-disk this is stored as an |
||
| }; | ||
|
|
||
| struct LeafCountInClassFail1 { | ||
| int fSize = 0; | ||
| unsigned char *fPayload = nullptr; //[fTypo]; | ||
| }; | ||
|
|
||
| struct LeafCountInClassFail2 { | ||
| char fSize = 0; // wrong count leaf type | ||
| unsigned char *fPayload = nullptr; //[fSize]; | ||
| }; | ||
|
|
||
| struct LeafCountInClassFail3 { | ||
| unsigned char *fPayload = nullptr; //[fSize]; | ||
| int fSize = 0; // declared after the array | ||
| }; | ||
|
|
||
| #endif | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The commit message says it's
Internal, but the declaration doesn't seem to be?