ATLAS Offline Software
CoraCoolDatabase.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // CoraCoolDatabase.cxx
6 // implematation for CoraCoolDatabase
7 // Richard Hawkings, started 10/06
8 
9 #include "CoralBase/AttributeSpecification.h"
10 #include "CoralBase/AttributeList.h"
11 #include "CoralBase/Attribute.h"
12 #include "CoralBase/Exception.h"
13 #include "RelationalAccess/IConnectionService.h"
14 #include "RelationalAccess/ISessionProxy.h"
15 #include "RelationalAccess/ITable.h"
16 #include "RelationalAccess/TableDescription.h"
17 #include "RelationalAccess/ITableDataEditor.h"
18 #include "RelationalAccess/ITransaction.h"
19 #include "RelationalAccess/ISchema.h"
20 #include "RelationalAccess/IQuery.h"
21 #include "RelationalAccess/ICursor.h"
22 #include "RelationalAccess/SchemaException.h"
23 
24 #include "CoolKernel/IFolder.h"
25 #include "CoolKernel/IFieldSpecification.h"
26 #include "CoolKernel/FolderSpecification.h"
27 
29 #include "CoraCoolSequence.h"
31 
33 
35 
36 // constructor with external COOL database reference
38  cool::IDatabasePtr cooldb,
39  coral::IConnectionService& coralsvc,
40  const bool readonly) :
41  m_cooldb(cooldb),
42  m_connected(false),
43  m_readonly(readonly),
44  m_coralsvc(coralsvc),
45  m_proxy(0),
46  m_log("CoraCool")
47 {
48  if (!extractCoralConStr(dbconn)) {
49  m_log << coral::Error << "Cannot derive CORAL connection string from: "
51  throw CoraCoolException("Bad connection string",
52  "CoraCoolDatabase::CoraCoolDatabase");
53  }
54  m_log << coral::Debug << "CORAL dbconnection string is: " << m_dbconn
56 }
57 
59  if (!m_connected) {
60  coral::AccessMode access=m_readonly ? coral::ReadOnly : coral::Update;
61  try {
63  m_connected=true;
64  }
65  catch (std::exception& e) {
66  m_log << coral::Error << "Exception caught: " << e.what() <<
68  m_connected=false;
69  }
70  }
71  return m_connected;
72 }
73 
75  if (m_connected) {
76  delete m_proxy;
77  m_connected=false;
78  }
79  return m_connected;
80 }
81 
82 bool CoraCoolDatabase::extractCoralConStr(const std::string_view coolstr) {
83  // extract CORAL database string from COOL one
84  bool dbok=false;
85  // first check for initial colon - if so, technology-specific string
86  std::string::size_type c1=coolstr.find(':');
87  if (c1!=std::string::npos) {
88  std::string_view techno,server,schema;
89  techno=coolstr.substr(0,c1);
90  std::string::size_type c2;
91  c2=coolstr.find(';');
92  if (c2==std::string::npos) c2=coolstr.size();
93  server=coolstr.substr(c1+3,c2-c1-3);
94  c1=coolstr.find("schema=");
95  if (c1!=std::string::npos) {
96  c2=coolstr.find(';',c1+7);
97  if (c2==std::string::npos) c2=coolstr.size();
98  schema=coolstr.substr(c1+7,c2-c1-7);
99  }
100  c1=coolstr.find("dbname=");
101  if (c1!=std::string::npos) {
102  c2=coolstr.find(';',c1+7);
103  if (c2==std::string::npos) c2=coolstr.size();
104  m_dbname=std::string(coolstr.substr(c1+7,c2-c1-7));
105  }
106  // construct the connection string
107  if (techno=="oracle" || techno=="mysql" || techno=="frontier") {
108  if (!server.empty() && !schema.empty()) {
109  m_dbconn=std::string(techno);
110  m_dbconn+= "://";
111  m_dbconn+=server;
112  m_dbconn+='/';
113  m_dbconn+=schema;
114  dbok=true;
115  }
116  } else if (techno=="sqlite") {
117  if (!schema.empty()) {
118  m_dbconn="sqlite_file:";
119  m_dbconn+=schema;
120  dbok=true;
121  }
122  }
123  } else {
124  c1=coolstr.find('/');
125  if (c1!=std::string::npos) {
126  m_dbconn=std::string(coolstr.substr(0,c1));
127  m_dbname=std::string(coolstr.substr(c1+1));
128  dbok=true;
129  }
130  }
131  if (m_dbname.empty()) dbok=false;
132  m_log << coral::Debug << "Extracted CORAL connection string: " << m_dbconn
133  << " and database name: " << m_dbname << " with status " << dbok <<
135  return dbok;
136 }
137 
139  const cool::IRecordSpecification& spec) {
140  std::string result="";
141  unsigned int n=spec.size();
142  for (unsigned int i=0;i<n;++i) {
143  const cool::IFieldSpecification& field=spec[i];
144  result+=field.name();
145  result+=':';
146  result+=field.storageType().name();
147  if (i<n-1) result+=',';
148  }
149  return result;
150 }
151 
152 bool CoraCoolDatabase::storeSpec(const std::string& tablename,
153  const std::string& spec) {
154  m_log << coral::Debug << "Store AttrList specification for table " <<
155  tablename << " : " << spec <<coral::MessageStream::endmsg;
156  // first check for existance of table
157  const std::string attrtable=m_dbname+"_CORACOOLATTR";
158  coral::ITable* table;
159  try {
160  table=&(m_proxy->nominalSchema().tableHandle(attrtable));
161  }
162  catch (coral::SchemaException& e) {
163  m_log << coral::Debug << "Creating table " << attrtable << coral::MessageStream::endmsg;
164  coral::TableDescription tdesc(attrtable);
165  tdesc.setName(attrtable);
166  tdesc.insertColumn("NAME","string",31,false);
167  tdesc.insertColumn("ATTRSPEC","string",4000,false);
168  tdesc.setPrimaryKey("NAME");
169  table=&(m_proxy->nominalSchema().createTable(tdesc));
170  // pause for thought
171  m_proxy->transaction().commit();
172  sleep(1);
173  m_proxy->transaction().start(false);
174  table=&(m_proxy->nominalSchema().tableHandle(attrtable));
175  }
176  if (table==0) {
177  m_log << coral::Error << "No pointer to " << attrtable << coral::MessageStream::endmsg;
178  return false;
179  }
180  // now update table with specification
181  try {
183  data.extend<std::string>("NAME");
184  data.extend<std::string>("ATTRSPEC");
185  data[0].data<std::string>()=tablename;
186  data[1].data<std::string>()=spec;
187  coral::ITableDataEditor& editor=table->dataEditor();
188  editor.insertRow(data);
189  }
190  catch (coral::SchemaException&e) {
191  m_log << coral::Error << "Could not insert " << tablename << " into "
192  << attrtable << " exception: " << e.what() <<
194  return false;
195  }
196  return true;
197 }
198 
200  const std::string& coraltable,
201  const cool::IRecordSpecification& fkspec,
202  const cool::IRecordSpecification& payloadspec,
203  const std::string& coralfk,
204  const std::string& coralpk,
205  const std::string& description,
207  const bool createParents) {
208 
209  // check input parameters
210  if (coraltable.size()>18) throw CoraCoolException(
211  "CORAL tablename too long (max 18 chars)",
212  "CoraCoolDatabase::createFolder");
213  // encode the folder description string
214  // first remove any existing coracool string
215  std::string::size_type p1,p2;
216  std::string newdesc=description;
217  p1=description.find("<coracool>");
218  p2=description.find("</coracool>");
219  if (p1!=std::string::npos && p2!=std::string::npos) {
220  newdesc=description.substr(0,p1);
221  newdesc.append(description, p2+11);
222  }
223  // COOL foreign key column is name of COOL payload attribute
224  newdesc+="<coracool>";
225  newdesc+=coraltable;
226  newdesc+=':';
227  newdesc+=fkspec[0].name();
228  newdesc+=':';
229  newdesc+= coralfk;
230  newdesc+=':';
231  newdesc+=coralpk;
232  newdesc+="</coracool>";
233  m_log << coral::Debug << "Created new description: " << newdesc <<
235 
236  // check for rows in key generation table, create if needed
237  // start transaction here
238  connect();
239  m_proxy->transaction().start(false);
240  CoraCoolSequence seqfk(m_dbname,m_dbname+"_"+coraltable+"_FK",m_proxy,true);
241  if (coralfk!=coralpk)
242  CoraCoolSequence seqpk(m_dbname,m_dbname+"_"+coraltable+"_PK",m_proxy,true);
243 
244  // endcode and store the attributelist specification in CORACOOLATTR table
245  if (!storeSpec(m_dbname+"_"+coraltable,
246  encodeAttrSpec(payloadspec)))
247  throw CoraCoolException("Cannot store payload specification",
248  "CoraCoolDatabase::createFolder");
249 
250  // create CORAL table
251  try {
252  m_log << coral::Debug << "Generate CORAL table:" << coraltable <<
254  coral::TableDescription tdesc("CoraCoolPayload");
255  tdesc.setName(m_dbname+"_"+coraltable);
256  for (unsigned int i=0;i<payloadspec.size();++i) {
257  const cool::IFieldSpecification& field=payloadspec[i];
258  int maxsize=field.storageType().maxSize();
259  if (field.storageType()==cool::StorageType::Blob64k) maxsize=0;
260  const std::string typen=coral::AttributeSpecification::typeNameForId(
261  field.storageType().cppType());
262  m_log << coral::Debug << "Insert column " << field.name() <<
263  " of type " << typen << std::endl;
264  tdesc.insertColumn(field.name(),typen,maxsize,false);
265  }
266  // declare primary key
267  tdesc.setPrimaryKey(coralpk);
268  // create separate index on FK if different
269  if (coralfk!=coralpk)
270  tdesc.createIndex(m_dbname+"_"+coraltable+"F",coralfk,false);
271 
272  m_proxy->nominalSchema().createTable(tdesc);
273  m_proxy->transaction().commit();
274  m_log << coral::Debug << "Created coral table " << coral::MessageStream::endmsg;
275 
276  // disconnect/reconnect to avoid connection problems
277  disconnect();
278  sleep(1);
279  connect();
280  }
281  catch (std::exception& e) {
282  // problem in table creation
283  throw CoraCoolException(e.what(),"CoraCoolDatabase::createFolder");
284  }
285 
286  // create corresponding COOL folder
287  // this has to go after CORAL manipulations otherwise get problems
288  // with schema consistency
289  // disconnect/reconnect to COOL first in order to reset COOL
290  // avoiding problems due to the reset database connection
291  m_log << coral::Debug << "Disconnect/reconnect COOL connection" <<
293  m_cooldb->closeDatabase();
294  m_cooldb->openDatabase();
295  m_log << coral::Debug << "Create COOL folder" << coolpath << coral::MessageStream::endmsg;
296 
297  m_cooldb->createFolder(coolpath,
298  cool::FolderSpecification(mode,fkspec),newdesc,createParents);
299  m_log << coral::Debug << "Created COOL folder" << coral::MessageStream::endmsg;
300 
301  // all structures created,
302  // generate return value by instantiating new folder
304  m_proxy, m_cooldb,this,m_log));
305  return folder;
306 }
307 
308 
309 CoraCoolFolderPtr CoraCoolDatabase::getFolder(const std::string& coolfolder) {
310  connect();
312  coolfolder,m_proxy,m_cooldb,this,m_log));
313  return folder;
314 }
315 
316 bool CoraCoolDatabase::existsFolder(const std::string& coolfolder) {
317  // first check if the COOL folder exists
318  if (!m_cooldb->existsFolder(coolfolder)) {
319  return false;
320  } else {
321  // if it does, check the folder description finds a coracool tag
322  // note this does not check the CORACOOL table actually exists
323  cool::IFolderPtr folder=m_cooldb->getFolder(coolfolder);
324  std::string tablename,keycolcool,fkeycolcoral,pkeycolcoral;
325  return parseFolderDescription(folder->description(),tablename,
326  keycolcool,fkeycolcoral,pkeycolcoral);
327  }
328 }
329 
330 bool CoraCoolDatabase::parseFolderDescription(const std::string& folderdesc,
331  std::string& tablename,
332  std::string& keycolcool,
333  std::string& fkeycolcoral,
334  std::string& pkeycolcoral) {
335  // parse the folder description string to extract CORAL table and FKs
336  // format <coracool>Table:COOL_key:CORAL_fkey:CORAL_pkey</coracool>
337  // if CORAL_pkey is missing, assumed to be same as CORAL_fkey
338  // return false for parsing problem or missing <coracool> specification
339  // otherwise set return arguments
340 
341  // find <coracool> part of the description
342  std::string::size_type p1,p2,c1,c2,c3;
343  p1=folderdesc.find("<coracool>");
344  p2=folderdesc.find("</coracool>");
345  if (p1==std::string::npos || p2==std::string::npos) return false;
346  // find the two : separating the values
347  c1=folderdesc.find(':',p1+10);
348  if (c1==std::string::npos) return false;
349  c2=folderdesc.find(':',c1+1);
350  if (c2==std::string::npos) return false;
351 
352  tablename=m_dbname;
353  tablename+= '_';
354  tablename.append(folderdesc,p1+10,c1-p1-10);
355  keycolcool=folderdesc.substr(c1+1,c2-c1-1);
356  fkeycolcoral=folderdesc.substr(c2+1,p2-c2-1);
357  // check for third colon to specify separate primary key
358  c3=folderdesc.find(':',c2+1);
359  if (c3!=std::string::npos) {
360  fkeycolcoral=folderdesc.substr(c2+1,c3-c2-1);
361  pkeycolcoral=folderdesc.substr(c3+1,p2-c3-1);
362  } else {
363  fkeycolcoral=folderdesc.substr(c2+1,p2-c2-1);
364  pkeycolcoral=fkeycolcoral;
365  }
366  return true;
367 }
368 
369 bool CoraCoolDatabase::deleteFolder(const std::string& coolfolder) {
370  m_log << coral::Debug << "Deleting folder " << coolfolder << coral::MessageStream::endmsg;
371  std::string desc;
372  // get COOL folder and description
373  try {
374  cool::IFolderPtr folder=m_cooldb->getFolder(coolfolder);
375  desc=folder->description();
376  // delete the COOL folder
377  m_cooldb->dropNode(coolfolder);
378  }
379  catch (cool::Exception& e) {
380  throw CoraCoolException(e.what(),"CoraCoolDatabase::deleteFolder");
381  }
382  // extract the CORAL folder name
383  std::string tablename,keycolcool,fkeycolcoral,pkeycolcoral;
384  if (parseFolderDescription(desc,tablename,keycolcool,
385  fkeycolcoral,pkeycolcoral)) {
386  m_log << coral::Debug << "Drop CORAL payload table " << tablename
388  // drop the CORAL table
389  connect();
390  m_proxy->transaction().start(false);
391  m_proxy->nominalSchema().dropIfExistsTable(tablename);
392  // remove primary/foreign key rows from sequence table
393  CoraCoolSequence seqfk(m_dbname,tablename+"_FK",m_proxy);
394  seqfk.dropSeq();
395  if (fkeycolcoral!=pkeycolcoral) {
396  CoraCoolSequence seqpk(m_dbname,tablename+"_PK",m_proxy);
397  seqpk.dropSeq();
398  }
399  // remove the row from the CORACOOLATTR table
400  coral::AttributeList bindvar;
401  bindvar.extend<std::string>("SNAME");
402  bindvar[0].data<std::string>()=tablename;
403  coral::ITable& table=m_proxy->nominalSchema().tableHandle(
404  m_dbname+"_CORACOOLATTR");
405  long rows=table.dataEditor().deleteRows("NAME=:SNAME",bindvar);
406  if (rows!=1) m_log << coral::Error << "Unexpected number of rows "
407  << rows << " with key " << tablename <<
408  " deleted from CORACOOLATTR table" << coral::MessageStream::endmsg;
409  m_proxy->transaction().commit();
410  // pause for thought
411  disconnect();
412  sleep(1);
413  connect();
414  }
415  return true;
416 }
CoraCoolDatabase::m_proxy
coral::ISessionProxy * m_proxy
Definition: CoraCoolDatabase.h:93
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
get_generator_info.result
result
Definition: get_generator_info.py:21
CaloCondBlobAlgs_fillNoiseFromASCII.spec
spec
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:47
CoraCoolFolder
Definition: CoraCoolFolder.h:37
extractSporadic.c1
c1
Definition: extractSporadic.py:134
CoraCoolSequence::dropSeq
bool dropSeq()
Definition: CoraCoolSequence.cxx:124
ReadOfcFromCool.field
field
Definition: ReadOfcFromCool.py:48
python.PyKernel.AttributeList
AttributeList
Definition: PyKernel.py:36
CoraCoolDatabase::m_log
coral::MessageStream m_log
Definition: CoraCoolDatabase.h:94
CheckTagAssociation.schema
schema
Definition: CheckTagAssociation.py:22
compileRPVLLRates_emergingFilterTest.c3
c3
Definition: compileRPVLLRates_emergingFilterTest.py:559
CaloCondBlobAlgs_fillNoiseFromASCII.desc
desc
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:54
lumiFormat.i
int i
Definition: lumiFormat.py:92
beamspotman.n
n
Definition: beamspotman.py:731
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
CoraCoolDatabase::disconnect
bool disconnect()
Definition: CoraCoolDatabase.cxx:74
calibdata.exception
exception
Definition: calibdata.py:496
CoraCoolDatabase::existsFolder
bool existsFolder(const std::string &coolfolder)
Definition: CoraCoolDatabase.cxx:316
CoraCoolDatabase::m_dbname
std::string m_dbname
Definition: CoraCoolDatabase.h:89
Preparation.mode
mode
Definition: Preparation.py:95
CoraCoolDatabase::storeSpec
bool storeSpec(const std::string &tablename, const std::string &spec)
Definition: CoraCoolDatabase.cxx:152
beamspotnt.rows
list rows
Definition: bin/beamspotnt.py:1112
CoraCoolDatabase::m_readonly
bool m_readonly
Definition: CoraCoolDatabase.h:91
CoraCoolSequence
Definition: CoraCoolSequence.h:15
pool::AccessMode
AccessMode
Definition of access modes.
Definition: Database/APR/StorageSvc/StorageSvc/pool.h:65
python.dummyaccess.access
def access(filename, mode)
Definition: dummyaccess.py:18
CoraCoolFolderPtr
boost::shared_ptr< CoraCoolFolder > CoraCoolFolderPtr
Definition: CoraCoolTypes.h:15
python.TriggerConfigAccess.maxsize
maxsize
Definition: TriggerConfigAccess.py:51
CoraCoolDatabase::parseFolderDescription
bool parseFolderDescription(const std::string &folderdesc, std::string &tablename, std::string &keycolcool, std::string &fkeycolcoral, std::string &pkeycolcoral)
Definition: CoraCoolDatabase.cxx:330
CoraCoolFolder.h
dumpBeamSpot.dbconn
dbconn
Definition: dumpBeamSpot.py:27
CoraCoolDatabase::encodeAttrSpec
std::string encodeAttrSpec(const cool::IRecordSpecification &spec)
Definition: CoraCoolDatabase.cxx:138
compileRPVLLRates.c2
c2
Definition: compileRPVLLRates.py:361
CoraCoolDatabase::m_cooldb
cool::IDatabasePtr m_cooldb
Definition: CoraCoolDatabase.h:87
EventContainers::Mode
Mode
Definition: IdentifiableContainerBase.h:13
python.ext.table_printer.table
list table
Definition: table_printer.py:81
CoraCoolDatabase::createFolder
CoraCoolFolderPtr createFolder(const std::string &coolpath, const std::string &coraltable, const cool::IRecordSpecification &fkspec, const cool::IRecordSpecification &payloadspec, const std::string &coralfk, const std::string &coralpk, const std::string &description="", const cool::FolderVersioning::Mode mode=cool::FolderVersioning::SINGLE_VERSION, const bool createParents=false)
Definition: CoraCoolDatabase.cxx:199
CoraCoolDatabase::extractCoralConStr
bool extractCoralConStr(std::string_view coolstr)
Definition: CoraCoolDatabase.cxx:82
CoraCoolDatabase::CoraCoolDatabase
CoraCoolDatabase(const std::string &m_dbconn, cool::IDatabasePtr cooldb, coral::IConnectionService &coralsvc, const bool readonly=false)
Definition: CoraCoolDatabase.cxx:37
DiTauMassTools::MaxHistStrategyV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:26
CoraCoolException
Definition: CoraCoolException.h:13
CoraCoolDatabase.h
CaloCondBlobAlgs_fillNoiseFromASCII.folder
folder
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:56
CoraCoolDatabase::m_dbconn
std::string m_dbconn
Definition: CoraCoolDatabase.h:88
CoraCoolDatabase::m_coralsvc
coral::IConnectionService & m_coralsvc
Definition: CoraCoolDatabase.h:92
CoraCoolSequence.h
python.html.AtlRunQueryDQSummary.server
server
Definition: AtlRunQueryDQSummary.py:22
checker_macros.h
Define macros for attributes used to control the static checker.
CoraCoolDatabase::connect
bool connect()
Definition: CoraCoolDatabase.cxx:58
CoraCoolException.h
CoraCoolDatabase::deleteFolder
bool deleteFolder(const std::string &coolfolder)
Definition: CoraCoolDatabase.cxx:369
CoraCoolDatabase::m_connected
bool m_connected
Definition: CoraCoolDatabase.h:90
description
std::string description
glabal timer - how long have I taken so far?
Definition: hcg.cxx:88
CoraCoolDatabase::getFolder
CoraCoolFolderPtr getFolder(const std::string &coolfolder)
Definition: CoraCoolDatabase.cxx:309