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 |