161{
162
163
164
165 int verbose_level = 1;
166 std::string connect_string;
167 std::string working_schema;
168 int schema_version = -1;
169 bool ls_base_versions_only = false;
170 bool ls_get_size = false;
171 bool ls_usage = false;
172 bool ls_description = false;
173 bool list_db = false;
174 std::string release;
175 std::string user;
176 std::string host;
178 std::string acrhived_since;
179 std::string acrhived_till;
180 std::string sorted_by;
181 const char * tmp_acrhived_since(0);
182 const char * tmp_acrhived_till(0);
183 const char * tz(0);
184 boost::local_time::time_zone_ptr tz_ptr;
185
186 for(int i = 1; i < argc; i++) {
187 const char * cp = argv[i];
188
189 if(!strcmp(cp,
"-h") || !strcmp(cp,
"--help")) {
usage();
return (EXIT_SUCCESS); }
190 else if(!strcmp(cp, "-b") || !strcmp(cp, "--base-data-only")) { ls_base_versions_only = true; }
191 else if(!strcmp(cp, "-l") || !strcmp(cp, "--list-releases")) { list_db = true; }
192 else if(!strcmp(cp, "-z") || !strcmp(cp, "--show-size")) { ls_get_size = true; }
193 else if(!strcmp(cp, "-u") || !strcmp(cp, "--show-usage")) { ls_usage = true; }
194 else if(!strcmp(cp, "-d") || !strcmp(cp, "--show-description")) { ls_description = true; }
195
196 else if(!strcmp(cp, "-t") || !strcmp(cp, "--sorted-by")) {
197 if(++i == argc) {
no_param(cp);
return (EXIT_FAILURE); }
else { sorted_by = argv[i]; }
198 }
199 else if(!strcmp(cp, "-r") || !strcmp(cp, "--release")) {
200 if(++i == argc) {
no_param(cp);
return (EXIT_FAILURE); }
else { release = argv[i]; }
201 }
202 else if(!strcmp(cp, "-e") || !strcmp(cp, "--user")) {
203 if(++i == argc) {
no_param(cp);
return (EXIT_FAILURE); }
else { user = argv[i]; }
204 }
205 else if(!strcmp(cp, "-o") || !strcmp(cp, "--host")) {
206 if(++i == argc) {
no_param(cp);
return (EXIT_FAILURE); }
else { host = argv[i]; }
207 }
208 else if(!strcmp(cp, "-p") || !strcmp(cp, "--partition")) {
209 if(++i == argc) {
no_param(cp);
return (EXIT_FAILURE); }
else {
partition = argv[i]; }
210 }
211 else if(!strcmp(cp, "-v") || !strcmp(cp, "--verbose-level")) {
212 if(++i == argc) {
no_param(cp);
return (EXIT_FAILURE); }
else { verbose_level = atoi(argv[i]); }
213 }
214 else if(!strcmp(cp, "-s") || !strcmp(cp, "--schema-version")) {
215 if(++i == argc) {
no_param(cp);
return (1); }
else { schema_version = atoi(argv[i]);}
216 }
217 else if(!strcmp(cp, "-c") || !strcmp(cp, "--connect-string")) {
218 if(++i == argc) {
no_param(cp);
return (1); }
else { connect_string = argv[i]; }
219 }
220 else if(!strcmp(cp, "-w") || !strcmp(cp, "--working-schema")) {
221 if(++i == argc) {
no_param(cp);
return (1); }
else { working_schema = argv[i]; }
222 }
223 else if(!strcmp(cp, "-S") || !strcmp(cp, "--archived-since")) {
224 if(++i == argc) {
no_param(cp);
return 1; }
else { tmp_acrhived_since = argv[i]; }
225 }
226 else if(!strcmp(cp, "-T") || !strcmp(cp, "--archived-till")) {
227 if(++i == argc) {
no_param(cp);
return 1; }
else { tmp_acrhived_till = argv[i]; }
228 }
229 else if(!strcmp(cp, "-Z") || !strcmp(cp, "--time-zone")) {
230 if(++i == argc) {
no_param(cp);
return 1; }
else { tz = argv[i]; }
231 }
232 else {
233 std::cerr << "ERROR: Unexpected parameter: \"" << cp << "\"\n\n";
235 return (EXIT_FAILURE);
236 }
237 }
238
239 if (tz)
240 {
241 try
242 {
244
245 if (!strcmp(tz, "list-regions"))
246 {
248 {
249 std::cout << i << std::endl;
250 }
251 return 0;
252 }
253
255 }
256 catch (const std::exception& ex)
257 {
258 std::cerr << "ERROR: time-zone db access failed: " << ex.what() << std::endl;
259 return 2;
260 }
261 }
262
263 if(connect_string.empty()) {
264 std::cerr << "ERROR: the connect string is required\n";
266 return EXIT_FAILURE;
267 }
268
269 if(working_schema.empty()) {
270 std::cerr << "ERROR: the working schema is required\n";
272 return EXIT_FAILURE;
273 }
274
275 try
276 {
277 if (tmp_acrhived_since)
278 {
281 );
282 }
283
284 if (tmp_acrhived_till)
285 {
288 );
289 }
290 }
291 catch (const std::exception& ex)
292 {
293 std::cerr << "ERROR: " << ex.what() << std::endl;
294 return 2;
295 }
296
297 try {
298
299 std::unique_ptr<coral::ConnectionService> connection;
300
301 {
303
304 if(list_db) {
305 coral::ITable& schema_table =
session->schema(working_schema).tableHandle(
"OKSSCHEMA" );
306 std::unique_ptr< coral::IQuery > query( schema_table.newQuery() );
307 query->setRowCacheSize( 10 );
308 query->setDistinct();
309 query->addToOutputList( "RELEASE" );
310 coral::ICursor& cursor = query->execute();
311
312 std::set<std::string> names;
313
314 while(cursor.next()) {
315 names.insert(cursor.currentRow().begin()->data<std::string>());
316 }
317
318 std::cout << "Found configuration archives for " << names.size() << " releases:\n";
319
320 for(std::set<std::string>::const_iterator i = names.begin(); i != names.end(); ++i) {
321 std::cout << " - \'" << *i << '\'' << std::endl;
322 }
323 }
324 else {
325 if(schema_version == 0) {
327 if(schema_version == 0) {
328 throw std::runtime_error( "Cannot get HEAD schema version." );
329 }
330 }
331
332 coral::ITable& archive_table =
session->schema(working_schema).tableHandle(
"OKSARCHIVE" );
333
334 std::list<std::string> conditions_list;
335 coral::AttributeList conditions;
336
337
338 std::unique_ptr< coral::IQuery > query (
session->schema(working_schema).newQuery());
339 query->setRowCacheSize( 1000 );
340
341 query->addToOutputList( "A.SCHEMAVERSION" );
342 query->addToOutputList( "A.BASEVERSION" );
343 query->addToOutputList( "A.VERSION" );
344 query->addToOutputList( "B.RELEASE" );
345 query->addToOutputList( "A.TIME" );
346 query->addToOutputList( "A.CREATEDBY" );
347 query->addToOutputList( "A.HOST" );
348
349 if(ls_description) {
350 query->addToOutputList( "A.DESCRIPTION" );
351 }
352
353 coral::IQueryDefinition& subQuery1 = query->defineSubQuery( "A" );
354 subQuery1.addToTableList( "OKSDATA" );
355 query->addToTableList( "A" );
356
357 coral::IQueryDefinition& subQuery2 = query->defineSubQuery( "B" );
358 subQuery2.addToTableList( "OKSSCHEMA" );
359 query->addToTableList( "B" );
360
361 conditions_list.push_back("A.SCHEMAVERSION = B.VERSION");
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392 if(schema_version != -1) {
393 conditions.extend<int>( "ver" );
394 conditions["ver"].data<int>() = schema_version;
395
396 if(ls_base_versions_only) {
397 conditions_list.push_back("A.SCHEMAVERSION = :ver AND A.VERSION = A.BASEVERSION");
398 }
399 else {
400 conditions_list.push_back("A.SCHEMAVERSION = :ver");
401 }
402 }
403 else if(ls_base_versions_only) {
404 conditions_list.push_back("A.VERSION = A.BASEVERSION");
405 }
406
407 if(!release.empty()) {
408 conditions.extend<std::string>( "rel" );
409 conditions["rel"].data<std::string>() = release;
410 conditions_list.push_back("B.RELEASE = :rel");
411 }
412
414 if(!ls_usage) {
415 if(ls_description == false) {
416 throw std::runtime_error( "cannot search by partition without \"-d\" or \"-u\" command line option" );
417 }
418 conditions.extend<std::string>( "prt1" );
419 conditions[
"prt1"].data<std::string>() = std::string(
"%partition ") +
partition +
'%';
420 conditions_list.push_back("A.DESCRIPTION like :prt1");
421 }
422 }
423
424 if(!acrhived_since.empty()) {
425 conditions.extend<std::string>( "ars" );
426 conditions["ars"].data<std::string>() = acrhived_since;
427 if(ls_usage) {
428 query->setDistinct();
429 coral::IQueryDefinition& subQuery3 = query->defineSubQuery( "C" );
430 subQuery3.addToTableList( "OKSARCHIVE" );
431 query->addToTableList( "C" );
432 std::string condition("C.TIME >= :ars AND A.SCHEMAVERSION = C.SCHEMAVERSION AND A.VERSION = C.DATAVERSION");
434 conditions.extend<std::string>( "prt2" );
435 conditions["prt2"].data<std::string>() = partition;
436 condition += (
has_a_pattern(partition) ?
" AND C.PARTITION like :prt2" :
" AND C.PARTITION = :prt2");
437 }
438 conditions_list.push_back(condition);
439 }
440 else {
441 conditions_list.push_back("A.TIME >= :ars");
442 }
443 }
444
445 if(!acrhived_till.empty()) {
446 conditions.extend<std::string>( "art" );
447 conditions["art"].data<std::string>() = acrhived_till;
448 conditions_list.push_back("A.TIME <= :art");
449 }
450
451 if(!user.empty()) {
452 conditions.extend<std::string>( "usr" );
453 conditions["usr"].data<std::string>() = user;
454 conditions_list.push_back(
has_a_pattern(user) ?
"A.CREATEDBY like :usr" :
"A.CREATEDBY = :usr");
455 }
456
457 if(!host.empty()) {
458 conditions.extend<std::string>( "hst" );
459 conditions["hst"].data<std::string>() = host;
460 conditions_list.push_back(
has_a_pattern(host) ?
"A.HOST like :hst" :
"A.HOST = :hst");
461 }
462
463 if(!sorted_by.empty()) {
464 for(const char * p = sorted_by.c_str(); *p != 0; ++p) {
465 if(ls_description == false && (*p == 'p' || *p == 'P')) {
466 throw std::runtime_error( "cannot sort by partition without \"-d\" command line option" );
467 }
468
469 switch (*p) {
470 case 'v': query->addToOrderList("A.SCHEMAVERSION"); query->addToOrderList("A.VERSION"); break;
471 case 'V': query->addToOrderList("A.SCHEMAVERSION DESC"); query->addToOrderList("A.VERSION DESC"); break;
472 case 't': query->addToOrderList("A.TIME"); break;
473 case 'T': query->addToOrderList("A.TIME DESC"); break;
474 case 'u': query->addToOrderList("A.CREATEDBY"); break;
475 case 'U': query->addToOrderList("A.CREATEDBY DESC"); break;
476 case 'h': query->addToOrderList("A.HOST"); break;
477 case 'H': query->addToOrderList("A.HOST DESC"); break;
478 case 'p': query->addToOrderList("A.DESCRIPTION"); break;
479 case 'P': query->addToOrderList("A.DESCRIPTION DESC"); break;
480
481
482 default:
483 std::stringstream text;
484 text << "ERROR: wrong value \'" << *p << "\' in the command line parameter: \"--sorted-by\" or \"-t\"";
485 throw std::runtime_error( text.str().c_str() );
486 }
487 }
488 }
489
490
491 std::string conditions_str;
492
493 for(std::list<std::string>::const_iterator i = conditions_list.begin(); i != conditions_list.end(); ++i) {
494 if(i != conditions_list.begin()) conditions_str += " AND ";
495 conditions_str += *i;
496 }
497
498 query->setCondition( conditions_str, conditions );
499
500 coral::ICursor& cursor = query->execute();
501
502
503 std::vector<TableRow> rows;
504
505
506
508 rows.push_back(
TableRow(
' ',
'|',
"Version",
"Release",(tz_ptr ?
"Date (local time)" :
"Date (UTC)"),
"User",
"Host",
"Size",
"Description"));
510
511 struct {
512 long num;
513 coral::ITable&
table;
514 } nums[] = {
515 {0,
session->schema(working_schema).tableHandle(
"OKSOBJECT" )},
516 {0,
session->schema(working_schema).tableHandle(
"OKSDATAVAL" )},
517 {0,
session->schema(working_schema).tableHandle(
"OKSDATAREL" )}
518 };
519
520 while(cursor.next()) {
521 const coral::AttributeList& row = cursor.currentRow();
522
523 std::string time, host, user;
525 std::string description; if(ls_description && !row["A.DESCRIPTION"].isNull()) description = row["A.DESCRIPTION"].data<std::string>();
526 std::string
r;
if(!row[
"B.RELEASE"].isNull())
r = row[
"B.RELEASE"].data<std::string>();
527 int sv = row["A.SCHEMAVERSION"].data<int>();
528 int dv = row["A.VERSION"].data<int>();
529 nums[0].num = nums[1].num = nums[2].num = 0;
530
531 if(ls_get_size) {
532 coral::AttributeList sizes_query_conditions;
533 sizes_query_conditions.extend<int>( "sv" );
534 sizes_query_conditions["sv"].data<int>() = sv;
535 sizes_query_conditions.extend<int>( "dv" );
536 sizes_query_conditions["dv"].data<int>() = dv;
537
538 for(unsigned int i = 0; i < 3; ++i) {
539 std::unique_ptr< coral::IQuery > query( nums[i].
table.newQuery() );
540 query->setRowCacheSize( 1 );
541 query->addToOutputList( "COUNT(*)");
542 query->defineOutputType( "COUNT(*)", "long");
543 query->setCondition( "SCHEMAVERSION = :sv AND DATAVERSION = :dv", sizes_query_conditions );
544
545 coral::ICursor&
c = query->execute();
546
548 nums[i].num = (
int)
c.currentRow().begin()->data<
long>();
549 }
550 }
551 }
552
553 rows.push_back(
555 sv, dv, row["A.BASEVERSION"].data<int>(),
556 r, time, user, host, description,
557 nums[0].num, nums[1].num, nums[2].num
558 )
559 );
560
561 if(ls_usage) {
562 std::unique_ptr< coral::IQuery > query( archive_table.newQuery() );
563 coral::AttributeList archive_query_conditions;
564 archive_query_conditions.extend<int>( "sv" );
565 archive_query_conditions["sv"].data<int>() = sv;
566 archive_query_conditions.extend<int>( "dv" );
567 archive_query_conditions["dv"].data<int>() = dv;
568 query->setRowCacheSize( 10 );
569 query->addToOutputList( "TIME");
570 query->addToOutputList( "PARTITION");
571 query->addToOutputList( "CREATEDBY");
572 query->addToOutputList( "HOST");
573 query->addToOutputList( "RUNNUMBER");
574
575 if(!sorted_by.empty()) {
576 for(const char * p = sorted_by.c_str(); *p != 0; ++p) {
577
578 switch (*p) {
579 case 'v': query->addToOrderList("RUNNUMBER"); break;
580 case 'V': query->addToOrderList("RUNNUMBER DESC"); break;
581 case 't': query->addToOrderList("TIME"); break;
582 case 'T': query->addToOrderList("TIME DESC"); break;
583 case 'u': query->addToOrderList("CREATEDBY"); break;
584 case 'U': query->addToOrderList("CREATEDBY DESC"); break;
585 case 'h': query->addToOrderList("HOST"); break;
586 case 'H': query->addToOrderList("HOST DESC"); break;
587 case 'p': query->addToOrderList("PARTITION"); break;
588 case 'P': query->addToOrderList("PARTITION DESC"); break;
589 }
590 }
591 }
592
593 std::string condition("SCHEMAVERSION = :sv AND DATAVERSION = :dv");
594
595 if(!acrhived_since.empty()) {
596 archive_query_conditions.extend<std::string>( "ars" );
597 archive_query_conditions["ars"].data<std::string>() = acrhived_since;
598 condition += " AND TIME >= :ars";
599 }
600
601 if(!acrhived_till.empty()) {
602 archive_query_conditions.extend<std::string>( "art" );
603 archive_query_conditions["art"].data<std::string>() = acrhived_till;
604 condition += " AND TIME <= :art";
605 }
606
608 archive_query_conditions.extend<std::string>( "prt" );
609 archive_query_conditions["prt"].data<std::string>() = partition;
610 condition += (
has_a_pattern(partition) ?
" AND PARTITION like :prt" :
" AND PARTITION = :prt");
611 }
612
613 query->setCondition( condition, archive_query_conditions );
614
615 coral::ICursor&
c = query->execute();
616
618 const coral::AttributeList& ar_row =
c.currentRow();
619 std::string ar_time, ar_host, ar_user;
621 std::string p; if(!ar_row["PARTITION"].isNull()) p = ar_row["PARTITION"].data<std::string>();
622
623 std::ostringstream
s;
624 s <<
"partition: " << p <<
" run: " << ar_row[
"RUNNUMBER"].data<
int>();
625
626 rows.push_back(
TableRow(
' ',
'|', 0, 0, 0, r, ar_time, ar_user, ar_host,
s.str()));
627 }
628 }
629 }
630
632
633
634
635 unsigned short cw[] = {1,1,1,1,1,1,1};
636 {
637 for(auto & i : rows) {
638 for(unsigned short j = 0; j < sizeof(cw)/sizeof(unsigned short); ++j) {
639 unsigned short len = i.m_items[j].size();
640 if(len > cw[j]) cw[j]=
len;
641 }
642 }
643 }
644
645
646
647
648 {
649 bool align_left[] = {false, true, true, true, true, false, true};
650
651 for(std::vector<TableRow>::const_iterator i = rows.begin(); i != rows.end(); ++i) {
652 std::cout.fill((*i).m_fill);
653 for(unsigned short j = 0; j < sizeof(cw)/sizeof(unsigned short); ++j) {
654 std::cout << (*i).m_separator << (*i).m_fill;
655 std::cout.setf((align_left[j] ? std::ios::left : std::ios::right), std::ios::adjustfield);
656 std::cout.width(cw[j]);
657 std::cout << (*i).m_items[j] << (*i).m_fill;
658 }
659 std::cout << (*i).m_separator << std::endl;
660 }
661 }
662
663 }
664
665 session->transaction().commit();
666
668 }
669
671 }
672
673 catch ( coral::Exception& e ) {
674 std::cerr << "CORAL exception: " << e.what() << std::endl;
675 return 1;
676 }
677
678 catch ( std::exception& e ) {
679 std::cerr << "Standard C++ exception : " << e.what() << std::endl;
680 return 2;
681 }
682
683 catch ( ... ) {
684 std::cerr << "Exception caught (...)" << std::endl;
685 return 3;
686 }
687
689
690 return 0;
691}
std::vector< std::string > get_regions()
Get known time zone regions.
boost::local_time::time_zone_ptr get_tz_ptr(const std::string ®ion)
Get boost time-zone pointer from string.
coral::ISessionProxy * start_coral_session(const std::string &connect_string, int mode, std::unique_ptr< coral::ConnectionService > &connection, int verbose_level)
Start coral session.
int get_head_schema_version(coral::ISessionProxy *session, const std::string &schema, const char *release=0, int verbose_level=1, const char *dx="")
Get HEAD schema version number.
void get_time_host_user(const coral::AttributeList &data, std::string &time, std::string &host, std::string &user, boost::local_time::time_zone_ptr tz_ptr, const char *prefix=0)
boost::posix_time::ptime str_2_posix_time(const std::string &in, boost::local_time::time_zone_ptr tz_ptr, const char *value)
std::string posix_time_2_iso_string(boost::posix_time::ptime t)
static bool has_a_pattern(const std::string &s)
static void no_param(const char *s)