source: trunk/FACT++/src/corsika2sql.cc@ 20115

Last change on this file since 20115 was 19964, checked in by tbretz, 5 years ago
Fix a none compile issue.
File size: 9.3 KB
Line 
1#include <boost/regex.hpp>
2#include <boost/algorithm/string/replace.hpp>
3
4#include "Database.h"
5
6#include "pal.h"
7#include "nova.h"
8#include "tools.h"
9#include "Time.h"
10#include "Configuration.h"
11
12using namespace std;
13
14// ------------------------------------------------------------------------
15
16void SetupConfiguration(Configuration &conf)
17{
18 po::options_description control("Calcsource options");
19 control.add_options()
20 ("uri,u", var<string>()
21#if BOOST_VERSION >= 104200
22 ->required()
23#endif
24 , "Database link as in\n\tuser:password@server[:port]/database[?compress=0|1].")
25 ("file", var<string>()->required(), "Corsika Input Card")
26 ("force", po_switch(), "Force processing even if there is no database connection")
27 ;
28
29 po::options_description debug("Debug options");
30 debug.add_options()
31 ("no-insert", po_switch(), "Does not insert or update any data to any table")
32 ("print-insert", po_switch(), "Print the INSERT/REPLACE queries")
33 ("verbose,v", var<uint16_t>(1), "Verbosity (0: quiet, 1: default, 2: more, 3, ...)")
34 ;
35
36 po::positional_options_description p;
37 p.add("file", 1); // The 1st positional options (n=1)
38
39 conf.AddOptions(control);
40 conf.AddOptions(debug);
41 conf.SetArgumentPositions(p);
42}
43
44void PrintUsage()
45{
46 cout <<
47 "corsika2sql - Fill a Corsika Input Card into a SQL table\n"
48 "\n\n"
49 "Usage: corsika2sql input-card [-u URI] [options]\n"
50 "\n"
51 ;
52 cout << endl;
53}
54
55bool ShowWarnings(Database &connection)
56{
57 try
58 {
59 const auto resw =
60 connection.query("SHOW WARNINGS").store();
61
62 for (size_t i=0; i<resw.num_rows(); i++)
63 {
64 const mysqlpp::Row &roww = resw[i];
65
66 cout << roww["Level"] << '[' << roww["Code"] << "]: ";
67 cout << roww["Message"] << '\n';
68 }
69 if (resw.num_rows())
70 cout << endl;
71 return true;
72 }
73 catch (const exception &e)
74 {
75 cerr << "\nSHOW WARNINGS\n\n";
76 cerr << "SQL query failed:\n" << e.what() << '\n' <<endl;
77 return false;
78 }
79}
80
81
82int main(int argc, const char* argv[])
83{
84 Time start;
85
86 Configuration conf(argv[0]);
87 conf.SetPrintUsage(PrintUsage);
88 SetupConfiguration(conf);
89
90 if (!conf.DoParse(argc, argv))
91 return 127;
92
93 // ----------------------------- Evaluate options --------------------------
94 const string uri = conf.Get<string>("uri");
95 const string file = conf.Get<string>("file");
96
97 const bool print_insert = conf.Get<bool>("print-insert");
98
99 const bool force = conf.Get<bool>("force");
100 const bool noinsert = conf.Get<bool>("no-insert");
101 const uint16_t verbose = conf.Get<uint16_t>("verbose");
102
103 // -------------------------------------------------------------------------
104 // Checking for database connection
105
106 Database connection(uri); // Keep alive while fetching rows
107
108 try
109 {
110 if (!force)
111 connection.connected();
112 }
113 catch (const exception &e)
114 {
115 cerr << "SQL connection failed: " << e.what() << endl;
116 return 1;
117 }
118
119
120 // -------------------------------------------------------------------------
121 // create INSERT/UPDATE query (calculate positions)
122
123 const mysqlpp::StoreQueryResult res =
124 connection.query("EXPLAIN `CorsikaSetup`").store();
125
126 map<string, uint16_t> fields;
127
128 for (size_t i=0; i<res.num_rows(); i++)
129 {
130 auto field = string(res[i]["Field"]);
131
132 int cnt = 0;
133
134 boost::smatch match;
135 if (boost::regex_match(field, match, boost::regex("([^\\[]+)(\\[([0-9]+)\\])$")))
136 {
137 cnt = stoi(match[3])+1;
138 field = match[1];
139 }
140
141 if (fields[field]<cnt)
142 fields[field] = cnt;
143 }
144
145 fields["SEED"] = 3;
146 fields["TELESCOPE"] = 5;
147
148 // -------------------------------------------------------------------------
149 // evaluate input card
150
151 vector<string> insert;
152 vector<string> seeds;
153 vector<string> telescopes;
154
155 string runnr;;
156 string buf;
157
158 ifstream fin(file);
159
160 while (getline(fin, buf))
161 {
162 string line = buf;
163 while (1)
164 {
165 boost::replace_all(buf, " ", " ");
166 if (line==buf)
167 break;
168 line = buf;
169 }
170
171 vector<string> vec = Tools::Split(Tools::Trim(line), " ");
172
173 const auto it = fields.find(vec[0]);
174 if (it==fields.end())
175 {
176 //if (verbose>1)
177 //cout << "Not found: " << vec[0] << " " << vec.size()-1 << endl;
178 continue;
179 }
180
181 const uint16_t N = ::max<uint16_t>(1, it->second);
182
183 if (N<vec.size()-1)
184 {
185 //if (verbose>1)
186 cerr << "Size mismatch: " << vec[0] << " " << N << "<" << vec.size()-1 << endl;
187 return 2;
188 }
189
190 if (vec[0]=="SEED")
191 {
192 seeds.emplace_back("'"+vec[1]+"','"+vec[2]+"','"+vec[3]+"'");
193 continue;
194 }
195 if (vec[0]=="TELESCOPE")
196 {
197 const auto tel = atoi((vec.size()>5?vec[5]:"0").c_str());
198 telescopes.emplace_back("'"+vec[1]+"','"+vec[2]+"','"+vec[3]+"'"+"'"+vec[4]+"',"+to_string(tel));
199 continue;
200 }
201 if (vec[0]=="RUNNR")
202 runnr = vec[1];
203
204 for (int i=1; i<N+1; i++)
205 {
206 if (vec[i]=="T")
207 vec[i]="1";
208 if (vec[i]=="F")
209 vec[i]="0";
210 }
211
212 if (it->second==0)
213 insert.emplace_back("`"+vec[0]+"`='"+vec[1]+"'");
214 else
215 {
216 for (int i=1; i<N+1; i++)
217 insert.emplace_back("`"+vec[0]+"["+to_string(i-1)+"]`='"+vec[i]+"'");
218 }
219 }
220
221 cout << "RUNNR=" << runnr << " => " << file << endl;
222
223 // -------------------------------------------------------------------------
224 // insert card data into table
225
226 const string query1 =
227 "REPLACE CorsikaSetup SET "+boost::join(insert, ",");
228
229 try
230 {
231 if (!noinsert)
232 {
233 const mysqlpp::SimpleResult res1 =
234 connection.query(query1).execute();
235
236 if (verbose>0 && res1.info())
237 cout << res1.info() << '\n' << endl;
238 }
239 }
240 catch (const exception &e)
241 {
242 cerr << query1 << "\n\n";
243 cerr << "SQL query (" << query1.length() << " bytes) failed:\n" << e.what() << endl;
244 return 3;
245 }
246
247 if (print_insert)
248 cout << query1 << endl;
249
250 if (!ShowWarnings(connection))
251 return 4;
252
253 // -------------------------------------------------------------------------
254 // insert seed data into table
255
256 if (!seeds.empty())
257 {
258 int i=0;
259 for (auto it=seeds.begin(); it!=seeds.end(); it++)
260 it->insert(0, runnr+","+to_string(i++)+",");
261
262 const string query2 =
263 "INSERT CorsikaSeed (RUNNR,idx,`SEED[0]`,`SEED[1]`,`SEED[2]`) VALUES ("+boost::join(seeds, "),(")+")";
264
265 try
266 {
267
268 const mysqlpp::SimpleResult res2a =
269 connection.query("DELETE FROM CorsikaSeed WHERE RUNNR="+runnr).execute();
270
271 if (verbose>0)
272 cout << res2a.info() << '\n' << endl;
273
274 if (!noinsert)
275 {
276 const mysqlpp::SimpleResult res2b =
277 connection.query(query2).execute();
278
279 if (verbose>0)
280 cout << res2b.info() << '\n' << endl;
281 }
282 }
283 catch (const exception &e)
284 {
285 cerr << query2 << "\n\n";
286 cerr << "SQL query (" << query2.length() << " bytes) failed:\n" << e.what() << endl;
287 return 5;
288 }
289
290 if (print_insert)
291 cout << query2 << endl;
292
293 if (!ShowWarnings(connection))
294 return 6;
295 }
296
297 // -------------------------------------------------------------------------
298 // insert telescope data into table
299
300 if (!telescopes.empty())
301 {
302 for (auto it=telescopes.begin(); it!=telescopes.end(); it++)
303 it->insert(0, runnr+",");
304
305 const string query2 =
306 "INSERT CorsikaTelescope (RUNNR,X,Y,Z,R,ID) VALUES ("+boost::join(telescopes, "),(")+")";
307
308 try
309 {
310
311 const mysqlpp::SimpleResult res2a =
312 connection.query("DELETE FROM CorsikaTelescope WHERE RUNNR="+runnr).execute();
313
314 if (verbose>0)
315 cout << res2a.info() << '\n' << endl;
316
317 if (!noinsert)
318 {
319 const mysqlpp::SimpleResult res2b =
320 connection.query(query2).execute();
321
322 if (verbose>0)
323 cout << res2b.info() << '\n' << endl;
324 }
325 }
326 catch (const exception &e)
327 {
328 cerr << query2 << "\n\n";
329 cerr << "SQL query (" << query2.length() << " bytes) failed:\n" << e.what() << endl;
330 return 5;
331 }
332
333 if (print_insert)
334 cout << query2 << endl;
335
336 if (!ShowWarnings(connection))
337 return 6;
338 }
339
340 // -------------------------------------------------------------------------
341
342 if (verbose>0)
343 {
344 const auto sec = Time().UnixTime()-start.UnixTime();
345 cout << "Total execution time: " << sec << "s\n";
346 }
347
348 return 0;
349}
Note: See TracBrowser for help on using the repository browser.