ATLAS Offline Software
Toggle main menu visibility
Loading...
Searching...
No Matches
Database
CoraCool
src
CoraCoolObjectIter.cxx
Go to the documentation of this file.
1
/*
2
Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3
*/
4
5
// CoraCoolObjectIter.cxx
6
// Implementation for CoraCoolObjectIter
7
// Richard Hawkings, started 10/2006
8
9
#include <sstream>
10
#include "RelationalAccess/ISessionProxy.h"
11
#include "RelationalAccess/ITransaction.h"
12
#include "RelationalAccess/ITable.h"
13
#include "RelationalAccess/IQuery.h"
14
#include "RelationalAccess/ICursor.h"
15
#include "CoolKernel/IObject.h"
16
#include "CoolKernel/Record.h"
17
#include "
CoraCool/CoraCoolFolder.h
"
18
#include "
CoraCool/CoraCoolObject.h
"
19
#include "
CoraCool/CoraCoolException.h
"
20
#include "
CoraCool/CoraCoolObjectIter.h
"
21
#include <unordered_map>
22
23
// performance tuning parameters
24
// maximum number of ranges and query terms to use for CORAL query
25
#define QB_SIZE 16
26
#define QB_TERMS 20
27
// buffer length for number of COOL channels and DB backend rowcache size
28
// tuned to be slightly larger than number of SCT modules
29
#define OI_BUFLEN 4200
30
#define OI_ROWCACHE 4200
31
32
CoraCoolObjectIter::CoraCoolObjectIter
(
CoraCoolFolder
* coracoolfolder,
33
cool::IObjectIteratorPtr coolitr) :
34
m_buflen
(
OI_BUFLEN
),
m_inbuf
(0),
m_nextobj
(0),
35
m_refValid
(false),
m_allDone
(false),
36
m_folder
(coracoolfolder),
m_coolitr
(
std
::move(coolitr)) {
37
m_data
.resize(
m_buflen
);
38
// assemble an AttributeListSpecification to share with the data objects
39
const
cool::RecordSpecification recspec=
m_folder
->payloadSpecification();
40
const
coral::AttributeList speclist = cool::Record(recspec).attributeList();
41
m_spec
=
new
coral::AttributeListSpecification();
42
for
(coral::AttributeList::const_iterator itr=speclist.begin();
43
itr!=speclist.end();++itr) {
44
const
coral::AttributeSpecification& aspec=itr->specification();
45
m_spec
->extend(aspec.name(),aspec.typeName());
46
}
47
}
48
49
CoraCoolObjectIter::~CoraCoolObjectIter
() {
50
if
(
m_spec
!=0)
m_spec
->release();
51
}
52
53
CoraCoolObjectPtr
CoraCoolObjectIter::next
() {
54
if
(
m_inbuf
>
m_nextobj
) {
55
// return data directly from the buffer - just increment counter
56
++
m_nextobj
;
57
}
else
if
(
iHasNext
()) {
58
readDataToBuffer
();
59
}
else
{
60
throw
CoraCoolException
(
"No more data in CoraCoolObjectIter"
,
61
"CoraCoolObjectIter::next"
);
62
}
63
return
m_data
.at(
m_nextobj
-1);
64
}
65
66
void
CoraCoolObjectIter::readDataToBuffer
(){
67
// read some data from the database - initialise buffer to empty
68
m_inbuf
=0;
69
// coloumn name of the FK in the CORAL table
70
const
std::string& coralkey=
m_folder
->coralFKey();
71
// buffer to build the query
72
QueryBuilder
qbuf(
QB_SIZE
);
73
coral::AttributeList fktype;
74
std::string fktypestr;
75
// keep map of FKvalue to list of associated COOL channels
76
typedef
std::vector<unsigned int> KeyVec;
77
typedef
std::unordered_map<long long,KeyVec > KeyMap;
78
KeyMap keymap;
79
80
while
(
m_inbuf
<
m_buflen
&&
iHasNext
() &&
81
qbuf.
size
()<
QB_SIZE
&& qbuf.
terms
()<
QB_TERMS
) {
82
// get the COOL object
83
const
cool::IObject& coolobj=
m_coolitr
->currentRef();
84
// reset so that next call to iHasNext will read the next one
85
m_refValid
=
false
;
86
// prepare CoraCoolObject to receive the payload data
87
CoraCoolObjectPtr
data(
new
CoraCoolObject
(coolobj.since(),
88
coolobj.until(),coolobj.channelId(),
m_spec
));
89
m_data
[
m_inbuf
]=data;
90
// setup the foreign key reference
91
const
coral::AttributeList& payload=coolobj.payload().attributeList();
92
// remember the type of the FK
93
if
(
m_inbuf
==0) {
94
fktypestr=payload[0].specification().typeName();
95
fktype=payload;
96
}
97
long
long
ikeyval=
numAttr
(fktypestr,payload[0]);
98
qbuf.
add
(ikeyval);
99
KeyMap::iterator kdata=keymap.find(ikeyval);
100
if
(kdata==keymap.end()) {
101
// new FK value - create vector of buffer positions for this one
102
kdata=keymap.insert(kdata,
103
KeyMap::value_type(ikeyval,KeyVec(8)));
104
KeyVec& keyvec=kdata->second;
105
keyvec.resize(1);
106
keyvec[0]=
m_inbuf
;
107
}
else
{
108
// add to list of buffers using this key
109
KeyVec& keyvec=kdata->second;
110
keyvec.push_back(
m_inbuf
);
111
}
112
++
m_inbuf
;
113
}
114
// setup the query
115
std::string bwhere;
116
coral::AttributeList bfkeys;
117
qbuf.
getQuery
(bwhere,coralkey,bfkeys,fktype[0].specification());
118
// execute the query
119
try
{
120
m_folder
->proxy()->transaction().start(
true
);
121
coral::IQuery*
query
=
m_folder
->table()->newQuery();
122
query
->setCondition(bwhere,bfkeys);
123
query
->setRowCacheSize(
OI_ROWCACHE
);
124
m_folder
->setOutputSpec(
query
);
125
coral::ICursor& cursor=
query
->execute();
126
KeyMap::const_iterator kdata=keymap.end();
127
long
long
okeyval=0;
128
while
(cursor.next()) {
129
const
coral::AttributeList&
res
=cursor.currentRow();
130
// check which buffer(s) this data is associated with
131
// maybe associated with more than one if referenceObject has been used
132
// so have to check all - no optimisation possible
133
const
long
long
keyval=
numAttr
(fktypestr,
res
[coralkey]);
134
if
(keyval!=okeyval || kdata==keymap.end()) {
135
kdata=keymap.find(keyval);
136
okeyval=keyval;
137
}
138
if
(kdata!=keymap.end()) {
139
KeyVec keyvec=kdata->second;
140
for
(KeyVec::const_iterator kitr=keyvec.begin();
141
kitr!=keyvec.end();++kitr) {
142
m_data
[*kitr]->add(
res
);
143
}
144
}
else
{
145
std::ostringstream skey;
146
skey <<
"CoraCool key remapping error for key "
<< keyval;
147
throw
CoraCoolException
(skey.str(),
"CoraCoolObjectIter::next"
);
148
}
149
}
150
delete
query
;
151
m_folder
->proxy()->transaction().commit();
152
}
153
catch
(coral::Exception& e) {
154
throw
CoraCoolException
(e.what(),
"CoraCoolObjectIter::next"
);
155
}
156
// next read will access next object from buffer (if existing)
157
// this invocation will return first object
158
m_nextobj
=1;
159
return
;
160
}
161
162
bool
CoraCoolObjectIter::hasNext
() {
163
return
(
m_inbuf
>
m_nextobj
||
iHasNext
());
164
}
165
166
bool
CoraCoolObjectIter::goToNext
() {
167
const
bool
nextExists=
hasNext
();
168
if
(
m_inbuf
>
m_nextobj
){
169
++
m_nextobj
;
//just update the index
170
}
else
if
(
iHasNext
()){
171
readDataToBuffer
();
172
}
else
{
173
//throw CoraCoolException("No more data in CoraCoolObjectIter","CoraCoolObjectIter::goToNext");
174
}
175
return
nextExists;
176
}
177
178
CoraCoolObject
&
CoraCoolObjectIter::currentRef
(){
179
return
*(
m_data
.at(
m_nextobj
-1));
180
}
181
182
void
CoraCoolObjectIter::close
() {
183
// release any resources associated with the query
184
// close underlying COOL query
185
m_coolitr
->close();
186
// release ownership of any CoraCoolObjects we have
187
for
(
unsigned
int
i=0;i<
m_buflen
;++i)
m_data
[i].reset();
188
}
189
190
bool
CoraCoolObjectIter::equalAttr
(
const
coral::Attribute& a1,
const
coral::Attribute& a2)
const
191
{
192
// compare two Attributes based on type and value
193
// deal with some special cases where the types are not the same
194
// the easy part - if types are same
195
std::string spec1=a1.specification().typeName();
196
std::string spec2=a2.specification().typeName();
197
if
(spec1==spec2) {
198
return
(a1==a2);
199
}
else
if
(
isNumAttr
(spec1) &&
isNumAttr
(spec2)) {
200
// convert to long long and compare
201
long
long
v1=
numAttr
(spec1,a1);
202
long
long
v2=
numAttr
(spec2,a2);
203
return
(v1==v2);
204
}
else
{
205
// unhandled case
206
return
false
;
207
}
208
}
209
210
bool
CoraCoolObjectIter::iHasNext
() {
211
// implement old-COOL-style iterator behaviour - return if next is valid
212
// can be called multiple times - after call currentRef will give data
213
if
(
m_refValid
)
return
true
;
214
if
(
m_allDone
)
return
false
;
215
if
(
m_coolitr
->goToNext()) {
216
m_refValid
=
true
;
217
return
true
;
218
}
else
{
219
m_refValid
=
false
;
220
m_allDone
=
true
;
221
return
false
;
222
}
223
}
224
225
bool
CoraCoolObjectIter::isNumAttr
(
const
std::string& spec)
const
{
226
return
(spec==
"long long"
|| spec==
"unsigned long long"
||
227
spec==
"int"
|| spec==
"unsigned int"
||
228
spec==
"long"
|| spec==
"unsigned long"
);
229
}
230
231
long
long
CoraCoolObjectIter::numAttr
(
const
std::string& spec,
232
const
coral::Attribute&
a
)
const
{
233
long
long
v=0;
234
if
(spec==
"long long"
) {
235
v=
a
.data<
long
long
>();
236
}
else
if
(spec==
"unsigned long long"
) {
237
v=
static_cast<
long
long
>
(
a
.data<
unsigned
long
long
>());
238
}
else
if
(spec==
"int"
) {
239
v=
static_cast<
long
long
>
(
a
.data<
int
>());
240
}
else
if
(spec==
"unsigned int"
) {
241
v=
static_cast<
long
long
>
(
a
.data<
unsigned
int
>());
242
}
else
if
(spec==
"long"
) {
243
v=
static_cast<
long
long
>
(
a
.data<
long
>());
244
}
else
if
(spec==
"unsigned long"
) {
245
v=
static_cast<
long
long
>
(
a
.data<
unsigned
long
>());
246
}
247
return
v;
248
}
249
250
CoraCoolObjectIter::QueryBuilder::QueryBuilder
(
const
unsigned
int
size
) :
251
m_terms
(0),
m_size
(0),
m_maxsize
(
size
) {
252
m_lower
=
new
long
long
[
m_maxsize
];
253
m_upper
=
new
long
long
[
m_maxsize
];
254
}
255
256
CoraCoolObjectIter::QueryBuilder::~QueryBuilder
() {
257
delete
[]
m_lower
;
258
delete
[]
m_upper
;
259
}
260
261
unsigned
int
CoraCoolObjectIter::QueryBuilder::add
(
const
long
long
value) {
262
// add the given value to the query sequence
263
// find where it must be inserted
264
unsigned
int
i=0;
265
unsigned
int
j=0;
266
bool
done=
false
;
267
for
(
unsigned
int
i=0;i<
m_size
;++i) {
268
if
(
m_lower
[i]-value<2 && value-
m_upper
[i]<2) {
269
// current range contains object or can be extended by one to contain it
270
// value is in current range or extends it
271
if
(
m_lower
[i]-value==1) --
m_lower
[i];
272
if
(value-
m_upper
[i]==1) ++
m_upper
[i];
273
// if range is of size 1, just changed from one to two-term query
274
if
(
m_upper
[i]-
m_lower
[i]==1) ++
m_terms
;
275
done=
true
;
276
break
;
277
}
278
// check if value has to be inserted after this position, if not found
279
if
(
m_upper
[i]<value) ++j;
280
}
281
if
(not done) {
282
// did not add to an existing range - make a new one at j
283
// move existing values up
284
if
(
m_size
<
m_maxsize
) {
285
for
(i=
m_size
;i!=j;--i) {
286
m_lower
[i]=
m_lower
[i-1];
287
m_upper
[i]=
m_upper
[i-1];
288
}
289
++
m_size
;
290
// add new range at j
291
m_lower
[j]=value;
292
m_upper
[j]=value;
293
++
m_terms
;
294
}
else
{
295
// if not enough room, return zero to signal error
296
return
0;
297
}
298
}
299
return
m_terms
;
300
}
301
302
void
CoraCoolObjectIter::QueryBuilder::getQuery
(std::string& where,
303
const
std::string& coralkey,
304
coral::AttributeList& fkeys,
const
coral::AttributeSpecification& spec) {
305
// try to compress the query by joining existing ranges if possible
306
unsigned
int
j=0;
307
for
(
unsigned
int
i=0;i<
m_size
;++i) {
308
long
long
lower=
m_lower
[i];
309
long
long
upper
=
m_upper
[i];
310
// check if this range can be absorbed into previous one
311
if
(i>0) {
312
if
(
m_lower
[i]-
m_upper
[j]<2) {
313
// if so, adjust upper limit of previous range to encompass this one
314
// and do not copy current range
315
m_upper
[j]=
m_upper
[i];
316
}
else
{
317
// note this never gets executed on first iteration - j lags 1 behind i
318
++j;
319
m_lower
[j]=lower;
320
m_upper
[j]=
upper
;
321
}
322
}
323
}
324
m_size
=j+1;
325
// build the query string and list of FK values to be used
326
unsigned
int
ikey=0;
327
for
(
unsigned
int
i=0;i<
m_size
;++i) {
328
if
(where.size()>0) where+=
" OR "
;
329
if
(
m_lower
[i]==
m_upper
[i]) {
330
// bounds are equal - simple equivalence term
331
std::string keyname=
addKey
(ikey,fkeys,spec,
m_lower
[i]);
332
where+=coralkey;
333
where+=
"=:"
;
334
where+=keyname;
335
}
else
{
336
// bounds are not equal - need A>=B and A<=C
337
std::string keyname=
addKey
(ikey,fkeys,spec,
m_lower
[i]);
338
where+=
'('
;
339
where+=coralkey;
340
where+=
">=:"
;
341
where+=keyname;
342
where+=
" AND "
;
343
where+=coralkey;
344
where+=
"<=:"
;
345
346
keyname=
addKey
(ikey,fkeys,spec,
m_upper
[i]);
347
where+=keyname;
348
where+=
')'
;
349
}
350
}
351
}
352
353
std::string
CoraCoolObjectIter::QueryBuilder::addKey
(
unsigned
int
& ikey,
354
coral::AttributeList& fkeys,
const
coral::AttributeSpecification& spec,
355
const
long
long
value) {
356
// return the name of the FK and add it to the list of FK bind variables
357
std::ostringstream skey;
358
skey <<
"B"
<< ikey;
359
std::string keyname=skey.str();
360
fkeys.extend(keyname,spec.type());
361
std::string typeName=spec.typeName();
362
if
(typeName==
"long long"
) {
363
fkeys[keyname].data<
long
long
>()=value;
364
}
else
if
(typeName==
"unsigned long long"
) {
365
fkeys[keyname].data<
unsigned
long
long
>()=value;
366
}
else
if
(typeName==
"int"
) {
367
fkeys[keyname].data<
int
>()=value;
368
}
else
if
(typeName==
"unsigned int"
) {
369
fkeys[keyname].data<
unsigned
int
>()=value;
370
}
else
if
(typeName==
"long"
) {
371
fkeys[keyname].data<
long
>()=value;
372
}
else
if
(typeName==
"unsigned long"
) {
373
fkeys[keyname].data<
unsigned
long
>()=value;
374
}
else
{
375
throw
CoraCoolException
(
"Unregognised type "
+typeName,
376
"CoraCoolObjectIter::QueryBuilder::addKey"
);
377
}
378
++ikey;
379
return
keyname;
380
}
CoraCoolException.h
CoraCoolFolder.h
QB_TERMS
#define QB_TERMS
Definition
CoraCoolObjectIter.cxx:26
QB_SIZE
#define QB_SIZE
Definition
CoraCoolObjectIter.cxx:25
OI_BUFLEN
#define OI_BUFLEN
Definition
CoraCoolObjectIter.cxx:29
OI_ROWCACHE
#define OI_ROWCACHE
Definition
CoraCoolObjectIter.cxx:30
CoraCoolObjectIter.h
CoraCoolObject.h
CoraCoolObjectPtr
boost::shared_ptr< CoraCoolObject > CoraCoolObjectPtr
Definition
CoraCoolTypes.h:19
res
std::pair< std::vector< unsigned int >, bool > res
Definition
JetGroupProductTest.cxx:11
upper
int upper(int c)
Definition
LArBadChannelParser.cxx:49
a
static Double_t a
Definition
LArPhysWaveHECTool.cxx:38
CoraCoolException
Definition
CoraCoolException.h:13
CoraCoolFolder
Definition
CoraCoolFolder.h:37
CoraCoolObjectIter::QueryBuilder
Definition
CoraCoolObjectIter.h:68
CoraCoolObjectIter::QueryBuilder::m_size
unsigned int m_size
Definition
CoraCoolObjectIter.h:95
CoraCoolObjectIter::QueryBuilder::size
unsigned int size() const
Definition
CoraCoolObjectIter.h:117
CoraCoolObjectIter::QueryBuilder::QueryBuilder
QueryBuilder()
CoraCoolObjectIter::QueryBuilder::m_maxsize
unsigned int m_maxsize
Definition
CoraCoolObjectIter.h:96
CoraCoolObjectIter::QueryBuilder::m_lower
long long * m_lower
Definition
CoraCoolObjectIter.h:97
CoraCoolObjectIter::QueryBuilder::~QueryBuilder
~QueryBuilder()
Definition
CoraCoolObjectIter.cxx:256
CoraCoolObjectIter::QueryBuilder::terms
unsigned int terms() const
Definition
CoraCoolObjectIter.h:119
CoraCoolObjectIter::QueryBuilder::m_upper
long long * m_upper
Definition
CoraCoolObjectIter.h:98
CoraCoolObjectIter::QueryBuilder::addKey
std::string addKey(unsigned int &key, coral::AttributeList &fkeys, const coral::AttributeSpecification &spec, const long long value)
Definition
CoraCoolObjectIter.cxx:353
CoraCoolObjectIter::QueryBuilder::add
unsigned int add(const long long value)
Definition
CoraCoolObjectIter.cxx:261
CoraCoolObjectIter::QueryBuilder::m_terms
unsigned int m_terms
Definition
CoraCoolObjectIter.h:94
CoraCoolObjectIter::QueryBuilder::getQuery
void getQuery(std::string &where, const std::string &coralkey, coral::AttributeList &fkeys, const coral::AttributeSpecification &spec)
Definition
CoraCoolObjectIter.cxx:302
CoraCoolObjectIter::next
CoraCoolObjectPtr next()
Definition
CoraCoolObjectIter.cxx:53
CoraCoolObjectIter::m_coolitr
cool::IObjectIteratorPtr m_coolitr
Definition
CoraCoolObjectIter.h:112
CoraCoolObjectIter::isNumAttr
bool isNumAttr(const std::string &spec) const
Definition
CoraCoolObjectIter.cxx:225
CoraCoolObjectIter::close
void close()
Definition
CoraCoolObjectIter.cxx:182
CoraCoolObjectIter::numAttr
long long numAttr(const std::string &spec, const coral::Attribute &a) const
Definition
CoraCoolObjectIter.cxx:231
CoraCoolObjectIter::goToNext
bool goToNext()
Definition
CoraCoolObjectIter.cxx:166
CoraCoolObjectIter::m_buflen
unsigned int m_buflen
Definition
CoraCoolObjectIter.h:106
CoraCoolObjectIter::equalAttr
bool equalAttr(const coral::Attribute &a1, const coral::Attribute &a2) const
Definition
CoraCoolObjectIter.cxx:190
CoraCoolObjectIter::m_refValid
bool m_refValid
Definition
CoraCoolObjectIter.h:109
CoraCoolObjectIter::m_spec
coral::AttributeListSpecification * m_spec
Definition
CoraCoolObjectIter.h:113
CoraCoolObjectIter::hasNext
bool hasNext()
Definition
CoraCoolObjectIter.cxx:162
CoraCoolObjectIter::m_nextobj
unsigned int m_nextobj
Definition
CoraCoolObjectIter.h:108
CoraCoolObjectIter::m_data
std::vector< CoraCoolObjectPtr > m_data
Definition
CoraCoolObjectIter.h:114
CoraCoolObjectIter::CoraCoolObjectIter
CoraCoolObjectIter()
CoraCoolObjectIter::~CoraCoolObjectIter
~CoraCoolObjectIter()
Definition
CoraCoolObjectIter.cxx:49
CoraCoolObjectIter::m_folder
CoraCoolFolder * m_folder
Definition
CoraCoolObjectIter.h:111
CoraCoolObjectIter::iHasNext
bool iHasNext()
Definition
CoraCoolObjectIter.cxx:210
CoraCoolObjectIter::currentRef
CoraCoolObject & currentRef()
Definition
CoraCoolObjectIter.cxx:178
CoraCoolObjectIter::m_inbuf
unsigned int m_inbuf
Definition
CoraCoolObjectIter.h:107
CoraCoolObjectIter::m_allDone
bool m_allDone
Definition
CoraCoolObjectIter.h:110
CoraCoolObjectIter::readDataToBuffer
void readDataToBuffer()
Definition
CoraCoolObjectIter.cxx:66
CoraCoolObject
Definition
CoraCoolObject.h:20
query
Definition
query.py:1
std
STL namespace.
Generated on
for ATLAS Offline Software by
1.17.0