OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 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 "chrome/browser/sync_file_system/local/local_file_change_tracker.h" | 5 #include "chrome/browser/sync_file_system/local/local_file_change_tracker.h" |
6 | 6 |
7 #include <queue> | 7 #include <queue> |
8 | 8 |
9 #include "base/location.h" | 9 #include "base/location.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/sequenced_task_runner.h" | 11 #include "base/sequenced_task_runner.h" |
12 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
13 #include "chrome/browser/sync_file_system/local/local_file_sync_status.h" | 13 #include "chrome/browser/sync_file_system/local/local_file_sync_status.h" |
14 #include "chrome/browser/sync_file_system/syncable_file_system_util.h" | 14 #include "chrome/browser/sync_file_system/syncable_file_system_util.h" |
15 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h" | 15 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h" |
16 #include "third_party/leveldatabase/src/include/leveldb/db.h" | 16 #include "third_party/leveldatabase/src/include/leveldb/db.h" |
17 #include "third_party/leveldatabase/src/include/leveldb/env.h" | 17 #include "third_party/leveldatabase/src/include/leveldb/env.h" |
18 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" | 18 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" |
19 #include "webkit/browser/fileapi/file_system_context.h" | 19 #include "storage/browser/fileapi/file_system_context.h" |
20 #include "webkit/browser/fileapi/file_system_file_util.h" | 20 #include "storage/browser/fileapi/file_system_file_util.h" |
21 #include "webkit/browser/fileapi/file_system_operation_context.h" | 21 #include "storage/browser/fileapi/file_system_operation_context.h" |
22 #include "webkit/common/fileapi/file_system_util.h" | 22 #include "storage/common/fileapi/file_system_util.h" |
23 | 23 |
24 using fileapi::FileSystemContext; | 24 using storage::FileSystemContext; |
25 using fileapi::FileSystemFileUtil; | 25 using storage::FileSystemFileUtil; |
26 using fileapi::FileSystemOperationContext; | 26 using storage::FileSystemOperationContext; |
27 using fileapi::FileSystemURL; | 27 using storage::FileSystemURL; |
28 using fileapi::FileSystemURLSet; | 28 using storage::FileSystemURLSet; |
29 | 29 |
30 namespace sync_file_system { | 30 namespace sync_file_system { |
31 | 31 |
32 namespace { | 32 namespace { |
33 const base::FilePath::CharType kDatabaseName[] = | 33 const base::FilePath::CharType kDatabaseName[] = |
34 FILE_PATH_LITERAL("LocalFileChangeTracker"); | 34 FILE_PATH_LITERAL("LocalFileChangeTracker"); |
35 const char kMark[] = "d"; | 35 const char kMark[] = "d"; |
36 } // namespace | 36 } // namespace |
37 | 37 |
38 // A database class that stores local file changes in a local database. This | 38 // A database class that stores local file changes in a local database. This |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 demoted_changes_.erase(url); | 165 demoted_changes_.erase(url); |
166 FileChangeMap::iterator found = changes_.find(url); | 166 FileChangeMap::iterator found = changes_.find(url); |
167 if (found == changes_.end()) | 167 if (found == changes_.end()) |
168 return; | 168 return; |
169 change_seqs_.erase(found->second.change_seq); | 169 change_seqs_.erase(found->second.change_seq); |
170 changes_.erase(found); | 170 changes_.erase(found); |
171 UpdateNumChanges(); | 171 UpdateNumChanges(); |
172 } | 172 } |
173 | 173 |
174 void LocalFileChangeTracker::CreateFreshMirrorForURL( | 174 void LocalFileChangeTracker::CreateFreshMirrorForURL( |
175 const fileapi::FileSystemURL& url) { | 175 const storage::FileSystemURL& url) { |
176 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 176 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
177 DCHECK(!ContainsKey(mirror_changes_, url)); | 177 DCHECK(!ContainsKey(mirror_changes_, url)); |
178 mirror_changes_[url] = ChangeInfo(); | 178 mirror_changes_[url] = ChangeInfo(); |
179 } | 179 } |
180 | 180 |
181 void LocalFileChangeTracker::RemoveMirrorAndCommitChangesForURL( | 181 void LocalFileChangeTracker::RemoveMirrorAndCommitChangesForURL( |
182 const fileapi::FileSystemURL& url) { | 182 const storage::FileSystemURL& url) { |
183 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 183 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
184 FileChangeMap::iterator found = mirror_changes_.find(url); | 184 FileChangeMap::iterator found = mirror_changes_.find(url); |
185 if (found == mirror_changes_.end()) | 185 if (found == mirror_changes_.end()) |
186 return; | 186 return; |
187 mirror_changes_.erase(found); | 187 mirror_changes_.erase(found); |
188 | 188 |
189 if (ContainsKey(changes_, url) || ContainsKey(demoted_changes_, url)) | 189 if (ContainsKey(changes_, url) || ContainsKey(demoted_changes_, url)) |
190 MarkDirtyOnDatabase(url); | 190 MarkDirtyOnDatabase(url); |
191 else | 191 else |
192 ClearDirtyOnDatabase(url); | 192 ClearDirtyOnDatabase(url); |
193 UpdateNumChanges(); | 193 UpdateNumChanges(); |
194 } | 194 } |
195 | 195 |
196 void LocalFileChangeTracker::ResetToMirrorAndCommitChangesForURL( | 196 void LocalFileChangeTracker::ResetToMirrorAndCommitChangesForURL( |
197 const fileapi::FileSystemURL& url) { | 197 const storage::FileSystemURL& url) { |
198 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 198 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
199 FileChangeMap::iterator found = mirror_changes_.find(url); | 199 FileChangeMap::iterator found = mirror_changes_.find(url); |
200 if (found == mirror_changes_.end() || found->second.change_list.empty()) { | 200 if (found == mirror_changes_.end() || found->second.change_list.empty()) { |
201 ClearChangesForURL(url); | 201 ClearChangesForURL(url); |
202 return; | 202 return; |
203 } | 203 } |
204 const ChangeInfo& info = found->second; | 204 const ChangeInfo& info = found->second; |
205 if (ContainsKey(demoted_changes_, url)) { | 205 if (ContainsKey(demoted_changes_, url)) { |
206 DCHECK(!ContainsKey(changes_, url)); | 206 DCHECK(!ContainsKey(changes_, url)); |
207 demoted_changes_[url] = info; | 207 demoted_changes_[url] = info; |
208 } else { | 208 } else { |
209 DCHECK(!ContainsKey(demoted_changes_, url)); | 209 DCHECK(!ContainsKey(demoted_changes_, url)); |
210 change_seqs_[info.change_seq] = url; | 210 change_seqs_[info.change_seq] = url; |
211 changes_[url] = info; | 211 changes_[url] = info; |
212 } | 212 } |
213 RemoveMirrorAndCommitChangesForURL(url); | 213 RemoveMirrorAndCommitChangesForURL(url); |
214 } | 214 } |
215 | 215 |
216 void LocalFileChangeTracker::DemoteChangesForURL( | 216 void LocalFileChangeTracker::DemoteChangesForURL( |
217 const fileapi::FileSystemURL& url) { | 217 const storage::FileSystemURL& url) { |
218 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 218 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
219 | 219 |
220 FileChangeMap::iterator found = changes_.find(url); | 220 FileChangeMap::iterator found = changes_.find(url); |
221 if (found == changes_.end()) | 221 if (found == changes_.end()) |
222 return; | 222 return; |
223 DCHECK(!ContainsKey(demoted_changes_, url)); | 223 DCHECK(!ContainsKey(demoted_changes_, url)); |
224 change_seqs_.erase(found->second.change_seq); | 224 change_seqs_.erase(found->second.change_seq); |
225 demoted_changes_.insert(*found); | 225 demoted_changes_.insert(*found); |
226 changes_.erase(found); | 226 changes_.erase(found); |
227 UpdateNumChanges(); | 227 UpdateNumChanges(); |
228 } | 228 } |
229 | 229 |
230 void LocalFileChangeTracker::PromoteDemotedChangesForURL( | 230 void LocalFileChangeTracker::PromoteDemotedChangesForURL( |
231 const fileapi::FileSystemURL& url) { | 231 const storage::FileSystemURL& url) { |
232 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 232 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
233 | 233 |
234 FileChangeMap::iterator iter = demoted_changes_.find(url); | 234 FileChangeMap::iterator iter = demoted_changes_.find(url); |
235 if (iter == demoted_changes_.end()) | 235 if (iter == demoted_changes_.end()) |
236 return; | 236 return; |
237 | 237 |
238 FileChangeList::List change_list = iter->second.change_list.list(); | 238 FileChangeList::List change_list = iter->second.change_list.list(); |
239 // Make sure that this URL is in no queues. | 239 // Make sure that this URL is in no queues. |
240 DCHECK(!ContainsKey(change_seqs_, iter->second.change_seq)); | 240 DCHECK(!ContainsKey(change_seqs_, iter->second.change_seq)); |
241 DCHECK(!ContainsKey(changes_, url)); | 241 DCHECK(!ContainsKey(changes_, url)); |
242 | 242 |
243 change_seqs_[iter->second.change_seq] = url; | 243 change_seqs_[iter->second.change_seq] = url; |
244 changes_.insert(*iter); | 244 changes_.insert(*iter); |
245 demoted_changes_.erase(iter); | 245 demoted_changes_.erase(iter); |
246 UpdateNumChanges(); | 246 UpdateNumChanges(); |
247 } | 247 } |
248 | 248 |
249 bool LocalFileChangeTracker::PromoteDemotedChanges() { | 249 bool LocalFileChangeTracker::PromoteDemotedChanges() { |
250 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 250 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
251 if (demoted_changes_.empty()) | 251 if (demoted_changes_.empty()) |
252 return false; | 252 return false; |
253 while (!demoted_changes_.empty()) { | 253 while (!demoted_changes_.empty()) { |
254 fileapi::FileSystemURL url = demoted_changes_.begin()->first; | 254 storage::FileSystemURL url = demoted_changes_.begin()->first; |
255 PromoteDemotedChangesForURL(url); | 255 PromoteDemotedChangesForURL(url); |
256 } | 256 } |
257 UpdateNumChanges(); | 257 UpdateNumChanges(); |
258 return true; | 258 return true; |
259 } | 259 } |
260 | 260 |
261 SyncStatusCode LocalFileChangeTracker::Initialize( | 261 SyncStatusCode LocalFileChangeTracker::Initialize( |
262 FileSystemContext* file_system_context) { | 262 FileSystemContext* file_system_context) { |
263 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 263 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
264 DCHECK(!initialized_); | 264 DCHECK(!initialized_); |
265 DCHECK(file_system_context); | 265 DCHECK(file_system_context); |
266 | 266 |
267 SyncStatusCode status = CollectLastDirtyChanges(file_system_context); | 267 SyncStatusCode status = CollectLastDirtyChanges(file_system_context); |
268 if (status == SYNC_STATUS_OK) | 268 if (status == SYNC_STATUS_OK) |
269 initialized_ = true; | 269 initialized_ = true; |
270 return status; | 270 return status; |
271 } | 271 } |
272 | 272 |
273 void LocalFileChangeTracker::ResetForFileSystem( | 273 void LocalFileChangeTracker::ResetForFileSystem(const GURL& origin, |
274 const GURL& origin, | 274 storage::FileSystemType type) { |
275 fileapi::FileSystemType type) { | |
276 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 275 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
277 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); | 276 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); |
278 for (FileChangeMap::iterator iter = changes_.begin(); | 277 for (FileChangeMap::iterator iter = changes_.begin(); |
279 iter != changes_.end();) { | 278 iter != changes_.end();) { |
280 fileapi::FileSystemURL url = iter->first; | 279 storage::FileSystemURL url = iter->first; |
281 int change_seq = iter->second.change_seq; | 280 int change_seq = iter->second.change_seq; |
282 // Advance |iter| before calling ResetForURL to avoid the iterator | 281 // Advance |iter| before calling ResetForURL to avoid the iterator |
283 // invalidation in it. | 282 // invalidation in it. |
284 ++iter; | 283 ++iter; |
285 if (url.origin() == origin && url.type() == type) | 284 if (url.origin() == origin && url.type() == type) |
286 ResetForURL(url, change_seq, batch.get()); | 285 ResetForURL(url, change_seq, batch.get()); |
287 } | 286 } |
288 | 287 |
289 for (FileChangeMap::iterator iter = demoted_changes_.begin(); | 288 for (FileChangeMap::iterator iter = demoted_changes_.begin(); |
290 iter != demoted_changes_.end();) { | 289 iter != demoted_changes_.end();) { |
291 fileapi::FileSystemURL url = iter->first; | 290 storage::FileSystemURL url = iter->first; |
292 int change_seq = iter->second.change_seq; | 291 int change_seq = iter->second.change_seq; |
293 // Advance |iter| before calling ResetForURL to avoid the iterator | 292 // Advance |iter| before calling ResetForURL to avoid the iterator |
294 // invalidation in it. | 293 // invalidation in it. |
295 ++iter; | 294 ++iter; |
296 if (url.origin() == origin && url.type() == type) | 295 if (url.origin() == origin && url.type() == type) |
297 ResetForURL(url, change_seq, batch.get()); | 296 ResetForURL(url, change_seq, batch.get()); |
298 } | 297 } |
299 | 298 |
300 // Fail to apply batch to database wouldn't have critical effect, they'll be | 299 // Fail to apply batch to database wouldn't have critical effect, they'll be |
301 // just marked deleted on next relaunch. | 300 // just marked deleted on next relaunch. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 DCHECK(file_util); | 356 DCHECK(file_util); |
358 scoped_ptr<FileSystemOperationContext> context( | 357 scoped_ptr<FileSystemOperationContext> context( |
359 new FileSystemOperationContext(file_system_context)); | 358 new FileSystemOperationContext(file_system_context)); |
360 | 359 |
361 base::File::Info file_info; | 360 base::File::Info file_info; |
362 base::FilePath platform_path; | 361 base::FilePath platform_path; |
363 | 362 |
364 while (!dirty_files.empty()) { | 363 while (!dirty_files.empty()) { |
365 const FileSystemURL url = dirty_files.front(); | 364 const FileSystemURL url = dirty_files.front(); |
366 dirty_files.pop(); | 365 dirty_files.pop(); |
367 DCHECK_EQ(url.type(), fileapi::kFileSystemTypeSyncable); | 366 DCHECK_EQ(url.type(), storage::kFileSystemTypeSyncable); |
368 | 367 |
369 switch (file_util->GetFileInfo(context.get(), url, | 368 switch (file_util->GetFileInfo(context.get(), url, |
370 &file_info, &platform_path)) { | 369 &file_info, &platform_path)) { |
371 case base::File::FILE_OK: { | 370 case base::File::FILE_OK: { |
372 if (!file_info.is_directory) { | 371 if (!file_info.is_directory) { |
373 RecordChange(url, FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, | 372 RecordChange(url, FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, |
374 SYNC_FILE_TYPE_FILE)); | 373 SYNC_FILE_TYPE_FILE)); |
375 break; | 374 break; |
376 } | 375 } |
377 | 376 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 info.change_list.Update(change); | 437 info.change_list.Update(change); |
439 if (info.change_list.empty()) { | 438 if (info.change_list.empty()) { |
440 changes->erase(url); | 439 changes->erase(url); |
441 return; | 440 return; |
442 } | 441 } |
443 info.change_seq = new_change_seq; | 442 info.change_seq = new_change_seq; |
444 if (change_seqs) | 443 if (change_seqs) |
445 (*change_seqs)[info.change_seq] = url; | 444 (*change_seqs)[info.change_seq] = url; |
446 } | 445 } |
447 | 446 |
448 void LocalFileChangeTracker::ResetForURL(const fileapi::FileSystemURL& url, | 447 void LocalFileChangeTracker::ResetForURL(const storage::FileSystemURL& url, |
449 int change_seq, | 448 int change_seq, |
450 leveldb::WriteBatch* batch) { | 449 leveldb::WriteBatch* batch) { |
451 mirror_changes_.erase(url); | 450 mirror_changes_.erase(url); |
452 demoted_changes_.erase(url); | 451 demoted_changes_.erase(url); |
453 change_seqs_.erase(change_seq); | 452 change_seqs_.erase(change_seq); |
454 changes_.erase(url); | 453 changes_.erase(url); |
455 | 454 |
456 std::string serialized_url; | 455 std::string serialized_url; |
457 if (!SerializeSyncableFileSystemURL(url, &serialized_url)) { | 456 if (!SerializeSyncableFileSystemURL(url, &serialized_url)) { |
458 NOTREACHED() << "Failed to serialize: " << url.DebugString(); | 457 NOTREACHED() << "Failed to serialize: " << url.DebugString(); |
459 return; | 458 return; |
460 } | 459 } |
461 batch->Delete(serialized_url); | 460 batch->Delete(serialized_url); |
462 } | 461 } |
463 | 462 |
464 // TrackerDB ------------------------------------------------------------------- | 463 // TrackerDB ------------------------------------------------------------------- |
465 | 464 |
466 LocalFileChangeTracker::TrackerDB::TrackerDB(const base::FilePath& base_path, | 465 LocalFileChangeTracker::TrackerDB::TrackerDB(const base::FilePath& base_path, |
467 leveldb::Env* env_override) | 466 leveldb::Env* env_override) |
468 : base_path_(base_path), | 467 : base_path_(base_path), |
469 env_override_(env_override), | 468 env_override_(env_override), |
470 db_status_(SYNC_STATUS_OK) {} | 469 db_status_(SYNC_STATUS_OK) {} |
471 | 470 |
472 SyncStatusCode LocalFileChangeTracker::TrackerDB::Init( | 471 SyncStatusCode LocalFileChangeTracker::TrackerDB::Init( |
473 RecoveryOption recovery_option) { | 472 RecoveryOption recovery_option) { |
474 if (db_.get() && db_status_ == SYNC_STATUS_OK) | 473 if (db_.get() && db_status_ == SYNC_STATUS_OK) |
475 return SYNC_STATUS_OK; | 474 return SYNC_STATUS_OK; |
476 | 475 |
477 std::string path = fileapi::FilePathToString( | 476 std::string path = |
478 base_path_.Append(kDatabaseName)); | 477 storage::FilePathToString(base_path_.Append(kDatabaseName)); |
479 leveldb::Options options; | 478 leveldb::Options options; |
480 options.max_open_files = 0; // Use minimum. | 479 options.max_open_files = 0; // Use minimum. |
481 options.create_if_missing = true; | 480 options.create_if_missing = true; |
482 if (env_override_) | 481 if (env_override_) |
483 options.env = env_override_; | 482 options.env = env_override_; |
484 leveldb::DB* db; | 483 leveldb::DB* db; |
485 leveldb::Status status = leveldb::DB::Open(options, path, &db); | 484 leveldb::Status status = leveldb::DB::Open(options, path, &db); |
486 if (status.ok()) { | 485 if (status.ok()) { |
487 db_.reset(db); | 486 db_.reset(db); |
488 return SYNC_STATUS_OK; | 487 return SYNC_STATUS_OK; |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
608 if (!status.ok() && !status.IsNotFound()) { | 607 if (!status.ok() && !status.IsNotFound()) { |
609 HandleError(FROM_HERE, status); | 608 HandleError(FROM_HERE, status); |
610 db_status_ = LevelDBStatusToSyncStatusCode(status); | 609 db_status_ = LevelDBStatusToSyncStatusCode(status); |
611 db_.reset(); | 610 db_.reset(); |
612 return db_status_; | 611 return db_status_; |
613 } | 612 } |
614 return SYNC_STATUS_OK; | 613 return SYNC_STATUS_OK; |
615 } | 614 } |
616 | 615 |
617 } // namespace sync_file_system | 616 } // namespace sync_file_system |
OLD | NEW |