@ -14,9 +14,13 @@ namespace ROCKSDB_NAMESPACE {
void WalAddition : : EncodeTo ( std : : string * dst ) const {
void WalAddition : : EncodeTo ( std : : string * dst ) const {
PutVarint64 ( dst , number_ ) ;
PutVarint64 ( dst , number_ ) ;
if ( metadata_ . HasSize ( ) ) {
if ( metadata_ . HasSyncedSize ( ) ) {
PutVarint32 ( dst , static_cast < uint32_t > ( WalAdditionTag : : kSize ) ) ;
PutVarint32 ( dst , static_cast < uint32_t > ( WalAdditionTag : : kSyncedSize ) ) ;
PutVarint64 ( dst , metadata_ . GetSizeInBytes ( ) ) ;
PutVarint64 ( dst , metadata_ . GetSyncedSizeInBytes ( ) ) ;
}
if ( metadata_ . IsClosed ( ) ) {
PutVarint32 ( dst , static_cast < uint32_t > ( WalAdditionTag : : kClosed ) ) ;
}
}
PutVarint32 ( dst , static_cast < uint32_t > ( WalAdditionTag : : kTerminate ) ) ;
PutVarint32 ( dst , static_cast < uint32_t > ( WalAdditionTag : : kTerminate ) ) ;
@ -36,12 +40,16 @@ Status WalAddition::DecodeFrom(Slice* src) {
}
}
WalAdditionTag tag = static_cast < WalAdditionTag > ( tag_value ) ;
WalAdditionTag tag = static_cast < WalAdditionTag > ( tag_value ) ;
switch ( tag ) {
switch ( tag ) {
case WalAdditionTag : : kSize : {
case WalAdditionTag : : kSyncedS ize : {
uint64_t size = 0 ;
uint64_t size = 0 ;
if ( ! GetVarint64 ( src , & size ) ) {
if ( ! GetVarint64 ( src , & size ) ) {
return Status : : Corruption ( class_name , " Error decoding WAL file size " ) ;
return Status : : Corruption ( class_name , " Error decoding WAL file size " ) ;
}
}
metadata_ . SetSizeInBytes ( size ) ;
metadata_ . SetSyncedSizeInBytes ( size ) ;
break ;
}
case WalAdditionTag : : kClosed : {
metadata_ . SetClosed ( ) ;
break ;
break ;
}
}
// TODO: process future tags such as checksum.
// TODO: process future tags such as checksum.
@ -57,14 +65,16 @@ Status WalAddition::DecodeFrom(Slice* src) {
}
}
JSONWriter & operator < < ( JSONWriter & jw , const WalAddition & wal ) {
JSONWriter & operator < < ( JSONWriter & jw , const WalAddition & wal ) {
jw < < " LogNumber " < < wal . GetLogNumber ( ) < < " SizeInBytes "
jw < < " LogNumber " < < wal . GetLogNumber ( ) < < " SyncedSizeInBytes "
< < wal . GetMetadata ( ) . GetSizeInBytes ( ) ;
< < wal . GetMetadata ( ) . GetSyncedSizeInBytes ( ) < < " Closed "
< < wal . GetMetadata ( ) . IsClosed ( ) ;
return jw ;
return jw ;
}
}
std : : ostream & operator < < ( std : : ostream & os , const WalAddition & wal ) {
std : : ostream & operator < < ( std : : ostream & os , const WalAddition & wal ) {
os < < " log_number: " < < wal . GetLogNumber ( )
os < < " log_number: " < < wal . GetLogNumber ( )
< < " size_in_bytes: " < < wal . GetMetadata ( ) . GetSizeInBytes ( ) ;
< < " synced_size_in_bytes: " < < wal . GetMetadata ( ) . GetSyncedSizeInBytes ( )
< < " closed: " < < wal . GetMetadata ( ) . IsClosed ( ) ;
return os ;
return os ;
}
}
@ -106,26 +116,33 @@ std::string WalDeletion::DebugString() const {
Status WalSet : : AddWal ( const WalAddition & wal ) {
Status WalSet : : AddWal ( const WalAddition & wal ) {
auto it = wals_ . lower_bound ( wal . GetLogNumber ( ) ) ;
auto it = wals_ . lower_bound ( wal . GetLogNumber ( ) ) ;
if ( wal . GetMetadata ( ) . HasSize ( ) ) {
bool existing = it ! = wals_ . end ( ) & & it - > first = = wal . GetLogNumber ( ) ;
// The WAL must exist without size.
if ( wal . GetMetadata ( ) . IsClosed ( ) ) {
if ( it = = wals_ . end ( ) | | it - > first ! = wal . GetLogNumber ( ) ) {
// The WAL must exist and not closed.
if ( ! existing ) {
std : : stringstream ss ;
std : : stringstream ss ;
ss < < " WAL " < < wal . GetLogNumber ( ) < < " is not created before closing " ;
ss < < " WAL " < < wal . GetLogNumber ( ) < < " is not created before closing " ;
return Status : : Corruption ( " WalSet " , ss . str ( ) ) ;
return Status : : Corruption ( " WalSet " , ss . str ( ) ) ;
}
}
if ( it - > second . HasSize ( ) ) {
if ( it - > second . IsClosed ( ) ) {
std : : stringstream ss ;
std : : stringstream ss ;
ss < < " WAL " < < wal . GetLogNumber ( ) < < " is closed more than once " ;
ss < < " WAL " < < wal . GetLogNumber ( ) < < " is closed more than once " ;
return Status : : Corruption ( " WalSet " , ss . str ( ) ) ;
return Status : : Corruption ( " WalSet " , ss . str ( ) ) ;
}
}
}
// If the WAL has synced size, it must >= the previous size.
if ( existing & & it - > second . HasSyncedSize ( ) & &
( ! wal . GetMetadata ( ) . HasSyncedSize ( ) | |
wal . GetMetadata ( ) . GetSyncedSizeInBytes ( ) <
it - > second . GetSyncedSizeInBytes ( ) ) ) {
std : : stringstream ss ;
ss < < " WAL " < < wal . GetLogNumber ( )
< < " must not have smaller synced size than previous one " ;
return Status : : Corruption ( " WalSet " , ss . str ( ) ) ;
}
if ( existing ) {
it - > second = wal . GetMetadata ( ) ;
it - > second = wal . GetMetadata ( ) ;
} else {
} else {
// The WAL must not exist beforehand.
if ( it ! = wals_ . end ( ) & & it - > first = = wal . GetLogNumber ( ) ) {
std : : stringstream ss ;
ss < < " WAL " < < wal . GetLogNumber ( ) < < " is created more than once " ;
return Status : : Corruption ( " WalSet " , ss . str ( ) ) ;
}
wals_ . insert ( it , { wal . GetLogNumber ( ) , wal . GetMetadata ( ) } ) ;
wals_ . insert ( it , { wal . GetLogNumber ( ) , wal . GetMetadata ( ) } ) ;
}
}
return Status : : OK ( ) ;
return Status : : OK ( ) ;
@ -150,7 +167,7 @@ Status WalSet::DeleteWal(const WalDeletion& wal) {
ss < < " WAL " < < wal . GetLogNumber ( ) < < " must exist before deletion " ;
ss < < " WAL " < < wal . GetLogNumber ( ) < < " must exist before deletion " ;
return Status : : Corruption ( " WalSet " , ss . str ( ) ) ;
return Status : : Corruption ( " WalSet " , ss . str ( ) ) ;
}
}
if ( ! it - > second . HasSize ( ) ) {
if ( ! it - > second . IsClosed ( ) ) {
std : : stringstream ss ;
std : : stringstream ss ;
ss < < " WAL " < < wal . GetLogNumber ( ) < < " must be closed before deletion " ;
ss < < " WAL " < < wal . GetLogNumber ( ) < < " must be closed before deletion " ;
return Status : : Corruption ( " WalSet " , ss . str ( ) ) ;
return Status : : Corruption ( " WalSet " , ss . str ( ) ) ;