rocksdb/util/status.cc

162 lines
5.0 KiB
C++
Raw Normal View History

// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
//
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
#include "rocksdb/status.h"
#include <stdio.h>
#ifdef OS_WIN
#include <string.h>
#endif
#include <cstring>
#include "port/port.h"
namespace ROCKSDB_NAMESPACE {
std::unique_ptr<const char[]> Status::CopyState(const char* s) {
const size_t cch = std::strlen(s) + 1; // +1 for the null terminator
char* rv = new char[cch];
std::strncpy(rv, s, cch);
return std::unique_ptr<const char[]>(rv);
}
static const char* msgs[static_cast<int>(Status::kMaxSubCode)] = {
"", // kNone
"Timeout Acquiring Mutex", // kMutexTimeout
"Timeout waiting to lock key", // kLockTimeout
"Failed to acquire lock due to max_num_locks limit", // kLockLimit
"No space left on device", // kNoSpace
"Deadlock", // kDeadlock
"Stale file handle", // kStaleFile
"Memory limit reached", // kMemoryLimit
Support for single-primary, multi-secondary instances (#4899) Summary: This PR allows RocksDB to run in single-primary, multi-secondary process mode. The writer is a regular RocksDB (e.g. an `DBImpl`) instance playing the role of a primary. Multiple `DBImplSecondary` processes (secondaries) share the same set of SST files, MANIFEST, WAL files with the primary. Secondaries tail the MANIFEST of the primary and apply updates to their own in-memory state of the file system, e.g. `VersionStorageInfo`. This PR has several components: 1. (Originally in #4745). Add a `PathNotFound` subcode to `IOError` to denote the failure when a secondary tries to open a file which has been deleted by the primary. 2. (Similar to #4602). Add `FragmentBufferedReader` to handle partially-read, trailing record at the end of a log from where future read can continue. 3. (Originally in #4710 and #4820). Add implementation of the secondary, i.e. `DBImplSecondary`. 3.1 Tail the primary's MANIFEST during recovery. 3.2 Tail the primary's MANIFEST during normal processing by calling `ReadAndApply`. 3.3 Tailing WAL will be in a future PR. 4. Add an example in 'examples/multi_processes_example.cc' to demonstrate the usage of secondary RocksDB instance in a multi-process setting. Instructions to run the example can be found at the beginning of the source code. Pull Request resolved: https://github.com/facebook/rocksdb/pull/4899 Differential Revision: D14510945 Pulled By: riversand963 fbshipit-source-id: 4ac1c5693e6012ad23f7b4b42d3c374fecbe8886
2019-03-26 23:41:31 +00:00
"Space limit reached", // kSpaceLimit
"No such file or directory", // kPathNotFound
// KMergeOperandsInsufficientCapacity
"Insufficient capacity for merge operands",
// kManualCompactionPaused
"Manual compaction paused",
" (overwritten)", // kOverwritten, subcode of OK
"Txn not prepared", // kTxnNotPrepared
"IO fenced off", // kIOFenced
};
Status::Status(Code _code, SubCode _subcode, const Slice& msg,
const Slice& msg2, Severity sev)
Combine data members of IOStatus with Status (#9549) Summary: Combine the data members retryable_, data_loss_ and scope_ of IOStatus with Status, as protected members. IOStatus is now defined as a derived class of Status with no new data, but additional methods. This will allow us to eventually track the result of FileSystem calls in RocksDB with one variable instead of two. Benchmark commands and results are below. The performance after changes seems slightly better. ```./db_bench -db=/data/mysql/rocksdb/prefix_scan -benchmarks="fillseq" -key_size=32 -value_size=512 -num=5000000 -use_direct_io_for_flush_and_compaction=true -target_file_size_base=16777216``` ```./db_bench -use_existing_db=true --db=/data/mysql/rocksdb/prefix_scan -benchmarks="readseq,seekrandom,readseq" -key_size=32 -value_size=512 -num=5000000 -seek_nexts=10000 -use_direct_reads=true -duration=60 -ops_between_duration_checks=1 -readonly=true -adaptive_readahead=false -threads=1 -cache_size=10485760000``` Before - seekrandom : 3715.432 micros/op 269 ops/sec; 1394.9 MB/s (16149 of 16149 found) seekrandom : 3687.177 micros/op 271 ops/sec; 1405.6 MB/s (16273 of 16273 found) seekrandom : 3709.646 micros/op 269 ops/sec; 1397.1 MB/s (16175 of 16175 found) readseq : 0.369 micros/op 2711321 ops/sec; 1406.6 MB/s readseq : 0.363 micros/op 2754092 ops/sec; 1428.8 MB/s readseq : 0.372 micros/op 2688046 ops/sec; 1394.6 MB/s After - seekrandom : 3606.830 micros/op 277 ops/sec; 1436.9 MB/s (16636 of 16636 found) seekrandom : 3594.467 micros/op 278 ops/sec; 1441.9 MB/s (16693 of 16693 found) seekrandom : 3597.919 micros/op 277 ops/sec; 1440.5 MB/s (16677 of 16677 found) readseq : 0.354 micros/op 2822809 ops/sec; 1464.5 MB/s readseq : 0.358 micros/op 2795080 ops/sec; 1450.1 MB/s readseq : 0.354 micros/op 2822889 ops/sec; 1464.5 MB/s Pull Request resolved: https://github.com/facebook/rocksdb/pull/9549 Reviewed By: pdillinger Differential Revision: D34310362 Pulled By: anand1976 fbshipit-source-id: 54b27756edf9c9ecfe730a2dce542a7a46743096
2022-02-22 18:34:57 +00:00
: code_(_code),
subcode_(_subcode),
sev_(sev),
retryable_(false),
data_loss_(false),
scope_(0) {
assert(subcode_ != kMaxSubCode);
const size_t len1 = msg.size();
const size_t len2 = msg2.size();
const size_t size = len1 + (len2 ? (2 + len2) : 0);
char* const result = new char[size + 1]; // +1 for null terminator
memcpy(result, msg.data(), len1);
if (len2) {
result[len1] = ':';
result[len1 + 1] = ' ';
memcpy(result + len1 + 2, msg2.data(), len2);
}
result[size] = '\0'; // null terminator for C style string
state_.reset(result);
}
Status Status::CopyAppendMessage(const Status& s, const Slice& delim,
const Slice& msg) {
// (No attempt at efficiency)
return Status(s.code(), s.subcode(), s.severity(),
std::string(s.getState()) + delim.ToString() + msg.ToString());
}
std::string Status::ToString() const {
#ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true;
#endif // ROCKSDB_ASSERT_STATUS_CHECKED
const char* type = nullptr;
switch (code_) {
case kOk:
return "OK";
case kNotFound:
type = "NotFound: ";
break;
case kCorruption:
type = "Corruption: ";
break;
case kNotSupported:
type = "Not implemented: ";
break;
case kInvalidArgument:
type = "Invalid argument: ";
break;
case kIOError:
type = "IO error: ";
break;
case kMergeInProgress:
type = "Merge in progress: ";
break;
case kIncomplete:
type = "Result incomplete: ";
break;
case kShutdownInProgress:
type = "Shutdown in progress: ";
break;
case kTimedOut:
type = "Operation timed out: ";
break;
case kAborted:
type = "Operation aborted: ";
break;
case kBusy:
type = "Resource busy: ";
break;
case kExpired:
type = "Operation expired: ";
break;
case kTryAgain:
type = "Operation failed. Try again.: ";
break;
case kCompactionTooLarge:
type = "Compaction too large: ";
break;
case kColumnFamilyDropped:
type = "Column family dropped: ";
break;
case kMaxCode:
assert(false);
break;
}
char tmp[30];
if (type == nullptr) {
// This should not happen since `code_` should be a valid non-`kMaxCode`
// member of the `Code` enum. The above switch-statement should have had a
// case assigning `type` to a corresponding string.
assert(false);
snprintf(tmp, sizeof(tmp), "Unknown code(%d): ", static_cast<int>(code()));
type = tmp;
}
std::string result(type);
if (subcode_ != kNone) {
uint32_t index = static_cast<int32_t>(subcode_);
assert(sizeof(msgs) / sizeof(msgs[0]) > index);
result.append(msgs[index]);
}
if (state_ != nullptr) {
if (subcode_ != kNone) {
result.append(": ");
}
result.append(state_.get());
}
return result;
}
} // namespace ROCKSDB_NAMESPACE