@ -7,6 +7,7 @@
# include <cstdint>
# include <cstdint>
# include "file/file_util.h"
# include "rocksdb/file_system.h"
# include "rocksdb/file_system.h"
# include "util/coding_lean.h"
# include "util/coding_lean.h"
@ -37,10 +38,31 @@ UniqueIdVerifier::UniqueIdVerifier(const std::string& db_name, Env* env)
exit ( 1 ) ;
exit ( 1 ) ;
}
}
// Avoid relying on ReopenWritableFile which is not supported by all
// file systems. Create a new file and copy the old file contents to it.
std : : string tmp_path = path_ + " .tmp " ;
st = fs - > FileExists ( tmp_path , opts , /*dbg*/ nullptr ) ;
if ( st . IsNotFound ( ) ) {
st = fs - > RenameFile ( path_ , tmp_path , opts , /*dbg*/ nullptr ) ;
// Either it should succeed or fail because src path doesn't exist
assert ( st . ok ( ) | | st . IsPathNotFound ( ) ) ;
} else {
// If path_ and tmp_path both exist, retain tmp_path as its
// guaranteed to be more complete. The order of operations are -
// 1. Rename path_ to tmp_path
// 2. Parse tmp_path contents
// 3. Create path_
// 4. Copy tmp_path contents to path_
// 5. Delete tmp_path
st = fs - > DeleteFile ( path_ , opts , /*dbg*/ nullptr ) ;
assert ( st . ok ( ) | | st . IsPathNotFound ( ) ) ;
}
uint64_t size = 0 ;
{
{
std : : unique_ptr < FSSequentialFile > reader ;
std : : unique_ptr < FSSequentialFile > reader ;
Status s =
Status s = fs - > NewSequentialFile ( tmp_path , FileOptions ( ) , & reader ,
fs - > NewSequentialFile ( path_ , FileOptions ( ) , & reader , /*dbg*/ nullptr ) ;
/*dbg*/ nullptr ) ;
if ( s . ok ( ) ) {
if ( s . ok ( ) ) {
// Load from file
// Load from file
std : : string id ( 24U , ' \0 ' ) ;
std : : string id ( 24U , ' \0 ' ) ;
@ -60,37 +82,57 @@ UniqueIdVerifier::UniqueIdVerifier(const std::string& db_name, Env* env)
fprintf ( stdout , " Warning: clearing corrupt unique id file \n " ) ;
fprintf ( stdout , " Warning: clearing corrupt unique id file \n " ) ;
id_set_ . clear ( ) ;
id_set_ . clear ( ) ;
reader . reset ( ) ;
reader . reset ( ) ;
s = fs - > DeleteFile ( path_ , opts , /*dbg*/ nullptr ) ;
s = fs - > DeleteFile ( tmp_ path, opts , /*dbg*/ nullptr ) ;
assert ( s . ok ( ) ) ;
assert ( s . ok ( ) ) ;
size = 0 ;
}
}
break ;
break ;
}
}
size + = 24U ;
VerifyNoWrite ( id ) ;
VerifyNoWrite ( id ) ;
}
}
} else {
} else {
// Newly created is ok.
// Newly created is ok.
// But FileSystem doesn't tell us whether non-existence was the cause of
// But FileSystem doesn't tell us whether non-existence was the cause of
// the failure. (Issue #9021)
// the failure. (Issue #9021)
Status s2 = fs - > FileExists ( path_ , opts , /*dbg*/ nullptr ) ;
Status s2 = fs - > FileExists ( tmp_ path, opts , /*dbg*/ nullptr ) ;
if ( ! s2 . IsNotFound ( ) ) {
if ( ! s2 . IsNotFound ( ) ) {
fprintf ( stderr , " Error opening unique id file: %s \n " ,
fprintf ( stderr , " Error opening unique id file: %s \n " ,
s . ToString ( ) . c_str ( ) ) ;
s . ToString ( ) . c_str ( ) ) ;
assert ( false ) ;
assert ( false ) ;
}
}
size = 0 ;
}
}
}
}
fprintf ( stdout , " (Re-)verified %zu unique IDs \n " , id_set_ . size ( ) ) ;
fprintf ( stdout , " (Re-)verified %zu unique IDs \n " , id_set_ . size ( ) ) ;
Status s = fs - > ReopenWritableFile ( path_ , FileOptions ( ) , & data_file_writer_ ,
/*dbg*/ nullptr ) ;
std : : unique_ptr < FSWritableFile > file_writer ;
if ( ! s . ok ( ) ) {
st = fs - > NewWritableFile ( path_ , FileOptions ( ) , & file_writer , /*dbg*/ nullptr ) ;
fprintf ( stderr , " Error opening unique id file for append: %s \n " ,
if ( ! st . ok ( ) ) {
s . ToString ( ) . c_str ( ) ) ;
fprintf ( stderr , " Error creating the unique ids file: %s \n " ,
st . ToString ( ) . c_str ( ) ) ;
assert ( false ) ;
}
data_file_writer_ . reset (
new WritableFileWriter ( std : : move ( file_writer ) , path_ , FileOptions ( ) ) ) ;
if ( size > 0 ) {
st = CopyFile ( fs . get ( ) , tmp_path , data_file_writer_ , size ,
/*use_fsync*/ true , /*io_tracer*/ nullptr ,
/*temparature*/ Temperature : : kHot ) ;
if ( ! st . ok ( ) ) {
fprintf ( stderr , " Error copying contents of old unique id file: %s \n " ,
st . ToString ( ) . c_str ( ) ) ;
assert ( false ) ;
assert ( false ) ;
}
}
}
st = fs - > DeleteFile ( tmp_path , opts , /*dbg*/ nullptr ) ;
assert ( st . ok ( ) | | st . IsPathNotFound ( ) ) ;
}
}
UniqueIdVerifier : : ~ UniqueIdVerifier ( ) {
UniqueIdVerifier : : ~ UniqueIdVerifier ( ) {
data_file_writer_ - > Close ( IOOptions ( ) , /*dbg*/ nullptr ) ;
IOStatus s = data_file_writer_ - > Close ( ) ;
assert ( s . ok ( ) ) ;
}
}
void UniqueIdVerifier : : VerifyNoWrite ( const std : : string & id ) {
void UniqueIdVerifier : : VerifyNoWrite ( const std : : string & id ) {
@ -112,14 +154,13 @@ void UniqueIdVerifier::Verify(const std::string& id) {
if ( id_set_ . size ( ) > = 4294967 ) {
if ( id_set_ . size ( ) > = 4294967 ) {
return ;
return ;
}
}
IOStatus s =
IOStatus s = data_file_writer_ - > Append ( Slice ( id ) ) ;
data_file_writer_ - > Append ( Slice ( id ) , IOOptions ( ) , /*dbg*/ nullptr ) ;
if ( ! s . ok ( ) ) {
if ( ! s . ok ( ) ) {
fprintf ( stderr , " Error writing to unique id file: %s \n " ,
fprintf ( stderr , " Error writing to unique id file: %s \n " ,
s . ToString ( ) . c_str ( ) ) ;
s . ToString ( ) . c_str ( ) ) ;
assert ( false ) ;
assert ( false ) ;
}
}
s = data_file_writer_ - > Flush ( IOOptions ( ) , /*dbg*/ nullptr ) ;
s = data_file_writer_ - > Flush ( ) ;
if ( ! s . ok ( ) ) {
if ( ! s . ok ( ) ) {
fprintf ( stderr , " Error flushing unique id file: %s \n " ,
fprintf ( stderr , " Error flushing unique id file: %s \n " ,
s . ToString ( ) . c_str ( ) ) ;
s . ToString ( ) . c_str ( ) ) ;