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/pickle.h" | 11 #include "base/pickle.h" |
11 #include "base/string_number_conversions.h" | 12 #include "base/string_number_conversions.h" |
12 #include "base/string_util.h" | 13 #include "base/string_util.h" |
13 #include "base/sys_string_conversions.h" | 14 #include "base/utf_string_conversions.h" |
ericu
2012/03/26 18:39:18
Is this header needed any more, now that you have
tzik
2012/03/27 02:44:18
Removed. No, it's not needed. Thanks!
| |
14 #include "third_party/leveldatabase/src/include/leveldb/iterator.h" | 15 #include "third_party/leveldatabase/src/include/leveldb/iterator.h" |
16 #include "third_party/leveldatabase/src/include/leveldb/status.h" | |
15 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" | 17 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" |
16 #include "webkit/fileapi/file_system_util.h" | 18 #include "webkit/fileapi/file_system_util.h" |
17 | 19 |
18 namespace { | 20 namespace { |
19 | 21 |
20 bool PickleFromFileInfo( | 22 bool PickleFromFileInfo( |
21 const fileapi::FileSystemDirectoryDatabase::FileInfo& info, | 23 const fileapi::FileSystemDirectoryDatabase::FileInfo& info, |
22 Pickle* pickle) { | 24 Pickle* pickle) { |
23 DCHECK(pickle); | 25 DCHECK(pickle); |
24 std::string data_path; | 26 std::string data_path; |
25 // Round off here to match the behavior of the filesystem on real files. | 27 // Round off here to match the behavior of the filesystem on real files. |
26 base::Time time = | 28 base::Time time = |
27 base::Time::FromDoubleT(floor(info.modification_time.ToDoubleT())); | 29 base::Time::FromDoubleT(floor(info.modification_time.ToDoubleT())); |
28 std::string name; | 30 std::string name; |
29 | 31 |
30 #if defined(OS_POSIX) | 32 data_path = fileapi::FilePathToString(info.data_path); |
31 data_path = info.data_path.value(); | 33 name = fileapi::FilePathToString(FilePath(info.name)); |
32 name = info.name; | 34 |
33 #elif defined(OS_WIN) | |
34 data_path = base::SysWideToUTF8(info.data_path.value()); | |
35 name = base::SysWideToUTF8(info.name); | |
36 #endif | |
37 if (pickle->WriteInt64(info.parent_id) && | 35 if (pickle->WriteInt64(info.parent_id) && |
38 pickle->WriteString(data_path) && | 36 pickle->WriteString(data_path) && |
39 pickle->WriteString(name) && | 37 pickle->WriteString(name) && |
40 pickle->WriteInt64(time.ToInternalValue())) | 38 pickle->WriteInt64(time.ToInternalValue())) |
41 return true; | 39 return true; |
42 | 40 |
43 NOTREACHED(); | 41 NOTREACHED(); |
44 return false; | 42 return false; |
45 } | 43 } |
46 | 44 |
47 bool FileInfoFromPickle( | 45 bool FileInfoFromPickle( |
48 const Pickle& pickle, | 46 const Pickle& pickle, |
49 fileapi::FileSystemDirectoryDatabase::FileInfo* info) { | 47 fileapi::FileSystemDirectoryDatabase::FileInfo* info) { |
50 PickleIterator iter(pickle); | 48 PickleIterator iter(pickle); |
51 std::string data_path; | 49 std::string data_path; |
52 std::string name; | 50 std::string name; |
53 int64 internal_time; | 51 int64 internal_time; |
54 | 52 |
55 if (pickle.ReadInt64(&iter, &info->parent_id) && | 53 if (pickle.ReadInt64(&iter, &info->parent_id) && |
56 pickle.ReadString(&iter, &data_path) && | 54 pickle.ReadString(&iter, &data_path) && |
57 pickle.ReadString(&iter, &name) && | 55 pickle.ReadString(&iter, &name) && |
58 pickle.ReadInt64(&iter, &internal_time)) { | 56 pickle.ReadInt64(&iter, &internal_time)) { |
59 #if defined(OS_POSIX) | 57 |
60 info->data_path = FilePath(data_path); | 58 info->data_path = fileapi::StringToFilePath(data_path); |
61 info->name = name; | 59 info->name = fileapi::StringToFilePath(name).value(); |
62 #elif defined(OS_WIN) | |
63 info->data_path = FilePath(base::SysUTF8ToWide(data_path)); | |
64 info->name = base::SysUTF8ToWide(name); | |
65 #endif | |
66 info->modification_time = base::Time::FromInternalValue(internal_time); | 60 info->modification_time = base::Time::FromInternalValue(internal_time); |
67 return true; | 61 return true; |
68 } | 62 } |
69 LOG(ERROR) << "Pickle could not be digested!"; | 63 LOG(ERROR) << "Pickle could not be digested!"; |
70 return false; | 64 return false; |
71 } | 65 } |
72 | 66 |
67 const FilePath::CharType kDirectoryDatabaseName[] = FILE_PATH_LITERAL("Paths"); | |
73 const char kChildLookupPrefix[] = "CHILD_OF:"; | 68 const char kChildLookupPrefix[] = "CHILD_OF:"; |
74 const char kChildLookupSeparator[] = ":"; | 69 const char kChildLookupSeparator[] = ":"; |
75 const char kLastFileIdKey[] = "LAST_FILE_ID"; | 70 const char kLastFileIdKey[] = "LAST_FILE_ID"; |
76 const char kLastIntegerKey[] = "LAST_INTEGER"; | 71 const char kLastIntegerKey[] = "LAST_INTEGER"; |
77 | 72 |
78 std::string GetChildLookupKey( | 73 std::string GetChildLookupKey( |
79 fileapi::FileSystemDirectoryDatabase::FileId parent_id, | 74 fileapi::FileSystemDirectoryDatabase::FileId parent_id, |
80 const FilePath::StringType& child_name) { | 75 const FilePath::StringType& child_name) { |
81 std::string name; | 76 std::string name; |
82 #if defined(OS_POSIX) | 77 name = fileapi::FilePathToString(FilePath(child_name)); |
83 name = child_name; | |
84 #elif defined(OS_WIN) | |
85 name = base::SysWideToUTF8(child_name); | |
86 #endif | |
87 return std::string(kChildLookupPrefix) + base::Int64ToString(parent_id) + | 78 return std::string(kChildLookupPrefix) + base::Int64ToString(parent_id) + |
88 std::string(kChildLookupSeparator) + name; | 79 std::string(kChildLookupSeparator) + name; |
89 } | 80 } |
90 | 81 |
91 std::string GetChildListingKeyPrefix( | 82 std::string GetChildListingKeyPrefix( |
92 fileapi::FileSystemDirectoryDatabase::FileId parent_id) { | 83 fileapi::FileSystemDirectoryDatabase::FileId parent_id) { |
93 return std::string(kChildLookupPrefix) + base::Int64ToString(parent_id) + | 84 return std::string(kChildLookupPrefix) + base::Int64ToString(parent_id) + |
94 std::string(kChildLookupSeparator); | 85 std::string(kChildLookupSeparator); |
95 } | 86 } |
96 | 87 |
(...skipping 13 matching lines...) Expand all Loading... | |
110 } // namespace | 101 } // namespace |
111 | 102 |
112 namespace fileapi { | 103 namespace fileapi { |
113 | 104 |
114 FileSystemDirectoryDatabase::FileInfo::FileInfo() : parent_id(0) { | 105 FileSystemDirectoryDatabase::FileInfo::FileInfo() : parent_id(0) { |
115 } | 106 } |
116 | 107 |
117 FileSystemDirectoryDatabase::FileInfo::~FileInfo() { | 108 FileSystemDirectoryDatabase::FileInfo::~FileInfo() { |
118 } | 109 } |
119 | 110 |
120 FileSystemDirectoryDatabase::FileSystemDirectoryDatabase(const FilePath& path) { | 111 FileSystemDirectoryDatabase::FileSystemDirectoryDatabase( |
121 #if defined(OS_POSIX) | 112 const FilePath& origin_data_directory) |
122 path_ = path.value(); | 113 : origin_data_directory_(origin_data_directory) { |
123 #elif defined(OS_WIN) | |
124 path_ = base::SysWideToUTF8(path.value()); | |
125 #endif | |
126 } | 114 } |
127 | 115 |
128 FileSystemDirectoryDatabase::~FileSystemDirectoryDatabase() { | 116 FileSystemDirectoryDatabase::~FileSystemDirectoryDatabase() { |
129 } | 117 } |
130 | 118 |
131 bool FileSystemDirectoryDatabase::GetChildWithName( | 119 bool FileSystemDirectoryDatabase::GetChildWithName( |
132 FileId parent_id, const FilePath::StringType& name, FileId* child_id) { | 120 FileId parent_id, const FilePath::StringType& name, FileId* child_id) { |
133 if (!Init()) | 121 if (!Init(FAIL_ON_CORRUPTION)) |
134 return false; | 122 return false; |
135 DCHECK(child_id); | 123 DCHECK(child_id); |
136 std::string child_key = GetChildLookupKey(parent_id, name); | 124 std::string child_key = GetChildLookupKey(parent_id, name); |
137 std::string child_id_string; | 125 std::string child_id_string; |
138 leveldb::Status status = | 126 leveldb::Status status = |
139 db_->Get(leveldb::ReadOptions(), child_key, &child_id_string); | 127 db_->Get(leveldb::ReadOptions(), child_key, &child_id_string); |
140 if (status.IsNotFound()) | 128 if (status.IsNotFound()) |
141 return false; | 129 return false; |
142 if (status.ok()) { | 130 if (status.ok()) { |
143 if (!base::StringToInt64(child_id_string, child_id)) { | 131 if (!base::StringToInt64(child_id_string, child_id)) { |
(...skipping 20 matching lines...) Expand all Loading... | |
164 if (!GetChildWithName(local_id, name, &local_id)) | 152 if (!GetChildWithName(local_id, name, &local_id)) |
165 return false; | 153 return false; |
166 } | 154 } |
167 *file_id = local_id; | 155 *file_id = local_id; |
168 return true; | 156 return true; |
169 } | 157 } |
170 | 158 |
171 bool FileSystemDirectoryDatabase::ListChildren( | 159 bool FileSystemDirectoryDatabase::ListChildren( |
172 FileId parent_id, std::vector<FileId>* children) { | 160 FileId parent_id, std::vector<FileId>* children) { |
173 // Check to add later: fail if parent is a file, at least in debug builds. | 161 // Check to add later: fail if parent is a file, at least in debug builds. |
174 if (!Init()) | 162 if (!Init(FAIL_ON_CORRUPTION)) |
175 return false; | 163 return false; |
176 DCHECK(children); | 164 DCHECK(children); |
177 std::string child_key_prefix = GetChildListingKeyPrefix(parent_id); | 165 std::string child_key_prefix = GetChildListingKeyPrefix(parent_id); |
178 | 166 |
179 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions())); | 167 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions())); |
180 iter->Seek(child_key_prefix); | 168 iter->Seek(child_key_prefix); |
181 children->clear(); | 169 children->clear(); |
182 while (iter->Valid() && | 170 while (iter->Valid() && |
183 StartsWithASCII(iter->key().ToString(), child_key_prefix, true)) { | 171 StartsWithASCII(iter->key().ToString(), child_key_prefix, true)) { |
184 std::string child_id_string = iter->value().ToString(); | 172 std::string child_id_string = iter->value().ToString(); |
185 FileId child_id; | 173 FileId child_id; |
186 if (!base::StringToInt64(child_id_string, &child_id)) { | 174 if (!base::StringToInt64(child_id_string, &child_id)) { |
187 LOG(ERROR) << "Hit database corruption!"; | 175 LOG(ERROR) << "Hit database corruption!"; |
188 return false; | 176 return false; |
189 } | 177 } |
190 children->push_back(child_id); | 178 children->push_back(child_id); |
191 iter->Next(); | 179 iter->Next(); |
192 } | 180 } |
193 return true; | 181 return true; |
194 } | 182 } |
195 | 183 |
196 bool FileSystemDirectoryDatabase::GetFileInfo(FileId file_id, FileInfo* info) { | 184 bool FileSystemDirectoryDatabase::GetFileInfo(FileId file_id, FileInfo* info) { |
197 if (!Init()) | 185 if (!Init(FAIL_ON_CORRUPTION)) |
198 return false; | 186 return false; |
199 DCHECK(info); | 187 DCHECK(info); |
200 std::string file_key = GetFileLookupKey(file_id); | 188 std::string file_key = GetFileLookupKey(file_id); |
201 std::string file_data_string; | 189 std::string file_data_string; |
202 leveldb::Status status = | 190 leveldb::Status status = |
203 db_->Get(leveldb::ReadOptions(), file_key, &file_data_string); | 191 db_->Get(leveldb::ReadOptions(), file_key, &file_data_string); |
204 if (status.ok()) { | 192 if (status.ok()) { |
205 return FileInfoFromPickle( | 193 return FileInfoFromPickle( |
206 Pickle(file_data_string.data(), file_data_string.length()), info); | 194 Pickle(file_data_string.data(), file_data_string.length()), info); |
207 } | 195 } |
208 // Special-case the root, for databases that haven't been initialized yet. | 196 // Special-case the root, for databases that haven't been initialized yet. |
209 // Without this, a query for the root's file info, made before creating the | 197 // Without this, a query for the root's file info, made before creating the |
210 // first file in the database, will fail and confuse callers. | 198 // first file in the database, will fail and confuse callers. |
211 if (status.IsNotFound() && !file_id) { | 199 if (status.IsNotFound() && !file_id) { |
212 info->name = FilePath::StringType(); | 200 info->name = FilePath::StringType(); |
213 info->data_path = FilePath(); | 201 info->data_path = FilePath(); |
214 info->modification_time = base::Time::Now(); | 202 info->modification_time = base::Time::Now(); |
215 info->parent_id = 0; | 203 info->parent_id = 0; |
216 return true; | 204 return true; |
217 } | 205 } |
218 HandleError(FROM_HERE, status); | 206 HandleError(FROM_HERE, status); |
219 return false; | 207 return false; |
220 } | 208 } |
221 | 209 |
222 bool FileSystemDirectoryDatabase::AddFileInfo( | 210 bool FileSystemDirectoryDatabase::AddFileInfo( |
223 const FileInfo& info, FileId* file_id) { | 211 const FileInfo& info, FileId* file_id) { |
224 if (!Init()) | 212 if (!Init(FAIL_ON_CORRUPTION)) |
225 return false; | 213 return false; |
226 DCHECK(file_id); | 214 DCHECK(file_id); |
227 std::string child_key = GetChildLookupKey(info.parent_id, info.name); | 215 std::string child_key = GetChildLookupKey(info.parent_id, info.name); |
228 std::string child_id_string; | 216 std::string child_id_string; |
229 leveldb::Status status = | 217 leveldb::Status status = |
230 db_->Get(leveldb::ReadOptions(), child_key, &child_id_string); | 218 db_->Get(leveldb::ReadOptions(), child_key, &child_id_string); |
231 if (status.ok()) { | 219 if (status.ok()) { |
232 LOG(ERROR) << "File exists already!"; | 220 LOG(ERROR) << "File exists already!"; |
233 return false; | 221 return false; |
234 } | 222 } |
(...skipping 21 matching lines...) Expand all Loading... | |
256 status = db_->Write(leveldb::WriteOptions(), &batch); | 244 status = db_->Write(leveldb::WriteOptions(), &batch); |
257 if (!status.ok()) { | 245 if (!status.ok()) { |
258 HandleError(FROM_HERE, status); | 246 HandleError(FROM_HERE, status); |
259 return false; | 247 return false; |
260 } | 248 } |
261 *file_id = temp_id; | 249 *file_id = temp_id; |
262 return true; | 250 return true; |
263 } | 251 } |
264 | 252 |
265 bool FileSystemDirectoryDatabase::RemoveFileInfo(FileId file_id) { | 253 bool FileSystemDirectoryDatabase::RemoveFileInfo(FileId file_id) { |
266 if (!Init()) | 254 if (!Init(FAIL_ON_CORRUPTION)) |
267 return false; | 255 return false; |
268 leveldb::WriteBatch batch; | 256 leveldb::WriteBatch batch; |
269 if (!RemoveFileInfoHelper(file_id, &batch)) | 257 if (!RemoveFileInfoHelper(file_id, &batch)) |
270 return false; | 258 return false; |
271 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); | 259 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); |
272 if (!status.ok()) { | 260 if (!status.ok()) { |
273 HandleError(FROM_HERE, status); | 261 HandleError(FROM_HERE, status); |
274 return false; | 262 return false; |
275 } | 263 } |
276 return true; | 264 return true; |
277 } | 265 } |
278 | 266 |
279 bool FileSystemDirectoryDatabase::UpdateFileInfo( | 267 bool FileSystemDirectoryDatabase::UpdateFileInfo( |
280 FileId file_id, const FileInfo& new_info) { | 268 FileId file_id, const FileInfo& new_info) { |
281 // TODO: We should also check to see that this doesn't create a loop, but | 269 // TODO: We should also check to see that this doesn't create a loop, but |
282 // perhaps only in a debug build. | 270 // perhaps only in a debug build. |
283 if (!Init()) | 271 if (!Init(FAIL_ON_CORRUPTION)) |
284 return false; | 272 return false; |
285 DCHECK(file_id); // You can't remove the root, ever. Just delete the DB. | 273 DCHECK(file_id); // You can't remove the root, ever. Just delete the DB. |
286 FileInfo old_info; | 274 FileInfo old_info; |
287 if (!GetFileInfo(file_id, &old_info)) | 275 if (!GetFileInfo(file_id, &old_info)) |
288 return false; | 276 return false; |
289 if (old_info.parent_id != new_info.parent_id && | 277 if (old_info.parent_id != new_info.parent_id && |
290 !VerifyIsDirectory(new_info.parent_id)) | 278 !VerifyIsDirectory(new_info.parent_id)) |
291 return false; | 279 return false; |
292 if (old_info.parent_id != new_info.parent_id || | 280 if (old_info.parent_id != new_info.parent_id || |
293 old_info.name != new_info.name) { | 281 old_info.name != new_info.name) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
357 pickle.size())); | 345 pickle.size())); |
358 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); | 346 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); |
359 if (!status.ok()) { | 347 if (!status.ok()) { |
360 HandleError(FROM_HERE, status); | 348 HandleError(FROM_HERE, status); |
361 return false; | 349 return false; |
362 } | 350 } |
363 return true; | 351 return true; |
364 } | 352 } |
365 | 353 |
366 bool FileSystemDirectoryDatabase::GetNextInteger(int64* next) { | 354 bool FileSystemDirectoryDatabase::GetNextInteger(int64* next) { |
367 if (!Init()) | 355 if (!Init(FAIL_ON_CORRUPTION)) |
368 return false; | 356 return false; |
369 DCHECK(next); | 357 DCHECK(next); |
370 std::string int_string; | 358 std::string int_string; |
371 leveldb::Status status = | 359 leveldb::Status status = |
372 db_->Get(leveldb::ReadOptions(), LastIntegerKey(), &int_string); | 360 db_->Get(leveldb::ReadOptions(), LastIntegerKey(), &int_string); |
373 if (status.ok()) { | 361 if (status.ok()) { |
374 int64 temp; | 362 int64 temp; |
375 if (!base::StringToInt64(int_string, &temp)) { | 363 if (!base::StringToInt64(int_string, &temp)) { |
376 LOG(ERROR) << "Hit database corruption!"; | 364 LOG(ERROR) << "Hit database corruption!"; |
377 return false; | 365 return false; |
(...skipping 14 matching lines...) Expand all Loading... | |
392 } | 380 } |
393 // The database must not yet exist; initialize it. | 381 // The database must not yet exist; initialize it. |
394 if (!StoreDefaultValues()) | 382 if (!StoreDefaultValues()) |
395 return false; | 383 return false; |
396 | 384 |
397 return GetNextInteger(next); | 385 return GetNextInteger(next); |
398 } | 386 } |
399 | 387 |
400 // static | 388 // static |
401 bool FileSystemDirectoryDatabase::DestroyDatabase(const FilePath& path) { | 389 bool FileSystemDirectoryDatabase::DestroyDatabase(const FilePath& path) { |
402 std::string name; | 390 std::string name = FilePathToString(path.Append(kDirectoryDatabaseName)); |
403 #if defined(OS_POSIX) | |
404 name = path.value(); | |
405 #elif defined(OS_WIN) | |
406 name = base::SysWideToUTF8(path.value()); | |
407 #endif | |
408 leveldb::Status status = leveldb::DestroyDB(name, leveldb::Options()); | 391 leveldb::Status status = leveldb::DestroyDB(name, leveldb::Options()); |
409 if (status.ok()) | 392 if (status.ok()) |
410 return true; | 393 return true; |
411 LOG(WARNING) << "Failed to destroy a database with status " << | 394 LOG(WARNING) << "Failed to destroy a database with status " << |
412 status.ToString(); | 395 status.ToString(); |
413 return false; | 396 return false; |
414 } | 397 } |
415 | 398 |
416 bool FileSystemDirectoryDatabase::Init() { | 399 bool FileSystemDirectoryDatabase::Init(RecoveryOption recovery_option) { |
417 if (db_.get()) | 400 if (db_.get()) |
418 return true; | 401 return true; |
419 | 402 |
420 leveldb::Options options; | 403 std::string path = |
421 options.create_if_missing = true; | 404 FilePathToString(origin_data_directory_.Append(kDirectoryDatabaseName)); |
422 leveldb::DB* db; | 405 leveldb::Options options; |
423 leveldb::Status status = leveldb::DB::Open(options, path_, &db); | 406 options.create_if_missing = true; |
424 if (status.ok()) { | 407 leveldb::DB* db; |
425 db_.reset(db); | 408 leveldb::Status status = leveldb::DB::Open(options, path, &db); |
426 return true; | 409 // TODO(tzik): Collect status metrics here. |
427 } | 410 if (status.ok()) { |
428 HandleError(FROM_HERE, status); | 411 db_.reset(db); |
429 return false; | 412 return true; |
413 } | |
414 HandleError(FROM_HERE, status); | |
415 | |
416 if (recovery_option == FAIL_ON_CORRUPTION) | |
417 return false; | |
418 | |
419 DCHECK_EQ(DELETE_ON_CORRUPTION, recovery_option); | |
420 if (!file_util::Delete(origin_data_directory_, true)) | |
421 return false; | |
422 if (!file_util::CreateDirectory(origin_data_directory_)) | |
423 return false; | |
424 return Init(FAIL_ON_CORRUPTION); | |
430 } | 425 } |
431 | 426 |
432 bool FileSystemDirectoryDatabase::StoreDefaultValues() { | 427 bool FileSystemDirectoryDatabase::StoreDefaultValues() { |
433 // Verify that this is a totally new database, and initialize it. | 428 // Verify that this is a totally new database, and initialize it. |
434 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions())); | 429 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions())); |
435 iter->SeekToFirst(); | 430 iter->SeekToFirst(); |
436 if (iter->Valid()) { // DB was not empty--we shouldn't have been called. | 431 if (iter->Valid()) { // DB was not empty--we shouldn't have been called. |
437 LOG(ERROR) << "File system origin database is corrupt!"; | 432 LOG(ERROR) << "File system origin database is corrupt!"; |
438 return false; | 433 return false; |
439 } | 434 } |
440 // This is always the first write into the database. If we ever add a | 435 // This is always the first write into the database. If we ever add a |
441 // version number, it should go in this transaction too. | 436 // version number, it should go in this transaction too. |
442 FileInfo root; | 437 FileInfo root; |
443 root.parent_id = 0; | 438 root.parent_id = 0; |
444 root.modification_time = base::Time::Now(); | 439 root.modification_time = base::Time::Now(); |
445 leveldb::WriteBatch batch; | 440 leveldb::WriteBatch batch; |
446 if (!AddFileInfoHelper(root, 0, &batch)) | 441 if (!AddFileInfoHelper(root, 0, &batch)) |
447 return false; | 442 return false; |
448 batch.Put(LastFileIdKey(), base::Int64ToString(0)); | 443 batch.Put(LastFileIdKey(), base::Int64ToString(0)); |
449 batch.Put(LastIntegerKey(), base::Int64ToString(-1)); | 444 batch.Put(LastIntegerKey(), base::Int64ToString(-1)); |
450 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); | 445 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); |
451 if (!status.ok()) { | 446 if (!status.ok()) { |
452 HandleError(FROM_HERE, status); | 447 HandleError(FROM_HERE, status); |
453 return false; | 448 return false; |
454 } | 449 } |
455 return true; | 450 return true; |
456 } | 451 } |
457 | 452 |
458 bool FileSystemDirectoryDatabase::GetLastFileId(FileId* file_id) { | 453 bool FileSystemDirectoryDatabase::GetLastFileId(FileId* file_id) { |
459 if (!Init()) | 454 if (!Init(FAIL_ON_CORRUPTION)) |
460 return false; | 455 return false; |
461 DCHECK(file_id); | 456 DCHECK(file_id); |
462 std::string id_string; | 457 std::string id_string; |
463 leveldb::Status status = | 458 leveldb::Status status = |
464 db_->Get(leveldb::ReadOptions(), LastFileIdKey(), &id_string); | 459 db_->Get(leveldb::ReadOptions(), LastFileIdKey(), &id_string); |
465 if (status.ok()) { | 460 if (status.ok()) { |
466 if (!base::StringToInt64(id_string, file_id)) { | 461 if (!base::StringToInt64(id_string, file_id)) { |
467 LOG(ERROR) << "Hit database corruption!"; | 462 LOG(ERROR) << "Hit database corruption!"; |
468 return false; | 463 return false; |
469 } | 464 } |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
539 | 534 |
540 void FileSystemDirectoryDatabase::HandleError( | 535 void FileSystemDirectoryDatabase::HandleError( |
541 const tracked_objects::Location& from_here, | 536 const tracked_objects::Location& from_here, |
542 leveldb::Status status) { | 537 leveldb::Status status) { |
543 LOG(ERROR) << "FileSystemDirectoryDatabase failed at: " | 538 LOG(ERROR) << "FileSystemDirectoryDatabase failed at: " |
544 << from_here.ToString() << " with error: " << status.ToString(); | 539 << from_here.ToString() << " with error: " << status.ToString(); |
545 db_.reset(); | 540 db_.reset(); |
546 } | 541 } |
547 | 542 |
548 } // namespace fileapi | 543 } // namespace fileapi |
OLD | NEW |