SQLamarr
The stand-alone ultra-fast simulation option for the LHCb experiment
python_bindings.cpp
1 // (c) Copyright 2022 CERN for the benefit of the LHCb Collaboration.
2 //
3 // This software is distributed under the terms of the GNU General Public
4 // Licence version 3 (GPL Version 3), copied verbatim in the file "LICENCE".
5 //
6 // In applying this licence, CERN does not waive the privileges and immunities
7 // granted to it by virtue of its status as an Intergovernmental Organization
8 // or submit itself to any jurisdiction.
9 
10 
11 #include <string.h>
12 #include <memory>
13 #include <exception>
14 #include <iostream>
15 #include "SQLamarr/HepMC2DataLoader.h"
16 #include "SQLamarr/PVFinder.h"
17 #include "SQLamarr/db_functions.h"
18 #include "SQLamarr/MCParticleSelector.h"
19 #include "SQLamarr/PVReconstruction.h"
20 #include "SQLamarr/Plugin.h"
21 #include "SQLamarr/GenerativePlugin.h"
22 #include "SQLamarr/GlobalPRNG.h"
23 #include "SQLamarr/TemporaryTable.h"
24 #include "SQLamarr/CleanEventStore.h"
25 #include "SQLamarr/EditEventStore.h"
26 #include "SQLamarr/UpdateDBConnection.h"
27 #include "SQLamarr/SQLiteError.h"
28 
29 constexpr int SQL_ERRORSHIFT = 10000;
30 constexpr int LOGIC_ERRORSHIFT = 20000;
31 
33 
34 typedef enum {
35  PVFinder
36  , MCParticleSelector
37  , PVReconstruction
38  , Plugin
39  , GenerativePlugin
40  , TemporaryTable
41  , CleanEventStore
42  , EditEventStore
43  , UpdateDBConnection
44  } TransformerType;
45 
47  TransformerType dtype;
48  void *p;
49 };
50 
51 SQLamarr::Transformer* resolve_polymorphic_transformer(TransformerPtr);
52 void clear_cache_if_any(TransformerPtr);
53 std::vector<std::string> tokenize (const char*);
54 
55 //==============================================================================
56 // make_database
57 //==============================================================================
58 extern "C"
59 void *make_database(const char* db_file)
60 {
61  SQLite3DB *db = new SQLite3DB(SQLamarr::make_database(db_file));
62  return reinterpret_cast<void *>(db);
63 }
64 
65 //==============================================================================
66 // delete_database
67 //==============================================================================
68 extern "C"
69 void del_database(void *db)
70 {
71  delete reinterpret_cast<SQLite3DB*> (db);
72 }
73 
74 //==============================================================================
75 // GlobalPRNG_get_or_create
76 //==============================================================================
77 extern "C"
78 void GlobalPRNG_get_or_create(void* db, int seed)
79 {
81  reinterpret_cast<SQLite3DB*>(db)->get(),
82  seed
83  );
84 }
85 
86 //==============================================================================
87 // HepMC2DataLoader
88 //==============================================================================
89 extern "C"
90 void* new_HepMC2DataLoader (void *db)
91 {
92  SQLite3DB *udb = reinterpret_cast<SQLite3DB *>(db);
93  return reinterpret_cast<void *> (new SQLamarr::HepMC2DataLoader(*udb));
94 }
95 
96 extern "C"
97 void del_HepMC2DataLoader (void *self)
98 {
99  delete reinterpret_cast<SQLamarr::HepMC2DataLoader *> (self);
100 }
101 
102 extern "C"
103 void HepMC2DataLoader_load (
104  void *self,
105  const char* file_path,
106  size_t runNumber,
107  size_t evtNumber,
108  const char *db_uri
109  )
110 {
111  auto loader = reinterpret_cast<SQLamarr::HepMC2DataLoader *>(self);
112  loader->sync_database(db_uri);
113  loader->load(file_path, runNumber, evtNumber);
114  loader->invalidate_cache();
115  loader->sync_database(db_uri);
116 }
117 
118 
119 //==============================================================================
120 // PVFinder
121 //==============================================================================
122 extern "C"
123 TransformerPtr new_PVFinder (void *db, int signal_status)
124 {
125  SQLite3DB *udb = reinterpret_cast<SQLite3DB *>(db);
126  auto p = new SQLamarr::PVFinder(*udb, signal_status);
127  return {PVFinder, p};
128 }
129 
130 //==============================================================================
131 // MCParticleSelector
132 //==============================================================================
133 extern "C"
134 TransformerPtr new_MCParticleSelector (void *db)
135 {
136  SQLite3DB *udb = reinterpret_cast<SQLite3DB *>(db);
137  return {
138  MCParticleSelector,
139  static_cast<void *> (new SQLamarr::MCParticleSelector(*udb))
140  };
141 }
142 
143 //==============================================================================
144 // PVReconstruction
145 //==============================================================================
146 extern "C"
147 TransformerPtr new_PVReconstruction (
148  void *db,
149  const char* file_path,
150  const char* table_name,
151  const char* condition
152  )
153 {
154  SQLite3DB *udb = reinterpret_cast<SQLite3DB *>(db);
156  file_path, table_name, condition);
157 
158  return {PVReconstruction, new SQLamarr::PVReconstruction(*udb, pars)};
159 }
160 
161 //==============================================================================
162 // Plugin
163 //==============================================================================
164 extern "C"
165 TransformerPtr new_Plugin (
166  void *db,
167  const char* library_path,
168  const char* function_name,
169  const char* query,
170  const char* output_table,
171  const char* semicolon_separated_outputs,
172  const char* semicolon_separated_references
173  )
174 {
175  SQLite3DB *udb = reinterpret_cast<SQLite3DB *>(db);
176 
177  return {Plugin, new SQLamarr::Plugin(*udb,
178  library_path,
179  function_name,
180  query,
181  output_table,
182  tokenize(semicolon_separated_outputs),
183  tokenize(semicolon_separated_references)
184  )};
185 }
186 
187 //==============================================================================
188 // GenerativePlugin
189 //==============================================================================
190 extern "C"
191 TransformerPtr new_GenerativePlugin (
192  void *db,
193  const char* library_path,
194  const char* function_name,
195  const char* query,
196  const char* output_table,
197  const char* semicolon_separated_outputs,
198  int n_random,
199  const char* semicolon_separated_references
200  )
201 {
202  SQLite3DB *udb = reinterpret_cast<SQLite3DB *>(db);
203 
204  return {GenerativePlugin, new SQLamarr::GenerativePlugin(*udb,
205  library_path,
206  function_name,
207  query,
208  output_table,
209  tokenize(semicolon_separated_outputs),
210  n_random,
211  tokenize(semicolon_separated_references)
212  )};
213 }
214 
215 
216 //==============================================================================
217 // TemporaryTable
218 //==============================================================================
219 extern "C"
220 TransformerPtr new_TemporaryTable (
221  void *db,
222  const char* output_table,
223  const char* semicolon_separated_outputs,
224  const char* semicolon_separated_queries,
225  bool make_persistent
226  )
227 {
228  SQLite3DB *udb = reinterpret_cast<SQLite3DB *>(db);
229 
230  return {TemporaryTable, new SQLamarr::TemporaryTable(*udb,
231  output_table,
232  tokenize(semicolon_separated_outputs),
233  tokenize(semicolon_separated_queries),
234  make_persistent
235  )};
236 }
237 
238 
239 //==============================================================================
240 // CleanEventStore
241 //==============================================================================
242 extern "C"
243 TransformerPtr new_CleanEventStore (void *db)
244 {
245  SQLite3DB *udb = reinterpret_cast<SQLite3DB *>(db);
246  return {CleanEventStore, new SQLamarr::CleanEventStore(*udb)};
247 }
248 
249 //==============================================================================
250 // EditEventStore
251 //==============================================================================
252 extern "C"
253 TransformerPtr new_EditEventStore (
254  void *db,
255  const char* semicolon_separated_queries
256  )
257 {
258  SQLite3DB *udb = reinterpret_cast<SQLite3DB *>(db);
259  return {EditEventStore, new SQLamarr::EditEventStore(*udb,
260  tokenize(semicolon_separated_queries)
261  )};
262 }
263 
264 //==============================================================================
265 // UpdateDBConnection
266 //==============================================================================
267 extern "C"
268 TransformerPtr new_UpdateDBConnection (
269  void *db,
270  const char* path
271  )
272 {
273  SQLite3DB *udb = reinterpret_cast<SQLite3DB *>(db);
274  return {UpdateDBConnection, new SQLamarr::UpdateDBConnection(*udb, path)};
275 }
276 
277 //==============================================================================
278 // Delete Transformer
279 //==============================================================================
280 extern "C"
281 void del_Transformer (TransformerPtr self)
282 {
283  switch (self.dtype)
284  {
285  case PVFinder:
286  delete reinterpret_cast<SQLamarr::PVFinder*> (self.p);
287  break;
288  case MCParticleSelector:
289  delete reinterpret_cast<SQLamarr::MCParticleSelector*> (self.p);
290  break;
291  case PVReconstruction:
292  delete reinterpret_cast<SQLamarr::PVReconstruction*> (self.p);
293  break;
294  case Plugin:
295  delete reinterpret_cast<SQLamarr::Plugin*> (self.p);
296  break;
297  case GenerativePlugin:
298  delete reinterpret_cast<SQLamarr::GenerativePlugin*> (self.p);
299  break;
300  case TemporaryTable:
301  delete reinterpret_cast<SQLamarr::TemporaryTable*> (self.p);
302  break;
303  case CleanEventStore:
304  delete reinterpret_cast<SQLamarr::CleanEventStore*> (self.p);
305  break;
306  case EditEventStore:
307  delete reinterpret_cast<SQLamarr::EditEventStore*> (self.p);
308  break;
309  case UpdateDBConnection:
310  delete reinterpret_cast<SQLamarr::UpdateDBConnection*> (self.p);
311  break;
312  default:
313  throw std::bad_cast();
314  }
315 }
316 
317 
318 //==============================================================================
319 // resolve_polymorphic_transformer
320 //==============================================================================
321 SQLamarr::Transformer* resolve_polymorphic_transformer(TransformerPtr self)
322 {
323  switch (self.dtype)
324  {
325  case PVFinder:
326  return reinterpret_cast<SQLamarr::PVFinder*> (self.p);
327  case MCParticleSelector:
328  return reinterpret_cast<SQLamarr::MCParticleSelector*> (self.p);
329  case PVReconstruction:
330  return reinterpret_cast<SQLamarr::PVReconstruction*> (self.p);
331  case Plugin:
332  return reinterpret_cast<SQLamarr::Plugin*> (self.p);
333  case GenerativePlugin:
334  return reinterpret_cast<SQLamarr::GenerativePlugin*> (self.p);
335  case TemporaryTable:
336  return reinterpret_cast<SQLamarr::TemporaryTable*> (self.p);
337  case CleanEventStore:
338  return reinterpret_cast<SQLamarr::CleanEventStore*> (self.p);
339  case EditEventStore:
340  return reinterpret_cast<SQLamarr::EditEventStore*> (self.p);
341  case UpdateDBConnection:
342  return reinterpret_cast<SQLamarr::UpdateDBConnection*> (self.p);
343  }
344 
345  throw std::bad_cast();
346 }
347 
348 //==============================================================================
349 // clear_cache_if_any
350 //==============================================================================
351 void clear_cache_if_any(TransformerPtr self)
352 {
353  switch (self.dtype)
354  {
355  case PVFinder:
356  reinterpret_cast<SQLamarr::PVFinder*> (self.p)->invalidate_cache();
357  break;
358  case MCParticleSelector:
359  reinterpret_cast<SQLamarr::MCParticleSelector*> (self.p)->invalidate_cache();
360  break;
361  case PVReconstruction:
362  reinterpret_cast<SQLamarr::PVReconstruction*> (self.p)->invalidate_cache();
363  break;
364  case Plugin:
365  reinterpret_cast<SQLamarr::Plugin*> (self.p)->invalidate_cache();
366  break;
367  case GenerativePlugin:
368  reinterpret_cast<SQLamarr::GenerativePlugin*> (self.p)->invalidate_cache();
369  break;
370  case TemporaryTable:
371  reinterpret_cast<SQLamarr::TemporaryTable*> (self.p)->invalidate_cache();
372  break;
373  case CleanEventStore:
374  reinterpret_cast<SQLamarr::CleanEventStore*> (self.p)->invalidate_cache();
375  break;
376  case EditEventStore:
377  reinterpret_cast<SQLamarr::EditEventStore*> (self.p)->invalidate_cache();
378  break;
379  case UpdateDBConnection:
380  break;
381  }
382 }
383 
384 //==============================================================================
385 // Execute Pipeline
386 //==============================================================================
387 extern "C"
388 int execute_pipeline(int algc, TransformerPtr* algv)
389 {
390  int iAlg;
391 
392  for (iAlg = 0; iAlg < algc; ++iAlg)
393  {
394  SQLamarr::Transformer* t = resolve_polymorphic_transformer(algv[iAlg]);
395  try
396  {
397  t->execute();
398  clear_cache_if_any(algv[iAlg]);
399  }
400  catch (const SQLamarr::SQLiteError& e)
401  {
402  std::cerr << "Caught SQL error processing #alg: " << iAlg << "\n";
403  std::cerr << e.what() << std::endl;
404  return SQL_ERRORSHIFT + iAlg;
405  }
406  catch (const std::logic_error& e)
407  {
408  std::cerr << "Caught logic error processing #alg: " << iAlg << "\n";
409  std::cerr << e.what() << std::endl;
410  return LOGIC_ERRORSHIFT + iAlg;
411  }
412  }
413 
414  return 0;
415 }
416 
417 
418 //==============================================================================
419 // Additional functions
420 //==============================================================================
421 std::vector<std::string> tokenize (const char* input_str)
422 {
423  // Return buffer
424  std::vector<std::string> ret;
425 
426  // Copy the input string in a writable buffer
427  char buf[16384];
428  strcpy(buf, input_str);
429 
430  // Tokenize the string
431  char *token = strtok(buf, ";");
432 
433  while (token != NULL)
434  {
435  ret.push_back(token);
436  token = strtok(NULL, ";");
437  }
438 
439  // Return buffer
440  return ret;
441 }
442 
443 
static SmearingParametrization load_parametrization(const std::string file_path, const std::string table_name, const std::string condition)
Instanciate a SmearingParametrization object from an SQLite file.
static PRNG * get_or_create(const sqlite3_context *db, uint64_t seed=no_seed)
Return a pointer to an initialized generator.
Definition: GlobalPRNG.h:99
Interface to an executable class used for polymorphism.
Definition: Transformer.h:17
virtual void execute()=0
Function to be overridden defining the execution step.
A database connection handler easying sharing the DB between C++ and Python.
Definition: db_functions.py:24
int LOGIC_ERRORSHIFT
Definition: Pipeline.py:21
SQLite3DB make_database(std::string filename, int flags=SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_URI, std::string init=std::string())
Initialize the database.
std::unique_ptr< sqlite3, void(*)(sqlite3 *)> SQLite3DB
Unique pointer to the sqlite3 connection.
Definition: db_functions.h:19
TransformerType dtype