1+ // Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+ // See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+ // All rights not expressly granted are reserved.
4+ //
5+ // This software is distributed under the terms of the GNU General Public
6+ // License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+ //
8+ // In applying this license CERN does not waive the privileges and immunities
9+ // granted to it by virtue of its status as an Intergovernmental Organization
10+ // or submit itself to any jurisdiction.
11+
12+ #include " TPCBase/CalArray.h"
13+ #include < TMemberStreamer.h>
14+ #include < TBuffer.h>
15+ #include < DataFormatsTPC/Defs.h>
16+ #include < iostream>
17+
18+ // to enable assert statements
19+ #ifdef NDEBUG
20+ #undef NDEBUG
21+ #include < cassert>
22+ #endif
23+
24+ // The following code provides a specific ROOT I/O streaming method
25+ // for the mData member of CalArray<o2::tpc::PadFlags>
26+ // This member was written incorrectly to the TFile in ROOT versions < 6.36, causing
27+ // segfaults when reading on ARM64 (occassionally).
28+ // We continue to write it in the incorrect format and fix the reading back.
29+
30+ // See also:
31+ // - https://github.com/root-project/root/pull/17009
32+ // - https://its.cern.ch/jira/browse/O2-4671
33+
34+ void MemberVectorPadFlagsStreamer (TBuffer& R__b, void * objp, int n)
35+ {
36+ if (n != 1 ) {
37+ std::cerr << " Error in MemberVectorPadFlagsStreamer : Unexpected n " << n << std::endl;
38+ return ;
39+ }
40+ std::vector<o2::tpc::PadFlags>* obj = static_cast <std::vector<o2::tpc::PadFlags>*>(objp);
41+ if (R__b.IsReading ()) {
42+ obj->clear ();
43+ std::vector<int > R__stl;
44+ R__stl.clear ();
45+ int R__n;
46+ R__b >> R__n;
47+ R__stl.reserve (R__n);
48+ for (int R__i = 0 ; R__i < R__n; R__i++) {
49+ Int_t readtemp;
50+ R__b >> readtemp;
51+ R__stl.push_back (readtemp);
52+ }
53+ auto data = reinterpret_cast <unsigned short *>(R__stl.data ());
54+ constexpr size_t bloatfactor = sizeof (int ) / sizeof (o2::tpc::PadFlags);
55+ for (int i = 0 ; i < bloatfactor * R__n; ++i) {
56+ obj->push_back (static_cast <o2::tpc::PadFlags>(data[i]));
57+ }
58+ } else {
59+ // We always save things with the old format.
60+ R__b << (int )obj->size () / 2 ;
61+ for (size_t i = 0 ; i < obj->size (); i++) {
62+ R__b << (short )obj->at (i);
63+ }
64+ }
65+ }
66+
67+ // register the streamer via static global initialization (on library load)
68+ // the streamer is only correct in combination with new ROOT
69+ #if ROOT_VERSION_CODE >= ROOT_VERSION(6, 33, 00)
70+ namespace ROOT
71+ {
72+ static __attribute__ ((used)) int _R__dummyStreamer_3 =
73+ ([]() {
74+ auto cl = TClass::GetClass<o2::tpc::CalArray<o2::tpc::PadFlags>>();
75+ if (cl) {
76+ if (!getenv (" TPC_PADFLAGS_STREAMER_OFF" )) {
77+ cl->AdoptMemberStreamer (" mData" , new TMemberStreamer (MemberVectorPadFlagsStreamer));
78+ }
79+ } else {
80+ // we should never come here ... and if we do we should assert/fail
81+ assert (false );
82+ }
83+ return 0 ;
84+ })();
85+ } // namespace ROOT
86+ #endif
0 commit comments