@ -25,7 +25,12 @@ class Status {
public :
public :
// Create a success status.
// Create a success status.
Status ( ) : code_ ( kOk ) , subcode_ ( kNone ) , sev_ ( kNoError ) , state_ ( nullptr ) { }
Status ( ) : code_ ( kOk ) , subcode_ ( kNone ) , sev_ ( kNoError ) , state_ ( nullptr ) { }
~ Status ( ) { delete [ ] state_ ; }
~ Status ( ) {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
assert ( checked_ ) ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
delete [ ] state_ ;
}
// Copy the specified status.
// Copy the specified status.
Status ( const Status & s ) ;
Status ( const Status & s ) ;
@ -43,6 +48,15 @@ class Status {
bool operator = = ( const Status & rhs ) const ;
bool operator = = ( const Status & rhs ) const ;
bool operator ! = ( const Status & rhs ) const ;
bool operator ! = ( const Status & rhs ) const ;
// In case of intentionally swallowing an error, user must explicitly call
// this function. That way we are easily able to search the code to find where
// error swallowing occurs.
void PermitUncheckedError ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
}
enum Code : unsigned char {
enum Code : unsigned char {
kOk = 0 ,
kOk = 0 ,
kNotFound = 1 ,
kNotFound = 1 ,
@ -63,7 +77,12 @@ class Status {
kMaxCode
kMaxCode
} ;
} ;
Code code ( ) const { return code_ ; }
Code code ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return code_ ;
}
enum SubCode : unsigned char {
enum SubCode : unsigned char {
kNone = 0 ,
kNone = 0 ,
@ -83,7 +102,12 @@ class Status {
kMaxSubCode
kMaxSubCode
} ;
} ;
SubCode subcode ( ) const { return subcode_ ; }
SubCode subcode ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return subcode_ ;
}
enum Severity : unsigned char {
enum Severity : unsigned char {
kNoError = 0 ,
kNoError = 0 ,
@ -95,10 +119,20 @@ class Status {
} ;
} ;
Status ( const Status & s , Severity sev ) ;
Status ( const Status & s , Severity sev ) ;
Severity severity ( ) const { return sev_ ; }
Severity severity ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return sev_ ;
}
// Returns a C style string indicating the message of the Status
// Returns a C style string indicating the message of the Status
const char * getState ( ) const { return state_ ; }
const char * getState ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return state_ ;
}
// Return a success status.
// Return a success status.
static Status OK ( ) { return Status ( ) ; }
static Status OK ( ) { return Status ( ) ; }
@ -233,65 +267,156 @@ class Status {
}
}
// Returns true iff the status indicates success.
// Returns true iff the status indicates success.
bool ok ( ) const { return code ( ) = = kOk ; }
bool ok ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return code ( ) = = kOk ;
}
// Returns true iff the status indicates success *with* something
// Returns true iff the status indicates success *with* something
// overwritten
// overwritten
bool IsOkOverwritten ( ) const {
bool IsOkOverwritten ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return code ( ) = = kOk & & subcode ( ) = = kOverwritten ;
return code ( ) = = kOk & & subcode ( ) = = kOverwritten ;
}
}
// Returns true iff the status indicates a NotFound error.
// Returns true iff the status indicates a NotFound error.
bool IsNotFound ( ) const { return code ( ) = = kNotFound ; }
bool IsNotFound ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return code ( ) = = kNotFound ;
}
// Returns true iff the status indicates a Corruption error.
// Returns true iff the status indicates a Corruption error.
bool IsCorruption ( ) const { return code ( ) = = kCorruption ; }
bool IsCorruption ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return code ( ) = = kCorruption ;
}
// Returns true iff the status indicates a NotSupported error.
// Returns true iff the status indicates a NotSupported error.
bool IsNotSupported ( ) const { return code ( ) = = kNotSupported ; }
bool IsNotSupported ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return code ( ) = = kNotSupported ;
}
// Returns true iff the status indicates an InvalidArgument error.
// Returns true iff the status indicates an InvalidArgument error.
bool IsInvalidArgument ( ) const { return code ( ) = = kInvalidArgument ; }
bool IsInvalidArgument ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return code ( ) = = kInvalidArgument ;
}
// Returns true iff the status indicates an IOError.
// Returns true iff the status indicates an IOError.
bool IsIOError ( ) const { return code ( ) = = kIOError ; }
bool IsIOError ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return code ( ) = = kIOError ;
}
// Returns true iff the status indicates an MergeInProgress.
// Returns true iff the status indicates an MergeInProgress.
bool IsMergeInProgress ( ) const { return code ( ) = = kMergeInProgress ; }
bool IsMergeInProgress ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return code ( ) = = kMergeInProgress ;
}
// Returns true iff the status indicates Incomplete
// Returns true iff the status indicates Incomplete
bool IsIncomplete ( ) const { return code ( ) = = kIncomplete ; }
bool IsIncomplete ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return code ( ) = = kIncomplete ;
}
// Returns true iff the status indicates Shutdown In progress
// Returns true iff the status indicates Shutdown In progress
bool IsShutdownInProgress ( ) const { return code ( ) = = kShutdownInProgress ; }
bool IsShutdownInProgress ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return code ( ) = = kShutdownInProgress ;
}
bool IsTimedOut ( ) const { return code ( ) = = kTimedOut ; }
bool IsTimedOut ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return code ( ) = = kTimedOut ;
}
bool IsAborted ( ) const { return code ( ) = = kAborted ; }
bool IsAborted ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return code ( ) = = kAborted ;
}
bool IsLockLimit ( ) const {
bool IsLockLimit ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return code ( ) = = kAborted & & subcode ( ) = = kLockLimit ;
return code ( ) = = kAborted & & subcode ( ) = = kLockLimit ;
}
}
// Returns true iff the status indicates that a resource is Busy and
// Returns true iff the status indicates that a resource is Busy and
// temporarily could not be acquired.
// temporarily could not be acquired.
bool IsBusy ( ) const { return code ( ) = = kBusy ; }
bool IsBusy ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return code ( ) = = kBusy ;
}
bool IsDeadlock ( ) const { return code ( ) = = kBusy & & subcode ( ) = = kDeadlock ; }
bool IsDeadlock ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return code ( ) = = kBusy & & subcode ( ) = = kDeadlock ;
}
// Returns true iff the status indicated that the operation has Expired.
// Returns true iff the status indicated that the operation has Expired.
bool IsExpired ( ) const { return code ( ) = = kExpired ; }
bool IsExpired ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return code ( ) = = kExpired ;
}
// Returns true iff the status indicates a TryAgain error.
// Returns true iff the status indicates a TryAgain error.
// This usually means that the operation failed, but may succeed if
// This usually means that the operation failed, but may succeed if
// re-attempted.
// re-attempted.
bool IsTryAgain ( ) const { return code ( ) = = kTryAgain ; }
bool IsTryAgain ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return code ( ) = = kTryAgain ;
}
// Returns true iff the status indicates the proposed compaction is too large
// Returns true iff the status indicates the proposed compaction is too large
bool IsCompactionTooLarge ( ) const { return code ( ) = = kCompactionTooLarge ; }
bool IsCompactionTooLarge ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return code ( ) = = kCompactionTooLarge ;
}
// Returns true iff the status indicates Column Family Dropped
// Returns true iff the status indicates Column Family Dropped
bool IsColumnFamilyDropped ( ) const { return code ( ) = = kColumnFamilyDropped ; }
bool IsColumnFamilyDropped ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return code ( ) = = kColumnFamilyDropped ;
}
// Returns true iff the status indicates a NoSpace error
// Returns true iff the status indicates a NoSpace error
// This is caused by an I/O error returning the specific "out of space"
// This is caused by an I/O error returning the specific "out of space"
@ -299,6 +424,9 @@ class Status {
// with a specific subcode, enabling users to take the appropriate action
// with a specific subcode, enabling users to take the appropriate action
// if needed
// if needed
bool IsNoSpace ( ) const {
bool IsNoSpace ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return ( code ( ) = = kIOError ) & & ( subcode ( ) = = kNoSpace ) ;
return ( code ( ) = = kIOError ) & & ( subcode ( ) = = kNoSpace ) ;
}
}
@ -306,6 +434,9 @@ class Status {
// cases where we limit the memory used in certain operations (eg. the size
// cases where we limit the memory used in certain operations (eg. the size
// of a write batch) in order to avoid out of memory exceptions.
// of a write batch) in order to avoid out of memory exceptions.
bool IsMemoryLimit ( ) const {
bool IsMemoryLimit ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return ( code ( ) = = kAborted ) & & ( subcode ( ) = = kMemoryLimit ) ;
return ( code ( ) = = kAborted ) & & ( subcode ( ) = = kMemoryLimit ) ;
}
}
@ -314,17 +445,26 @@ class Status {
// directory" error condition. A PathNotFound error is an I/O error with
// directory" error condition. A PathNotFound error is an I/O error with
// a specific subcode, enabling users to take appropriate action if necessary
// a specific subcode, enabling users to take appropriate action if necessary
bool IsPathNotFound ( ) const {
bool IsPathNotFound ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return ( code ( ) = = kIOError ) & & ( subcode ( ) = = kPathNotFound ) ;
return ( code ( ) = = kIOError ) & & ( subcode ( ) = = kPathNotFound ) ;
}
}
// Returns true iff the status indicates manual compaction paused. This
// Returns true iff the status indicates manual compaction paused. This
// is caused by a call to PauseManualCompaction
// is caused by a call to PauseManualCompaction
bool IsManualCompactionPaused ( ) const {
bool IsManualCompactionPaused ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return ( code ( ) = = kIncomplete ) & & ( subcode ( ) = = kManualCompactionPaused ) ;
return ( code ( ) = = kIncomplete ) & & ( subcode ( ) = = kManualCompactionPaused ) ;
}
}
// Returns true iff the status indicates a TxnNotPrepared error.
// Returns true iff the status indicates a TxnNotPrepared error.
bool IsTxnNotPrepared ( ) const {
bool IsTxnNotPrepared ( ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return ( code ( ) = = kInvalidArgument ) & & ( subcode ( ) = = kTxnNotPrepared ) ;
return ( code ( ) = = kInvalidArgument ) & & ( subcode ( ) = = kTxnNotPrepared ) ;
}
}
@ -342,6 +482,9 @@ class Status {
SubCode subcode_ ;
SubCode subcode_ ;
Severity sev_ ;
Severity sev_ ;
const char * state_ ;
const char * state_ ;
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
mutable bool checked_ = false ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
explicit Status ( Code _code , SubCode _subcode = kNone )
explicit Status ( Code _code , SubCode _subcode = kNone )
: code_ ( _code ) , subcode_ ( _subcode ) , sev_ ( kNoError ) , state_ ( nullptr ) { }
: code_ ( _code ) , subcode_ ( _subcode ) , sev_ ( kNoError ) , state_ ( nullptr ) { }
@ -355,16 +498,26 @@ class Status {
inline Status : : Status ( const Status & s )
inline Status : : Status ( const Status & s )
: code_ ( s . code_ ) , subcode_ ( s . subcode_ ) , sev_ ( s . sev_ ) {
: code_ ( s . code_ ) , subcode_ ( s . subcode_ ) , sev_ ( s . sev_ ) {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
s . checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
state_ = ( s . state_ = = nullptr ) ? nullptr : CopyState ( s . state_ ) ;
state_ = ( s . state_ = = nullptr ) ? nullptr : CopyState ( s . state_ ) ;
}
}
inline Status : : Status ( const Status & s , Severity sev )
inline Status : : Status ( const Status & s , Severity sev )
: code_ ( s . code_ ) , subcode_ ( s . subcode_ ) , sev_ ( sev ) {
: code_ ( s . code_ ) , subcode_ ( s . subcode_ ) , sev_ ( sev ) {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
s . checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
state_ = ( s . state_ = = nullptr ) ? nullptr : CopyState ( s . state_ ) ;
state_ = ( s . state_ = = nullptr ) ? nullptr : CopyState ( s . state_ ) ;
}
}
inline Status & Status : : operator = ( const Status & s ) {
inline Status & Status : : operator = ( const Status & s ) {
// The following condition catches both aliasing (when this == &s),
// The following condition catches both aliasing (when this == &s),
// and the common case where both s and *this are ok.
// and the common case where both s and *this are ok.
if ( this ! = & s ) {
if ( this ! = & s ) {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
s . checked_ = true ;
checked_ = false ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
code_ = s . code_ ;
code_ = s . code_ ;
subcode_ = s . subcode_ ;
subcode_ = s . subcode_ ;
sev_ = s . sev_ ;
sev_ = s . sev_ ;
@ -379,6 +532,9 @@ inline Status::Status(Status&& s)
noexcept
noexcept
# endif
# endif
: Status ( ) {
: Status ( ) {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
s . checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
* this = std : : move ( s ) ;
* this = std : : move ( s ) ;
}
}
@ -388,6 +544,10 @@ inline Status& Status::operator=(Status&& s)
# endif
# endif
{
{
if ( this ! = & s ) {
if ( this ! = & s ) {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
s . checked_ = true ;
checked_ = false ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
code_ = std : : move ( s . code_ ) ;
code_ = std : : move ( s . code_ ) ;
s . code_ = kOk ;
s . code_ = kOk ;
subcode_ = std : : move ( s . subcode_ ) ;
subcode_ = std : : move ( s . subcode_ ) ;
@ -402,10 +562,18 @@ inline Status& Status::operator=(Status&& s)
}
}
inline bool Status : : operator = = ( const Status & rhs ) const {
inline bool Status : : operator = = ( const Status & rhs ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
rhs . checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return ( code_ = = rhs . code_ ) ;
return ( code_ = = rhs . code_ ) ;
}
}
inline bool Status : : operator ! = ( const Status & rhs ) const {
inline bool Status : : operator ! = ( const Status & rhs ) const {
# ifdef ROCKSDB_ASSERT_STATUS_CHECKED
checked_ = true ;
rhs . checked_ = true ;
# endif // ROCKSDB_ASSERT_STATUS_CHECKED
return ! ( * this = = rhs ) ;
return ! ( * this = = rhs ) ;
}
}