summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/sync_file_system/local/local_file_change_tracker.cc48
-rw-r--r--chrome/browser/sync_file_system/local/local_file_change_tracker.h9
-rw-r--r--chrome/browser/sync_file_system/local/local_file_change_tracker_unittest.cc58
3 files changed, 104 insertions, 11 deletions
diff --git a/chrome/browser/sync_file_system/local/local_file_change_tracker.cc b/chrome/browser/sync_file_system/local/local_file_change_tracker.cc
index 3b42634..0f6f186 100644
--- a/chrome/browser/sync_file_system/local/local_file_change_tracker.cc
+++ b/chrome/browser/sync_file_system/local/local_file_change_tracker.cc
@@ -13,6 +13,7 @@
#include "chrome/browser/sync_file_system/local/local_file_sync_status.h"
#include "chrome/browser/sync_file_system/syncable_file_system_util.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h"
+#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
#include "webkit/browser/fileapi/file_system_context.h"
#include "webkit/browser/fileapi/file_system_file_util.h"
#include "webkit/browser/fileapi/file_system_operation_context.h"
@@ -42,6 +43,7 @@ class LocalFileChangeTracker::TrackerDB {
SyncStatusCode ClearDirty(const std::string& url);
SyncStatusCode GetDirtyEntries(
std::queue<FileSystemURL>* dirty_files);
+ SyncStatusCode WriteBatch(scoped_ptr<leveldb::WriteBatch> batch);
private:
enum RecoveryOption {
@@ -205,6 +207,37 @@ SyncStatusCode LocalFileChangeTracker::Initialize(
return status;
}
+void LocalFileChangeTracker::ResetForFileSystem(
+ const GURL& origin,
+ fileapi::FileSystemType type) {
+ DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
+ scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
+ for (FileChangeMap::iterator iter = changes_.begin();
+ iter != changes_.end();) {
+ fileapi::FileSystemURL url = iter->first;
+ if (url.origin() != origin || url.type() != type) {
+ ++iter;
+ continue;
+ }
+ mirror_changes_.erase(url);
+ change_seqs_.erase(iter->second.change_seq);
+ changes_.erase(iter++);
+
+ std::string serialized_url;
+ const bool should_success =
+ SerializeSyncableFileSystemURL(url, &serialized_url);
+ if (!should_success) {
+ NOTREACHED() << "Failed to serialize: " << url.DebugString();
+ continue;
+ }
+ batch->Delete(serialized_url);
+ }
+ // Fail to apply batch to database wouldn't have critical effect, they'll be
+ // just marked deleted on next relaunch.
+ tracker_db_->WriteBatch(batch.Pass());
+ UpdateNumChanges();
+}
+
void LocalFileChangeTracker::UpdateNumChanges() {
base::AutoLock lock(num_changes_lock_);
num_changes_ = static_cast<int64>(change_seqs_.size());
@@ -471,4 +504,19 @@ SyncStatusCode LocalFileChangeTracker::TrackerDB::GetDirtyEntries(
return SYNC_STATUS_OK;
}
+SyncStatusCode LocalFileChangeTracker::TrackerDB::WriteBatch(
+ scoped_ptr<leveldb::WriteBatch> batch) {
+ if (db_status_ != SYNC_STATUS_OK)
+ return db_status_;
+
+ leveldb::Status status = db_->Write(leveldb::WriteOptions(), batch.get());
+ if (!status.ok() && !status.IsNotFound()) {
+ HandleError(FROM_HERE, status);
+ db_status_ = LevelDBStatusToSyncStatusCode(status);
+ db_.reset();
+ return db_status_;
+ }
+ return SYNC_STATUS_OK;
+}
+
} // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/local/local_file_change_tracker.h b/chrome/browser/sync_file_system/local/local_file_change_tracker.h
index 456a489..9fafc7d 100644
--- a/chrome/browser/sync_file_system/local/local_file_change_tracker.h
+++ b/chrome/browser/sync_file_system/local/local_file_change_tracker.h
@@ -90,14 +90,17 @@ class LocalFileChangeTracker
// left after the last shutdown (if any).
SyncStatusCode Initialize(fileapi::FileSystemContext* file_system_context);
+ // Resets all the changes recorded for the given |origin| and |type|.
+ // TODO(kinuko,nhiroki): Ideally this should be automatically called in
+ // DeleteFileSystem via QuotaUtil::DeleteOriginDataOnFileThread.
+ void ResetForFileSystem(const GURL& origin, fileapi::FileSystemType type);
+
// This method is (exceptionally) thread-safe.
int64 num_changes() const {
base::AutoLock lock(num_changes_lock_);
return num_changes_;
}
- void UpdateNumChanges();
-
private:
class TrackerDB;
friend class CannedSyncableFileSystem;
@@ -118,6 +121,8 @@ class LocalFileChangeTracker
FileChangeMap;
typedef std::map<int64, fileapi::FileSystemURL> ChangeSeqMap;
+ void UpdateNumChanges();
+
// This does mostly same as calling GetNextChangedURLs with max_url=0
// except that it returns urls in set rather than in deque.
// Used only in testings.
diff --git a/chrome/browser/sync_file_system/local/local_file_change_tracker_unittest.cc b/chrome/browser/sync_file_system/local/local_file_change_tracker_unittest.cc
index 6c5f3b6..4125d97 100644
--- a/chrome/browser/sync_file_system/local/local_file_change_tracker_unittest.cc
+++ b/chrome/browser/sync_file_system/local/local_file_change_tracker_unittest.cc
@@ -101,6 +101,10 @@ class LocalFileChangeTrackerTest : public testing::Test {
change_tracker()->CollectLastDirtyChanges(file_system_context());
}
+ void GetAllChangedURLs(fileapi::FileSystemURLSet* urls) {
+ change_tracker()->GetAllChangedURLs(urls);
+ }
+
ScopedEnableSyncFSDirectoryOperation enable_directory_operation_;
base::MessageLoop message_loop_;
CannedSyncableFileSystem file_system_;
@@ -566,8 +570,6 @@ TEST_F(LocalFileChangeTrackerTest, NextChangedURLsWithRecursiveCopy) {
TEST_F(LocalFileChangeTrackerTest, NextChangedURLsWithRecursiveRemove) {
EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_.OpenFileSystem());
- FileSystemURLSet urls;
-
const char kPath0[] = "dir a";
const char kPath1[] = "dir a/file1";
const char kPath2[] = "dir a/file2";
@@ -582,8 +584,8 @@ TEST_F(LocalFileChangeTrackerTest, NextChangedURLsWithRecursiveRemove) {
EXPECT_EQ(base::PLATFORM_FILE_OK,
file_system_.Remove(URL(kPath0), true /* recursive */));
- std::deque<FileSystemURL> urls_to_process;
- change_tracker()->GetNextChangedURLs(&urls_to_process, 0);
+ FileSystemURLSet urls;
+ GetAllChangedURLs(&urls);
// This is actually not really desirable, but since the directory
// creation and deletion have been offset now we only have two
@@ -595,13 +597,51 @@ TEST_F(LocalFileChangeTrackerTest, NextChangedURLsWithRecursiveRemove) {
// TODO(kinuko): For micro optimization we could probably restore the ADD
// change type (other than ADD_OR_UPDATE) and offset file ADD+DELETE
// changes too.
- ASSERT_EQ(2U, urls_to_process.size());
+ ASSERT_EQ(2U, urls.size());
// The exact order of recursive removal cannot be determined.
- EXPECT_TRUE(URL(kPath1) == urls_to_process[0] ||
- URL(kPath2) == urls_to_process[0]);
- EXPECT_TRUE(URL(kPath1) == urls_to_process[1] ||
- URL(kPath2) == urls_to_process[1]);
+ EXPECT_TRUE(ContainsKey(urls, URL(kPath1)));
+ EXPECT_TRUE(ContainsKey(urls, URL(kPath2)));
+}
+
+TEST_F(LocalFileChangeTrackerTest, ResetForFileSystem) {
+ EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_.OpenFileSystem());
+
+ const char kPath0[] = "dir a";
+ const char kPath1[] = "dir a/file";
+ const char kPath2[] = "dir a/subdir";
+ const char kPath3[] = "dir b";
+
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ file_system_.CreateDirectory(URL(kPath0)));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ file_system_.CreateFile(URL(kPath1)));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ file_system_.CreateDirectory(URL(kPath2)));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ file_system_.CreateDirectory(URL(kPath3)));
+
+ FileSystemURLSet urls;
+ GetAllChangedURLs(&urls);
+ EXPECT_EQ(4u, urls.size());
+ EXPECT_TRUE(ContainsKey(urls, URL(kPath0)));
+ EXPECT_TRUE(ContainsKey(urls, URL(kPath1)));
+ EXPECT_TRUE(ContainsKey(urls, URL(kPath2)));
+ EXPECT_TRUE(ContainsKey(urls, URL(kPath3)));
+
+ // Reset all changes for the file system.
+ change_tracker()->ResetForFileSystem(
+ file_system_.origin(), file_system_.type());
+
+ GetAllChangedURLs(&urls);
+ EXPECT_TRUE(urls.empty());
+
+ // Make sure they're gone from the database too.
+ DropChangesInTracker();
+ RestoreChangesFromTrackerDB();
+
+ GetAllChangedURLs(&urls);
+ EXPECT_TRUE(urls.empty());
}
} // namespace sync_file_system