2016-02-09 23:12:00 +00:00
|
|
|
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
2017-07-15 23:03:42 +00:00
|
|
|
// 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).
|
2013-10-16 21:59:46 +00:00
|
|
|
//
|
2011-03-18 22:37:00 +00:00
|
|
|
// 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.
|
|
|
|
|
2017-01-04 02:17:12 +00:00
|
|
|
#include "rocksdb/status.h"
|
2022-10-26 19:08:20 +00:00
|
|
|
|
2024-03-04 18:08:32 +00:00
|
|
|
#include <cstdio>
|
2018-07-19 22:07:22 +00:00
|
|
|
#ifdef OS_WIN
|
|
|
|
#include <string.h>
|
|
|
|
#endif
|
2017-01-04 02:17:12 +00:00
|
|
|
#include <cstring>
|
2022-10-26 19:08:20 +00:00
|
|
|
|
2011-03-18 22:37:00 +00:00
|
|
|
#include "port/port.h"
|
|
|
|
|
2020-02-20 20:07:53 +00:00
|
|
|
namespace ROCKSDB_NAMESPACE {
|
2011-03-18 22:37:00 +00:00
|
|
|
|
2022-02-08 02:20:51 +00:00
|
|
|
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);
|
2011-05-21 02:17:43 +00:00
|
|
|
}
|
|
|
|
|
2018-07-23 22:42:15 +00:00
|
|
|
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
|
2019-03-26 23:41:31 +00:00
|
|
|
"Space limit reached", // kSpaceLimit
|
|
|
|
"No such file or directory", // kPathNotFound
|
2019-09-17 04:00:13 +00:00
|
|
|
// KMergeOperandsInsufficientCapacity
|
|
|
|
"Insufficient capacity for merge operands",
|
|
|
|
// kManualCompactionPaused
|
|
|
|
"Manual compaction paused",
|
2023-02-17 18:58:46 +00:00
|
|
|
" (overwritten)", // kOverwritten, subcode of OK
|
|
|
|
"Txn not prepared", // kTxnNotPrepared
|
|
|
|
"IO fenced off", // kIOFenced
|
|
|
|
"Merge operator failed", // kMergeOperatorFailed
|
2023-09-22 20:49:19 +00:00
|
|
|
"Number of operands merged exceeded threshold", // kMergeOperandThresholdExceeded
|
2018-07-23 22:42:15 +00:00
|
|
|
};
|
|
|
|
|
2018-07-20 21:34:07 +00:00
|
|
|
Status::Status(Code _code, SubCode _subcode, const Slice& msg,
|
2021-05-20 04:40:43 +00:00
|
|
|
const Slice& msg2, Severity sev)
|
2022-02-22 18:34:57 +00:00
|
|
|
: code_(_code),
|
|
|
|
subcode_(_subcode),
|
|
|
|
sev_(sev),
|
|
|
|
retryable_(false),
|
|
|
|
data_loss_(false),
|
|
|
|
scope_(0) {
|
2016-09-07 19:37:45 +00:00
|
|
|
assert(subcode_ != kMaxSubCode);
|
2017-01-04 02:17:12 +00:00
|
|
|
const size_t len1 = msg.size();
|
|
|
|
const size_t len2 = msg2.size();
|
|
|
|
const size_t size = len1 + (len2 ? (2 + len2) : 0);
|
2018-07-13 17:47:49 +00:00
|
|
|
char* const result = new char[size + 1]; // +1 for null terminator
|
2017-01-04 02:17:12 +00:00
|
|
|
memcpy(result, msg.data(), len1);
|
2011-05-21 02:17:43 +00:00
|
|
|
if (len2) {
|
2017-01-04 02:17:12 +00:00
|
|
|
result[len1] = ':';
|
|
|
|
result[len1 + 1] = ' ';
|
|
|
|
memcpy(result + len1 + 2, msg2.data(), len2);
|
2011-03-18 22:37:00 +00:00
|
|
|
}
|
2017-01-04 02:17:12 +00:00
|
|
|
result[size] = '\0'; // null terminator for C style string
|
2022-02-08 02:20:51 +00:00
|
|
|
state_.reset(result);
|
2011-03-18 22:37:00 +00:00
|
|
|
}
|
|
|
|
|
2022-12-09 18:03:47 +00:00
|
|
|
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());
|
|
|
|
}
|
|
|
|
|
2011-03-18 22:37:00 +00:00
|
|
|
std::string Status::ToString() const {
|
2020-05-08 19:36:49 +00:00
|
|
|
#ifdef ROCKSDB_ASSERT_STATUS_CHECKED
|
|
|
|
checked_ = true;
|
|
|
|
#endif // ROCKSDB_ASSERT_STATUS_CHECKED
|
2021-01-16 12:23:12 +00:00
|
|
|
const char* type = nullptr;
|
2013-12-26 21:49:04 +00:00
|
|
|
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:
|
2014-02-12 19:42:54 +00:00
|
|
|
type = "Merge in progress: ";
|
|
|
|
break;
|
|
|
|
case kIncomplete:
|
|
|
|
type = "Result incomplete: ";
|
|
|
|
break;
|
|
|
|
case kShutdownInProgress:
|
|
|
|
type = "Shutdown in progress: ";
|
2013-12-26 21:49:04 +00:00
|
|
|
break;
|
Pessimistic Transactions
Summary:
Initial implementation of Pessimistic Transactions. This diff contains the api changes discussed in D38913. This diff is pretty large, so let me know if people would prefer to meet up to discuss it.
MyRocks folks: please take a look at the API in include/rocksdb/utilities/transaction[_db].h and let me know if you have any issues.
Also, you'll notice a couple of TODOs in the implementation of RollbackToSavePoint(). After chatting with Siying, I'm going to send out a separate diff for an alternate implementation of this feature that implements the rollback inside of WriteBatch/WriteBatchWithIndex. We can then decide which route is preferable.
Next, I'm planning on doing some perf testing and then integrating this diff into MongoRocks for further testing.
Test Plan: Unit tests, db_bench parallel testing.
Reviewers: igor, rven, sdong, yhchiang, yoshinorim
Reviewed By: sdong
Subscribers: hermanlee4, maykov, spetrunia, leveldb, dhruba
Differential Revision: https://reviews.facebook.net/D40869
2015-05-26 00:37:33 +00:00
|
|
|
case kTimedOut:
|
|
|
|
type = "Operation timed out: ";
|
|
|
|
break;
|
CompactFiles, EventListener and GetDatabaseMetaData
Summary:
This diff adds three sets of APIs to RocksDB.
= GetColumnFamilyMetaData =
* This APIs allow users to obtain the current state of a RocksDB instance on one column family.
* See GetColumnFamilyMetaData in include/rocksdb/db.h
= EventListener =
* A virtual class that allows users to implement a set of
call-back functions which will be called when specific
events of a RocksDB instance happens.
* To register EventListener, simply insert an EventListener to ColumnFamilyOptions::listeners
= CompactFiles =
* CompactFiles API inputs a set of file numbers and an output level, and RocksDB
will try to compact those files into the specified level.
= Example =
* Example code can be found in example/compact_files_example.cc, which implements
a simple external compactor using EventListener, GetColumnFamilyMetaData, and
CompactFiles API.
Test Plan:
listener_test
compactor_test
example/compact_files_example
export ROCKSDB_TESTS=CompactFiles
db_test
export ROCKSDB_TESTS=MetaData
db_test
Reviewers: ljin, igor, rven, sdong
Reviewed By: sdong
Subscribers: MarkCallaghan, dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D24705
2014-11-07 22:45:18 +00:00
|
|
|
case kAborted:
|
|
|
|
type = "Operation aborted: ";
|
|
|
|
break;
|
2015-05-29 21:36:35 +00:00
|
|
|
case kBusy:
|
|
|
|
type = "Resource busy: ";
|
|
|
|
break;
|
2015-07-31 03:31:36 +00:00
|
|
|
case kExpired:
|
|
|
|
type = "Operation expired: ";
|
|
|
|
break;
|
|
|
|
case kTryAgain:
|
|
|
|
type = "Operation failed. Try again.: ";
|
|
|
|
break;
|
2021-01-16 12:23:12 +00:00
|
|
|
case kCompactionTooLarge:
|
|
|
|
type = "Compaction too large: ";
|
|
|
|
break;
|
2019-05-20 17:37:37 +00:00
|
|
|
case kColumnFamilyDropped:
|
|
|
|
type = "Column family dropped: ";
|
|
|
|
break;
|
2021-01-16 12:23:12 +00:00
|
|
|
case kMaxCode:
|
|
|
|
assert(false);
|
2013-12-26 21:49:04 +00:00
|
|
|
break;
|
|
|
|
}
|
2021-01-16 12:23:12 +00:00
|
|
|
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;
|
|
|
|
}
|
2013-12-26 21:49:04 +00:00
|
|
|
std::string result(type);
|
2015-08-14 23:45:05 +00:00
|
|
|
if (subcode_ != kNone) {
|
|
|
|
uint32_t index = static_cast<int32_t>(subcode_);
|
2020-07-10 01:11:41 +00:00
|
|
|
assert(sizeof(msgs) / sizeof(msgs[0]) > index);
|
2015-08-14 23:45:05 +00:00
|
|
|
result.append(msgs[index]);
|
|
|
|
}
|
|
|
|
|
2013-12-26 21:49:04 +00:00
|
|
|
if (state_ != nullptr) {
|
2021-02-18 20:24:07 +00:00
|
|
|
if (subcode_ != kNone) {
|
|
|
|
result.append(": ");
|
|
|
|
}
|
2022-02-08 02:20:51 +00:00
|
|
|
result.append(state_.get());
|
2011-03-18 22:37:00 +00:00
|
|
|
}
|
2013-12-26 21:49:04 +00:00
|
|
|
return result;
|
2011-03-18 22:37:00 +00:00
|
|
|
}
|
|
|
|
|
2020-02-20 20:07:53 +00:00
|
|
|
} // namespace ROCKSDB_NAMESPACE
|