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