1*9507f98cSAndroid Build Coastguard Worker // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2*9507f98cSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*9507f98cSAndroid Build Coastguard Worker // found in the LICENSE file. See the AUTHORS file for names of contributors.
4*9507f98cSAndroid Build Coastguard Worker
5*9507f98cSAndroid Build Coastguard Worker #include "helpers/memenv/memenv.h"
6*9507f98cSAndroid Build Coastguard Worker
7*9507f98cSAndroid Build Coastguard Worker #include <cstring>
8*9507f98cSAndroid Build Coastguard Worker #include <limits>
9*9507f98cSAndroid Build Coastguard Worker #include <map>
10*9507f98cSAndroid Build Coastguard Worker #include <string>
11*9507f98cSAndroid Build Coastguard Worker #include <vector>
12*9507f98cSAndroid Build Coastguard Worker
13*9507f98cSAndroid Build Coastguard Worker #include "leveldb/env.h"
14*9507f98cSAndroid Build Coastguard Worker #include "leveldb/status.h"
15*9507f98cSAndroid Build Coastguard Worker #include "port/port.h"
16*9507f98cSAndroid Build Coastguard Worker #include "port/thread_annotations.h"
17*9507f98cSAndroid Build Coastguard Worker #include "util/mutexlock.h"
18*9507f98cSAndroid Build Coastguard Worker
19*9507f98cSAndroid Build Coastguard Worker namespace leveldb {
20*9507f98cSAndroid Build Coastguard Worker
21*9507f98cSAndroid Build Coastguard Worker namespace {
22*9507f98cSAndroid Build Coastguard Worker
23*9507f98cSAndroid Build Coastguard Worker class FileState {
24*9507f98cSAndroid Build Coastguard Worker public:
25*9507f98cSAndroid Build Coastguard Worker // FileStates are reference counted. The initial reference count is zero
26*9507f98cSAndroid Build Coastguard Worker // and the caller must call Ref() at least once.
FileState()27*9507f98cSAndroid Build Coastguard Worker FileState() : refs_(0), size_(0) {}
28*9507f98cSAndroid Build Coastguard Worker
29*9507f98cSAndroid Build Coastguard Worker // No copying allowed.
30*9507f98cSAndroid Build Coastguard Worker FileState(const FileState&) = delete;
31*9507f98cSAndroid Build Coastguard Worker FileState& operator=(const FileState&) = delete;
32*9507f98cSAndroid Build Coastguard Worker
33*9507f98cSAndroid Build Coastguard Worker // Increase the reference count.
Ref()34*9507f98cSAndroid Build Coastguard Worker void Ref() {
35*9507f98cSAndroid Build Coastguard Worker MutexLock lock(&refs_mutex_);
36*9507f98cSAndroid Build Coastguard Worker ++refs_;
37*9507f98cSAndroid Build Coastguard Worker }
38*9507f98cSAndroid Build Coastguard Worker
39*9507f98cSAndroid Build Coastguard Worker // Decrease the reference count. Delete if this is the last reference.
Unref()40*9507f98cSAndroid Build Coastguard Worker void Unref() {
41*9507f98cSAndroid Build Coastguard Worker bool do_delete = false;
42*9507f98cSAndroid Build Coastguard Worker
43*9507f98cSAndroid Build Coastguard Worker {
44*9507f98cSAndroid Build Coastguard Worker MutexLock lock(&refs_mutex_);
45*9507f98cSAndroid Build Coastguard Worker --refs_;
46*9507f98cSAndroid Build Coastguard Worker assert(refs_ >= 0);
47*9507f98cSAndroid Build Coastguard Worker if (refs_ <= 0) {
48*9507f98cSAndroid Build Coastguard Worker do_delete = true;
49*9507f98cSAndroid Build Coastguard Worker }
50*9507f98cSAndroid Build Coastguard Worker }
51*9507f98cSAndroid Build Coastguard Worker
52*9507f98cSAndroid Build Coastguard Worker if (do_delete) {
53*9507f98cSAndroid Build Coastguard Worker delete this;
54*9507f98cSAndroid Build Coastguard Worker }
55*9507f98cSAndroid Build Coastguard Worker }
56*9507f98cSAndroid Build Coastguard Worker
Size() const57*9507f98cSAndroid Build Coastguard Worker uint64_t Size() const {
58*9507f98cSAndroid Build Coastguard Worker MutexLock lock(&blocks_mutex_);
59*9507f98cSAndroid Build Coastguard Worker return size_;
60*9507f98cSAndroid Build Coastguard Worker }
61*9507f98cSAndroid Build Coastguard Worker
Truncate()62*9507f98cSAndroid Build Coastguard Worker void Truncate() {
63*9507f98cSAndroid Build Coastguard Worker MutexLock lock(&blocks_mutex_);
64*9507f98cSAndroid Build Coastguard Worker for (char*& block : blocks_) {
65*9507f98cSAndroid Build Coastguard Worker delete[] block;
66*9507f98cSAndroid Build Coastguard Worker }
67*9507f98cSAndroid Build Coastguard Worker blocks_.clear();
68*9507f98cSAndroid Build Coastguard Worker size_ = 0;
69*9507f98cSAndroid Build Coastguard Worker }
70*9507f98cSAndroid Build Coastguard Worker
Read(uint64_t offset,size_t n,Slice * result,char * scratch) const71*9507f98cSAndroid Build Coastguard Worker Status Read(uint64_t offset, size_t n, Slice* result, char* scratch) const {
72*9507f98cSAndroid Build Coastguard Worker MutexLock lock(&blocks_mutex_);
73*9507f98cSAndroid Build Coastguard Worker if (offset > size_) {
74*9507f98cSAndroid Build Coastguard Worker return Status::IOError("Offset greater than file size.");
75*9507f98cSAndroid Build Coastguard Worker }
76*9507f98cSAndroid Build Coastguard Worker const uint64_t available = size_ - offset;
77*9507f98cSAndroid Build Coastguard Worker if (n > available) {
78*9507f98cSAndroid Build Coastguard Worker n = static_cast<size_t>(available);
79*9507f98cSAndroid Build Coastguard Worker }
80*9507f98cSAndroid Build Coastguard Worker if (n == 0) {
81*9507f98cSAndroid Build Coastguard Worker *result = Slice();
82*9507f98cSAndroid Build Coastguard Worker return Status::OK();
83*9507f98cSAndroid Build Coastguard Worker }
84*9507f98cSAndroid Build Coastguard Worker
85*9507f98cSAndroid Build Coastguard Worker assert(offset / kBlockSize <= std::numeric_limits<size_t>::max());
86*9507f98cSAndroid Build Coastguard Worker size_t block = static_cast<size_t>(offset / kBlockSize);
87*9507f98cSAndroid Build Coastguard Worker size_t block_offset = offset % kBlockSize;
88*9507f98cSAndroid Build Coastguard Worker size_t bytes_to_copy = n;
89*9507f98cSAndroid Build Coastguard Worker char* dst = scratch;
90*9507f98cSAndroid Build Coastguard Worker
91*9507f98cSAndroid Build Coastguard Worker while (bytes_to_copy > 0) {
92*9507f98cSAndroid Build Coastguard Worker size_t avail = kBlockSize - block_offset;
93*9507f98cSAndroid Build Coastguard Worker if (avail > bytes_to_copy) {
94*9507f98cSAndroid Build Coastguard Worker avail = bytes_to_copy;
95*9507f98cSAndroid Build Coastguard Worker }
96*9507f98cSAndroid Build Coastguard Worker std::memcpy(dst, blocks_[block] + block_offset, avail);
97*9507f98cSAndroid Build Coastguard Worker
98*9507f98cSAndroid Build Coastguard Worker bytes_to_copy -= avail;
99*9507f98cSAndroid Build Coastguard Worker dst += avail;
100*9507f98cSAndroid Build Coastguard Worker block++;
101*9507f98cSAndroid Build Coastguard Worker block_offset = 0;
102*9507f98cSAndroid Build Coastguard Worker }
103*9507f98cSAndroid Build Coastguard Worker
104*9507f98cSAndroid Build Coastguard Worker *result = Slice(scratch, n);
105*9507f98cSAndroid Build Coastguard Worker return Status::OK();
106*9507f98cSAndroid Build Coastguard Worker }
107*9507f98cSAndroid Build Coastguard Worker
Append(const Slice & data)108*9507f98cSAndroid Build Coastguard Worker Status Append(const Slice& data) {
109*9507f98cSAndroid Build Coastguard Worker const char* src = data.data();
110*9507f98cSAndroid Build Coastguard Worker size_t src_len = data.size();
111*9507f98cSAndroid Build Coastguard Worker
112*9507f98cSAndroid Build Coastguard Worker MutexLock lock(&blocks_mutex_);
113*9507f98cSAndroid Build Coastguard Worker while (src_len > 0) {
114*9507f98cSAndroid Build Coastguard Worker size_t avail;
115*9507f98cSAndroid Build Coastguard Worker size_t offset = size_ % kBlockSize;
116*9507f98cSAndroid Build Coastguard Worker
117*9507f98cSAndroid Build Coastguard Worker if (offset != 0) {
118*9507f98cSAndroid Build Coastguard Worker // There is some room in the last block.
119*9507f98cSAndroid Build Coastguard Worker avail = kBlockSize - offset;
120*9507f98cSAndroid Build Coastguard Worker } else {
121*9507f98cSAndroid Build Coastguard Worker // No room in the last block; push new one.
122*9507f98cSAndroid Build Coastguard Worker blocks_.push_back(new char[kBlockSize]);
123*9507f98cSAndroid Build Coastguard Worker avail = kBlockSize;
124*9507f98cSAndroid Build Coastguard Worker }
125*9507f98cSAndroid Build Coastguard Worker
126*9507f98cSAndroid Build Coastguard Worker if (avail > src_len) {
127*9507f98cSAndroid Build Coastguard Worker avail = src_len;
128*9507f98cSAndroid Build Coastguard Worker }
129*9507f98cSAndroid Build Coastguard Worker std::memcpy(blocks_.back() + offset, src, avail);
130*9507f98cSAndroid Build Coastguard Worker src_len -= avail;
131*9507f98cSAndroid Build Coastguard Worker src += avail;
132*9507f98cSAndroid Build Coastguard Worker size_ += avail;
133*9507f98cSAndroid Build Coastguard Worker }
134*9507f98cSAndroid Build Coastguard Worker
135*9507f98cSAndroid Build Coastguard Worker return Status::OK();
136*9507f98cSAndroid Build Coastguard Worker }
137*9507f98cSAndroid Build Coastguard Worker
138*9507f98cSAndroid Build Coastguard Worker private:
139*9507f98cSAndroid Build Coastguard Worker enum { kBlockSize = 8 * 1024 };
140*9507f98cSAndroid Build Coastguard Worker
141*9507f98cSAndroid Build Coastguard Worker // Private since only Unref() should be used to delete it.
~FileState()142*9507f98cSAndroid Build Coastguard Worker ~FileState() { Truncate(); }
143*9507f98cSAndroid Build Coastguard Worker
144*9507f98cSAndroid Build Coastguard Worker port::Mutex refs_mutex_;
145*9507f98cSAndroid Build Coastguard Worker int refs_ GUARDED_BY(refs_mutex_);
146*9507f98cSAndroid Build Coastguard Worker
147*9507f98cSAndroid Build Coastguard Worker mutable port::Mutex blocks_mutex_;
148*9507f98cSAndroid Build Coastguard Worker std::vector<char*> blocks_ GUARDED_BY(blocks_mutex_);
149*9507f98cSAndroid Build Coastguard Worker uint64_t size_ GUARDED_BY(blocks_mutex_);
150*9507f98cSAndroid Build Coastguard Worker };
151*9507f98cSAndroid Build Coastguard Worker
152*9507f98cSAndroid Build Coastguard Worker class SequentialFileImpl : public SequentialFile {
153*9507f98cSAndroid Build Coastguard Worker public:
SequentialFileImpl(FileState * file)154*9507f98cSAndroid Build Coastguard Worker explicit SequentialFileImpl(FileState* file) : file_(file), pos_(0) {
155*9507f98cSAndroid Build Coastguard Worker file_->Ref();
156*9507f98cSAndroid Build Coastguard Worker }
157*9507f98cSAndroid Build Coastguard Worker
~SequentialFileImpl()158*9507f98cSAndroid Build Coastguard Worker ~SequentialFileImpl() override { file_->Unref(); }
159*9507f98cSAndroid Build Coastguard Worker
Read(size_t n,Slice * result,char * scratch)160*9507f98cSAndroid Build Coastguard Worker Status Read(size_t n, Slice* result, char* scratch) override {
161*9507f98cSAndroid Build Coastguard Worker Status s = file_->Read(pos_, n, result, scratch);
162*9507f98cSAndroid Build Coastguard Worker if (s.ok()) {
163*9507f98cSAndroid Build Coastguard Worker pos_ += result->size();
164*9507f98cSAndroid Build Coastguard Worker }
165*9507f98cSAndroid Build Coastguard Worker return s;
166*9507f98cSAndroid Build Coastguard Worker }
167*9507f98cSAndroid Build Coastguard Worker
Skip(uint64_t n)168*9507f98cSAndroid Build Coastguard Worker Status Skip(uint64_t n) override {
169*9507f98cSAndroid Build Coastguard Worker if (pos_ > file_->Size()) {
170*9507f98cSAndroid Build Coastguard Worker return Status::IOError("pos_ > file_->Size()");
171*9507f98cSAndroid Build Coastguard Worker }
172*9507f98cSAndroid Build Coastguard Worker const uint64_t available = file_->Size() - pos_;
173*9507f98cSAndroid Build Coastguard Worker if (n > available) {
174*9507f98cSAndroid Build Coastguard Worker n = available;
175*9507f98cSAndroid Build Coastguard Worker }
176*9507f98cSAndroid Build Coastguard Worker pos_ += n;
177*9507f98cSAndroid Build Coastguard Worker return Status::OK();
178*9507f98cSAndroid Build Coastguard Worker }
179*9507f98cSAndroid Build Coastguard Worker
180*9507f98cSAndroid Build Coastguard Worker private:
181*9507f98cSAndroid Build Coastguard Worker FileState* file_;
182*9507f98cSAndroid Build Coastguard Worker uint64_t pos_;
183*9507f98cSAndroid Build Coastguard Worker };
184*9507f98cSAndroid Build Coastguard Worker
185*9507f98cSAndroid Build Coastguard Worker class RandomAccessFileImpl : public RandomAccessFile {
186*9507f98cSAndroid Build Coastguard Worker public:
RandomAccessFileImpl(FileState * file)187*9507f98cSAndroid Build Coastguard Worker explicit RandomAccessFileImpl(FileState* file) : file_(file) { file_->Ref(); }
188*9507f98cSAndroid Build Coastguard Worker
~RandomAccessFileImpl()189*9507f98cSAndroid Build Coastguard Worker ~RandomAccessFileImpl() override { file_->Unref(); }
190*9507f98cSAndroid Build Coastguard Worker
Read(uint64_t offset,size_t n,Slice * result,char * scratch) const191*9507f98cSAndroid Build Coastguard Worker Status Read(uint64_t offset, size_t n, Slice* result,
192*9507f98cSAndroid Build Coastguard Worker char* scratch) const override {
193*9507f98cSAndroid Build Coastguard Worker return file_->Read(offset, n, result, scratch);
194*9507f98cSAndroid Build Coastguard Worker }
195*9507f98cSAndroid Build Coastguard Worker
196*9507f98cSAndroid Build Coastguard Worker private:
197*9507f98cSAndroid Build Coastguard Worker FileState* file_;
198*9507f98cSAndroid Build Coastguard Worker };
199*9507f98cSAndroid Build Coastguard Worker
200*9507f98cSAndroid Build Coastguard Worker class WritableFileImpl : public WritableFile {
201*9507f98cSAndroid Build Coastguard Worker public:
WritableFileImpl(FileState * file)202*9507f98cSAndroid Build Coastguard Worker WritableFileImpl(FileState* file) : file_(file) { file_->Ref(); }
203*9507f98cSAndroid Build Coastguard Worker
~WritableFileImpl()204*9507f98cSAndroid Build Coastguard Worker ~WritableFileImpl() override { file_->Unref(); }
205*9507f98cSAndroid Build Coastguard Worker
Append(const Slice & data)206*9507f98cSAndroid Build Coastguard Worker Status Append(const Slice& data) override { return file_->Append(data); }
207*9507f98cSAndroid Build Coastguard Worker
Close()208*9507f98cSAndroid Build Coastguard Worker Status Close() override { return Status::OK(); }
Flush()209*9507f98cSAndroid Build Coastguard Worker Status Flush() override { return Status::OK(); }
Sync()210*9507f98cSAndroid Build Coastguard Worker Status Sync() override { return Status::OK(); }
211*9507f98cSAndroid Build Coastguard Worker
212*9507f98cSAndroid Build Coastguard Worker private:
213*9507f98cSAndroid Build Coastguard Worker FileState* file_;
214*9507f98cSAndroid Build Coastguard Worker };
215*9507f98cSAndroid Build Coastguard Worker
216*9507f98cSAndroid Build Coastguard Worker class NoOpLogger : public Logger {
217*9507f98cSAndroid Build Coastguard Worker public:
Logv(const char * format,std::va_list ap)218*9507f98cSAndroid Build Coastguard Worker void Logv(const char* format, std::va_list ap) override {}
219*9507f98cSAndroid Build Coastguard Worker };
220*9507f98cSAndroid Build Coastguard Worker
221*9507f98cSAndroid Build Coastguard Worker class InMemoryEnv : public EnvWrapper {
222*9507f98cSAndroid Build Coastguard Worker public:
InMemoryEnv(Env * base_env)223*9507f98cSAndroid Build Coastguard Worker explicit InMemoryEnv(Env* base_env) : EnvWrapper(base_env) {}
224*9507f98cSAndroid Build Coastguard Worker
~InMemoryEnv()225*9507f98cSAndroid Build Coastguard Worker ~InMemoryEnv() override {
226*9507f98cSAndroid Build Coastguard Worker for (const auto& kvp : file_map_) {
227*9507f98cSAndroid Build Coastguard Worker kvp.second->Unref();
228*9507f98cSAndroid Build Coastguard Worker }
229*9507f98cSAndroid Build Coastguard Worker }
230*9507f98cSAndroid Build Coastguard Worker
231*9507f98cSAndroid Build Coastguard Worker // Partial implementation of the Env interface.
NewSequentialFile(const std::string & fname,SequentialFile ** result)232*9507f98cSAndroid Build Coastguard Worker Status NewSequentialFile(const std::string& fname,
233*9507f98cSAndroid Build Coastguard Worker SequentialFile** result) override {
234*9507f98cSAndroid Build Coastguard Worker MutexLock lock(&mutex_);
235*9507f98cSAndroid Build Coastguard Worker if (file_map_.find(fname) == file_map_.end()) {
236*9507f98cSAndroid Build Coastguard Worker *result = nullptr;
237*9507f98cSAndroid Build Coastguard Worker return Status::IOError(fname, "File not found");
238*9507f98cSAndroid Build Coastguard Worker }
239*9507f98cSAndroid Build Coastguard Worker
240*9507f98cSAndroid Build Coastguard Worker *result = new SequentialFileImpl(file_map_[fname]);
241*9507f98cSAndroid Build Coastguard Worker return Status::OK();
242*9507f98cSAndroid Build Coastguard Worker }
243*9507f98cSAndroid Build Coastguard Worker
NewRandomAccessFile(const std::string & fname,RandomAccessFile ** result)244*9507f98cSAndroid Build Coastguard Worker Status NewRandomAccessFile(const std::string& fname,
245*9507f98cSAndroid Build Coastguard Worker RandomAccessFile** result) override {
246*9507f98cSAndroid Build Coastguard Worker MutexLock lock(&mutex_);
247*9507f98cSAndroid Build Coastguard Worker if (file_map_.find(fname) == file_map_.end()) {
248*9507f98cSAndroid Build Coastguard Worker *result = nullptr;
249*9507f98cSAndroid Build Coastguard Worker return Status::IOError(fname, "File not found");
250*9507f98cSAndroid Build Coastguard Worker }
251*9507f98cSAndroid Build Coastguard Worker
252*9507f98cSAndroid Build Coastguard Worker *result = new RandomAccessFileImpl(file_map_[fname]);
253*9507f98cSAndroid Build Coastguard Worker return Status::OK();
254*9507f98cSAndroid Build Coastguard Worker }
255*9507f98cSAndroid Build Coastguard Worker
NewWritableFile(const std::string & fname,WritableFile ** result)256*9507f98cSAndroid Build Coastguard Worker Status NewWritableFile(const std::string& fname,
257*9507f98cSAndroid Build Coastguard Worker WritableFile** result) override {
258*9507f98cSAndroid Build Coastguard Worker MutexLock lock(&mutex_);
259*9507f98cSAndroid Build Coastguard Worker FileSystem::iterator it = file_map_.find(fname);
260*9507f98cSAndroid Build Coastguard Worker
261*9507f98cSAndroid Build Coastguard Worker FileState* file;
262*9507f98cSAndroid Build Coastguard Worker if (it == file_map_.end()) {
263*9507f98cSAndroid Build Coastguard Worker // File is not currently open.
264*9507f98cSAndroid Build Coastguard Worker file = new FileState();
265*9507f98cSAndroid Build Coastguard Worker file->Ref();
266*9507f98cSAndroid Build Coastguard Worker file_map_[fname] = file;
267*9507f98cSAndroid Build Coastguard Worker } else {
268*9507f98cSAndroid Build Coastguard Worker file = it->second;
269*9507f98cSAndroid Build Coastguard Worker file->Truncate();
270*9507f98cSAndroid Build Coastguard Worker }
271*9507f98cSAndroid Build Coastguard Worker
272*9507f98cSAndroid Build Coastguard Worker *result = new WritableFileImpl(file);
273*9507f98cSAndroid Build Coastguard Worker return Status::OK();
274*9507f98cSAndroid Build Coastguard Worker }
275*9507f98cSAndroid Build Coastguard Worker
NewAppendableFile(const std::string & fname,WritableFile ** result)276*9507f98cSAndroid Build Coastguard Worker Status NewAppendableFile(const std::string& fname,
277*9507f98cSAndroid Build Coastguard Worker WritableFile** result) override {
278*9507f98cSAndroid Build Coastguard Worker MutexLock lock(&mutex_);
279*9507f98cSAndroid Build Coastguard Worker FileState** sptr = &file_map_[fname];
280*9507f98cSAndroid Build Coastguard Worker FileState* file = *sptr;
281*9507f98cSAndroid Build Coastguard Worker if (file == nullptr) {
282*9507f98cSAndroid Build Coastguard Worker file = new FileState();
283*9507f98cSAndroid Build Coastguard Worker file->Ref();
284*9507f98cSAndroid Build Coastguard Worker }
285*9507f98cSAndroid Build Coastguard Worker *result = new WritableFileImpl(file);
286*9507f98cSAndroid Build Coastguard Worker return Status::OK();
287*9507f98cSAndroid Build Coastguard Worker }
288*9507f98cSAndroid Build Coastguard Worker
FileExists(const std::string & fname)289*9507f98cSAndroid Build Coastguard Worker bool FileExists(const std::string& fname) override {
290*9507f98cSAndroid Build Coastguard Worker MutexLock lock(&mutex_);
291*9507f98cSAndroid Build Coastguard Worker return file_map_.find(fname) != file_map_.end();
292*9507f98cSAndroid Build Coastguard Worker }
293*9507f98cSAndroid Build Coastguard Worker
GetChildren(const std::string & dir,std::vector<std::string> * result)294*9507f98cSAndroid Build Coastguard Worker Status GetChildren(const std::string& dir,
295*9507f98cSAndroid Build Coastguard Worker std::vector<std::string>* result) override {
296*9507f98cSAndroid Build Coastguard Worker MutexLock lock(&mutex_);
297*9507f98cSAndroid Build Coastguard Worker result->clear();
298*9507f98cSAndroid Build Coastguard Worker
299*9507f98cSAndroid Build Coastguard Worker for (const auto& kvp : file_map_) {
300*9507f98cSAndroid Build Coastguard Worker const std::string& filename = kvp.first;
301*9507f98cSAndroid Build Coastguard Worker
302*9507f98cSAndroid Build Coastguard Worker if (filename.size() >= dir.size() + 1 && filename[dir.size()] == '/' &&
303*9507f98cSAndroid Build Coastguard Worker Slice(filename).starts_with(Slice(dir))) {
304*9507f98cSAndroid Build Coastguard Worker result->push_back(filename.substr(dir.size() + 1));
305*9507f98cSAndroid Build Coastguard Worker }
306*9507f98cSAndroid Build Coastguard Worker }
307*9507f98cSAndroid Build Coastguard Worker
308*9507f98cSAndroid Build Coastguard Worker return Status::OK();
309*9507f98cSAndroid Build Coastguard Worker }
310*9507f98cSAndroid Build Coastguard Worker
RemoveFileInternal(const std::string & fname)311*9507f98cSAndroid Build Coastguard Worker void RemoveFileInternal(const std::string& fname)
312*9507f98cSAndroid Build Coastguard Worker EXCLUSIVE_LOCKS_REQUIRED(mutex_) {
313*9507f98cSAndroid Build Coastguard Worker if (file_map_.find(fname) == file_map_.end()) {
314*9507f98cSAndroid Build Coastguard Worker return;
315*9507f98cSAndroid Build Coastguard Worker }
316*9507f98cSAndroid Build Coastguard Worker
317*9507f98cSAndroid Build Coastguard Worker file_map_[fname]->Unref();
318*9507f98cSAndroid Build Coastguard Worker file_map_.erase(fname);
319*9507f98cSAndroid Build Coastguard Worker }
320*9507f98cSAndroid Build Coastguard Worker
RemoveFile(const std::string & fname)321*9507f98cSAndroid Build Coastguard Worker Status RemoveFile(const std::string& fname) override {
322*9507f98cSAndroid Build Coastguard Worker MutexLock lock(&mutex_);
323*9507f98cSAndroid Build Coastguard Worker if (file_map_.find(fname) == file_map_.end()) {
324*9507f98cSAndroid Build Coastguard Worker return Status::IOError(fname, "File not found");
325*9507f98cSAndroid Build Coastguard Worker }
326*9507f98cSAndroid Build Coastguard Worker
327*9507f98cSAndroid Build Coastguard Worker RemoveFileInternal(fname);
328*9507f98cSAndroid Build Coastguard Worker return Status::OK();
329*9507f98cSAndroid Build Coastguard Worker }
330*9507f98cSAndroid Build Coastguard Worker
CreateDir(const std::string & dirname)331*9507f98cSAndroid Build Coastguard Worker Status CreateDir(const std::string& dirname) override { return Status::OK(); }
332*9507f98cSAndroid Build Coastguard Worker
RemoveDir(const std::string & dirname)333*9507f98cSAndroid Build Coastguard Worker Status RemoveDir(const std::string& dirname) override { return Status::OK(); }
334*9507f98cSAndroid Build Coastguard Worker
GetFileSize(const std::string & fname,uint64_t * file_size)335*9507f98cSAndroid Build Coastguard Worker Status GetFileSize(const std::string& fname, uint64_t* file_size) override {
336*9507f98cSAndroid Build Coastguard Worker MutexLock lock(&mutex_);
337*9507f98cSAndroid Build Coastguard Worker if (file_map_.find(fname) == file_map_.end()) {
338*9507f98cSAndroid Build Coastguard Worker return Status::IOError(fname, "File not found");
339*9507f98cSAndroid Build Coastguard Worker }
340*9507f98cSAndroid Build Coastguard Worker
341*9507f98cSAndroid Build Coastguard Worker *file_size = file_map_[fname]->Size();
342*9507f98cSAndroid Build Coastguard Worker return Status::OK();
343*9507f98cSAndroid Build Coastguard Worker }
344*9507f98cSAndroid Build Coastguard Worker
RenameFile(const std::string & src,const std::string & target)345*9507f98cSAndroid Build Coastguard Worker Status RenameFile(const std::string& src,
346*9507f98cSAndroid Build Coastguard Worker const std::string& target) override {
347*9507f98cSAndroid Build Coastguard Worker MutexLock lock(&mutex_);
348*9507f98cSAndroid Build Coastguard Worker if (file_map_.find(src) == file_map_.end()) {
349*9507f98cSAndroid Build Coastguard Worker return Status::IOError(src, "File not found");
350*9507f98cSAndroid Build Coastguard Worker }
351*9507f98cSAndroid Build Coastguard Worker
352*9507f98cSAndroid Build Coastguard Worker RemoveFileInternal(target);
353*9507f98cSAndroid Build Coastguard Worker file_map_[target] = file_map_[src];
354*9507f98cSAndroid Build Coastguard Worker file_map_.erase(src);
355*9507f98cSAndroid Build Coastguard Worker return Status::OK();
356*9507f98cSAndroid Build Coastguard Worker }
357*9507f98cSAndroid Build Coastguard Worker
LockFile(const std::string & fname,FileLock ** lock)358*9507f98cSAndroid Build Coastguard Worker Status LockFile(const std::string& fname, FileLock** lock) override {
359*9507f98cSAndroid Build Coastguard Worker *lock = new FileLock;
360*9507f98cSAndroid Build Coastguard Worker return Status::OK();
361*9507f98cSAndroid Build Coastguard Worker }
362*9507f98cSAndroid Build Coastguard Worker
UnlockFile(FileLock * lock)363*9507f98cSAndroid Build Coastguard Worker Status UnlockFile(FileLock* lock) override {
364*9507f98cSAndroid Build Coastguard Worker delete lock;
365*9507f98cSAndroid Build Coastguard Worker return Status::OK();
366*9507f98cSAndroid Build Coastguard Worker }
367*9507f98cSAndroid Build Coastguard Worker
GetTestDirectory(std::string * path)368*9507f98cSAndroid Build Coastguard Worker Status GetTestDirectory(std::string* path) override {
369*9507f98cSAndroid Build Coastguard Worker *path = "/test";
370*9507f98cSAndroid Build Coastguard Worker return Status::OK();
371*9507f98cSAndroid Build Coastguard Worker }
372*9507f98cSAndroid Build Coastguard Worker
NewLogger(const std::string & fname,Logger ** result)373*9507f98cSAndroid Build Coastguard Worker Status NewLogger(const std::string& fname, Logger** result) override {
374*9507f98cSAndroid Build Coastguard Worker *result = new NoOpLogger;
375*9507f98cSAndroid Build Coastguard Worker return Status::OK();
376*9507f98cSAndroid Build Coastguard Worker }
377*9507f98cSAndroid Build Coastguard Worker
378*9507f98cSAndroid Build Coastguard Worker private:
379*9507f98cSAndroid Build Coastguard Worker // Map from filenames to FileState objects, representing a simple file system.
380*9507f98cSAndroid Build Coastguard Worker typedef std::map<std::string, FileState*> FileSystem;
381*9507f98cSAndroid Build Coastguard Worker
382*9507f98cSAndroid Build Coastguard Worker port::Mutex mutex_;
383*9507f98cSAndroid Build Coastguard Worker FileSystem file_map_ GUARDED_BY(mutex_);
384*9507f98cSAndroid Build Coastguard Worker };
385*9507f98cSAndroid Build Coastguard Worker
386*9507f98cSAndroid Build Coastguard Worker } // namespace
387*9507f98cSAndroid Build Coastguard Worker
NewMemEnv(Env * base_env)388*9507f98cSAndroid Build Coastguard Worker Env* NewMemEnv(Env* base_env) { return new InMemoryEnv(base_env); }
389*9507f98cSAndroid Build Coastguard Worker
390*9507f98cSAndroid Build Coastguard Worker } // namespace leveldb
391