dc9d70de65
Summary: Optimistic transactions supporting begin/commit/rollback semantics. Currently relies on checking the memtable to determine if there are any collisions at commit time. Not yet implemented would be a way of enuring the memtable has some minimum amount of history so that we won't fail to commit when the memtable is empty. You should probably start with transaction.h to get an overview of what is currently supported. Test Plan: Added a new test, but still need to look into stress testing. Reviewers: yhchiang, igor, rven, sdong Reviewed By: sdong Subscribers: adamretter, MarkCallaghan, leveldb, dhruba Differential Revision: https://reviews.facebook.net/D33435
176 lines
5.8 KiB
C++
176 lines
5.8 KiB
C++
// Copyright (c) 2013, Facebook, Inc. All rights reserved.
|
|
// This source code is licensed under the BSD-style license found in the
|
|
// LICENSE file in the root directory of this source tree. An additional grant
|
|
// of patent rights can be found in the PATENTS file in the same 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.
|
|
//
|
|
// A Status encapsulates the result of an operation. It may indicate success,
|
|
// or it may indicate an error with an associated error message.
|
|
//
|
|
// Multiple threads can invoke const methods on a Status without
|
|
// external synchronization, but if any of the threads may call a
|
|
// non-const method, all threads accessing the same Status must use
|
|
// external synchronization.
|
|
|
|
#ifndef STORAGE_ROCKSDB_INCLUDE_STATUS_H_
|
|
#define STORAGE_ROCKSDB_INCLUDE_STATUS_H_
|
|
|
|
#include <string>
|
|
#include "rocksdb/slice.h"
|
|
|
|
namespace rocksdb {
|
|
|
|
class Status {
|
|
public:
|
|
// Create a success status.
|
|
Status() : code_(kOk), state_(nullptr) { }
|
|
~Status() { delete[] state_; }
|
|
|
|
// Copy the specified status.
|
|
Status(const Status& s);
|
|
void operator=(const Status& s);
|
|
|
|
// Return a success status.
|
|
static Status OK() { return Status(); }
|
|
|
|
// Return error status of an appropriate type.
|
|
static Status NotFound(const Slice& msg, const Slice& msg2 = Slice()) {
|
|
return Status(kNotFound, msg, msg2);
|
|
}
|
|
// Fast path for not found without malloc;
|
|
static Status NotFound() {
|
|
return Status(kNotFound);
|
|
}
|
|
static Status Corruption(const Slice& msg, const Slice& msg2 = Slice()) {
|
|
return Status(kCorruption, msg, msg2);
|
|
}
|
|
static Status NotSupported(const Slice& msg, const Slice& msg2 = Slice()) {
|
|
return Status(kNotSupported, msg, msg2);
|
|
}
|
|
static Status InvalidArgument(const Slice& msg, const Slice& msg2 = Slice()) {
|
|
return Status(kInvalidArgument, msg, msg2);
|
|
}
|
|
static Status IOError(const Slice& msg, const Slice& msg2 = Slice()) {
|
|
return Status(kIOError, msg, msg2);
|
|
}
|
|
static Status MergeInProgress(const Slice& msg, const Slice& msg2 = Slice()) {
|
|
return Status(kMergeInProgress, msg, msg2);
|
|
}
|
|
static Status Incomplete(const Slice& msg, const Slice& msg2 = Slice()) {
|
|
return Status(kIncomplete, msg, msg2);
|
|
}
|
|
static Status ShutdownInProgress() {
|
|
return Status(kShutdownInProgress);
|
|
}
|
|
static Status ShutdownInProgress(const Slice& msg,
|
|
const Slice& msg2 = Slice()) {
|
|
return Status(kShutdownInProgress, msg, msg2);
|
|
}
|
|
static Status TimedOut() {
|
|
return Status(kTimedOut);
|
|
}
|
|
static Status TimedOut(const Slice& msg, const Slice& msg2 = Slice()) {
|
|
return Status(kTimedOut, msg, msg2);
|
|
}
|
|
static Status Aborted() {
|
|
return Status(kAborted);
|
|
}
|
|
static Status Aborted(const Slice& msg, const Slice& msg2 = Slice()) {
|
|
return Status(kAborted, msg, msg2);
|
|
}
|
|
static Status Busy() { return Status(kBusy); }
|
|
static Status Busy(const Slice& msg, const Slice& msg2 = Slice()) {
|
|
return Status(kBusy, msg, msg2);
|
|
}
|
|
|
|
// Returns true iff the status indicates success.
|
|
bool ok() const { return code() == kOk; }
|
|
|
|
// Returns true iff the status indicates a NotFound error.
|
|
bool IsNotFound() const { return code() == kNotFound; }
|
|
|
|
// Returns true iff the status indicates a Corruption error.
|
|
bool IsCorruption() const { return code() == kCorruption; }
|
|
|
|
// Returns true iff the status indicates a NotSupported error.
|
|
bool IsNotSupported() const { return code() == kNotSupported; }
|
|
|
|
// Returns true iff the status indicates an InvalidArgument error.
|
|
bool IsInvalidArgument() const { return code() == kInvalidArgument; }
|
|
|
|
// Returns true iff the status indicates an IOError.
|
|
bool IsIOError() const { return code() == kIOError; }
|
|
|
|
// Returns true iff the status indicates an MergeInProgress.
|
|
bool IsMergeInProgress() const { return code() == kMergeInProgress; }
|
|
|
|
// Returns true iff the status indicates Incomplete
|
|
bool IsIncomplete() const { return code() == kIncomplete; }
|
|
|
|
// Returns true iff the status indicates Shutdown In progress
|
|
bool IsShutdownInProgress() const { return code() == kShutdownInProgress; }
|
|
|
|
bool IsTimedOut() const { return code() == kTimedOut; }
|
|
|
|
bool IsAborted() const { return code() == kAborted; }
|
|
|
|
// Returns true iff the status indicates that a resource is Busy and
|
|
// temporarily could not be acquired.
|
|
bool IsBusy() const { return code() == kBusy; }
|
|
|
|
// Return a string representation of this status suitable for printing.
|
|
// Returns the string "OK" for success.
|
|
std::string ToString() const;
|
|
|
|
enum Code {
|
|
kOk = 0,
|
|
kNotFound = 1,
|
|
kCorruption = 2,
|
|
kNotSupported = 3,
|
|
kInvalidArgument = 4,
|
|
kIOError = 5,
|
|
kMergeInProgress = 6,
|
|
kIncomplete = 7,
|
|
kShutdownInProgress = 8,
|
|
kTimedOut = 9,
|
|
kAborted = 10,
|
|
kBusy = 11,
|
|
};
|
|
|
|
Code code() const {
|
|
return code_;
|
|
}
|
|
private:
|
|
// A nullptr state_ (which is always the case for OK) means the message
|
|
// is empty.
|
|
// of the following form:
|
|
// state_[0..3] == length of message
|
|
// state_[4..] == message
|
|
Code code_;
|
|
const char* state_;
|
|
|
|
explicit Status(Code _code) : code_(_code), state_(nullptr) {}
|
|
Status(Code _code, const Slice& msg, const Slice& msg2);
|
|
static const char* CopyState(const char* s);
|
|
};
|
|
|
|
inline Status::Status(const Status& s) {
|
|
code_ = s.code_;
|
|
state_ = (s.state_ == nullptr) ? nullptr : CopyState(s.state_);
|
|
}
|
|
inline void Status::operator=(const Status& s) {
|
|
// The following condition catches both aliasing (when this == &s),
|
|
// and the common case where both s and *this are ok.
|
|
code_ = s.code_;
|
|
if (state_ != s.state_) {
|
|
delete[] state_;
|
|
state_ = (s.state_ == nullptr) ? nullptr : CopyState(s.state_);
|
|
}
|
|
}
|
|
|
|
} // namespace rocksdb
|
|
|
|
#endif // STORAGE_ROCKSDB_INCLUDE_STATUS_H_
|