@ -305,8 +305,8 @@ void BlobDBImpl::StartBackgroundTasks() {
kDeleteCheckPeriodMillisecs ,
kDeleteCheckPeriodMillisecs ,
std : : bind ( & BlobDBImpl : : EvictCompacted , this , std : : placeholders : : _1 ) ) ;
std : : bind ( & BlobDBImpl : : EvictCompacted , this , std : : placeholders : : _1 ) ) ;
tqueue_ . add (
tqueue_ . add (
kDeleteObsoleted FilesPeriodMillisecs ,
kDeleteObsoleteFilesPeriodMillisecs ,
std : : bind ( & BlobDBImpl : : DeleteObsFiles , this , std : : placeholders : : _1 ) ) ;
std : : bind ( & BlobDBImpl : : DeleteObsolete Files , this , std : : placeholders : : _1 ) ) ;
tqueue_ . add ( kSanityCheckPeriodMillisecs ,
tqueue_ . add ( kSanityCheckPeriodMillisecs ,
std : : bind ( & BlobDBImpl : : SanityCheck , this , std : : placeholders : : _1 ) ) ;
std : : bind ( & BlobDBImpl : : SanityCheck , this , std : : placeholders : : _1 ) ) ;
tqueue_ . add ( kWriteAmplificationStatsPeriodMillisecs ,
tqueue_ . add ( kWriteAmplificationStatsPeriodMillisecs ,
@ -1117,15 +1117,25 @@ Status BlobDBImpl::AppendSN(const std::shared_ptr<BlobFile>& bfile,
}
}
std : : vector < Status > BlobDBImpl : : MultiGet (
std : : vector < Status > BlobDBImpl : : MultiGet (
const ReadOptions & options ,
const ReadOptions & read_ options,
const std : : vector < ColumnFamilyHandle * > & column_family ,
const std : : vector < ColumnFamilyHandle * > & column_family ,
const std : : vector < Slice > & keys , std : : vector < std : : string > * values ) {
const std : : vector < Slice > & keys , std : : vector < std : : string > * values ) {
// Get a snapshot to avoid blob file get deleted between we
// fetch and index entry and reading from the file.
ReadOptions ro ( read_options ) ;
bool snapshot_created = SetSnapshotIfNeeded ( & ro ) ;
std : : vector < std : : string > values_lsm ;
std : : vector < std : : string > values_lsm ;
values_lsm . resize ( keys . size ( ) ) ;
values_lsm . resize ( keys . size ( ) ) ;
auto statuses = db_ - > MultiGet ( options , column_family , keys , & values_lsm ) ;
auto statuses = db_ - > MultiGet ( ro , column_family , keys , & values_lsm ) ;
TEST_SYNC_POINT ( " BlobDBImpl::MultiGet:AfterIndexEntryGet:1 " ) ;
TEST_SYNC_POINT ( " BlobDBImpl::MultiGet:AfterIndexEntryGet:2 " ) ;
values - > resize ( keys . size ( ) ) ;
assert ( statuses . size ( ) = = keys . size ( ) ) ;
for ( size_t i = 0 ; i < keys . size ( ) ; + + i ) {
for ( size_t i = 0 ; i < keys . size ( ) ; + + i ) {
if ( ! statuses [ i ] . ok ( ) ) continue ;
if ( ! statuses [ i ] . ok ( ) ) {
continue ;
}
auto cfh = reinterpret_cast < ColumnFamilyHandleImpl * > ( column_family [ i ] ) ;
auto cfh = reinterpret_cast < ColumnFamilyHandleImpl * > ( column_family [ i ] ) ;
auto cfd = cfh - > cfd ( ) ;
auto cfd = cfh - > cfd ( ) ;
@ -1133,9 +1143,21 @@ std::vector<Status> BlobDBImpl::MultiGet(
Status s = CommonGet ( cfd , keys [ i ] , values_lsm [ i ] , & ( ( * values ) [ i ] ) ) ;
Status s = CommonGet ( cfd , keys [ i ] , values_lsm [ i ] , & ( ( * values ) [ i ] ) ) ;
statuses [ i ] = s ;
statuses [ i ] = s ;
}
}
if ( snapshot_created ) {
db_ - > ReleaseSnapshot ( ro . snapshot ) ;
}
return statuses ;
return statuses ;
}
}
bool BlobDBImpl : : SetSnapshotIfNeeded ( ReadOptions * read_options ) {
assert ( read_options ! = nullptr ) ;
if ( read_options - > snapshot ! = nullptr ) {
return false ;
}
read_options - > snapshot = db_ - > GetSnapshot ( ) ;
return true ;
}
Status BlobDBImpl : : CommonGet ( const ColumnFamilyData * cfd , const Slice & key ,
Status BlobDBImpl : : CommonGet ( const ColumnFamilyData * cfd , const Slice & key ,
const std : : string & index_entry , std : : string * value ,
const std : : string & index_entry , std : : string * value ,
SequenceNumber * sequence ) {
SequenceNumber * sequence ) {
@ -1172,11 +1194,6 @@ Status BlobDBImpl::CommonGet(const ColumnFamilyData* cfd, const Slice& key,
bfile = hitr - > second ;
bfile = hitr - > second ;
}
}
if ( bfile - > Obsolete ( ) ) {
return Status : : NotFound (
" Blob Not Found as blob file was garbage collected " ) ;
}
// 0 - size
// 0 - size
if ( ! handle . size ( ) & & value ! = nullptr ) {
if ( ! handle . size ( ) & & value ! = nullptr ) {
value - > clear ( ) ;
value - > clear ( ) ;
@ -1274,25 +1291,30 @@ Status BlobDBImpl::CommonGet(const ColumnFamilyData* cfd, const Slice& key,
return s ;
return s ;
}
}
Status BlobDBImpl : : Get ( const ReadOptions & options ,
Status BlobDBImpl : : Get ( const ReadOptions & read_ options,
ColumnFamilyHandle * column_family , const Slice & key ,
ColumnFamilyHandle * column_family , const Slice & key ,
PinnableSlice * value ) {
PinnableSlice * value ) {
auto cfh = reinterpret_cast < ColumnFamilyHandleImpl * > ( column_family ) ;
auto cfh = reinterpret_cast < ColumnFamilyHandleImpl * > ( column_family ) ;
auto cfd = cfh - > cfd ( ) ;
auto cfd = cfh - > cfd ( ) ;
// Get a snapshot to avoid blob file get deleted between we
// fetch and index entry and reading from the file.
// TODO(yiwu): For Get() retry if file not found would be a simpler strategy.
ReadOptions ro ( read_options ) ;
bool snapshot_created = SetSnapshotIfNeeded ( & ro ) ;
Status s ;
Status s ;
std : : string index_entry ;
std : : string index_entry ;
s = db_ - > Get ( options , column_family , key , & index_entry ) ;
s = db_ - > Get ( ro , column_family , key , & index_entry ) ;
if ( ! s . ok ( ) ) {
TEST_SYNC_POINT ( " BlobDBImpl::Get:AfterIndexEntryGet:1 " ) ;
if ( debug_level_ > = 3 )
TEST_SYNC_POINT ( " BlobDBImpl::Get:AfterIndexEntryGet:2 " ) ;
ROCKS_LOG_WARN ( db_options_ . info_log ,
if ( s . ok ( ) ) {
" Get Failed on LSM KEY: %s status: '%s' " ,
s = CommonGet ( cfd , key , index_entry , value - > GetSelf ( ) ) ;
key . ToString ( ) . c_str ( ) , s . ToString ( ) . c_str ( ) ) ;
value - > PinSelf ( ) ;
return s ;
}
if ( snapshot_created ) {
db_ - > ReleaseSnapshot ( ro . snapshot ) ;
}
}
s = CommonGet ( cfd , key , index_entry , value - > GetSelf ( ) ) ;
value - > PinSelf ( ) ;
return s ;
return s ;
}
}
@ -1302,6 +1324,8 @@ Slice BlobDBIterator::value() const {
auto cfh = reinterpret_cast < ColumnFamilyHandleImpl * > ( cfh_ ) ;
auto cfh = reinterpret_cast < ColumnFamilyHandleImpl * > ( cfh_ ) ;
auto cfd = cfh - > cfd ( ) ;
auto cfd = cfh - > cfd ( ) ;
TEST_SYNC_POINT ( " BlobDBIterator::value:BeforeGetBlob:1 " ) ;
TEST_SYNC_POINT ( " BlobDBIterator::value:BeforeGetBlob:2 " ) ;
Status s = db_impl_ - > CommonGet ( cfd , iter_ - > key ( ) , index_entry . ToString ( false ) ,
Status s = db_impl_ - > CommonGet ( cfd , iter_ - > key ( ) , index_entry . ToString ( false ) ,
& vpart_ ) ;
& vpart_ ) ;
return Slice ( vpart_ ) ;
return Slice ( vpart_ ) ;
@ -1977,7 +2001,7 @@ bool BlobDBImpl::ShouldGCFile(std::shared_ptr<BlobFile> bfile, uint64_t now,
return false ;
return false ;
}
}
std : : pair < bool , int64_t > BlobDBImpl : : DeleteObsFiles ( bool aborted ) {
std : : pair < bool , int64_t > BlobDBImpl : : DeleteObsolete Files ( bool aborted ) {
if ( aborted ) return std : : make_pair ( false , - 1 ) ;
if ( aborted ) return std : : make_pair ( false , - 1 ) ;
{
{
@ -2002,6 +2026,7 @@ std::pair<bool, int64_t> BlobDBImpl::DeleteObsFiles(bool aborted) {
}
}
}
}
blob_files_ . erase ( bfile - > BlobFileNumber ( ) ) ;
Status s = env_ - > DeleteFile ( bfile - > PathName ( ) ) ;
Status s = env_ - > DeleteFile ( bfile - > PathName ( ) ) ;
if ( ! s . ok ( ) ) {
if ( ! s . ok ( ) ) {
ROCKS_LOG_ERROR ( db_options_ . info_log ,
ROCKS_LOG_ERROR ( db_options_ . info_log ,
@ -2026,7 +2051,9 @@ std::pair<bool, int64_t> BlobDBImpl::DeleteObsFiles(bool aborted) {
// put files back into obsolete if for some reason, delete failed
// put files back into obsolete if for some reason, delete failed
if ( ! tobsolete . empty ( ) ) {
if ( ! tobsolete . empty ( ) ) {
WriteLock wl ( & mutex_ ) ;
WriteLock wl ( & mutex_ ) ;
for ( auto bfile : tobsolete ) obsolete_files_ . push_front ( bfile ) ;
for ( auto bfile : tobsolete ) {
obsolete_files_ . push_front ( bfile ) ;
}
}
}
return std : : make_pair ( ! aborted , - 1 ) ;
return std : : make_pair ( ! aborted , - 1 ) ;
@ -2212,8 +2239,6 @@ std::pair<bool, int64_t> BlobDBImpl::RunGC(bool aborted) {
WriteLock wl ( & mutex_ ) ;
WriteLock wl ( & mutex_ ) ;
for ( auto bfile : obsoletes ) {
for ( auto bfile : obsoletes ) {
bool last_file = ( bfile = = obsoletes . back ( ) ) ;
bool last_file = ( bfile = = obsoletes . back ( ) ) ;
// remove from global list so writers
blob_files_ . erase ( bfile - > BlobFileNumber ( ) ) ;
if ( ! evict_cb ) {
if ( ! evict_cb ) {
bfile - > SetCanBeDeleted ( ) ;
bfile - > SetCanBeDeleted ( ) ;
@ -2231,10 +2256,14 @@ std::pair<bool, int64_t> BlobDBImpl::RunGC(bool aborted) {
return std : : make_pair ( true , - 1 ) ;
return std : : make_pair ( true , - 1 ) ;
}
}
Iterator * BlobDBImpl : : NewIterator ( const ReadOptions & opts ,
Iterator * BlobDBImpl : : NewIterator ( const ReadOptions & read_ option s,
ColumnFamilyHandle * column_family ) {
ColumnFamilyHandle * column_family ) {
return new BlobDBIterator ( db_ - > NewIterator ( opts , column_family ) ,
// Get a snapshot to avoid blob file get deleted between we
column_family , this ) ;
// fetch and index entry and reading from the file.
ReadOptions ro ( read_options ) ;
bool snapshot_created = SetSnapshotIfNeeded ( & ro ) ;
return new BlobDBIterator ( db_ - > NewIterator ( ro , column_family ) , column_family ,
this , snapshot_created , ro . snapshot ) ;
}
}
Status DestroyBlobDB ( const std : : string & dbname , const Options & options ,
Status DestroyBlobDB ( const std : : string & dbname , const Options & options ,
@ -2283,6 +2312,7 @@ Status BlobDBImpl::TEST_GetSequenceNumber(const Slice& key,
}
}
std : : vector < std : : shared_ptr < BlobFile > > BlobDBImpl : : TEST_GetBlobFiles ( ) const {
std : : vector < std : : shared_ptr < BlobFile > > BlobDBImpl : : TEST_GetBlobFiles ( ) const {
ReadLock l ( & mutex_ ) ;
std : : vector < std : : shared_ptr < BlobFile > > blob_files ;
std : : vector < std : : shared_ptr < BlobFile > > blob_files ;
for ( auto & p : blob_files_ ) {
for ( auto & p : blob_files_ ) {
blob_files . emplace_back ( p . second ) ;
blob_files . emplace_back ( p . second ) ;
@ -2300,6 +2330,10 @@ std::vector<std::shared_ptr<BlobFile>> BlobDBImpl::TEST_GetObsoleteFiles()
return obsolete_files ;
return obsolete_files ;
}
}
void BlobDBImpl : : TEST_DeleteObsoleteFiles ( ) {
DeleteObsoleteFiles ( false /*abort*/ ) ;
}
void BlobDBImpl : : TEST_CloseBlobFile ( std : : shared_ptr < BlobFile > & bfile ) {
void BlobDBImpl : : TEST_CloseBlobFile ( std : : shared_ptr < BlobFile > & bfile ) {
CloseSeqWrite ( bfile , false /*abort*/ ) ;
CloseSeqWrite ( bfile , false /*abort*/ ) ;
}
}
@ -2310,6 +2344,16 @@ Status BlobDBImpl::TEST_GCFileAndUpdateLSM(std::shared_ptr<BlobFile>& bfile,
}
}
void BlobDBImpl : : TEST_RunGC ( ) { RunGC ( false /*abort*/ ) ; }
void BlobDBImpl : : TEST_RunGC ( ) { RunGC ( false /*abort*/ ) ; }
void BlobDBImpl : : TEST_ObsoleteFile ( std : : shared_ptr < BlobFile > & bfile ) {
uint64_t number = bfile - > BlobFileNumber ( ) ;
assert ( blob_files_ . count ( number ) > 0 ) ;
bfile - > SetCanBeDeleted ( ) ;
{
WriteLock l ( & mutex_ ) ;
obsolete_files_ . push_back ( bfile ) ;
}
}
# endif // !NDEBUG
# endif // !NDEBUG
} // namespace blob_db
} // namespace blob_db