202{
203
204
205
206 int verbose_level = 1;
207 std::string connect_string;
208 std::string working_schema;
209 int schema_version = -1;
210 bool ls_base_versions_only = false;
211 bool ls_get_size = false;
212 bool ls_usage = false;
213 bool ls_description = false;
214 bool list_db = false;
215 std::string release;
216 std::string user;
217 std::string host;
219 std::string acrhived_since;
220 std::string acrhived_till;
221 std::string sorted_by;
222 const char* tmp_acrhived_since(0);
223 const char* tmp_acrhived_till(0);
224 const char* tz(0);
225 boost::local_time::time_zone_ptr tz_ptr;
226
227 for (int i = 1; i < argc; i++) {
228 const char* cp = argv[i];
229
230 if (!strcmp(cp, "-h") || !strcmp(cp, "--help")) {
232 return (EXIT_SUCCESS);
233 } else if (!strcmp(cp, "-b") || !strcmp(cp, "--base-data-only")) {
234 ls_base_versions_only = true;
235 } else if (!strcmp(cp, "-l") || !strcmp(cp, "--list-releases")) {
236 list_db = true;
237 } else if (!strcmp(cp, "-z") || !strcmp(cp, "--show-size")) {
238 ls_get_size = true;
239 } else if (!strcmp(cp, "-u") || !strcmp(cp, "--show-usage")) {
240 ls_usage = true;
241 } else if (!strcmp(cp, "-d") || !strcmp(cp, "--show-description")) {
242 ls_description = true;
243 }
244
245 else if (!strcmp(cp, "-t") || !strcmp(cp, "--sorted-by")) {
246 if (++i == argc) {
248 return (EXIT_FAILURE);
249 } else {
250 sorted_by = argv[i];
251 }
252 } else if (!strcmp(cp, "-r") || !strcmp(cp, "--release")) {
253 if (++i == argc) {
255 return (EXIT_FAILURE);
256 } else {
257 release = argv[i];
258 }
259 } else if (!strcmp(cp, "-e") || !strcmp(cp, "--user")) {
260 if (++i == argc) {
262 return (EXIT_FAILURE);
263 } else {
264 user = argv[i];
265 }
266 } else if (!strcmp(cp, "-o") || !strcmp(cp, "--host")) {
267 if (++i == argc) {
269 return (EXIT_FAILURE);
270 } else {
271 host = argv[i];
272 }
273 } else if (!strcmp(cp, "-p") || !strcmp(cp, "--partition")) {
274 if (++i == argc) {
276 return (EXIT_FAILURE);
277 } else {
279 }
280 } else if (!strcmp(cp, "-v") || !strcmp(cp, "--verbose-level")) {
281 if (++i == argc) {
283 return (EXIT_FAILURE);
284 } else {
285 verbose_level = atoi(argv[i]);
286 }
287 } else if (!strcmp(cp, "-s") || !strcmp(cp, "--schema-version")) {
288 if (++i == argc) {
290 return (1);
291 } else {
292 schema_version = atoi(argv[i]);
293 }
294 } else if (!strcmp(cp, "-c") || !strcmp(cp, "--connect-string")) {
295 if (++i == argc) {
297 return (1);
298 } else {
299 connect_string = argv[i];
300 }
301 } else if (!strcmp(cp, "-w") || !strcmp(cp, "--working-schema")) {
302 if (++i == argc) {
304 return (1);
305 } else {
306 working_schema = argv[i];
307 }
308 } else if (!strcmp(cp, "-S") || !strcmp(cp, "--archived-since")) {
309 if (++i == argc) {
311 return 1;
312 } else {
313 tmp_acrhived_since = argv[i];
314 }
315 } else if (!strcmp(cp, "-T") || !strcmp(cp, "--archived-till")) {
316 if (++i == argc) {
318 return 1;
319 } else {
320 tmp_acrhived_till = argv[i];
321 }
322 } else if (!strcmp(cp, "-Z") || !strcmp(cp, "--time-zone")) {
323 if (++i == argc) {
325 return 1;
326 } else {
327 tz = argv[i];
328 }
329 } else {
330 std::cerr << "ERROR: Unexpected parameter: \"" << cp << "\"\n\n";
332 return (EXIT_FAILURE);
333 }
334 }
335
336 if (tz) {
337 try {
339
340 if (!strcmp(tz, "list-regions")) {
342 std::cout << i << std::endl;
343 }
344 return 0;
345 }
346
348 } catch (const std::exception& ex) {
349 std::cerr << "ERROR: time-zone db access failed: " << ex.what() << std::endl;
350 return 2;
351 }
352 }
353
354 if (connect_string.empty()) {
355 std::cerr << "ERROR: the connect string is required\n";
357 return EXIT_FAILURE;
358 }
359
360 if (working_schema.empty()) {
361 std::cerr << "ERROR: the working schema is required\n";
363 return EXIT_FAILURE;
364 }
365
366 try {
367 if (tmp_acrhived_since) {
368 acrhived_since =
370 }
371
372 if (tmp_acrhived_till) {
373 acrhived_till =
375 }
376 } catch (const std::exception& ex) {
377 std::cerr << "ERROR: " << ex.what() << std::endl;
378 return 2;
379 }
380
381 try {
382
383 std::unique_ptr<coral::ConnectionService> connection;
384
385 {
386 std::unique_ptr<coral::ISessionProxy>
session(
388
389 if (list_db) {
390 coral::ITable& schema_table =
session->schema(working_schema).tableHandle(
"OKSSCHEMA");
391 std::unique_ptr<coral::IQuery> query(schema_table.newQuery());
392 query->setRowCacheSize(10);
393 query->setDistinct();
394 query->addToOutputList("RELEASE");
395 coral::ICursor& cursor = query->execute();
396
397 std::set<std::string> names;
398
399 while (cursor.next()) {
400 names.insert(cursor.currentRow().begin()->data<std::string>());
401 }
402
403 std::cout << "Found configuration archives for " << names.size() << " releases:\n";
404
405 for (std::set<std::string>::const_iterator i = names.begin(); i != names.end(); ++i) {
406 std::cout << " - \'" << *i << '\'' << std::endl;
407 }
408 } else {
409 if (schema_version == 0) {
410 schema_version =
412 if (schema_version == 0) {
413 throw std::runtime_error("Cannot get HEAD schema version.");
414 }
415 }
416
417 coral::ITable& archive_table =
session->schema(working_schema).tableHandle(
"OKSARCHIVE");
418
419 std::list<std::string> conditions_list;
420 coral::AttributeList conditions;
421
422 std::unique_ptr<coral::IQuery> query(
session->schema(working_schema).newQuery());
423 query->setRowCacheSize(1000);
424
425 query->addToOutputList("A.SCHEMAVERSION");
426 query->addToOutputList("A.BASEVERSION");
427 query->addToOutputList("A.VERSION");
428 query->addToOutputList("B.RELEASE");
429 query->addToOutputList("A.TIME");
430 query->addToOutputList("A.CREATEDBY");
431 query->addToOutputList("A.HOST");
432
433 if (ls_description) {
434 query->addToOutputList("A.DESCRIPTION");
435 }
436
437 coral::IQueryDefinition& subQuery1 = query->defineSubQuery("A");
438 subQuery1.addToTableList("OKSDATA");
439 query->addToTableList("A");
440
441 coral::IQueryDefinition& subQuery2 = query->defineSubQuery("B");
442 subQuery2.addToTableList("OKSSCHEMA");
443 query->addToTableList("B");
444
445 conditions_list.push_back("A.SCHEMAVERSION = B.VERSION");
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476 if (schema_version != -1) {
477 conditions.extend<int>("ver");
478 conditions["ver"].data<int>() = schema_version;
479
480 if (ls_base_versions_only) {
481 conditions_list.push_back("A.SCHEMAVERSION = :ver AND A.VERSION = A.BASEVERSION");
482 } else {
483 conditions_list.push_back("A.SCHEMAVERSION = :ver");
484 }
485 } else if (ls_base_versions_only) {
486 conditions_list.push_back("A.VERSION = A.BASEVERSION");
487 }
488
489 if (!release.empty()) {
490 conditions.extend<std::string>("rel");
491 conditions["rel"].data<std::string>() = release;
492 conditions_list.push_back("B.RELEASE = :rel");
493 }
494
496 if (!ls_usage) {
497 if (ls_description == false) {
498 throw std::runtime_error("cannot search by partition without \"-d\" or \"-u\" command line option");
499 }
500 conditions.extend<std::string>("prt1");
501 conditions[
"prt1"].data<std::string>() = std::string(
"%partition ") +
partition +
'%';
502 conditions_list.push_back("A.DESCRIPTION like :prt1");
503 }
504 }
505
506 if (!acrhived_since.empty()) {
507 conditions.extend<std::string>("ars");
508 conditions["ars"].data<std::string>() = acrhived_since;
509 if (ls_usage) {
510 query->setDistinct();
511 coral::IQueryDefinition& subQuery3 = query->defineSubQuery("C");
512 subQuery3.addToTableList("OKSARCHIVE");
513 query->addToTableList("C");
514 std::string condition("C.TIME >= :ars AND A.SCHEMAVERSION = C.SCHEMAVERSION AND A.VERSION = C.DATAVERSION");
516 conditions.extend<std::string>("prt2");
517 conditions["prt2"].data<std::string>() = partition;
518 condition += (
has_a_pattern(partition) ?
" AND C.PARTITION like :prt2" :
" AND C.PARTITION = :prt2");
519 }
520 conditions_list.push_back(condition);
521 } else {
522 conditions_list.push_back("A.TIME >= :ars");
523 }
524 }
525
526 if (!acrhived_till.empty()) {
527 conditions.extend<std::string>("art");
528 conditions["art"].data<std::string>() = acrhived_till;
529 conditions_list.push_back("A.TIME <= :art");
530 }
531
532 if (!user.empty()) {
533 conditions.extend<std::string>("usr");
534 conditions["usr"].data<std::string>() = user;
535 conditions_list.push_back(
has_a_pattern(user) ?
"A.CREATEDBY like :usr" :
"A.CREATEDBY = :usr");
536 }
537
538 if (!host.empty()) {
539 conditions.extend<std::string>("hst");
540 conditions["hst"].data<std::string>() = host;
541 conditions_list.push_back(
has_a_pattern(host) ?
"A.HOST like :hst" :
"A.HOST = :hst");
542 }
543
544 if (!sorted_by.empty()) {
545 for (const char* p = sorted_by.c_str(); *p != 0; ++p) {
546 if (ls_description == false && (*p == 'p' || *p == 'P')) {
547 throw std::runtime_error("cannot sort by partition without \"-d\" command line option");
548 }
549
550 switch (*p) {
551 case 'v':
552 query->addToOrderList("A.SCHEMAVERSION");
553 query->addToOrderList("A.VERSION");
554 break;
555 case 'V':
556 query->addToOrderList("A.SCHEMAVERSION DESC");
557 query->addToOrderList("A.VERSION DESC");
558 break;
559 case 't':
560 query->addToOrderList("A.TIME");
561 break;
562 case 'T':
563 query->addToOrderList("A.TIME DESC");
564 break;
565 case 'u':
566 query->addToOrderList("A.CREATEDBY");
567 break;
568 case 'U':
569 query->addToOrderList("A.CREATEDBY DESC");
570 break;
571 case 'h':
572 query->addToOrderList("A.HOST");
573 break;
574 case 'H':
575 query->addToOrderList("A.HOST DESC");
576 break;
577 case 'p':
578 query->addToOrderList("A.DESCRIPTION");
579 break;
580 case 'P':
581 query->addToOrderList("A.DESCRIPTION DESC");
582 break;
583
584
585 default:
586 std::stringstream text;
587 text << "ERROR: wrong value \'" << *p << "\' in the command line parameter: \"--sorted-by\" or \"-t\"";
588 throw std::runtime_error(text.str().c_str());
589 }
590 }
591 }
592
593 std::string conditions_str;
594
595 for (std::list<std::string>::const_iterator i = conditions_list.begin(); i != conditions_list.end(); ++i) {
596 if (i != conditions_list.begin())
597 conditions_str += " AND ";
598 conditions_str += *i;
599 }
600
601 query->setCondition(conditions_str, conditions);
602
603 coral::ICursor& cursor = query->execute();
604
605 std::vector<TableRow> rows;
606
607
608
611 '|',
612 "Version",
613 "Release",
614 (tz_ptr ? "Date (local time)" : "Date (UTC)"),
615 "User",
616 "Host",
617 "Size",
618 "Description"));
620
621 struct
622 {
623 long num;
624 coral::ITable&
table;
625 } nums[] = { { 0,
session->schema(working_schema).tableHandle(
"OKSOBJECT") },
626 { 0,
session->schema(working_schema).tableHandle(
"OKSDATAVAL") },
627 { 0,
session->schema(working_schema).tableHandle(
"OKSDATAREL") } };
628
629 while (cursor.next()) {
630 const coral::AttributeList& row = cursor.currentRow();
631
632 std::string time, host, user;
634 std::string description;
635 if (ls_description && !row["A.DESCRIPTION"].isNull())
636 description = row["A.DESCRIPTION"].data<std::string>();
638 if (!row["B.RELEASE"].isNull())
639 r = row[
"B.RELEASE"].data<std::string>();
640 int sv = row["A.SCHEMAVERSION"].data<int>();
641 int dv = row["A.VERSION"].data<int>();
642 nums[0].num = nums[1].num = nums[2].num = 0;
643
644 if (ls_get_size) {
645 coral::AttributeList sizes_query_conditions;
646 sizes_query_conditions.extend<int>("sv");
647 sizes_query_conditions["sv"].data<int>() = sv;
648 sizes_query_conditions.extend<int>("dv");
649 sizes_query_conditions["dv"].data<int>() = dv;
650
651 for (unsigned int i = 0; i < 3; ++i) {
652 std::unique_ptr<coral::IQuery> query(nums[i].
table.newQuery());
653 query->setRowCacheSize(1);
654 query->addToOutputList("COUNT(*)");
655 query->defineOutputType("COUNT(*)", "long");
656 query->setCondition("SCHEMAVERSION = :sv AND DATAVERSION = :dv", sizes_query_conditions);
657
658 coral::ICursor&
c = query->execute();
659
661 nums[i].num = (
int)
c.currentRow().begin()->data<
long>();
662 }
663 }
664 }
665
667 '|',
668 sv,
669 dv,
670 row["A.BASEVERSION"].data<int>(),
671 r,
672 time,
673 user,
674 host,
675 description,
676 nums[0].num,
677 nums[1].num,
678 nums[2].num));
679
680 if (ls_usage) {
681 std::unique_ptr<coral::IQuery> query(archive_table.newQuery());
682 coral::AttributeList archive_query_conditions;
683 archive_query_conditions.extend<int>("sv");
684 archive_query_conditions["sv"].data<int>() = sv;
685 archive_query_conditions.extend<int>("dv");
686 archive_query_conditions["dv"].data<int>() = dv;
687 query->setRowCacheSize(10);
688 query->addToOutputList("TIME");
689 query->addToOutputList("PARTITION");
690 query->addToOutputList("CREATEDBY");
691 query->addToOutputList("HOST");
692 query->addToOutputList("RUNNUMBER");
693
694 if (!sorted_by.empty()) {
695 for (const char* p = sorted_by.c_str(); *p != 0; ++p) {
696
697 switch (*p) {
698 case 'v':
699 query->addToOrderList("RUNNUMBER");
700 break;
701 case 'V':
702 query->addToOrderList("RUNNUMBER DESC");
703 break;
704 case 't':
705 query->addToOrderList("TIME");
706 break;
707 case 'T':
708 query->addToOrderList("TIME DESC");
709 break;
710 case 'u':
711 query->addToOrderList("CREATEDBY");
712 break;
713 case 'U':
714 query->addToOrderList("CREATEDBY DESC");
715 break;
716 case 'h':
717 query->addToOrderList("HOST");
718 break;
719 case 'H':
720 query->addToOrderList("HOST DESC");
721 break;
722 case 'p':
723 query->addToOrderList("PARTITION");
724 break;
725 case 'P':
726 query->addToOrderList("PARTITION DESC");
727 break;
728 }
729 }
730 }
731
732 std::string condition("SCHEMAVERSION = :sv AND DATAVERSION = :dv");
733
734 if (!acrhived_since.empty()) {
735 archive_query_conditions.extend<std::string>("ars");
736 archive_query_conditions["ars"].data<std::string>() = acrhived_since;
737 condition += " AND TIME >= :ars";
738 }
739
740 if (!acrhived_till.empty()) {
741 archive_query_conditions.extend<std::string>("art");
742 archive_query_conditions["art"].data<std::string>() = acrhived_till;
743 condition += " AND TIME <= :art";
744 }
745
747 archive_query_conditions.extend<std::string>("prt");
748 archive_query_conditions["prt"].data<std::string>() = partition;
749 condition += (
has_a_pattern(partition) ?
" AND PARTITION like :prt" :
" AND PARTITION = :prt");
750 }
751
752 query->setCondition(condition, archive_query_conditions);
753
754 coral::ICursor&
c = query->execute();
755
757 const coral::AttributeList& ar_row =
c.currentRow();
758 std::string ar_time, ar_host, ar_user;
760 std::string p;
761 if (!ar_row["PARTITION"].isNull())
762 p = ar_row["PARTITION"].data<std::string>();
763
764 std::ostringstream
s;
765 s <<
"partition: " << p <<
" run: " << ar_row[
"RUNNUMBER"].data<
int>();
766
767 rows.push_back(
TableRow(
' ',
'|', 0, 0, 0, r, ar_time, ar_user, ar_host,
s.str()));
768 }
769 }
770 }
771
773
774
775
776 unsigned short cw[] = { 1, 1, 1, 1, 1, 1, 1 };
777 {
778 for (auto& i : rows) {
779 for (unsigned short j = 0; j < sizeof(cw) / sizeof(unsigned short); ++j) {
780 unsigned short len = i.m_items[j].size();
781 if (len > cw[j])
783 }
784 }
785 }
786
787
788
789 {
790 bool align_left[] = { false, true, true, true, true, false, true };
791
792 for (std::vector<TableRow>::const_iterator i = rows.begin(); i != rows.end(); ++i) {
793 std::cout.fill((*i).m_fill);
794 for (unsigned short j = 0; j < sizeof(cw) / sizeof(unsigned short); ++j) {
795 std::cout << (*i).m_separator << (*i).m_fill;
796 std::cout.setf((align_left[j] ? std::ios::left : std::ios::right), std::ios::adjustfield);
797 std::cout.width(cw[j]);
798 std::cout << (*i).m_items[j] << (*i).m_fill;
799 }
800 std::cout << (*i).m_separator << std::endl;
801 }
802 }
803 }
804
805 session->transaction().commit();
806
808 }
809
811 }
812
813 catch (coral::Exception& e) {
814 std::cerr << "CORAL exception: " << e.what() << std::endl;
815 return 1;
816 }
817
818 catch (std::exception& e) {
819 std::cerr << "Standard C++ exception : " << e.what() << std::endl;
820 return 2;
821 }
822
823 catch (...) {
824 std::cerr << "Exception caught (...)" << std::endl;
825 return 3;
826 }
827
829
830 return 0;
831}
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.
static void usage(const char *s)
static void no_param(const char *s)
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)
TableRow(const char fill, const char separator)