summaryrefslogtreecommitdiff
path: root/chromium/components/leveldb
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/components/leveldb')
-rw-r--r--chromium/components/leveldb/env_mojo.cc134
-rw-r--r--chromium/components/leveldb/env_mojo.h18
-rw-r--r--chromium/components/leveldb/leveldb_app.cc19
-rw-r--r--chromium/components/leveldb/leveldb_app.h10
-rw-r--r--chromium/components/leveldb/leveldb_database_impl.cc63
-rw-r--r--chromium/components/leveldb/leveldb_database_impl.h16
-rw-r--r--chromium/components/leveldb/leveldb_mojo_proxy.cc9
-rw-r--r--chromium/components/leveldb/leveldb_mojo_proxy.h12
-rw-r--r--chromium/components/leveldb/leveldb_service_impl.cc38
-rw-r--r--chromium/components/leveldb/leveldb_service_impl.h19
-rw-r--r--chromium/components/leveldb/leveldb_service_unittest.cc12
-rw-r--r--chromium/components/leveldb/public/interfaces/BUILD.gn2
-rw-r--r--chromium/components/leveldb/public/interfaces/leveldb.mojom9
-rw-r--r--chromium/components/leveldb/remote_iterator_unittest.cc2
14 files changed, 285 insertions, 78 deletions
diff --git a/chromium/components/leveldb/env_mojo.cc b/chromium/components/leveldb/env_mojo.cc
index 9b98405d125..0f17d71ec4b 100644
--- a/chromium/components/leveldb/env_mojo.cc
+++ b/chromium/components/leveldb/env_mojo.cc
@@ -45,6 +45,9 @@ Status FilesystemErrorToStatus(FileError error,
char buf[512];
snprintf(buf, sizeof(buf), "%s (MojoFSError: %d::%s)", err_str.c_str(),
method, MethodIDToString(method));
+
+ // TOOD(crbug.com/760362): Map FileError::NOT_FOUND to Status::NotFound, after
+ // fixing LevelDB to handle the NotFound correctly.
return Status::IOError(filename, buf);
}
@@ -218,6 +221,10 @@ class MojoWritableFile : public leveldb::WritableFile {
leveldb::Status SyncParent() {
FileError error = thread_->SyncDirectory(dir_, parent_dir_);
+ if (error != FileError::OK) {
+ uma_logger_->RecordOSError(leveldb_env::kSyncParent,
+ static_cast<base::File::Error>(error));
+ }
return error == FileError::OK
? Status::OK()
: Status::IOError(filename_,
@@ -257,6 +264,58 @@ class Thread : public base::PlatformThread::Delegate {
DISALLOW_COPY_AND_ASSIGN(Thread);
};
+class Retrier {
+ public:
+ Retrier(leveldb_env::MethodID method, MojoRetrierProvider* provider)
+ : start_(base::TimeTicks::Now()),
+ limit_(start_ + base::TimeDelta::FromMilliseconds(
+ provider->MaxRetryTimeMillis())),
+ last_(start_),
+ time_to_sleep_(base::TimeDelta::FromMilliseconds(10)),
+ success_(true),
+ method_(method),
+ last_error_(base::File::FILE_OK),
+ provider_(provider) {}
+
+ ~Retrier() {
+ if (success_) {
+ provider_->RecordRetryTime(method_, last_ - start_);
+ if (last_error_ != base::File::FILE_OK) {
+ DCHECK_LT(last_error_, 0);
+ provider_->RecordRecoveredFromError(method_, last_error_);
+ }
+ }
+ }
+
+ bool ShouldKeepTrying(FileError error) {
+ return ShouldKeepTrying(static_cast<base::File::Error>(error));
+ }
+
+ bool ShouldKeepTrying(base::File::Error last_error) {
+ DCHECK_NE(last_error, base::File::FILE_OK);
+ last_error_ = last_error;
+ if (last_ < limit_) {
+ base::PlatformThread::Sleep(time_to_sleep_);
+ last_ = base::TimeTicks::Now();
+ return true;
+ }
+ success_ = false;
+ return false;
+ }
+
+ private:
+ base::TimeTicks start_;
+ base::TimeTicks limit_;
+ base::TimeTicks last_;
+ base::TimeDelta time_to_sleep_;
+ bool success_;
+ leveldb_env::MethodID method_;
+ base::File::Error last_error_;
+ MojoRetrierProvider* provider_;
+
+ DISALLOW_COPY_AND_ASSIGN(Retrier);
+};
+
} // namespace
MojoEnv::MojoEnv(scoped_refptr<LevelDBMojoProxy> file_thread,
@@ -358,7 +417,11 @@ Status MojoEnv::DeleteFile(const std::string& fname) {
Status MojoEnv::CreateDir(const std::string& dirname) {
TRACE_EVENT1("leveldb", "MojoEnv::CreateDir", "dirname", dirname);
- FileError error = thread_->CreateDir(dir_, dirname);
+ Retrier retrier(leveldb_env::kCreateDir, this);
+ FileError error;
+ do {
+ error = thread_->CreateDir(dir_, dirname);
+ } while (error != FileError::OK && retrier.ShouldKeepTrying(error));
if (error != FileError::OK)
RecordFileError(leveldb_env::kCreateDir, error);
return FilesystemErrorToStatus(error, dirname, leveldb_env::kCreateDir);
@@ -383,7 +446,13 @@ Status MojoEnv::GetFileSize(const std::string& fname, uint64_t* file_size) {
Status MojoEnv::RenameFile(const std::string& src, const std::string& target) {
TRACE_EVENT2("leveldb", "MojoEnv::RenameFile", "src", src, "target", target);
- FileError error = thread_->RenameFile(dir_, src, target);
+ if (!thread_->FileExists(dir_, src))
+ return Status::OK();
+ Retrier retrier(leveldb_env::kRenameFile, this);
+ FileError error;
+ do {
+ error = thread_->RenameFile(dir_, src, target);
+ } while (error != FileError::OK && retrier.ShouldKeepTrying(error));
if (error != FileError::OK)
RecordFileError(leveldb_env::kRenameFile, error);
return FilesystemErrorToStatus(error, src, leveldb_env::kRenameFile);
@@ -392,8 +461,11 @@ Status MojoEnv::RenameFile(const std::string& src, const std::string& target) {
Status MojoEnv::LockFile(const std::string& fname, FileLock** lock) {
TRACE_EVENT1("leveldb", "MojoEnv::LockFile", "fname", fname);
- std::pair<FileError, LevelDBMojoProxy::OpaqueLock*> p =
- thread_->LockFile(dir_, fname);
+ Retrier retrier(leveldb_env::kLockFile, this);
+ std::pair<FileError, LevelDBMojoProxy::OpaqueLock*> p;
+ do {
+ p = thread_->LockFile(dir_, fname);
+ } while (p.first != FileError::OK && retrier.ShouldKeepTrying(p.first));
if (p.first != FileError::OK)
RecordFileError(leveldb_env::kLockFile, p.first);
@@ -443,6 +515,26 @@ Status MojoEnv::NewLogger(const std::string& fname, Logger** result) {
}
}
+uint64_t MojoEnv::NowMicros() {
+ return base::TimeTicks::Now().ToInternalValue();
+}
+
+void MojoEnv::SleepForMicroseconds(int micros) {
+ // Round up to the next millisecond.
+ base::PlatformThread::Sleep(base::TimeDelta::FromMicroseconds(micros));
+}
+
+void MojoEnv::Schedule(void (*function)(void* arg), void* arg) {
+ base::PostTaskWithTraits(FROM_HERE,
+ {base::MayBlock(), base::WithBaseSyncPrimitives(),
+ base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
+ base::Bind(function, arg));
+}
+
+void MojoEnv::StartThread(void (*function)(void* arg), void* arg) {
+ new Thread(function, arg); // Will self-delete.
+}
+
void MojoEnv::RecordErrorAt(leveldb_env::MethodID method) const {
UMA_HISTOGRAM_ENUMERATION("MojoLevelDBEnv.IOError", method,
leveldb_env::kNumEntries);
@@ -464,29 +556,29 @@ void MojoEnv::RecordBytesWritten(int amount) const {
UMA_HISTOGRAM_COUNTS_10M("Storage.BytesWritten.MojoLevelDBEnv", amount);
}
-void MojoEnv::RecordFileError(leveldb_env::MethodID method,
- FileError error) const {
- RecordOSError(method, static_cast<base::File::Error>(error));
-}
-
-uint64_t MojoEnv::NowMicros() {
- return base::TimeTicks::Now().ToInternalValue();
+int MojoEnv::MaxRetryTimeMillis() const {
+ return 1000;
}
-void MojoEnv::SleepForMicroseconds(int micros) {
- // Round up to the next millisecond.
- base::PlatformThread::Sleep(base::TimeDelta::FromMicroseconds(micros));
+void MojoEnv::RecordRetryTime(leveldb_env::MethodID method,
+ base::TimeDelta time) const {
+ std::string uma_name = std::string("MojoLevelDBEnv.TimeUntilSuccessFor") +
+ MethodIDToString(method);
+ UmaHistogramCustomTimes(uma_name, time, base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMilliseconds(1001), 42);
}
-void MojoEnv::Schedule(void (*function)(void* arg), void* arg) {
- base::PostTaskWithTraits(FROM_HERE,
- {base::MayBlock(), base::WithBaseSyncPrimitives(),
- base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
- base::Bind(function, arg));
+void MojoEnv::RecordRecoveredFromError(leveldb_env::MethodID method,
+ base::File::Error error) const {
+ std::string uma_name =
+ std::string("MojoLevelDBEnv.RetryRecoveredFromErrorIn") +
+ MethodIDToString(method);
+ base::UmaHistogramExactLinear(uma_name, -error, -base::File::FILE_ERROR_MAX);
}
-void MojoEnv::StartThread(void (*function)(void* arg), void* arg) {
- new Thread(function, arg); // Will self-delete.
+void MojoEnv::RecordFileError(leveldb_env::MethodID method,
+ FileError error) const {
+ RecordOSError(method, static_cast<base::File::Error>(error));
}
} // namespace leveldb
diff --git a/chromium/components/leveldb/env_mojo.h b/chromium/components/leveldb/env_mojo.h
index ca0f683902e..db240462131 100644
--- a/chromium/components/leveldb/env_mojo.h
+++ b/chromium/components/leveldb/env_mojo.h
@@ -12,12 +12,23 @@
namespace leveldb {
+class MojoRetrierProvider {
+ public:
+ virtual int MaxRetryTimeMillis() const = 0;
+ virtual void RecordRetryTime(leveldb_env::MethodID method,
+ base::TimeDelta time) const = 0;
+ virtual void RecordRecoveredFromError(leveldb_env::MethodID method,
+ base::File::Error error) const = 0;
+};
+
// An implementation of the leveldb operating system interaction code which
// proxies to a specified mojo:filesystem directory. Most of these methods are
// synchronous and block on responses from the filesystem service. That's fine
// since, for the most part, they merely open files or check for a file's
// existence.
-class MojoEnv : public Env, public leveldb_env::UMALogger {
+class MojoEnv : public Env,
+ public leveldb_env::UMALogger,
+ public MojoRetrierProvider {
public:
MojoEnv(scoped_refptr<LevelDBMojoProxy> file_thread,
LevelDBMojoProxy::OpaqueDir* dir);
@@ -56,6 +67,11 @@ class MojoEnv : public Env, public leveldb_env::UMALogger {
base::File::Error error) const override;
void RecordBytesRead(int amount) const override;
void RecordBytesWritten(int amount) const override;
+ int MaxRetryTimeMillis() const override;
+ void RecordRetryTime(leveldb_env::MethodID method,
+ base::TimeDelta time) const override;
+ void RecordRecoveredFromError(leveldb_env::MethodID method,
+ base::File::Error error) const override;
void RecordFileError(leveldb_env::MethodID method,
filesystem::mojom::FileError error) const;
diff --git a/chromium/components/leveldb/leveldb_app.cc b/chromium/components/leveldb/leveldb_app.cc
index cd5447ea05e..76b48b38b19 100644
--- a/chromium/components/leveldb/leveldb_app.cc
+++ b/chromium/components/leveldb/leveldb_app.cc
@@ -4,12 +4,15 @@
#include "components/leveldb/leveldb_app.h"
+#include "base/task_scheduler/post_task.h"
#include "components/leveldb/leveldb_service_impl.h"
#include "services/service_manager/public/cpp/service_context.h"
namespace leveldb {
-LevelDBApp::LevelDBApp() : file_thread_("LevelDBFile") {
+LevelDBApp::LevelDBApp()
+ : file_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
+ {base::MayBlock(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN})) {
registry_.AddInterface<mojom::LevelDBService>(
base::Bind(&LevelDBApp::Create, base::Unretained(this)));
}
@@ -22,18 +25,12 @@ void LevelDBApp::OnBindInterface(
const service_manager::BindSourceInfo& source_info,
const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) {
- registry_.BindInterface(source_info, interface_name,
- std::move(interface_pipe));
+ registry_.BindInterface(interface_name, std::move(interface_pipe));
}
-void LevelDBApp::Create(const service_manager::BindSourceInfo& source_info,
- leveldb::mojom::LevelDBServiceRequest request) {
- if (!service_) {
- if (!file_thread_.IsRunning())
- file_thread_.Start();
- service_.reset(
- new LevelDBServiceImpl(file_thread_.message_loop()->task_runner()));
- }
+void LevelDBApp::Create(leveldb::mojom::LevelDBServiceRequest request) {
+ if (!service_)
+ service_.reset(new LevelDBServiceImpl(file_task_runner_));
bindings_.AddBinding(service_.get(), std::move(request));
}
diff --git a/chromium/components/leveldb/leveldb_app.h b/chromium/components/leveldb/leveldb_app.h
index 78d542b3437..f5696a31d6b 100644
--- a/chromium/components/leveldb/leveldb_app.h
+++ b/chromium/components/leveldb/leveldb_app.h
@@ -7,12 +7,15 @@
#include <memory>
-#include "base/threading/thread.h"
#include "components/leveldb/public/interfaces/leveldb.mojom.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/cpp/service.h"
+namespace base {
+class SequencedTaskRunner;
+}
+
namespace leveldb {
class LevelDBApp : public service_manager::Service {
@@ -27,14 +30,13 @@ class LevelDBApp : public service_manager::Service {
const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) override;
- void Create(const service_manager::BindSourceInfo& source_info,
- leveldb::mojom::LevelDBServiceRequest request);
+ void Create(leveldb::mojom::LevelDBServiceRequest request);
std::unique_ptr<mojom::LevelDBService> service_;
service_manager::BinderRegistry registry_;
mojo::BindingSet<mojom::LevelDBService> bindings_;
- base::Thread file_thread_;
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
DISALLOW_COPY_AND_ASSIGN(LevelDBApp);
};
diff --git a/chromium/components/leveldb/leveldb_database_impl.cc b/chromium/components/leveldb/leveldb_database_impl.cc
index 59ab0787066..f0f509a28c6 100644
--- a/chromium/components/leveldb/leveldb_database_impl.cc
+++ b/chromium/components/leveldb/leveldb_database_impl.cc
@@ -4,14 +4,19 @@
#include "components/leveldb/leveldb_database_impl.h"
+#include <inttypes.h>
#include <map>
#include <string>
#include <utility>
#include "base/optional.h"
#include "base/rand_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "base/trace_event/memory_dump_manager.h"
#include "components/leveldb/env_mojo.h"
#include "components/leveldb/public/cpp/util.h"
+#include "third_party/leveldatabase/env_chromium.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h"
#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
@@ -37,10 +42,22 @@ leveldb::Status ForEachWithPrefix(leveldb::DB* db,
LevelDBDatabaseImpl::LevelDBDatabaseImpl(
std::unique_ptr<leveldb::Env> environment,
- std::unique_ptr<leveldb::DB> db)
- : environment_(std::move(environment)), db_(std::move(db)) {}
+ std::unique_ptr<leveldb::DB> db,
+ std::unique_ptr<leveldb::Cache> cache,
+ base::Optional<base::trace_event::MemoryAllocatorDumpGuid> memory_dump_id)
+ : environment_(std::move(environment)),
+ cache_(std::move(cache)),
+ db_(std::move(db)),
+ memory_dump_id_(memory_dump_id) {
+ base::trace_event::MemoryDumpManager::GetInstance()
+ ->RegisterDumpProviderWithSequencedTaskRunner(
+ this, "MojoLevelDB", base::SequencedTaskRunnerHandle::Get(),
+ MemoryDumpProvider::Options());
+}
LevelDBDatabaseImpl::~LevelDBDatabaseImpl() {
+ base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
+ this);
for (auto& p : iterator_map_)
delete p.second;
for (auto& p : snapshot_map_)
@@ -270,6 +287,48 @@ void LevelDBDatabaseImpl::IteratorPrev(const base::UnguessableToken& iterator,
ReplyToIteratorMessage(it->second, std::move(callback));
}
+bool LevelDBDatabaseImpl::OnMemoryDump(
+ const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) {
+ std::string name = base::StringPrintf("leveldb/mojo/0x%" PRIXPTR,
+ reinterpret_cast<uintptr_t>(db_.get()));
+ auto* mad = pmd->CreateAllocatorDump(name);
+
+ uint64_t memory_usage = 0;
+ std::string memory_usage_string;
+ bool got_memory_usage =
+ db_->GetProperty("leveldb.approximate-memory-usage",
+ &memory_usage_string) &&
+ base::StringToUint64(memory_usage_string, &memory_usage);
+ DCHECK(got_memory_usage);
+ mad->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ memory_usage);
+ if (cache_) {
+ auto* cache_mad = pmd->CreateAllocatorDump(name + "/block_cache");
+ cache_mad->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ cache_->TotalCharge());
+ }
+
+ // All leveldb databases are already dumped by leveldb_env::DBTracker. Add
+ // an edge to avoid double counting.
+ pmd->AddSuballocation(mad->guid(),
+ leveldb_env::DBTracker::GetMemoryDumpName(db_.get()));
+
+ if (memory_dump_id_) {
+ auto* global_dump = pmd->CreateSharedGlobalAllocatorDump(*memory_dump_id_);
+ pmd->AddOwnershipEdge(global_dump->guid(), mad->guid());
+ // Add size to global dump to propagate the size of the database to the
+ // client's dump.
+ global_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ memory_usage);
+ }
+
+ return true;
+}
+
void LevelDBDatabaseImpl::ReplyToIteratorMessage(
leveldb::Iterator* it,
IteratorSeekToFirstCallback callback) {
diff --git a/chromium/components/leveldb/leveldb_database_impl.h b/chromium/components/leveldb/leveldb_database_impl.h
index 277748d49ef..31c9cbabb05 100644
--- a/chromium/components/leveldb/leveldb_database_impl.h
+++ b/chromium/components/leveldb/leveldb_database_impl.h
@@ -7,18 +7,24 @@
#include <memory>
+#include "base/trace_event/memory_dump_provider.h"
#include "base/unguessable_token.h"
#include "components/leveldb/public/interfaces/leveldb.mojom.h"
#include "mojo/public/cpp/bindings/interface_request.h"
+#include "third_party/leveldatabase/src/include/leveldb/cache.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h"
namespace leveldb {
// The backing to a database object that we pass to our called.
-class LevelDBDatabaseImpl : public mojom::LevelDBDatabase {
+class LevelDBDatabaseImpl : public mojom::LevelDBDatabase,
+ public base::trace_event::MemoryDumpProvider {
public:
LevelDBDatabaseImpl(std::unique_ptr<leveldb::Env> environment,
- std::unique_ptr<leveldb::DB> db);
+ std::unique_ptr<leveldb::DB> db,
+ std::unique_ptr<leveldb::Cache> cache,
+ base::Optional<base::trace_event::MemoryAllocatorDumpGuid>
+ memory_dump_id);
~LevelDBDatabaseImpl() override;
// Overridden from LevelDBDatabase:
@@ -56,6 +62,10 @@ class LevelDBDatabaseImpl : public mojom::LevelDBDatabase {
void IteratorPrev(const base::UnguessableToken& iterator,
IteratorPrevCallback callback) override;
+ // base::trace_event::MemoryDumpProvider implementation.
+ bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) override;
+
private:
// Returns the state of |it| to a caller. Note: This assumes that all the
// iterator movement methods have the same callback signature. We don't
@@ -67,7 +77,9 @@ class LevelDBDatabaseImpl : public mojom::LevelDBDatabase {
leveldb::WriteBatch* batch);
std::unique_ptr<leveldb::Env> environment_;
+ std::unique_ptr<leveldb::Cache> cache_;
std::unique_ptr<leveldb::DB> db_;
+ base::Optional<base::trace_event::MemoryAllocatorDumpGuid> memory_dump_id_;
std::map<base::UnguessableToken, const Snapshot*> snapshot_map_;
diff --git a/chromium/components/leveldb/leveldb_mojo_proxy.cc b/chromium/components/leveldb/leveldb_mojo_proxy.cc
index 523859c3762..5c78d33d317 100644
--- a/chromium/components/leveldb/leveldb_mojo_proxy.cc
+++ b/chromium/components/leveldb/leveldb_mojo_proxy.cc
@@ -8,7 +8,6 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/single_thread_task_runner.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
@@ -28,9 +27,9 @@ struct LevelDBMojoProxy::OpaqueDir {
};
LevelDBMojoProxy::LevelDBMojoProxy(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ scoped_refptr<base::SequencedTaskRunner> task_runner)
: task_runner_(std::move(task_runner)), outstanding_opaque_dirs_(0) {
- DCHECK(!task_runner_->BelongsToCurrentThread());
+ DCHECK(!task_runner_->RunsTasksInCurrentSequence());
}
LevelDBMojoProxy::OpaqueDir* LevelDBMojoProxy::RegisterDirectory(
@@ -144,7 +143,7 @@ LevelDBMojoProxy::~LevelDBMojoProxy() {
}
void LevelDBMojoProxy::RunInternal(const base::Closure& task) {
- if (task_runner_->BelongsToCurrentThread()) {
+ if (task_runner_->RunsTasksInCurrentSequence()) {
task.Run();
} else {
base::WaitableEvent done_event(
@@ -291,7 +290,7 @@ void LevelDBMojoProxy::RenameFileImpl(OpaqueDir* dir,
const std::string& new_path,
filesystem::mojom::FileError* out_error) {
mojo::SyncCallRestrictions::ScopedAllowSyncCall allow_sync;
- bool completed = dir->directory->Rename(old_path, new_path, out_error);
+ bool completed = dir->directory->Replace(old_path, new_path, out_error);
DCHECK(completed);
}
diff --git a/chromium/components/leveldb/leveldb_mojo_proxy.h b/chromium/components/leveldb/leveldb_mojo_proxy.h
index 2eef1a41d1d..4b5e0ad6908 100644
--- a/chromium/components/leveldb/leveldb_mojo_proxy.h
+++ b/chromium/components/leveldb/leveldb_mojo_proxy.h
@@ -14,13 +14,11 @@
#include "base/callback_forward.h"
#include "base/files/file.h"
#include "base/memory/ref_counted.h"
+#include "base/sequenced_task_runner.h"
+
#include "base/synchronization/waitable_event.h"
#include "components/filesystem/public/interfaces/directory.mojom.h"
-namespace base {
-class SingleThreadTaskRunner;
-}
-
namespace leveldb {
// A proxy for thread safe access to Mojo objects from multiple threads.
@@ -35,7 +33,7 @@ namespace leveldb {
class LevelDBMojoProxy : public base::RefCountedThreadSafe<LevelDBMojoProxy> {
public:
explicit LevelDBMojoProxy(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ scoped_refptr<base::SequencedTaskRunner> task_runner);
// A private struct to hide the underlying file that holds the lock from our
// callers, forcing them to go through our LockFile()/UnlockFile() interface
@@ -152,9 +150,9 @@ class LevelDBMojoProxy : public base::RefCountedThreadSafe<LevelDBMojoProxy> {
void UnlockFileImpl(std::unique_ptr<OpaqueLock> lock,
filesystem::mojom::FileError* out_error);
- // The task runner which represents the thread that all mojo objects are
+ // The task runner which represents the sequence that all mojo objects are
// bound to.
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
int outstanding_opaque_dirs_;
diff --git a/chromium/components/leveldb/leveldb_service_impl.cc b/chromium/components/leveldb/leveldb_service_impl.cc
index f2e4eb8597d..a6406166403 100644
--- a/chromium/components/leveldb/leveldb_service_impl.cc
+++ b/chromium/components/leveldb/leveldb_service_impl.cc
@@ -22,7 +22,7 @@
namespace leveldb {
LevelDBServiceImpl::LevelDBServiceImpl(
- scoped_refptr<base::SingleThreadTaskRunner> file_task_runner)
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner)
: thread_(new LevelDBMojoProxy(std::move(file_task_runner))) {}
LevelDBServiceImpl::~LevelDBServiceImpl() {}
@@ -30,16 +30,21 @@ LevelDBServiceImpl::~LevelDBServiceImpl() {}
void LevelDBServiceImpl::Open(
filesystem::mojom::DirectoryPtr directory,
const std::string& dbname,
+ const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ memory_dump_id,
leveldb::mojom::LevelDBDatabaseAssociatedRequest database,
OpenCallback callback) {
OpenWithOptions(leveldb::mojom::OpenOptions::New(), std::move(directory),
- dbname, std::move(database), std::move(callback));
+ dbname, memory_dump_id, std::move(database),
+ std::move(callback));
}
void LevelDBServiceImpl::OpenWithOptions(
leveldb::mojom::OpenOptionsPtr open_options,
filesystem::mojom::DirectoryPtr directory,
const std::string& dbname,
+ const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ memory_dump_id,
leveldb::mojom::LevelDBDatabaseAssociatedRequest database,
OpenCallback callback) {
leveldb::Options options;
@@ -59,20 +64,26 @@ void LevelDBServiceImpl::OpenWithOptions(
std::unique_ptr<MojoEnv> env_mojo(new MojoEnv(thread_, dir));
options.env = env_mojo.get();
- leveldb::DB* db = nullptr;
- leveldb::Status s = leveldb::DB::Open(options, dbname, &db);
+ std::unique_ptr<leveldb::Cache> cache(
+ leveldb::NewLRUCache(open_options->block_cache_size));
+ options.block_cache = cache.get();
+
+ std::unique_ptr<leveldb::DB> db;
+ leveldb::Status s = leveldb_env::OpenDB(options, dbname, &db);
if (s.ok()) {
- mojo::MakeStrongAssociatedBinding(
- base::MakeUnique<LevelDBDatabaseImpl>(std::move(env_mojo),
- base::WrapUnique(db)),
- std::move(database));
+ mojo::MakeStrongAssociatedBinding(base::MakeUnique<LevelDBDatabaseImpl>(
+ std::move(env_mojo), std::move(db),
+ std::move(cache), memory_dump_id),
+ std::move(database));
}
std::move(callback).Run(LeveldbStatusToError(s));
}
void LevelDBServiceImpl::OpenInMemory(
+ const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ memory_dump_id,
leveldb::mojom::LevelDBDatabaseAssociatedRequest database,
OpenCallback callback) {
leveldb::Options options;
@@ -83,13 +94,14 @@ void LevelDBServiceImpl::OpenInMemory(
leveldb::NewMemEnv(leveldb::Env::Default()));
options.env = env.get();
- leveldb::DB* db = nullptr;
- leveldb::Status s = leveldb::DB::Open(options, "", &db);
+ std::unique_ptr<leveldb::DB> db;
+ leveldb::Status s = leveldb_env::OpenDB(options, "", &db);
if (s.ok()) {
- mojo::MakeStrongAssociatedBinding(base::MakeUnique<LevelDBDatabaseImpl>(
- std::move(env), base::WrapUnique(db)),
- std::move(database));
+ mojo::MakeStrongAssociatedBinding(
+ base::MakeUnique<LevelDBDatabaseImpl>(std::move(env), std::move(db),
+ nullptr, memory_dump_id),
+ std::move(database));
}
std::move(callback).Run(LeveldbStatusToError(s));
diff --git a/chromium/components/leveldb/leveldb_service_impl.h b/chromium/components/leveldb/leveldb_service_impl.h
index 9a5beed6d99..1d5fab0b3d3 100644
--- a/chromium/components/leveldb/leveldb_service_impl.h
+++ b/chromium/components/leveldb/leveldb_service_impl.h
@@ -6,11 +6,14 @@
#define COMPONENTS_LEVELDB_LEVELDB_SERVICE_IMPL_H_
#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
#include "components/leveldb/leveldb_mojo_proxy.h"
#include "components/leveldb/public/interfaces/leveldb.mojom.h"
#include "mojo/public/cpp/bindings/binding_set.h"
+namespace base {
+class SequencedTaskRunner;
+}
+
namespace leveldb {
// Creates LevelDBDatabases based scoped to a |directory|/|dbname|.
@@ -19,23 +22,29 @@ class LevelDBServiceImpl : public mojom::LevelDBService {
// The |file_task_runner| is used to run tasks to interact with the
// file_service. Specifically this task runner must NOT be the same as the
// task runner this implementation runs on, or deadlock might occur.
- LevelDBServiceImpl(
- scoped_refptr<base::SingleThreadTaskRunner> file_task_runner);
+ LevelDBServiceImpl(scoped_refptr<base::SequencedTaskRunner> file_task_runner);
~LevelDBServiceImpl() override;
// Overridden from LevelDBService:
void Open(filesystem::mojom::DirectoryPtr directory,
const std::string& dbname,
+ const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ memory_dump_id,
leveldb::mojom::LevelDBDatabaseAssociatedRequest database,
OpenCallback callback) override;
void OpenWithOptions(
leveldb::mojom::OpenOptionsPtr open_options,
filesystem::mojom::DirectoryPtr directory,
const std::string& dbname,
+ const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ memory_dump_id,
leveldb::mojom::LevelDBDatabaseAssociatedRequest database,
OpenCallback callback) override;
- void OpenInMemory(leveldb::mojom::LevelDBDatabaseAssociatedRequest database,
- OpenInMemoryCallback callback) override;
+ void OpenInMemory(
+ const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ memory_dump_id,
+ leveldb::mojom::LevelDBDatabaseAssociatedRequest database,
+ OpenInMemoryCallback callback) override;
void Destroy(filesystem::mojom::DirectoryPtr directory,
const std::string& dbname,
DestroyCallback callback) override;
diff --git a/chromium/components/leveldb/leveldb_service_unittest.cc b/chromium/components/leveldb/leveldb_service_unittest.cc
index 0651b07a56f..0ffefeb7e9a 100644
--- a/chromium/components/leveldb/leveldb_service_unittest.cc
+++ b/chromium/components/leveldb/leveldb_service_unittest.cc
@@ -98,7 +98,7 @@ void LevelDBSyncOpenInMemory(mojom::LevelDBService* leveldb,
mojom::LevelDBDatabaseAssociatedRequest database,
mojom::DatabaseError* out_error) {
base::RunLoop run_loop;
- leveldb->OpenInMemory(std::move(database),
+ leveldb->OpenInMemory(base::nullopt, std::move(database),
Capture(out_error, run_loop.QuitClosure()));
run_loop.Run();
}
@@ -265,7 +265,7 @@ TEST_F(LevelDBServiceTest, Reconnect) {
options->create_if_missing = true;
base::RunLoop run_loop;
leveldb()->OpenWithOptions(std::move(options), std::move(directory), "test",
- MakeRequest(&database),
+ base::nullopt, MakeRequest(&database),
Capture(&error, run_loop.QuitClosure()));
run_loop.Run();
EXPECT_EQ(mojom::DatabaseError::OK, error);
@@ -285,7 +285,8 @@ TEST_F(LevelDBServiceTest, Reconnect) {
// Reconnect to the database.
mojom::LevelDBDatabaseAssociatedPtr database;
base::RunLoop run_loop;
- leveldb()->Open(std::move(directory), "test", MakeRequest(&database),
+ leveldb()->Open(std::move(directory), "test", base::nullopt,
+ MakeRequest(&database),
Capture(&error, run_loop.QuitClosure()));
run_loop.Run();
EXPECT_EQ(mojom::DatabaseError::OK, error);
@@ -315,7 +316,7 @@ TEST_F(LevelDBServiceTest, Destroy) {
options->create_if_missing = true;
base::RunLoop run_loop;
leveldb()->OpenWithOptions(std::move(options), std::move(directory), "test",
- MakeRequest(&database),
+ base::nullopt, MakeRequest(&database),
Capture(&error, run_loop.QuitClosure()));
run_loop.Run();
EXPECT_EQ(mojom::DatabaseError::OK, error);
@@ -347,7 +348,8 @@ TEST_F(LevelDBServiceTest, Destroy) {
// Reconnect to the database should fail.
mojom::LevelDBDatabaseAssociatedPtr database;
base::RunLoop run_loop;
- leveldb()->Open(std::move(directory), "test", MakeRequest(&database),
+ leveldb()->Open(std::move(directory), "test", base::nullopt,
+ MakeRequest(&database),
Capture(&error, run_loop.QuitClosure()));
run_loop.Run();
EXPECT_EQ(mojom::DatabaseError::INVALID_ARGUMENT, error);
diff --git a/chromium/components/leveldb/public/interfaces/BUILD.gn b/chromium/components/leveldb/public/interfaces/BUILD.gn
index 514eeb9f785..1b3172e6408 100644
--- a/chromium/components/leveldb/public/interfaces/BUILD.gn
+++ b/chromium/components/leveldb/public/interfaces/BUILD.gn
@@ -5,6 +5,8 @@
import("//mojo/public/tools/bindings/mojom.gni")
mojom("interfaces") {
+ support_lazy_serialization = true
+
sources = [
"leveldb.mojom",
]
diff --git a/chromium/components/leveldb/public/interfaces/leveldb.mojom b/chromium/components/leveldb/public/interfaces/leveldb.mojom
index 11e56709553..938bd730d4a 100644
--- a/chromium/components/leveldb/public/interfaces/leveldb.mojom
+++ b/chromium/components/leveldb/public/interfaces/leveldb.mojom
@@ -6,6 +6,7 @@ module leveldb.mojom;
import "components/filesystem/public/interfaces/directory.mojom";
import "mojo/common/unguessable_token.mojom";
+import "mojo/common/memory_allocator_dump_cross_process_uid.mojom";
enum DatabaseError {
OK,
@@ -58,6 +59,9 @@ struct OpenOptions {
// https://code.google.com/p/chromium/issues/detail?id=227313#c11 for
// details.)
int32 max_open_files = 80;
+
+ // Default size is 8 megabytes.
+ uint64 block_cache_size = 8388608;
};
// Service which hands out databases.
@@ -66,16 +70,19 @@ interface LevelDBService {
// Fails if the database doesn't already exist.
Open(filesystem.mojom.Directory directory,
string dbname,
+ mojo.common.mojom.MemoryAllocatorDumpCrossProcessUid? memory_dump_id,
associated LevelDBDatabase& database) => (DatabaseError status);
// Open the database with the specified "name" in the specified "directory".
OpenWithOptions(OpenOptions options,
filesystem.mojom.Directory directory,
string dbname,
+ mojo.common.mojom.MemoryAllocatorDumpCrossProcessUid? memory_dump_id,
associated LevelDBDatabase& database) => (DatabaseError status);
// Opens a database stored purely in memory.
- OpenInMemory(associated LevelDBDatabase& database) => (DatabaseError status);
+ OpenInMemory(mojo.common.mojom.MemoryAllocatorDumpCrossProcessUid? memory_dump_id,
+ associated LevelDBDatabase& database) => (DatabaseError status);
// Destroys the contents of the specified database. Returns OK if the database
// already didn't exist.
diff --git a/chromium/components/leveldb/remote_iterator_unittest.cc b/chromium/components/leveldb/remote_iterator_unittest.cc
index 8665711ae65..f37bd48d1a1 100644
--- a/chromium/components/leveldb/remote_iterator_unittest.cc
+++ b/chromium/components/leveldb/remote_iterator_unittest.cc
@@ -52,7 +52,7 @@ class RemoteIteratorTest : public service_manager::test::ServiceTest {
mojom::DatabaseError error;
base::RunLoop run_loop;
- leveldb()->OpenInMemory(MakeRequest(&database_),
+ leveldb()->OpenInMemory(base::nullopt, MakeRequest(&database_),
Capture(&error, run_loop.QuitClosure()));
run_loop.Run();
EXPECT_EQ(mojom::DatabaseError::OK, error);