add rocksdb::WritableFileWrapper similar to rocksdb::EnvWrapper
Summary: It used to be no good (known to me) non-intrusive way to wrap WritableFile - you can't call protected virtual methods of the wrapped pointer to WritableFile. This diff adds a convenience class WritableFileWrapper that makes wrapping WritableFile both possible and easy. Test Plan: `make clean; make -j release`, `make clean; OPT=-DROCKSDB_LITE make release`, `make clean; USE_CLANG=1 make -j all`. Reviewers: sdong, yhchiang, rven Reviewed By: rven Subscribers: dhruba, tnovak, march Differential Revision: https://reviews.facebook.net/D39147
This commit is contained in:
parent
a187e66ad0
commit
2ecac9f96d
@ -543,6 +543,8 @@ class WritableFile {
|
||||
void operator=(const WritableFile&);
|
||||
|
||||
protected:
|
||||
friend class WritableFileWrapper;
|
||||
|
||||
Env::IOPriority io_priority_;
|
||||
};
|
||||
|
||||
@ -878,6 +880,47 @@ class EnvWrapper : public Env {
|
||||
Env* target_;
|
||||
};
|
||||
|
||||
// An implementation of WritableFile that forwards all calls to another
|
||||
// WritableFile. May be useful to clients who wish to override just part of the
|
||||
// functionality of another WritableFile.
|
||||
// It's declared as friend of WritableFile to allow forwarding calls to
|
||||
// protected virtual methods.
|
||||
class WritableFileWrapper : public WritableFile {
|
||||
public:
|
||||
explicit WritableFileWrapper(WritableFile* t) : target_(t) { }
|
||||
|
||||
Status Append(const Slice& data) override { return target_->Append(data); }
|
||||
Status Close() override { return target_->Close(); }
|
||||
Status Flush() override { return target_->Flush(); }
|
||||
Status Sync() override { return target_->Sync(); }
|
||||
Status Fsync() override { return target_->Fsync(); }
|
||||
void SetIOPriority(Env::IOPriority pri) override {
|
||||
target_->SetIOPriority(pri);
|
||||
}
|
||||
uint64_t GetFileSize() override { return target_->GetFileSize(); }
|
||||
void GetPreallocationStatus(size_t* block_size,
|
||||
size_t* last_allocated_block) override {
|
||||
target_->GetPreallocationStatus(block_size, last_allocated_block);
|
||||
}
|
||||
size_t GetUniqueId(char* id, size_t max_size) const override {
|
||||
return target_->GetUniqueId(id, max_size);
|
||||
}
|
||||
Status InvalidateCache(size_t offset, size_t length) override {
|
||||
return target_->InvalidateCache(offset, length);
|
||||
}
|
||||
|
||||
protected:
|
||||
Status Allocate(off_t offset, off_t len) override {
|
||||
return target_->Allocate(offset, len);
|
||||
}
|
||||
Status RangeSync(off_t offset, off_t nbytes) override {
|
||||
return target_->RangeSync(offset, nbytes);
|
||||
}
|
||||
|
||||
private:
|
||||
WritableFile* target_;
|
||||
};
|
||||
|
||||
// Returns a new environment that stores its data in memory and delegates
|
||||
// all non-file-storage tasks to base_env. The caller must delete the result
|
||||
// when it is no longer needed.
|
||||
|
@ -982,6 +982,87 @@ TEST_F(EnvPosixTest, Preallocation) {
|
||||
ASSERT_EQ(last_allocated_block, 7UL);
|
||||
}
|
||||
|
||||
// Test that all WritableFileWrapper forwards all calls to WritableFile.
|
||||
TEST_F(EnvPosixTest, WritableFileWrapper) {
|
||||
class Base : public WritableFile {
|
||||
public:
|
||||
mutable int *step_;
|
||||
|
||||
void inc(int x) const {
|
||||
EXPECT_EQ(x, (*step_)++);
|
||||
}
|
||||
|
||||
explicit Base(int* step) : step_(step) {
|
||||
inc(0);
|
||||
}
|
||||
|
||||
Status Append(const Slice& data) override { inc(1); return Status::OK(); }
|
||||
Status Close() override { inc(2); return Status::OK(); }
|
||||
Status Flush() override { inc(3); return Status::OK(); }
|
||||
Status Sync() override { inc(4); return Status::OK(); }
|
||||
Status Fsync() override { inc(5); return Status::OK(); }
|
||||
void SetIOPriority(Env::IOPriority pri) override { inc(6); }
|
||||
uint64_t GetFileSize() override { inc(7); return 0; }
|
||||
void GetPreallocationStatus(size_t* block_size,
|
||||
size_t* last_allocated_block) override {
|
||||
inc(8);
|
||||
}
|
||||
size_t GetUniqueId(char* id, size_t max_size) const override {
|
||||
inc(9);
|
||||
return 0;
|
||||
}
|
||||
Status InvalidateCache(size_t offset, size_t length) override {
|
||||
inc(10);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
protected:
|
||||
Status Allocate(off_t offset, off_t len) override {
|
||||
inc(11);
|
||||
return Status::OK();
|
||||
}
|
||||
Status RangeSync(off_t offset, off_t nbytes) override {
|
||||
inc(12);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
public:
|
||||
~Base() {
|
||||
inc(13);
|
||||
}
|
||||
};
|
||||
|
||||
class Wrapper : public WritableFileWrapper {
|
||||
public:
|
||||
explicit Wrapper(WritableFile* target) : WritableFileWrapper(target) {}
|
||||
|
||||
void CallProtectedMethods() {
|
||||
Allocate(0, 0);
|
||||
RangeSync(0, 0);
|
||||
}
|
||||
};
|
||||
|
||||
int step = 0;
|
||||
|
||||
{
|
||||
Base b(&step);
|
||||
Wrapper w(&b);
|
||||
w.Append(Slice());
|
||||
w.Close();
|
||||
w.Flush();
|
||||
w.Sync();
|
||||
w.Fsync();
|
||||
w.SetIOPriority(Env::IOPriority::IO_HIGH);
|
||||
w.GetFileSize();
|
||||
w.GetPreallocationStatus(nullptr, nullptr);
|
||||
w.GetUniqueId(nullptr, 0);
|
||||
w.InvalidateCache(0, 0);
|
||||
w.CallProtectedMethods();
|
||||
}
|
||||
|
||||
EXPECT_EQ(14, step);
|
||||
}
|
||||
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
Loading…
Reference in New Issue
Block a user