| 629 | } |
| 630 | |
| 631 | SpanDB* SpanDB::Open() { |
| 632 | // Remove old rpcz directory even if crash occurs. |
| 633 | if (!FLAGS_rpcz_keep_span_db) { |
| 634 | butil::FileEnumerator dirs(butil::FilePath(FLAGS_rpcz_database_dir), false, |
| 635 | butil::FileEnumerator::DIRECTORIES, "[0-9]*.[0-9]*.[0-9]*"); |
| 636 | for (auto name = dirs.Next(); !name.empty(); name = dirs.Next()) { |
| 637 | butil::DeleteFile(name, true); |
| 638 | } |
| 639 | } |
| 640 | |
| 641 | SpanDB local; |
| 642 | leveldb::Status st; |
| 643 | char prefix[64]; |
| 644 | time_t rawtime; |
| 645 | time(&rawtime); |
| 646 | struct tm lt_buf; |
| 647 | struct tm* timeinfo = localtime_r(&rawtime, <_buf); |
| 648 | const size_t nw = strftime(prefix, sizeof(prefix), |
| 649 | "/%Y%m%d.%H%M%S", timeinfo); |
| 650 | const int nw2 = snprintf(prefix + nw, sizeof(prefix) - nw, ".%d", |
| 651 | getpid()); |
| 652 | leveldb::Options options; |
| 653 | options.create_if_missing = true; |
| 654 | options.error_if_exists = true; |
| 655 | |
| 656 | local.id_db_name.append(FLAGS_rpcz_database_dir); |
| 657 | local.id_db_name.append(prefix, nw + nw2); |
| 658 | // Create the dir first otherwise leveldb fails. |
| 659 | butil::File::Error error; |
| 660 | const butil::FilePath dir(local.id_db_name); |
| 661 | if (!butil::CreateDirectoryAndGetError(dir, &error)) { |
| 662 | LOG(ERROR) << "Fail to create directory=`" << dir.value() << ", " |
| 663 | << error; |
| 664 | return NULL; |
| 665 | } |
| 666 | |
| 667 | local.id_db_name.append("/id.db"); |
| 668 | st = leveldb::DB::Open(options, local.id_db_name.c_str(), &local.id_db); |
| 669 | if (!st.ok()) { |
| 670 | LOG(ERROR) << "Fail to open id_db: " << st.ToString(); |
| 671 | return NULL; |
| 672 | } |
| 673 | |
| 674 | local.time_db_name.append(FLAGS_rpcz_database_dir); |
| 675 | local.time_db_name.append(prefix, nw + nw2); |
| 676 | local.time_db_name.append("/time.db"); |
| 677 | st = leveldb::DB::Open(options, local.time_db_name.c_str(), &local.time_db); |
| 678 | if (!st.ok()) { |
| 679 | LOG(ERROR) << "Fail to open time_db: " << st.ToString(); |
| 680 | return NULL; |
| 681 | } |
| 682 | SpanDB* db = new (std::nothrow) SpanDB; |
| 683 | if (NULL == db) { |
| 684 | return NULL; |
| 685 | } |
| 686 | LOG(INFO) << "Opened " << local.id_db_name << " and " |
| 687 | << local.time_db_name; |
| 688 | Swap(local, *db); |