1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file. 4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/leveldb/leveldb_database.h" 6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <cerrno> 8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/basictypes.h" 10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/files/file.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/logging.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/metrics/histogram.h" 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string16.h" 157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/strings/string_piece.h" 16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/strings/stringprintf.h" 17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/sys_info.h" 19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/indexed_db/indexed_db_class_factory.h" 20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/leveldb/leveldb_comparator.h" 21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/indexed_db/leveldb/leveldb_iterator_impl.h" 22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/leveldb/leveldb_write_batch.h" 237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/leveldatabase/env_chromium.h" 24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/leveldatabase/env_idb.h" 25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/leveldatabase/src/helpers/memenv/memenv.h" 26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/leveldatabase/src/include/leveldb/db.h" 27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/leveldatabase/src/include/leveldb/env.h" 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "third_party/leveldatabase/src/include/leveldb/filter_policy.h" 29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/leveldatabase/src/include/leveldb/slice.h" 30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing base::StringPiece; 32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace content { 34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Forcing flushes to disk at the end of a transaction guarantees that the 364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// data hit disk, but drastically impacts throughput when the filesystem is 374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// busy with background compactions. Not syncing trades off reliability for 384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// performance. Note that background compactions which move data from the 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// log to SSTs are always done with reliable writes. 404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// 414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Sync writes are necessary on Windows for quota calculations; POSIX 424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// calculates file sizes correctly even when not synced to disk. 434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#if defined(OS_WIN) 444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static const bool kSyncWrites = true; 454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#else 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// TODO(dgrogan): Either remove the #if block or change this back to false. 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// See http://crbug.com/338385. 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static const bool kSyncWrites = true; 494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif 504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstatic leveldb::Slice MakeSlice(const StringPiece& s) { 527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return leveldb::Slice(s.begin(), s.size()); 53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstatic StringPiece MakeStringPiece(const leveldb::Slice& s) { 567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return StringPiece(s.data(), s.size()); 57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 59effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochLevelDBDatabase::ComparatorAdapter::ComparatorAdapter( 60effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const LevelDBComparator* comparator) 61effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch : comparator_(comparator) {} 62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 63effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochint LevelDBDatabase::ComparatorAdapter::Compare(const leveldb::Slice& a, 64effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const leveldb::Slice& b) const { 65effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return comparator_->Compare(MakeStringPiece(a), MakeStringPiece(b)); 66effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 68effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst char* LevelDBDatabase::ComparatorAdapter::Name() const { 69effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return comparator_->Name(); 70effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 72effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// TODO(jsbell): Support the methods below in the future. 73effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid LevelDBDatabase::ComparatorAdapter::FindShortestSeparator( 74effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::string* start, 75effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const leveldb::Slice& limit) const {} 76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 77effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid LevelDBDatabase::ComparatorAdapter::FindShortSuccessor( 78effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::string* key) const {} 79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)LevelDBSnapshot::LevelDBSnapshot(LevelDBDatabase* db) 81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) : db_(db->db_.get()), snapshot_(db_->GetSnapshot()) {} 82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)LevelDBSnapshot::~LevelDBSnapshot() { db_->ReleaseSnapshot(snapshot_); } 84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)LevelDBDatabase::LevelDBDatabase() {} 86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)LevelDBDatabase::~LevelDBDatabase() { 88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // db_'s destructor uses comparator_adapter_; order of deletion is important. 89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) db_.reset(); 90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) comparator_adapter_.reset(); 91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) env_.reset(); 92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistatic leveldb::Status OpenDB( 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci leveldb::Comparator* comparator, 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci leveldb::Env* env, 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const base::FilePath& path, 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci leveldb::DB** db, 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<const leveldb::FilterPolicy>* filter_policy) { 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci filter_policy->reset(leveldb::NewBloomFilterPolicy(10)); 101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) leveldb::Options options; 102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) options.comparator = comparator; 103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) options.create_if_missing = true; 104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) options.paranoid_checks = true; 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci options.filter_policy = filter_policy->get(); 1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) options.compression = leveldb::kSnappyCompression; 107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // For info about the troubles we've run into with this parameter, see: 109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // https://code.google.com/p/chromium/issues/detail?id=227313#c11 110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) options.max_open_files = 80; 111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) options.env = env; 112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // ChromiumEnv assumes UTF8, converts back to FilePath before using. 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci leveldb::Status s = leveldb::DB::Open(options, path.AsUTF8Unsafe(), db); 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return s; 117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status LevelDBDatabase::Destroy(const base::FilePath& file_name) { 120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) leveldb::Options options; 121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) options.env = leveldb::IDBEnv(); 122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // ChromiumEnv assumes UTF8, converts back to FilePath before using. 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return leveldb::DestroyDB(file_name.AsUTF8Unsafe(), options); 124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace { 1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class LockImpl : public LevelDBLock { 1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public: 1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) explicit LockImpl(leveldb::Env* env, leveldb::FileLock* lock) 1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) : env_(env), lock_(lock) {} 1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual ~LockImpl() { env_->UnlockFile(lock_); } 1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private: 1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) leveldb::Env* env_; 1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) leveldb::FileLock* lock_; 135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(LockImpl); 1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}; 138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} // namespace 1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)scoped_ptr<LevelDBLock> LevelDBDatabase::LockForTesting( 1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const base::FilePath& file_name) { 1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) leveldb::Env* env = leveldb::IDBEnv(); 1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::FilePath lock_path = file_name.AppendASCII("LOCK"); 1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) leveldb::FileLock* lock = NULL; 1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) leveldb::Status status = env->LockFile(lock_path.AsUTF8Unsafe(), &lock); 1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!status.ok()) 1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return scoped_ptr<LevelDBLock>(); 1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(lock); 1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return scoped_ptr<LevelDBLock>(new LockImpl(env, lock)); 1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int CheckFreeSpace(const char* const type, 153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::FilePath& file_name) { 154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string name = 155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string("WebCore.IndexedDB.LevelDB.Open") + type + "FreeDiskSpace"; 156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int64 free_disk_space_in_k_bytes = 157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::SysInfo::AmountOfFreeDiskSpace(file_name) / 1024; 158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (free_disk_space_in_k_bytes < 0) { 159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Histogram::FactoryGet( 160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "WebCore.IndexedDB.LevelDB.FreeDiskSpaceFailure", 161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1, 162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 2 /*boundary*/, 163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 2 /*boundary*/ + 1, 164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::HistogramBase::kUmaTargetedHistogramFlag)->Add(1 /*sample*/); 165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return -1; 166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 167424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) int clamped_disk_space_k_bytes = free_disk_space_in_k_bytes > INT_MAX 168424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) ? INT_MAX 169424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) : free_disk_space_in_k_bytes; 170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const uint64 histogram_max = static_cast<uint64>(1e9); 171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) COMPILE_ASSERT(histogram_max <= INT_MAX, histogram_max_too_big); 172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Histogram::FactoryGet(name, 173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1, 174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) histogram_max, 175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 11 /*buckets*/, 176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::HistogramBase::kUmaTargetedHistogramFlag) 177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ->Add(clamped_disk_space_k_bytes); 178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return clamped_disk_space_k_bytes; 179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic void ParseAndHistogramIOErrorDetails(const std::string& histogram_name, 182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const leveldb::Status& s) { 183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch leveldb_env::MethodID method; 184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int error = -1; 185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch leveldb_env::ErrorParsingResult result = 186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch leveldb_env::ParseMethodAndError(s.ToString().c_str(), &method, &error); 187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (result == leveldb_env::NONE) 188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string method_histogram_name(histogram_name); 190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch method_histogram_name.append(".EnvMethod"); 191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::LinearHistogram::FactoryGet( 192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch method_histogram_name, 193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1, 194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch leveldb_env::kNumEntries, 195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch leveldb_env::kNumEntries + 1, 196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::HistogramBase::kUmaTargetedHistogramFlag)->Add(method); 197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string error_histogram_name(histogram_name); 199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (result == leveldb_env::METHOD_AND_PFE) { 201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK_LT(error, 0); 202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch error_histogram_name.append(std::string(".PFE.") + 203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch leveldb_env::MethodIDToString(method)); 204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::LinearHistogram::FactoryGet( 205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch error_histogram_name, 206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1, 207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) -base::File::FILE_ERROR_MAX, 208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) -base::File::FILE_ERROR_MAX + 1, 209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::HistogramBase::kUmaTargetedHistogramFlag)->Add(-error); 210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else if (result == leveldb_env::METHOD_AND_ERRNO) { 211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch error_histogram_name.append(std::string(".Errno.") + 212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch leveldb_env::MethodIDToString(method)); 213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::LinearHistogram::FactoryGet( 214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch error_histogram_name, 215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1, 216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ERANGE + 1, 217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ERANGE + 2, 218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::HistogramBase::kUmaTargetedHistogramFlag)->Add(error); 219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic void ParseAndHistogramCorruptionDetails( 223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& histogram_name, 224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const leveldb::Status& status) { 2250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) int error = leveldb_env::GetCorruptionCode(status); 226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK_GE(error, 0); 227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string corruption_histogram_name(histogram_name); 228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch corruption_histogram_name.append(".Corruption"); 2290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const int kNumPatterns = leveldb_env::GetNumCorruptionCodes(); 230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::LinearHistogram::FactoryGet( 231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch corruption_histogram_name, 232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1, 2331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) kNumPatterns, 234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kNumPatterns + 1, 235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::HistogramBase::kUmaTargetedHistogramFlag)->Add(error); 236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)static void HistogramLevelDBError(const std::string& histogram_name, 239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const leveldb::Status& s) { 240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (s.ok()) { 241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NOTREACHED(); 242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) enum { 245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LEVEL_DB_NOT_FOUND, 246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LEVEL_DB_CORRUPTION, 247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LEVEL_DB_IO_ERROR, 248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LEVEL_DB_OTHER, 249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LEVEL_DB_MAX_ERROR 250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) }; 251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int leveldb_error = LEVEL_DB_OTHER; 252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (s.IsNotFound()) 253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) leveldb_error = LEVEL_DB_NOT_FOUND; 254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) else if (s.IsCorruption()) 255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) leveldb_error = LEVEL_DB_CORRUPTION; 256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) else if (s.IsIOError()) 257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) leveldb_error = LEVEL_DB_IO_ERROR; 258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Histogram::FactoryGet(histogram_name, 259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1, 260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LEVEL_DB_MAX_ERROR, 261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LEVEL_DB_MAX_ERROR + 1, 262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::HistogramBase::kUmaTargetedHistogramFlag) 263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ->Add(leveldb_error); 264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (s.IsIOError()) 265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ParseAndHistogramIOErrorDetails(histogram_name, s); 266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch else 267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ParseAndHistogramCorruptionDetails(histogram_name, s); 268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 270424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)leveldb::Status LevelDBDatabase::Open(const base::FilePath& file_name, 271424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const LevelDBComparator* comparator, 272424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) scoped_ptr<LevelDBDatabase>* result, 273424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) bool* is_disk_full) { 2746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::TimeTicks begin_time = base::TimeTicks::Now(); 2756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<ComparatorAdapter> comparator_adapter( 277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) new ComparatorAdapter(comparator)); 278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) leveldb::DB* db; 2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<const leveldb::FilterPolicy> filter_policy; 2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const leveldb::Status s = OpenDB(comparator_adapter.get(), 2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci leveldb::IDBEnv(), 2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci file_name, 2841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &db, 2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &filter_policy); 286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!s.ok()) { 288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) HistogramLevelDBError("WebCore.IndexedDB.LevelDBOpenErrors", s); 289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int free_space_k_bytes = CheckFreeSpace("Failure", file_name); 290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Disks with <100k of free space almost never succeed in opening a 291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // leveldb database. 292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (is_disk_full) 293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *is_disk_full = free_space_k_bytes >= 0 && free_space_k_bytes < 100; 294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 295868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LOG(ERROR) << "Failed to open LevelDB database from " 296868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) << file_name.AsUTF8Unsafe() << "," << s.ToString(); 297ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return s; 298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 3006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) UMA_HISTOGRAM_MEDIUM_TIMES("WebCore.IndexedDB.LevelDB.OpenTime", 3016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::TimeTicks::Now() - begin_time); 3026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CheckFreeSpace("Success", file_name); 304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 305ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch (*result).reset(new LevelDBDatabase); 306ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch (*result)->db_ = make_scoped_ptr(db); 307ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch (*result)->comparator_adapter_ = comparator_adapter.Pass(); 308ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch (*result)->comparator_ = comparator; 3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci (*result)->filter_policy_ = filter_policy.Pass(); 310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 311ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return s; 312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)scoped_ptr<LevelDBDatabase> LevelDBDatabase::OpenInMemory( 315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const LevelDBComparator* comparator) { 316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<ComparatorAdapter> comparator_adapter( 317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) new ComparatorAdapter(comparator)); 318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<leveldb::Env> in_memory_env(leveldb::NewMemEnv(leveldb::IDBEnv())); 319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) leveldb::DB* db; 3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<const leveldb::FilterPolicy> filter_policy; 3221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const leveldb::Status s = OpenDB(comparator_adapter.get(), 3231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci in_memory_env.get(), 3241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::FilePath(), 3251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &db, 3261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &filter_policy); 327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!s.ok()) { 329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LOG(ERROR) << "Failed to open in-memory LevelDB database: " << s.ToString(); 330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return scoped_ptr<LevelDBDatabase>(); 331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<LevelDBDatabase> result(new LevelDBDatabase); 334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) result->env_ = in_memory_env.Pass(); 335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) result->db_ = make_scoped_ptr(db); 336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) result->comparator_adapter_ = comparator_adapter.Pass(); 337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) result->comparator_ = comparator; 3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci result->filter_policy_ = filter_policy.Pass(); 339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return result.Pass(); 341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 343a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status LevelDBDatabase::Put(const StringPiece& key, 344a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string* value) { 3456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::TimeTicks begin_time = base::TimeTicks::Now(); 3466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) leveldb::WriteOptions write_options; 3484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) write_options.sync = kSyncWrites; 349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const leveldb::Status s = 351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) db_->Put(write_options, MakeSlice(key), MakeSlice(*value)); 352a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!s.ok()) 353a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LOG(ERROR) << "LevelDB put failed: " << s.ToString(); 3546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) else 3556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) UMA_HISTOGRAM_TIMES("WebCore.IndexedDB.LevelDB.PutTime", 3566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::TimeTicks::Now() - begin_time); 357a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return s; 358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 360a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status LevelDBDatabase::Remove(const StringPiece& key) { 361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) leveldb::WriteOptions write_options; 3624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) write_options.sync = kSyncWrites; 363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const leveldb::Status s = db_->Delete(write_options, MakeSlice(key)); 365a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!s.IsNotFound()) 366a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LOG(ERROR) << "LevelDB remove failed: " << s.ToString(); 367a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return s; 368868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 370a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status LevelDBDatabase::Get(const StringPiece& key, 371a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string* value, 372a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool* found, 373a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const LevelDBSnapshot* snapshot) { 374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *found = false; 375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) leveldb::ReadOptions read_options; 376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) read_options.verify_checksums = true; // TODO(jsbell): Disable this if the 377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // performance impact is too great. 378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) read_options.snapshot = snapshot ? snapshot->snapshot_ : 0; 379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const leveldb::Status s = db_->Get(read_options, MakeSlice(key), value); 381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (s.ok()) { 382868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *found = true; 383a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return s; 384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (s.IsNotFound()) 386a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return leveldb::Status::OK(); 3877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch HistogramLevelDBError("WebCore.IndexedDB.LevelDBReadErrors", s); 388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LOG(ERROR) << "LevelDB get failed: " << s.ToString(); 389a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return s; 390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 392a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status LevelDBDatabase::Write(const LevelDBWriteBatch& write_batch) { 3936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::TimeTicks begin_time = base::TimeTicks::Now(); 394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) leveldb::WriteOptions write_options; 3954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) write_options.sync = kSyncWrites; 396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const leveldb::Status s = 398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) db_->Write(write_options, write_batch.write_batch_.get()); 399a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!s.ok()) { 400a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) HistogramLevelDBError("WebCore.IndexedDB.LevelDBWriteErrors", s); 401a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LOG(ERROR) << "LevelDB write failed: " << s.ToString(); 4026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else { 4036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) UMA_HISTOGRAM_TIMES("WebCore.IndexedDB.LevelDB.WriteTime", 4046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::TimeTicks::Now() - begin_time); 405a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 406a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return s; 407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)scoped_ptr<LevelDBIterator> LevelDBDatabase::CreateIterator( 410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const LevelDBSnapshot* snapshot) { 411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) leveldb::ReadOptions read_options; 412868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) read_options.verify_checksums = true; // TODO(jsbell): Disable this if the 413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // performance impact is too great. 414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) read_options.snapshot = snapshot ? snapshot->snapshot_ : 0; 415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<leveldb::Iterator> i(db_->NewIterator(read_options)); 417116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return scoped_ptr<LevelDBIterator>( 418116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch IndexedDBClassFactory::Get()->CreateIteratorImpl(i.Pass())); 419868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const LevelDBComparator* LevelDBDatabase::Comparator() const { 422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return comparator_; 423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 424868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void LevelDBDatabase::Compact(const base::StringPiece& start, 4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::StringPiece& stop) { 4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const leveldb::Slice start_slice = MakeSlice(start); 4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const leveldb::Slice stop_slice = MakeSlice(stop); 4295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // NULL batch means just wait for earlier writes to be done 4305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) db_->Write(leveldb::WriteOptions(), NULL); 4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) db_->CompactRange(&start_slice, &stop_slice); 4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 434e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid LevelDBDatabase::CompactAll() { db_->CompactRange(NULL, NULL); } 435e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 436868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} // namespace content 437