| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/indexed_db/leveldb/leveldb_database.h" | 5 #include "content/browser/indexed_db/leveldb/leveldb_database.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 | 102 |
| 103 bool LevelDBDatabase::Destroy(const base::FilePath& file_name) { | 103 bool LevelDBDatabase::Destroy(const base::FilePath& file_name) { |
| 104 leveldb::Options options; | 104 leveldb::Options options; |
| 105 options.env = leveldb::IDBEnv(); | 105 options.env = leveldb::IDBEnv(); |
| 106 // ChromiumEnv assumes UTF8, converts back to FilePath before using. | 106 // ChromiumEnv assumes UTF8, converts back to FilePath before using. |
| 107 const leveldb::Status s = | 107 const leveldb::Status s = |
| 108 leveldb::DestroyDB(file_name.AsUTF8Unsafe(), options); | 108 leveldb::DestroyDB(file_name.AsUTF8Unsafe(), options); |
| 109 return s.ok(); | 109 return s.ok(); |
| 110 } | 110 } |
| 111 | 111 |
| 112 static void HistogramFreeSpace(const char* type, | 112 static int CheckFreeSpace(const char* type, const base::FilePath& file_name) { |
| 113 const base::FilePath& file_name) { | 113 // TODO(dgrogan): Change string16 -> std::string. |
| 114 string16 name = ASCIIToUTF16("WebCore.IndexedDB.LevelDB.Open") + | 114 string16 name = ASCIIToUTF16("WebCore.IndexedDB.LevelDB.Open") + |
| 115 ASCIIToUTF16(type) + ASCIIToUTF16("FreeDiskSpace"); | 115 ASCIIToUTF16(type) + ASCIIToUTF16("FreeDiskSpace"); |
| 116 int64 free_disk_space_in_k_bytes = | 116 int64 free_disk_space_in_k_bytes = |
| 117 base::SysInfo::AmountOfFreeDiskSpace(file_name) / 1024; | 117 base::SysInfo::AmountOfFreeDiskSpace(file_name) / 1024; |
| 118 if (free_disk_space_in_k_bytes < 0) { | 118 if (free_disk_space_in_k_bytes < 0) { |
| 119 base::Histogram::FactoryGet( | 119 base::Histogram::FactoryGet( |
| 120 "WebCore.IndexedDB.LevelDB.FreeDiskSpaceFailure", | 120 "WebCore.IndexedDB.LevelDB.FreeDiskSpaceFailure", |
| 121 1, | 121 1, |
| 122 2 /*boundary*/, | 122 2 /*boundary*/, |
| 123 2 /*boundary*/ + 1, | 123 2 /*boundary*/ + 1, |
| 124 base::HistogramBase::kUmaTargetedHistogramFlag)->Add(1 /*sample*/); | 124 base::HistogramBase::kUmaTargetedHistogramFlag)->Add(1 /*sample*/); |
| 125 return; | 125 return -1; |
| 126 } | 126 } |
| 127 int clamped_disk_space_k_bytes = | 127 int clamped_disk_space_k_bytes = |
| 128 free_disk_space_in_k_bytes > INT_MAX ? INT_MAX | 128 free_disk_space_in_k_bytes > INT_MAX ? INT_MAX |
| 129 : free_disk_space_in_k_bytes; | 129 : free_disk_space_in_k_bytes; |
| 130 const uint64 histogram_max = static_cast<uint64>(1e9); | 130 const uint64 histogram_max = static_cast<uint64>(1e9); |
| 131 COMPILE_ASSERT(histogram_max <= INT_MAX, histogram_max_too_big); | 131 COMPILE_ASSERT(histogram_max <= INT_MAX, histogram_max_too_big); |
| 132 base::Histogram::FactoryGet(UTF16ToUTF8(name), | 132 base::Histogram::FactoryGet(UTF16ToUTF8(name), |
| 133 1, | 133 1, |
| 134 histogram_max, | 134 histogram_max, |
| 135 11 /*buckets*/, | 135 11 /*buckets*/, |
| 136 base::HistogramBase::kUmaTargetedHistogramFlag) | 136 base::HistogramBase::kUmaTargetedHistogramFlag) |
| 137 ->Add(clamped_disk_space_k_bytes); | 137 ->Add(clamped_disk_space_k_bytes); |
| 138 return clamped_disk_space_k_bytes; |
| 138 } | 139 } |
| 139 | 140 |
| 140 static void HistogramLevelDBError(const char* histogram_name, | 141 static void HistogramLevelDBError(const char* histogram_name, |
| 141 const leveldb::Status& s) { | 142 const leveldb::Status& s) { |
| 142 DCHECK(!s.ok()); | 143 DCHECK(!s.ok()); |
| 143 enum { | 144 enum { |
| 144 LEVEL_DB_NOT_FOUND, | 145 LEVEL_DB_NOT_FOUND, |
| 145 LEVEL_DB_CORRUPTION, | 146 LEVEL_DB_CORRUPTION, |
| 146 LEVEL_DB_IO_ERROR, | 147 LEVEL_DB_IO_ERROR, |
| 147 LEVEL_DB_OTHER, | 148 LEVEL_DB_OTHER, |
| 148 LEVEL_DB_MAX_ERROR | 149 LEVEL_DB_MAX_ERROR |
| 149 }; | 150 }; |
| 150 int leveldb_error = LEVEL_DB_OTHER; | 151 int leveldb_error = LEVEL_DB_OTHER; |
| 151 if (s.IsNotFound()) | 152 if (s.IsNotFound()) |
| 152 leveldb_error = LEVEL_DB_NOT_FOUND; | 153 leveldb_error = LEVEL_DB_NOT_FOUND; |
| 153 else if (s.IsCorruption()) | 154 else if (s.IsCorruption()) |
| 154 leveldb_error = LEVEL_DB_CORRUPTION; | 155 leveldb_error = LEVEL_DB_CORRUPTION; |
| 155 else if (s.IsIOError()) | 156 else if (s.IsIOError()) |
| 156 leveldb_error = LEVEL_DB_IO_ERROR; | 157 leveldb_error = LEVEL_DB_IO_ERROR; |
| 157 base::Histogram::FactoryGet(histogram_name, | 158 base::Histogram::FactoryGet(histogram_name, |
| 158 1, | 159 1, |
| 159 LEVEL_DB_MAX_ERROR, | 160 LEVEL_DB_MAX_ERROR, |
| 160 LEVEL_DB_MAX_ERROR + 1, | 161 LEVEL_DB_MAX_ERROR + 1, |
| 161 base::HistogramBase::kUmaTargetedHistogramFlag) | 162 base::HistogramBase::kUmaTargetedHistogramFlag) |
| 162 ->Add(leveldb_error); | 163 ->Add(leveldb_error); |
| 163 } | 164 } |
| 164 | 165 |
| 165 scoped_ptr<LevelDBDatabase> LevelDBDatabase::Open( | 166 scoped_ptr<LevelDBDatabase> LevelDBDatabase::Open( |
| 166 const base::FilePath& file_name, | 167 const base::FilePath& file_name, |
| 167 const LevelDBComparator* comparator) { | 168 const LevelDBComparator* comparator, |
| 169 bool* is_disk_full) { |
| 168 scoped_ptr<ComparatorAdapter> comparator_adapter( | 170 scoped_ptr<ComparatorAdapter> comparator_adapter( |
| 169 new ComparatorAdapter(comparator)); | 171 new ComparatorAdapter(comparator)); |
| 170 | 172 |
| 171 leveldb::DB* db; | 173 leveldb::DB* db; |
| 172 const leveldb::Status s = | 174 const leveldb::Status s = |
| 173 OpenDB(comparator_adapter.get(), leveldb::IDBEnv(), file_name, &db); | 175 OpenDB(comparator_adapter.get(), leveldb::IDBEnv(), file_name, &db); |
| 174 | 176 |
| 175 if (!s.ok()) { | 177 if (!s.ok()) { |
| 176 HistogramLevelDBError("WebCore.IndexedDB.LevelDBOpenErrors", s); | 178 HistogramLevelDBError("WebCore.IndexedDB.LevelDBOpenErrors", s); |
| 177 HistogramFreeSpace("Failure", file_name); | 179 int free_space_k_bytes = CheckFreeSpace("Failure", file_name); |
| 180 // Disks with <100k of free space almost never succeed in opening a |
| 181 // leveldb database. |
| 182 if (is_disk_full) |
| 183 *is_disk_full = free_space_k_bytes >= 0 && free_space_k_bytes < 100; |
| 178 | 184 |
| 179 LOG(ERROR) << "Failed to open LevelDB database from " | 185 LOG(ERROR) << "Failed to open LevelDB database from " |
| 180 << file_name.AsUTF8Unsafe() << "," << s.ToString(); | 186 << file_name.AsUTF8Unsafe() << "," << s.ToString(); |
| 181 return scoped_ptr<LevelDBDatabase>(); | 187 return scoped_ptr<LevelDBDatabase>(); |
| 182 } | 188 } |
| 183 | 189 |
| 184 HistogramFreeSpace("Success", file_name); | 190 CheckFreeSpace("Success", file_name); |
| 185 | 191 |
| 186 scoped_ptr<LevelDBDatabase> result(new LevelDBDatabase); | 192 scoped_ptr<LevelDBDatabase> result(new LevelDBDatabase); |
| 187 result->db_ = make_scoped_ptr(db); | 193 result->db_ = make_scoped_ptr(db); |
| 188 result->comparator_adapter_ = comparator_adapter.Pass(); | 194 result->comparator_adapter_ = comparator_adapter.Pass(); |
| 189 result->comparator_ = comparator; | 195 result->comparator_ = comparator; |
| 190 | 196 |
| 191 return result.Pass(); | 197 return result.Pass(); |
| 192 } | 198 } |
| 193 | 199 |
| 194 scoped_ptr<LevelDBDatabase> LevelDBDatabase::OpenInMemory( | 200 scoped_ptr<LevelDBDatabase> LevelDBDatabase::OpenInMemory( |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 350 if (!i) // TODO(jsbell): Double check if we actually need to check this. | 356 if (!i) // TODO(jsbell): Double check if we actually need to check this. |
| 351 return scoped_ptr<LevelDBIterator>(); | 357 return scoped_ptr<LevelDBIterator>(); |
| 352 return scoped_ptr<LevelDBIterator>(new IteratorImpl(i.Pass())); | 358 return scoped_ptr<LevelDBIterator>(new IteratorImpl(i.Pass())); |
| 353 } | 359 } |
| 354 | 360 |
| 355 const LevelDBComparator* LevelDBDatabase::Comparator() const { | 361 const LevelDBComparator* LevelDBDatabase::Comparator() const { |
| 356 return comparator_; | 362 return comparator_; |
| 357 } | 363 } |
| 358 | 364 |
| 359 } // namespace content | 365 } // namespace content |
| OLD | NEW |