| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "webkit/fileapi/file_system_directory_database.h" | 5 #include "webkit/fileapi/file_system_directory_database.h" |
| 6 | 6 |
| 7 #include <math.h> | 7 #include <math.h> |
| 8 | 8 |
| 9 #include "base/file_util.h" |
| 9 #include "base/location.h" | 10 #include "base/location.h" |
| 10 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
| 11 #include "base/pickle.h" | 12 #include "base/pickle.h" |
| 12 #include "base/string_number_conversions.h" | 13 #include "base/string_number_conversions.h" |
| 13 #include "base/string_util.h" | 14 #include "base/string_util.h" |
| 14 #include "base/sys_string_conversions.h" | |
| 15 #include "third_party/leveldatabase/src/include/leveldb/db.h" | 15 #include "third_party/leveldatabase/src/include/leveldb/db.h" |
| 16 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" | 16 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" |
| 17 #include "webkit/fileapi/file_system_util.h" | 17 #include "webkit/fileapi/file_system_util.h" |
| 18 | 18 |
| 19 namespace { | 19 namespace { |
| 20 | 20 |
| 21 bool PickleFromFileInfo( | 21 bool PickleFromFileInfo( |
| 22 const fileapi::FileSystemDirectoryDatabase::FileInfo& info, | 22 const fileapi::FileSystemDirectoryDatabase::FileInfo& info, |
| 23 Pickle* pickle) { | 23 Pickle* pickle) { |
| 24 DCHECK(pickle); | 24 DCHECK(pickle); |
| 25 std::string data_path; | 25 std::string data_path; |
| 26 // Round off here to match the behavior of the filesystem on real files. | 26 // Round off here to match the behavior of the filesystem on real files. |
| 27 base::Time time = | 27 base::Time time = |
| 28 base::Time::FromDoubleT(floor(info.modification_time.ToDoubleT())); | 28 base::Time::FromDoubleT(floor(info.modification_time.ToDoubleT())); |
| 29 std::string name; | 29 std::string name; |
| 30 | 30 |
| 31 #if defined(OS_POSIX) | 31 data_path = fileapi::FilePathToString(info.data_path); |
| 32 data_path = info.data_path.value(); | 32 name = fileapi::FilePathToString(FilePath(info.name)); |
| 33 name = info.name; | 33 |
| 34 #elif defined(OS_WIN) | |
| 35 data_path = base::SysWideToUTF8(info.data_path.value()); | |
| 36 name = base::SysWideToUTF8(info.name); | |
| 37 #endif | |
| 38 if (pickle->WriteInt64(info.parent_id) && | 34 if (pickle->WriteInt64(info.parent_id) && |
| 39 pickle->WriteString(data_path) && | 35 pickle->WriteString(data_path) && |
| 40 pickle->WriteString(name) && | 36 pickle->WriteString(name) && |
| 41 pickle->WriteInt64(time.ToInternalValue())) | 37 pickle->WriteInt64(time.ToInternalValue())) |
| 42 return true; | 38 return true; |
| 43 | 39 |
| 44 NOTREACHED(); | 40 NOTREACHED(); |
| 45 return false; | 41 return false; |
| 46 } | 42 } |
| 47 | 43 |
| 48 bool FileInfoFromPickle( | 44 bool FileInfoFromPickle( |
| 49 const Pickle& pickle, | 45 const Pickle& pickle, |
| 50 fileapi::FileSystemDirectoryDatabase::FileInfo* info) { | 46 fileapi::FileSystemDirectoryDatabase::FileInfo* info) { |
| 51 PickleIterator iter(pickle); | 47 PickleIterator iter(pickle); |
| 52 std::string data_path; | 48 std::string data_path; |
| 53 std::string name; | 49 std::string name; |
| 54 int64 internal_time; | 50 int64 internal_time; |
| 55 | 51 |
| 56 if (pickle.ReadInt64(&iter, &info->parent_id) && | 52 if (pickle.ReadInt64(&iter, &info->parent_id) && |
| 57 pickle.ReadString(&iter, &data_path) && | 53 pickle.ReadString(&iter, &data_path) && |
| 58 pickle.ReadString(&iter, &name) && | 54 pickle.ReadString(&iter, &name) && |
| 59 pickle.ReadInt64(&iter, &internal_time)) { | 55 pickle.ReadInt64(&iter, &internal_time)) { |
| 60 #if defined(OS_POSIX) | 56 |
| 61 info->data_path = FilePath(data_path); | 57 info->data_path = fileapi::StringToFilePath(data_path); |
| 62 info->name = name; | 58 info->name = fileapi::StringToFilePath(name).value(); |
| 63 #elif defined(OS_WIN) | |
| 64 info->data_path = FilePath(base::SysUTF8ToWide(data_path)); | |
| 65 info->name = base::SysUTF8ToWide(name); | |
| 66 #endif | |
| 67 info->modification_time = base::Time::FromInternalValue(internal_time); | 59 info->modification_time = base::Time::FromInternalValue(internal_time); |
| 68 return true; | 60 return true; |
| 69 } | 61 } |
| 70 LOG(ERROR) << "Pickle could not be digested!"; | 62 LOG(ERROR) << "Pickle could not be digested!"; |
| 71 return false; | 63 return false; |
| 72 } | 64 } |
| 73 | 65 |
| 66 const FilePath::CharType kDirectoryDatabaseName[] = FILE_PATH_LITERAL("Paths"); |
| 74 const char kChildLookupPrefix[] = "CHILD_OF:"; | 67 const char kChildLookupPrefix[] = "CHILD_OF:"; |
| 75 const char kChildLookupSeparator[] = ":"; | 68 const char kChildLookupSeparator[] = ":"; |
| 76 const char kLastFileIdKey[] = "LAST_FILE_ID"; | 69 const char kLastFileIdKey[] = "LAST_FILE_ID"; |
| 77 const char kLastIntegerKey[] = "LAST_INTEGER"; | 70 const char kLastIntegerKey[] = "LAST_INTEGER"; |
| 78 const int64 kMinimumReportIntervalHours = 1; | 71 const int64 kMinimumReportIntervalHours = 1; |
| 79 const char kInitStatusHistogramLabel[] = "FileSystem.DirectoryDatabaseInit"; | 72 const char kInitStatusHistogramLabel[] = "FileSystem.DirectoryDatabaseInit"; |
| 80 | 73 |
| 81 enum InitStatus { | 74 enum InitStatus { |
| 82 INIT_STATUS_OK = 0, | 75 INIT_STATUS_OK = 0, |
| 83 INIT_STATUS_CORRUPTION, | 76 INIT_STATUS_CORRUPTION, |
| 84 INIT_STATUS_MAX | 77 INIT_STATUS_MAX |
| 85 }; | 78 }; |
| 86 | 79 |
| 87 std::string GetChildLookupKey( | 80 std::string GetChildLookupKey( |
| 88 fileapi::FileSystemDirectoryDatabase::FileId parent_id, | 81 fileapi::FileSystemDirectoryDatabase::FileId parent_id, |
| 89 const FilePath::StringType& child_name) { | 82 const FilePath::StringType& child_name) { |
| 90 std::string name; | 83 std::string name; |
| 91 #if defined(OS_POSIX) | 84 name = fileapi::FilePathToString(FilePath(child_name)); |
| 92 name = child_name; | |
| 93 #elif defined(OS_WIN) | |
| 94 name = base::SysWideToUTF8(child_name); | |
| 95 #endif | |
| 96 return std::string(kChildLookupPrefix) + base::Int64ToString(parent_id) + | 85 return std::string(kChildLookupPrefix) + base::Int64ToString(parent_id) + |
| 97 std::string(kChildLookupSeparator) + name; | 86 std::string(kChildLookupSeparator) + name; |
| 98 } | 87 } |
| 99 | 88 |
| 100 std::string GetChildListingKeyPrefix( | 89 std::string GetChildListingKeyPrefix( |
| 101 fileapi::FileSystemDirectoryDatabase::FileId parent_id) { | 90 fileapi::FileSystemDirectoryDatabase::FileId parent_id) { |
| 102 return std::string(kChildLookupPrefix) + base::Int64ToString(parent_id) + | 91 return std::string(kChildLookupPrefix) + base::Int64ToString(parent_id) + |
| 103 std::string(kChildLookupSeparator); | 92 std::string(kChildLookupSeparator); |
| 104 } | 93 } |
| 105 | 94 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 119 } // namespace | 108 } // namespace |
| 120 | 109 |
| 121 namespace fileapi { | 110 namespace fileapi { |
| 122 | 111 |
| 123 FileSystemDirectoryDatabase::FileInfo::FileInfo() : parent_id(0) { | 112 FileSystemDirectoryDatabase::FileInfo::FileInfo() : parent_id(0) { |
| 124 } | 113 } |
| 125 | 114 |
| 126 FileSystemDirectoryDatabase::FileInfo::~FileInfo() { | 115 FileSystemDirectoryDatabase::FileInfo::~FileInfo() { |
| 127 } | 116 } |
| 128 | 117 |
| 129 FileSystemDirectoryDatabase::FileSystemDirectoryDatabase(const FilePath& path) { | 118 FileSystemDirectoryDatabase::FileSystemDirectoryDatabase( |
| 130 #if defined(OS_POSIX) | 119 const FilePath& filesystem_data_directory) |
| 131 path_ = path.value(); | 120 : filesystem_data_directory_(filesystem_data_directory) { |
| 132 #elif defined(OS_WIN) | |
| 133 path_ = base::SysWideToUTF8(path.value()); | |
| 134 #endif | |
| 135 } | 121 } |
| 136 | 122 |
| 137 FileSystemDirectoryDatabase::~FileSystemDirectoryDatabase() { | 123 FileSystemDirectoryDatabase::~FileSystemDirectoryDatabase() { |
| 138 } | 124 } |
| 139 | 125 |
| 140 bool FileSystemDirectoryDatabase::GetChildWithName( | 126 bool FileSystemDirectoryDatabase::GetChildWithName( |
| 141 FileId parent_id, const FilePath::StringType& name, FileId* child_id) { | 127 FileId parent_id, const FilePath::StringType& name, FileId* child_id) { |
| 142 if (!Init()) | 128 if (!Init(FAIL_ON_CORRUPTION)) |
| 143 return false; | 129 return false; |
| 144 DCHECK(child_id); | 130 DCHECK(child_id); |
| 145 std::string child_key = GetChildLookupKey(parent_id, name); | 131 std::string child_key = GetChildLookupKey(parent_id, name); |
| 146 std::string child_id_string; | 132 std::string child_id_string; |
| 147 leveldb::Status status = | 133 leveldb::Status status = |
| 148 db_->Get(leveldb::ReadOptions(), child_key, &child_id_string); | 134 db_->Get(leveldb::ReadOptions(), child_key, &child_id_string); |
| 149 if (status.IsNotFound()) | 135 if (status.IsNotFound()) |
| 150 return false; | 136 return false; |
| 151 if (status.ok()) { | 137 if (status.ok()) { |
| 152 if (!base::StringToInt64(child_id_string, child_id)) { | 138 if (!base::StringToInt64(child_id_string, child_id)) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 173 if (!GetChildWithName(local_id, name, &local_id)) | 159 if (!GetChildWithName(local_id, name, &local_id)) |
| 174 return false; | 160 return false; |
| 175 } | 161 } |
| 176 *file_id = local_id; | 162 *file_id = local_id; |
| 177 return true; | 163 return true; |
| 178 } | 164 } |
| 179 | 165 |
| 180 bool FileSystemDirectoryDatabase::ListChildren( | 166 bool FileSystemDirectoryDatabase::ListChildren( |
| 181 FileId parent_id, std::vector<FileId>* children) { | 167 FileId parent_id, std::vector<FileId>* children) { |
| 182 // Check to add later: fail if parent is a file, at least in debug builds. | 168 // Check to add later: fail if parent is a file, at least in debug builds. |
| 183 if (!Init()) | 169 if (!Init(FAIL_ON_CORRUPTION)) |
| 184 return false; | 170 return false; |
| 185 DCHECK(children); | 171 DCHECK(children); |
| 186 std::string child_key_prefix = GetChildListingKeyPrefix(parent_id); | 172 std::string child_key_prefix = GetChildListingKeyPrefix(parent_id); |
| 187 | 173 |
| 188 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions())); | 174 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions())); |
| 189 iter->Seek(child_key_prefix); | 175 iter->Seek(child_key_prefix); |
| 190 children->clear(); | 176 children->clear(); |
| 191 while (iter->Valid() && | 177 while (iter->Valid() && |
| 192 StartsWithASCII(iter->key().ToString(), child_key_prefix, true)) { | 178 StartsWithASCII(iter->key().ToString(), child_key_prefix, true)) { |
| 193 std::string child_id_string = iter->value().ToString(); | 179 std::string child_id_string = iter->value().ToString(); |
| 194 FileId child_id; | 180 FileId child_id; |
| 195 if (!base::StringToInt64(child_id_string, &child_id)) { | 181 if (!base::StringToInt64(child_id_string, &child_id)) { |
| 196 LOG(ERROR) << "Hit database corruption!"; | 182 LOG(ERROR) << "Hit database corruption!"; |
| 197 return false; | 183 return false; |
| 198 } | 184 } |
| 199 children->push_back(child_id); | 185 children->push_back(child_id); |
| 200 iter->Next(); | 186 iter->Next(); |
| 201 } | 187 } |
| 202 return true; | 188 return true; |
| 203 } | 189 } |
| 204 | 190 |
| 205 bool FileSystemDirectoryDatabase::GetFileInfo(FileId file_id, FileInfo* info) { | 191 bool FileSystemDirectoryDatabase::GetFileInfo(FileId file_id, FileInfo* info) { |
| 206 if (!Init()) | 192 if (!Init(FAIL_ON_CORRUPTION)) |
| 207 return false; | 193 return false; |
| 208 DCHECK(info); | 194 DCHECK(info); |
| 209 std::string file_key = GetFileLookupKey(file_id); | 195 std::string file_key = GetFileLookupKey(file_id); |
| 210 std::string file_data_string; | 196 std::string file_data_string; |
| 211 leveldb::Status status = | 197 leveldb::Status status = |
| 212 db_->Get(leveldb::ReadOptions(), file_key, &file_data_string); | 198 db_->Get(leveldb::ReadOptions(), file_key, &file_data_string); |
| 213 if (status.ok()) { | 199 if (status.ok()) { |
| 214 return FileInfoFromPickle( | 200 return FileInfoFromPickle( |
| 215 Pickle(file_data_string.data(), file_data_string.length()), info); | 201 Pickle(file_data_string.data(), file_data_string.length()), info); |
| 216 } | 202 } |
| 217 // Special-case the root, for databases that haven't been initialized yet. | 203 // Special-case the root, for databases that haven't been initialized yet. |
| 218 // Without this, a query for the root's file info, made before creating the | 204 // Without this, a query for the root's file info, made before creating the |
| 219 // first file in the database, will fail and confuse callers. | 205 // first file in the database, will fail and confuse callers. |
| 220 if (status.IsNotFound() && !file_id) { | 206 if (status.IsNotFound() && !file_id) { |
| 221 info->name = FilePath::StringType(); | 207 info->name = FilePath::StringType(); |
| 222 info->data_path = FilePath(); | 208 info->data_path = FilePath(); |
| 223 info->modification_time = base::Time::Now(); | 209 info->modification_time = base::Time::Now(); |
| 224 info->parent_id = 0; | 210 info->parent_id = 0; |
| 225 return true; | 211 return true; |
| 226 } | 212 } |
| 227 HandleError(FROM_HERE, status); | 213 HandleError(FROM_HERE, status); |
| 228 return false; | 214 return false; |
| 229 } | 215 } |
| 230 | 216 |
| 231 bool FileSystemDirectoryDatabase::AddFileInfo( | 217 bool FileSystemDirectoryDatabase::AddFileInfo( |
| 232 const FileInfo& info, FileId* file_id) { | 218 const FileInfo& info, FileId* file_id) { |
| 233 if (!Init()) | 219 if (!Init(FAIL_ON_CORRUPTION)) |
| 234 return false; | 220 return false; |
| 235 DCHECK(file_id); | 221 DCHECK(file_id); |
| 236 std::string child_key = GetChildLookupKey(info.parent_id, info.name); | 222 std::string child_key = GetChildLookupKey(info.parent_id, info.name); |
| 237 std::string child_id_string; | 223 std::string child_id_string; |
| 238 leveldb::Status status = | 224 leveldb::Status status = |
| 239 db_->Get(leveldb::ReadOptions(), child_key, &child_id_string); | 225 db_->Get(leveldb::ReadOptions(), child_key, &child_id_string); |
| 240 if (status.ok()) { | 226 if (status.ok()) { |
| 241 LOG(ERROR) << "File exists already!"; | 227 LOG(ERROR) << "File exists already!"; |
| 242 return false; | 228 return false; |
| 243 } | 229 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 265 status = db_->Write(leveldb::WriteOptions(), &batch); | 251 status = db_->Write(leveldb::WriteOptions(), &batch); |
| 266 if (!status.ok()) { | 252 if (!status.ok()) { |
| 267 HandleError(FROM_HERE, status); | 253 HandleError(FROM_HERE, status); |
| 268 return false; | 254 return false; |
| 269 } | 255 } |
| 270 *file_id = temp_id; | 256 *file_id = temp_id; |
| 271 return true; | 257 return true; |
| 272 } | 258 } |
| 273 | 259 |
| 274 bool FileSystemDirectoryDatabase::RemoveFileInfo(FileId file_id) { | 260 bool FileSystemDirectoryDatabase::RemoveFileInfo(FileId file_id) { |
| 275 if (!Init()) | 261 if (!Init(FAIL_ON_CORRUPTION)) |
| 276 return false; | 262 return false; |
| 277 leveldb::WriteBatch batch; | 263 leveldb::WriteBatch batch; |
| 278 if (!RemoveFileInfoHelper(file_id, &batch)) | 264 if (!RemoveFileInfoHelper(file_id, &batch)) |
| 279 return false; | 265 return false; |
| 280 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); | 266 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); |
| 281 if (!status.ok()) { | 267 if (!status.ok()) { |
| 282 HandleError(FROM_HERE, status); | 268 HandleError(FROM_HERE, status); |
| 283 return false; | 269 return false; |
| 284 } | 270 } |
| 285 return true; | 271 return true; |
| 286 } | 272 } |
| 287 | 273 |
| 288 bool FileSystemDirectoryDatabase::UpdateFileInfo( | 274 bool FileSystemDirectoryDatabase::UpdateFileInfo( |
| 289 FileId file_id, const FileInfo& new_info) { | 275 FileId file_id, const FileInfo& new_info) { |
| 290 // TODO: We should also check to see that this doesn't create a loop, but | 276 // TODO: We should also check to see that this doesn't create a loop, but |
| 291 // perhaps only in a debug build. | 277 // perhaps only in a debug build. |
| 292 if (!Init()) | 278 if (!Init(FAIL_ON_CORRUPTION)) |
| 293 return false; | 279 return false; |
| 294 DCHECK(file_id); // You can't remove the root, ever. Just delete the DB. | 280 DCHECK(file_id); // You can't remove the root, ever. Just delete the DB. |
| 295 FileInfo old_info; | 281 FileInfo old_info; |
| 296 if (!GetFileInfo(file_id, &old_info)) | 282 if (!GetFileInfo(file_id, &old_info)) |
| 297 return false; | 283 return false; |
| 298 if (old_info.parent_id != new_info.parent_id && | 284 if (old_info.parent_id != new_info.parent_id && |
| 299 !VerifyIsDirectory(new_info.parent_id)) | 285 !VerifyIsDirectory(new_info.parent_id)) |
| 300 return false; | 286 return false; |
| 301 if (old_info.parent_id != new_info.parent_id || | 287 if (old_info.parent_id != new_info.parent_id || |
| 302 old_info.name != new_info.name) { | 288 old_info.name != new_info.name) { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 pickle.size())); | 352 pickle.size())); |
| 367 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); | 353 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); |
| 368 if (!status.ok()) { | 354 if (!status.ok()) { |
| 369 HandleError(FROM_HERE, status); | 355 HandleError(FROM_HERE, status); |
| 370 return false; | 356 return false; |
| 371 } | 357 } |
| 372 return true; | 358 return true; |
| 373 } | 359 } |
| 374 | 360 |
| 375 bool FileSystemDirectoryDatabase::GetNextInteger(int64* next) { | 361 bool FileSystemDirectoryDatabase::GetNextInteger(int64* next) { |
| 376 if (!Init()) | 362 if (!Init(FAIL_ON_CORRUPTION)) |
| 377 return false; | 363 return false; |
| 378 DCHECK(next); | 364 DCHECK(next); |
| 379 std::string int_string; | 365 std::string int_string; |
| 380 leveldb::Status status = | 366 leveldb::Status status = |
| 381 db_->Get(leveldb::ReadOptions(), LastIntegerKey(), &int_string); | 367 db_->Get(leveldb::ReadOptions(), LastIntegerKey(), &int_string); |
| 382 if (status.ok()) { | 368 if (status.ok()) { |
| 383 int64 temp; | 369 int64 temp; |
| 384 if (!base::StringToInt64(int_string, &temp)) { | 370 if (!base::StringToInt64(int_string, &temp)) { |
| 385 LOG(ERROR) << "Hit database corruption!"; | 371 LOG(ERROR) << "Hit database corruption!"; |
| 386 return false; | 372 return false; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 401 } | 387 } |
| 402 // The database must not yet exist; initialize it. | 388 // The database must not yet exist; initialize it. |
| 403 if (!StoreDefaultValues()) | 389 if (!StoreDefaultValues()) |
| 404 return false; | 390 return false; |
| 405 | 391 |
| 406 return GetNextInteger(next); | 392 return GetNextInteger(next); |
| 407 } | 393 } |
| 408 | 394 |
| 409 // static | 395 // static |
| 410 bool FileSystemDirectoryDatabase::DestroyDatabase(const FilePath& path) { | 396 bool FileSystemDirectoryDatabase::DestroyDatabase(const FilePath& path) { |
| 411 std::string name; | 397 std::string name = FilePathToString(path.Append(kDirectoryDatabaseName)); |
| 412 #if defined(OS_POSIX) | |
| 413 name = path.value(); | |
| 414 #elif defined(OS_WIN) | |
| 415 name = base::SysWideToUTF8(path.value()); | |
| 416 #endif | |
| 417 leveldb::Status status = leveldb::DestroyDB(name, leveldb::Options()); | 398 leveldb::Status status = leveldb::DestroyDB(name, leveldb::Options()); |
| 418 if (status.ok()) | 399 if (status.ok()) |
| 419 return true; | 400 return true; |
| 420 LOG(WARNING) << "Failed to destroy a database with status " << | 401 LOG(WARNING) << "Failed to destroy a database with status " << |
| 421 status.ToString(); | 402 status.ToString(); |
| 422 return false; | 403 return false; |
| 423 } | 404 } |
| 424 | 405 |
| 425 bool FileSystemDirectoryDatabase::Init() { | 406 bool FileSystemDirectoryDatabase::Init(RecoveryOption recovery_option) { |
| 426 if (db_.get()) | 407 if (db_.get()) |
| 427 return true; | 408 return true; |
| 428 | 409 |
| 429 leveldb::Options options; | 410 std::string path = |
| 430 options.create_if_missing = true; | 411 FilePathToString(filesystem_data_directory_.Append( |
| 431 leveldb::DB* db; | 412 kDirectoryDatabaseName)); |
| 432 leveldb::Status status = leveldb::DB::Open(options, path_, &db); | 413 leveldb::Options options; |
| 433 ReportInitStatus(status); | 414 options.create_if_missing = true; |
| 434 if (status.ok()) { | 415 leveldb::DB* db; |
| 435 db_.reset(db); | 416 leveldb::Status status = leveldb::DB::Open(options, path, &db); |
| 436 return true; | 417 ReportInitStatus(status); |
| 437 } | 418 if (status.ok()) { |
| 438 HandleError(FROM_HERE, status); | 419 db_.reset(db); |
| 439 return false; | 420 return true; |
| 421 } |
| 422 HandleError(FROM_HERE, status); |
| 423 |
| 424 if (recovery_option == FAIL_ON_CORRUPTION) |
| 425 return false; |
| 426 |
| 427 DCHECK_EQ(DELETE_ON_CORRUPTION, recovery_option); |
| 428 if (!file_util::Delete(filesystem_data_directory_, true)) |
| 429 return false; |
| 430 if (!file_util::CreateDirectory(filesystem_data_directory_)) |
| 431 return false; |
| 432 return Init(FAIL_ON_CORRUPTION); |
| 440 } | 433 } |
| 441 | 434 |
| 442 void FileSystemDirectoryDatabase::ReportInitStatus( | 435 void FileSystemDirectoryDatabase::ReportInitStatus( |
| 443 const leveldb::Status& status) { | 436 const leveldb::Status& status) { |
| 444 base::Time now = base::Time::Now(); | 437 base::Time now = base::Time::Now(); |
| 445 const base::TimeDelta minimum_interval = | 438 const base::TimeDelta minimum_interval = |
| 446 base::TimeDelta::FromHours(kMinimumReportIntervalHours); | 439 base::TimeDelta::FromHours(kMinimumReportIntervalHours); |
| 447 if (last_reported_time_ + minimum_interval >= now) | 440 if (last_reported_time_ + minimum_interval >= now) |
| 448 return; | 441 return; |
| 449 last_reported_time_ = now; | 442 last_reported_time_ = now; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 477 batch.Put(LastIntegerKey(), base::Int64ToString(-1)); | 470 batch.Put(LastIntegerKey(), base::Int64ToString(-1)); |
| 478 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); | 471 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); |
| 479 if (!status.ok()) { | 472 if (!status.ok()) { |
| 480 HandleError(FROM_HERE, status); | 473 HandleError(FROM_HERE, status); |
| 481 return false; | 474 return false; |
| 482 } | 475 } |
| 483 return true; | 476 return true; |
| 484 } | 477 } |
| 485 | 478 |
| 486 bool FileSystemDirectoryDatabase::GetLastFileId(FileId* file_id) { | 479 bool FileSystemDirectoryDatabase::GetLastFileId(FileId* file_id) { |
| 487 if (!Init()) | 480 if (!Init(FAIL_ON_CORRUPTION)) |
| 488 return false; | 481 return false; |
| 489 DCHECK(file_id); | 482 DCHECK(file_id); |
| 490 std::string id_string; | 483 std::string id_string; |
| 491 leveldb::Status status = | 484 leveldb::Status status = |
| 492 db_->Get(leveldb::ReadOptions(), LastFileIdKey(), &id_string); | 485 db_->Get(leveldb::ReadOptions(), LastFileIdKey(), &id_string); |
| 493 if (status.ok()) { | 486 if (status.ok()) { |
| 494 if (!base::StringToInt64(id_string, file_id)) { | 487 if (!base::StringToInt64(id_string, file_id)) { |
| 495 LOG(ERROR) << "Hit database corruption!"; | 488 LOG(ERROR) << "Hit database corruption!"; |
| 496 return false; | 489 return false; |
| 497 } | 490 } |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 567 | 560 |
| 568 void FileSystemDirectoryDatabase::HandleError( | 561 void FileSystemDirectoryDatabase::HandleError( |
| 569 const tracked_objects::Location& from_here, | 562 const tracked_objects::Location& from_here, |
| 570 const leveldb::Status& status) { | 563 const leveldb::Status& status) { |
| 571 LOG(ERROR) << "FileSystemDirectoryDatabase failed at: " | 564 LOG(ERROR) << "FileSystemDirectoryDatabase failed at: " |
| 572 << from_here.ToString() << " with error: " << status.ToString(); | 565 << from_here.ToString() << " with error: " << status.ToString(); |
| 573 db_.reset(); | 566 db_.reset(); |
| 574 } | 567 } |
| 575 | 568 |
| 576 } // namespace fileapi | 569 } // namespace fileapi |
| OLD | NEW |