Change the File System File Wrappers to std::unique_ptr (#8618)

Summary:
This allows the wrapper classes to own the wrapped object and eliminates confusion as to ownership.  Previously, many classes implemented their own ownership solutions.  Fixes https://github.com/facebook/rocksdb/issues/8606

Pull Request resolved: https://github.com/facebook/rocksdb/pull/8618

Reviewed By: pdillinger

Differential Revision: D30136064

Pulled By: mrambacher

fbshipit-source-id: d0bf471df8818dbb1770a86335fe98f761cca193
This commit is contained in:
mrambacher 2021-09-13 08:45:13 -07:00 committed by Facebook GitHub Bot
parent 2a2b3e03a5
commit dafa584fd1
8 changed files with 107 additions and 53 deletions

View File

@ -3235,13 +3235,11 @@ INSTANTIATE_TEST_CASE_P(ParallelIO, DBBasicTestWithParallelIO,
// Forward declaration // Forward declaration
class DeadlineFS; class DeadlineFS;
class DeadlineRandomAccessFile : public FSRandomAccessFileWrapper { class DeadlineRandomAccessFile : public FSRandomAccessFileOwnerWrapper {
public: public:
DeadlineRandomAccessFile(DeadlineFS& fs, DeadlineRandomAccessFile(DeadlineFS& fs,
std::unique_ptr<FSRandomAccessFile>& file) std::unique_ptr<FSRandomAccessFile>& file)
: FSRandomAccessFileWrapper(file.get()), : FSRandomAccessFileOwnerWrapper(std::move(file)), fs_(fs) {}
fs_(fs),
file_(std::move(file)) {}
IOStatus Read(uint64_t offset, size_t len, const IOOptions& opts, IOStatus Read(uint64_t offset, size_t len, const IOOptions& opts,
Slice* result, char* scratch, Slice* result, char* scratch,

View File

@ -131,12 +131,12 @@ class FileSystemPtr {
// for tracing. It overrides methods we are interested in tracing and extends // for tracing. It overrides methods we are interested in tracing and extends
// FSSequentialFileWrapper, which forwards all methods that are not explicitly // FSSequentialFileWrapper, which forwards all methods that are not explicitly
// overridden. // overridden.
class FSSequentialFileTracingWrapper : public FSSequentialFileWrapper { class FSSequentialFileTracingWrapper : public FSSequentialFileOwnerWrapper {
public: public:
FSSequentialFileTracingWrapper(FSSequentialFile* t, FSSequentialFileTracingWrapper(std::unique_ptr<FSSequentialFile>&& t,
std::shared_ptr<IOTracer> io_tracer, std::shared_ptr<IOTracer> io_tracer,
const std::string& file_name) const std::string& file_name)
: FSSequentialFileWrapper(t), : FSSequentialFileOwnerWrapper(std::move(t)),
io_tracer_(io_tracer), io_tracer_(io_tracer),
clock_(SystemClock::Default().get()), clock_(SystemClock::Default().get()),
file_name_(file_name) {} file_name_(file_name) {}
@ -169,9 +169,8 @@ class FSSequentialFilePtr {
FSSequentialFilePtr(std::unique_ptr<FSSequentialFile>&& fs, FSSequentialFilePtr(std::unique_ptr<FSSequentialFile>&& fs,
const std::shared_ptr<IOTracer>& io_tracer, const std::shared_ptr<IOTracer>& io_tracer,
const std::string& file_name) const std::string& file_name)
: fs_(std::move(fs)), : io_tracer_(io_tracer),
io_tracer_(io_tracer), fs_tracer_(std::move(fs), io_tracer_,
fs_tracer_(fs_.get(), io_tracer_,
file_name.substr(file_name.find_last_of("/\\") + file_name.substr(file_name.find_last_of("/\\") +
1) /* pass file name */) {} 1) /* pass file name */) {}
@ -179,7 +178,7 @@ class FSSequentialFilePtr {
if (io_tracer_ && io_tracer_->is_tracing_enabled()) { if (io_tracer_ && io_tracer_->is_tracing_enabled()) {
return const_cast<FSSequentialFileTracingWrapper*>(&fs_tracer_); return const_cast<FSSequentialFileTracingWrapper*>(&fs_tracer_);
} else { } else {
return fs_.get(); return fs_tracer_.target();
} }
} }
@ -187,12 +186,11 @@ class FSSequentialFilePtr {
if (io_tracer_ && io_tracer_->is_tracing_enabled()) { if (io_tracer_ && io_tracer_->is_tracing_enabled()) {
return const_cast<FSSequentialFileTracingWrapper*>(&fs_tracer_); return const_cast<FSSequentialFileTracingWrapper*>(&fs_tracer_);
} else { } else {
return fs_.get(); return fs_tracer_.target();
} }
} }
private: private:
std::unique_ptr<FSSequentialFile> fs_;
std::shared_ptr<IOTracer> io_tracer_; std::shared_ptr<IOTracer> io_tracer_;
FSSequentialFileTracingWrapper fs_tracer_; FSSequentialFileTracingWrapper fs_tracer_;
}; };
@ -203,12 +201,12 @@ class FSSequentialFilePtr {
// binary format for tracing. It overrides methods we are interested in tracing // binary format for tracing. It overrides methods we are interested in tracing
// and extends FSRandomAccessFileWrapper, which forwards all methods that are // and extends FSRandomAccessFileWrapper, which forwards all methods that are
// not explicitly overridden. // not explicitly overridden.
class FSRandomAccessFileTracingWrapper : public FSRandomAccessFileWrapper { class FSRandomAccessFileTracingWrapper : public FSRandomAccessFileOwnerWrapper {
public: public:
FSRandomAccessFileTracingWrapper(FSRandomAccessFile* t, FSRandomAccessFileTracingWrapper(std::unique_ptr<FSRandomAccessFile>&& t,
std::shared_ptr<IOTracer> io_tracer, std::shared_ptr<IOTracer> io_tracer,
const std::string& file_name) const std::string& file_name)
: FSRandomAccessFileWrapper(t), : FSRandomAccessFileOwnerWrapper(std::move(t)),
io_tracer_(io_tracer), io_tracer_(io_tracer),
clock_(SystemClock::Default().get()), clock_(SystemClock::Default().get()),
file_name_(file_name) {} file_name_(file_name) {}
@ -244,9 +242,8 @@ class FSRandomAccessFilePtr {
FSRandomAccessFilePtr(std::unique_ptr<FSRandomAccessFile>&& fs, FSRandomAccessFilePtr(std::unique_ptr<FSRandomAccessFile>&& fs,
const std::shared_ptr<IOTracer>& io_tracer, const std::shared_ptr<IOTracer>& io_tracer,
const std::string& file_name) const std::string& file_name)
: fs_(std::move(fs)), : io_tracer_(io_tracer),
io_tracer_(io_tracer), fs_tracer_(std::move(fs), io_tracer_,
fs_tracer_(fs_.get(), io_tracer_,
file_name.substr(file_name.find_last_of("/\\") + file_name.substr(file_name.find_last_of("/\\") +
1) /* pass file name */) {} 1) /* pass file name */) {}
@ -254,7 +251,7 @@ class FSRandomAccessFilePtr {
if (io_tracer_ && io_tracer_->is_tracing_enabled()) { if (io_tracer_ && io_tracer_->is_tracing_enabled()) {
return const_cast<FSRandomAccessFileTracingWrapper*>(&fs_tracer_); return const_cast<FSRandomAccessFileTracingWrapper*>(&fs_tracer_);
} else { } else {
return fs_.get(); return fs_tracer_.target();
} }
} }
@ -262,12 +259,11 @@ class FSRandomAccessFilePtr {
if (io_tracer_ && io_tracer_->is_tracing_enabled()) { if (io_tracer_ && io_tracer_->is_tracing_enabled()) {
return const_cast<FSRandomAccessFileTracingWrapper*>(&fs_tracer_); return const_cast<FSRandomAccessFileTracingWrapper*>(&fs_tracer_);
} else { } else {
return fs_.get(); return fs_tracer_.target();
} }
} }
private: private:
std::unique_ptr<FSRandomAccessFile> fs_;
std::shared_ptr<IOTracer> io_tracer_; std::shared_ptr<IOTracer> io_tracer_;
FSRandomAccessFileTracingWrapper fs_tracer_; FSRandomAccessFileTracingWrapper fs_tracer_;
}; };
@ -278,12 +274,12 @@ class FSRandomAccessFilePtr {
// for tracing. It overrides methods we are interested in tracing and extends // for tracing. It overrides methods we are interested in tracing and extends
// FSWritableFileWrapper, which forwards all methods that are not explicitly // FSWritableFileWrapper, which forwards all methods that are not explicitly
// overridden. // overridden.
class FSWritableFileTracingWrapper : public FSWritableFileWrapper { class FSWritableFileTracingWrapper : public FSWritableFileOwnerWrapper {
public: public:
FSWritableFileTracingWrapper(FSWritableFile* t, FSWritableFileTracingWrapper(std::unique_ptr<FSWritableFile>&& t,
std::shared_ptr<IOTracer> io_tracer, std::shared_ptr<IOTracer> io_tracer,
const std::string& file_name) const std::string& file_name)
: FSWritableFileWrapper(t), : FSWritableFileOwnerWrapper(std::move(t)),
io_tracer_(io_tracer), io_tracer_(io_tracer),
clock_(SystemClock::Default().get()), clock_(SystemClock::Default().get()),
file_name_(file_name) {} file_name_(file_name) {}
@ -334,9 +330,9 @@ class FSWritableFilePtr {
FSWritableFilePtr(std::unique_ptr<FSWritableFile>&& fs, FSWritableFilePtr(std::unique_ptr<FSWritableFile>&& fs,
const std::shared_ptr<IOTracer>& io_tracer, const std::shared_ptr<IOTracer>& io_tracer,
const std::string& file_name) const std::string& file_name)
: fs_(std::move(fs)), io_tracer_(io_tracer) { : io_tracer_(io_tracer) {
fs_tracer_.reset(new FSWritableFileTracingWrapper( fs_tracer_.reset(new FSWritableFileTracingWrapper(
fs_.get(), io_tracer_, std::move(fs), io_tracer_,
file_name.substr(file_name.find_last_of("/\\") + file_name.substr(file_name.find_last_of("/\\") +
1) /* pass file name */)); 1) /* pass file name */));
} }
@ -345,26 +341,26 @@ class FSWritableFilePtr {
if (io_tracer_ && io_tracer_->is_tracing_enabled()) { if (io_tracer_ && io_tracer_->is_tracing_enabled()) {
return fs_tracer_.get(); return fs_tracer_.get();
} else { } else {
return fs_.get(); return fs_tracer_->target();
} }
} }
FSWritableFile* get() const { FSWritableFile* get() const {
if (io_tracer_ && io_tracer_->is_tracing_enabled()) { if (io_tracer_ && io_tracer_->is_tracing_enabled()) {
return fs_tracer_.get(); return fs_tracer_.get();
} else if (fs_tracer_) {
return fs_tracer_->target();
} else { } else {
return fs_.get(); return nullptr;
} }
} }
void reset() { void reset() {
fs_.reset();
fs_tracer_.reset(); fs_tracer_.reset();
io_tracer_ = nullptr; io_tracer_ = nullptr;
} }
private: private:
std::unique_ptr<FSWritableFile> fs_;
std::shared_ptr<IOTracer> io_tracer_; std::shared_ptr<IOTracer> io_tracer_;
std::unique_ptr<FSWritableFileTracingWrapper> fs_tracer_; std::unique_ptr<FSWritableFileTracingWrapper> fs_tracer_;
}; };
@ -375,12 +371,12 @@ class FSWritableFilePtr {
// for tracing. It overrides methods we are interested in tracing and extends // for tracing. It overrides methods we are interested in tracing and extends
// FSRandomRWFileWrapper, which forwards all methods that are not explicitly // FSRandomRWFileWrapper, which forwards all methods that are not explicitly
// overridden. // overridden.
class FSRandomRWFileTracingWrapper : public FSRandomRWFileWrapper { class FSRandomRWFileTracingWrapper : public FSRandomRWFileOwnerWrapper {
public: public:
FSRandomRWFileTracingWrapper(FSRandomRWFile* t, FSRandomRWFileTracingWrapper(std::unique_ptr<FSRandomRWFile>&& t,
std::shared_ptr<IOTracer> io_tracer, std::shared_ptr<IOTracer> io_tracer,
const std::string& file_name) const std::string& file_name)
: FSRandomRWFileWrapper(t), : FSRandomRWFileOwnerWrapper(std::move(t)),
io_tracer_(io_tracer), io_tracer_(io_tracer),
clock_(SystemClock::Default().get()), clock_(SystemClock::Default().get()),
file_name_(file_name) {} file_name_(file_name) {}
@ -419,9 +415,8 @@ class FSRandomRWFilePtr {
FSRandomRWFilePtr(std::unique_ptr<FSRandomRWFile>&& fs, FSRandomRWFilePtr(std::unique_ptr<FSRandomRWFile>&& fs,
std::shared_ptr<IOTracer> io_tracer, std::shared_ptr<IOTracer> io_tracer,
const std::string& file_name) const std::string& file_name)
: fs_(std::move(fs)), : io_tracer_(io_tracer),
io_tracer_(io_tracer), fs_tracer_(std::move(fs), io_tracer_,
fs_tracer_(fs_.get(), io_tracer_,
file_name.substr(file_name.find_last_of("/\\") + file_name.substr(file_name.find_last_of("/\\") +
1) /* pass file name */) {} 1) /* pass file name */) {}
@ -429,7 +424,7 @@ class FSRandomRWFilePtr {
if (io_tracer_ && io_tracer_->is_tracing_enabled()) { if (io_tracer_ && io_tracer_->is_tracing_enabled()) {
return const_cast<FSRandomRWFileTracingWrapper*>(&fs_tracer_); return const_cast<FSRandomRWFileTracingWrapper*>(&fs_tracer_);
} else { } else {
return fs_.get(); return fs_tracer_.target();
} }
} }
@ -437,12 +432,11 @@ class FSRandomRWFilePtr {
if (io_tracer_ && io_tracer_->is_tracing_enabled()) { if (io_tracer_ && io_tracer_->is_tracing_enabled()) {
return const_cast<FSRandomRWFileTracingWrapper*>(&fs_tracer_); return const_cast<FSRandomRWFileTracingWrapper*>(&fs_tracer_);
} else { } else {
return fs_.get(); return fs_tracer_.target();
} }
} }
private: private:
std::unique_ptr<FSRandomRWFile> fs_;
std::shared_ptr<IOTracer> io_tracer_; std::shared_ptr<IOTracer> io_tracer_;
FSRandomRWFileTracingWrapper fs_tracer_; FSRandomRWFileTracingWrapper fs_tracer_;
}; };

View File

@ -10,12 +10,11 @@ namespace ROCKSDB_NAMESPACE {
class MockFS; class MockFS;
class MockRandomAccessFile : public FSRandomAccessFileWrapper { class MockRandomAccessFile : public FSRandomAccessFileOwnerWrapper {
public: public:
MockRandomAccessFile(std::unique_ptr<FSRandomAccessFile>& file, MockRandomAccessFile(std::unique_ptr<FSRandomAccessFile>& file,
bool support_prefetch, std::atomic_int& prefetch_count) bool support_prefetch, std::atomic_int& prefetch_count)
: FSRandomAccessFileWrapper(file.get()), : FSRandomAccessFileOwnerWrapper(std::move(file)),
file_(std::move(file)),
support_prefetch_(support_prefetch), support_prefetch_(support_prefetch),
prefetch_count_(prefetch_count) {} prefetch_count_(prefetch_count) {}
@ -30,7 +29,6 @@ class MockRandomAccessFile : public FSRandomAccessFileWrapper {
} }
private: private:
std::unique_ptr<FSRandomAccessFile> file_;
const bool support_prefetch_; const bool support_prefetch_;
std::atomic_int& prefetch_count_; std::atomic_int& prefetch_count_;
}; };

View File

@ -1340,6 +1340,8 @@ class FileSystemWrapper : public FileSystem {
class FSSequentialFileWrapper : public FSSequentialFile { class FSSequentialFileWrapper : public FSSequentialFile {
public: public:
// Creates a FileWrapper around the input File object and without
// taking ownership of the object
explicit FSSequentialFileWrapper(FSSequentialFile* t) : target_(t) {} explicit FSSequentialFileWrapper(FSSequentialFile* t) : target_(t) {}
FSSequentialFile* target() const { return target_; } FSSequentialFile* target() const { return target_; }
@ -1366,8 +1368,21 @@ class FSSequentialFileWrapper : public FSSequentialFile {
FSSequentialFile* target_; FSSequentialFile* target_;
}; };
class FSSequentialFileOwnerWrapper : public FSSequentialFileWrapper {
public:
// Creates a FileWrapper around the input File object and takes
// ownership of the object
explicit FSSequentialFileOwnerWrapper(std::unique_ptr<FSSequentialFile>&& t)
: FSSequentialFileWrapper(t.get()), guard_(std::move(t)) {}
private:
std::unique_ptr<FSSequentialFile> guard_;
};
class FSRandomAccessFileWrapper : public FSRandomAccessFile { class FSRandomAccessFileWrapper : public FSRandomAccessFile {
public: public:
// Creates a FileWrapper around the input File object and without
// taking ownership of the object
explicit FSRandomAccessFileWrapper(FSRandomAccessFile* t) : target_(t) {} explicit FSRandomAccessFileWrapper(FSRandomAccessFile* t) : target_(t) {}
FSRandomAccessFile* target() const { return target_; } FSRandomAccessFile* target() const { return target_; }
@ -1398,11 +1413,26 @@ class FSRandomAccessFileWrapper : public FSRandomAccessFile {
} }
private: private:
std::unique_ptr<FSRandomAccessFile> guard_;
FSRandomAccessFile* target_; FSRandomAccessFile* target_;
}; };
class FSRandomAccessFileOwnerWrapper : public FSRandomAccessFileWrapper {
public:
// Creates a FileWrapper around the input File object and takes
// ownership of the object
explicit FSRandomAccessFileOwnerWrapper(
std::unique_ptr<FSRandomAccessFile>&& t)
: FSRandomAccessFileWrapper(t.get()), guard_(std::move(t)) {}
private:
std::unique_ptr<FSRandomAccessFile> guard_;
};
class FSWritableFileWrapper : public FSWritableFile { class FSWritableFileWrapper : public FSWritableFile {
public: public:
// Creates a FileWrapper around the input File object and without
// taking ownership of the object
explicit FSWritableFileWrapper(FSWritableFile* t) : target_(t) {} explicit FSWritableFileWrapper(FSWritableFile* t) : target_(t) {}
FSWritableFile* target() const { return target_; } FSWritableFile* target() const { return target_; }
@ -1500,8 +1530,21 @@ class FSWritableFileWrapper : public FSWritableFile {
FSWritableFile* target_; FSWritableFile* target_;
}; };
class FSWritableFileOwnerWrapper : public FSWritableFileWrapper {
public:
// Creates a FileWrapper around the input File object and takes
// ownership of the object
explicit FSWritableFileOwnerWrapper(std::unique_ptr<FSWritableFile>&& t)
: FSWritableFileWrapper(t.get()), guard_(std::move(t)) {}
private:
std::unique_ptr<FSWritableFile> guard_;
};
class FSRandomRWFileWrapper : public FSRandomRWFile { class FSRandomRWFileWrapper : public FSRandomRWFile {
public: public:
// Creates a FileWrapper around the input File object and without
// taking ownership of the object
explicit FSRandomRWFileWrapper(FSRandomRWFile* t) : target_(t) {} explicit FSRandomRWFileWrapper(FSRandomRWFile* t) : target_(t) {}
FSRandomRWFile* target() const { return target_; } FSRandomRWFile* target() const { return target_; }
@ -1536,8 +1579,28 @@ class FSRandomRWFileWrapper : public FSRandomRWFile {
FSRandomRWFile* target_; FSRandomRWFile* target_;
}; };
class FSRandomRWFileOwnerWrapper : public FSRandomRWFileWrapper {
public:
// Creates a FileWrapper around the input File object and takes
// ownership of the object
explicit FSRandomRWFileOwnerWrapper(std::unique_ptr<FSRandomRWFile>&& t)
: FSRandomRWFileWrapper(t.get()), guard_(std::move(t)) {}
private:
std::unique_ptr<FSRandomRWFile> guard_;
};
class FSDirectoryWrapper : public FSDirectory { class FSDirectoryWrapper : public FSDirectory {
public: public:
// Creates a FileWrapper around the input File object and takes
// ownership of the object
explicit FSDirectoryWrapper(std::unique_ptr<FSDirectory>&& t)
: guard_(std::move(t)) {
target_ = guard_.get();
}
// Creates a FileWrapper around the input File object and without
// taking ownership of the object
explicit FSDirectoryWrapper(FSDirectory* t) : target_(t) {} explicit FSDirectoryWrapper(FSDirectory* t) : target_(t) {}
IOStatus Fsync(const IOOptions& options, IODebugContext* dbg) override { IOStatus Fsync(const IOOptions& options, IODebugContext* dbg) override {
@ -1548,6 +1611,7 @@ class FSDirectoryWrapper : public FSDirectory {
} }
private: private:
std::unique_ptr<FSDirectory> guard_;
FSDirectory* target_; FSDirectory* target_;
}; };

View File

@ -81,7 +81,7 @@ IOStatus SimulatedHybridFileSystem::NewRandomAccessFile(
} }
IOStatus s = target()->NewRandomAccessFile(fname, file_opts, result, dbg); IOStatus s = target()->NewRandomAccessFile(fname, file_opts, result, dbg);
result->reset( result->reset(
new SimulatedHybridRaf(result->release(), rate_limiter_, temperature)); new SimulatedHybridRaf(std::move(*result), rate_limiter_, temperature));
return s; return s;
} }

View File

@ -59,12 +59,12 @@ class SimulatedHybridFileSystem : public FileSystemWrapper {
// Simulated random access file that can control IOPs and latency to simulate // Simulated random access file that can control IOPs and latency to simulate
// specific storage media // specific storage media
class SimulatedHybridRaf : public FSRandomAccessFileWrapper { class SimulatedHybridRaf : public FSRandomAccessFileOwnerWrapper {
public: public:
SimulatedHybridRaf(FSRandomAccessFile* t, SimulatedHybridRaf(std::unique_ptr<FSRandomAccessFile>&& t,
std::shared_ptr<RateLimiter> rate_limiter, std::shared_ptr<RateLimiter> rate_limiter,
Temperature temperature) Temperature temperature)
: FSRandomAccessFileWrapper(t), : FSRandomAccessFileOwnerWrapper(std::move(t)),
rate_limiter_(rate_limiter), rate_limiter_(rate_limiter),
temperature_(temperature) {} temperature_(temperature) {}

View File

@ -544,7 +544,7 @@ IOStatus FaultInjectionTestFS::NewSequentialFile(
} }
IOStatus io_s = target()->NewSequentialFile(fname, file_opts, result, dbg); IOStatus io_s = target()->NewSequentialFile(fname, file_opts, result, dbg);
if (io_s.ok()) { if (io_s.ok()) {
result->reset(new TestFSSequentialFile(result->release(), this)); result->reset(new TestFSSequentialFile(std::move(*result), this));
} }
return io_s; return io_s;
} }

View File

@ -150,10 +150,11 @@ class TestFSRandomAccessFile : public FSRandomAccessFile {
FaultInjectionTestFS* fs_; FaultInjectionTestFS* fs_;
}; };
class TestFSSequentialFile : public FSSequentialFileWrapper { class TestFSSequentialFile : public FSSequentialFileOwnerWrapper {
public: public:
explicit TestFSSequentialFile(FSSequentialFile* f, FaultInjectionTestFS* fs) explicit TestFSSequentialFile(std::unique_ptr<FSSequentialFile>&& f,
: FSSequentialFileWrapper(f), target_guard_(f), fs_(fs) {} FaultInjectionTestFS* fs)
: FSSequentialFileOwnerWrapper(std::move(f)), fs_(fs) {}
IOStatus Read(size_t n, const IOOptions& options, Slice* result, IOStatus Read(size_t n, const IOOptions& options, Slice* result,
char* scratch, IODebugContext* dbg) override; char* scratch, IODebugContext* dbg) override;
IOStatus PositionedRead(uint64_t offset, size_t n, const IOOptions& options, IOStatus PositionedRead(uint64_t offset, size_t n, const IOOptions& options,
@ -161,7 +162,6 @@ class TestFSSequentialFile : public FSSequentialFileWrapper {
IODebugContext* dbg) override; IODebugContext* dbg) override;
private: private:
std::unique_ptr<FSSequentialFile> target_guard_;
FaultInjectionTestFS* fs_; FaultInjectionTestFS* fs_;
}; };