summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormukai@chromium.org <mukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-02 17:16:34 +0000
committermukai@chromium.org <mukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-02 17:16:34 +0000
commitd4c7bdc5e8864e1383d05ad3c4bf9ec9aaf9b0d4 (patch)
tree9aadd5805cf59a3c07d72af5685470a558c1e349
parentbf4adf79297bc1d3c55bfa0d72b9c082e724c7a2 (diff)
downloadchromium_src-d4c7bdc5e8864e1383d05ad3c4bf9ec9aaf9b0d4.zip
chromium_src-d4c7bdc5e8864e1383d05ad3c4bf9ec9aaf9b0d4.tar.gz
chromium_src-d4c7bdc5e8864e1383d05ad3c4bf9ec9aaf9b0d4.tar.bz2
Prevent duplicated runs of initialization of root directory.
BUG=chromium-os:28761 TEST=manually + unittest passed locally Review URL: https://chromiumcodereview.appspot.com/9963047 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@130153 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/chromeos/gdata/gdata_file_system.cc66
-rw-r--r--chrome/browser/chromeos/gdata/gdata_file_system.h4
-rw-r--r--chrome/browser/chromeos/gdata/gdata_file_system_unittest.cc34
-rw-r--r--chrome/browser/chromeos/gdata/gdata_files.cc4
-rw-r--r--chrome/browser/chromeos/gdata/gdata_files.h4
5 files changed, 108 insertions, 4 deletions
diff --git a/chrome/browser/chromeos/gdata/gdata_file_system.cc b/chrome/browser/chromeos/gdata/gdata_file_system.cc
index ef69992..35cb99e 100644
--- a/chrome/browser/chromeos/gdata/gdata_file_system.cc
+++ b/chrome/browser/chromeos/gdata/gdata_file_system.cc
@@ -343,6 +343,26 @@ void RunGetCacheStateCallbackHelper(
callback.Run(*error, *cache_state);
}
+// The class to wait for the initial load of root feed and runs the callback
+// after the initialization.
+class InitialLoadObserver : public GDataFileSystemInterface::Observer {
+ public:
+ InitialLoadObserver(GDataFileSystemInterface* file_system,
+ const base::Closure& callback)
+ : file_system_(file_system), callback_(callback) {}
+
+ virtual void OnInitialLoadFinished() OVERRIDE {
+ if (!callback_.is_null())
+ base::MessageLoopProxy::current()->PostTask(FROM_HERE, callback_);
+ file_system_->RemoveObserver(this);
+ base::MessageLoopProxy::current()->DeleteSoon(FROM_HERE, this);
+ }
+
+ private:
+ GDataFileSystemInterface* file_system_;
+ base::Closure callback_;
+};
+
} // namespace
// FindFileDelegate class implementation.
@@ -573,9 +593,21 @@ void GDataFileSystem::FindFileByPathAsync(
const FilePath& search_file_path,
const FindFileCallback& callback) {
base::AutoLock lock(lock_);
- if (root_->origin() == UNINITIALIZED) {
+ if (root_->origin() == INITIALIZING) {
+ // If root feed is not initialized but the initilization process has
+ // already started, add an observer to execute the remaining task after
+ // the end of the initialization.
+ AddObserver(new InitialLoadObserver(
+ this,
+ base::Bind(&GDataFileSystem::FindFileByPathOnCallingThread,
+ GetWeakPtrForCurrentThread(),
+ search_file_path,
+ callback)));
+ return;
+ } else if (root_->origin() == UNINITIALIZED) {
// Load root feed from this disk cache. Upon completion, kick off server
// fetching.
+ root_->set_origin(INITIALIZING);
LoadRootFeedFromCache(FEED_CHUNK_INITIAL,
search_file_path,
true, // should_load_from_server
@@ -584,6 +616,7 @@ void GDataFileSystem::FindFileByPathAsync(
} else if (root_->NeedsRefresh()) {
// If content is stale or from disk from cache, fetch content from
// the server.
+ root_->set_origin(REFRESHING);
LoadFeedFromServer(search_file_path, callback);
return;
}
@@ -1778,7 +1811,7 @@ void GDataFileSystem::OnGetDocuments(
bool initial_read = false;
{
base::AutoLock lock(lock_);
- initial_read = root_->origin() == UNINITIALIZED;
+ initial_read = root_->origin() == INITIALIZING;
}
bool has_more_data = current_feed->GetNextFeedURL(&next_feed_url) &&
@@ -1912,6 +1945,8 @@ void GDataFileSystem::OnLoadRootFeed(
// If the first chunk was ok, get the rest of the feed from disk cache if
// we haven't fetched content from the server in the meantime.
if (*error == base::PLATFORM_FILE_OK) {
+ base::AutoLock lock(lock_);
+ root_->set_origin(REFRESHING);
LoadRootFeedFromCache(FEED_CHUNK_REST,
search_file_path,
false, // should_load_from_server
@@ -1921,6 +1956,12 @@ void GDataFileSystem::OnLoadRootFeed(
if (!should_load_from_server)
return;
+ {
+ base::AutoLock lock(lock_);
+ if (root_->origin() != INITIALIZING)
+ root_->set_origin(REFRESHING);
+ }
+
// Kick of the retreival of the feed from server. If we have previously
// |reported| to the original callback, then we just need to refresh the
// content without continuing search upon operation completion.
@@ -2273,7 +2314,8 @@ base::PlatformFileError GDataFileSystem::UpdateDirectoryWithDocumentFeed(
base::AutoLock lock(lock_);
// Don't send directory content change notification while performing
// the initial content retreival.
- bool should_nofify = root_->origin() != UNINITIALIZED;
+ bool should_notify_directory_changed = root_->origin() != INITIALIZING;
+ bool should_notify_initial_load = root_->origin() == INITIALIZING;
root_->set_origin(origin);
root_->set_refresh_time(base::Time::Now());
@@ -2374,8 +2416,10 @@ base::PlatformFileError GDataFileSystem::UpdateDirectoryWithDocumentFeed(
dir->AddFile(file.release());
}
- if (should_nofify)
+ if (should_notify_directory_changed)
NotifyDirectoryChanged(root_->GetFilePath());
+ if (should_notify_initial_load)
+ NotifyInitialLoadFinished();
return base::PLATFORM_FILE_OK;
}
@@ -2447,6 +2491,20 @@ void GDataFileSystem::NotifyDirectoryChanged(const FilePath& directory_path) {
FOR_EACH_OBSERVER(Observer, observers_, OnDirectoryChanged(directory_path));
}
+void GDataFileSystem::NotifyInitialLoadFinished() {
+ DVLOG(1) << "Initial load finished";
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&GDataFileSystem::NotifyInitialLoadFinished, ui_weak_ptr_));
+ return;
+ }
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ // Notify the observers that root directory has been initialized.
+ FOR_EACH_OBSERVER(Observer, observers_, OnInitialLoadFinished());
+}
+
base::PlatformFileError GDataFileSystem::AddNewDirectory(
const FilePath& directory_path, base::Value* entry_value) {
if (!entry_value)
diff --git a/chrome/browser/chromeos/gdata/gdata_file_system.h b/chrome/browser/chromeos/gdata/gdata_file_system.h
index 3c32924..c97c702 100644
--- a/chrome/browser/chromeos/gdata/gdata_file_system.h
+++ b/chrome/browser/chromeos/gdata/gdata_file_system.h
@@ -162,6 +162,9 @@ class GDataFileSystemInterface {
// changed directory.
virtual void OnDirectoryChanged(const FilePath& directory_path) {}
+ // Triggered when the file system is initially loaded.
+ virtual void OnInitialLoadFinished() {}
+
protected:
virtual ~Observer() {}
};
@@ -867,6 +870,7 @@ class GDataFileSystem : public GDataFileSystemInterface {
void NotifyFileUnpinned(const std::string& resource_id,
const std::string& md5);
void NotifyDirectoryChanged(const FilePath& directory_path);
+ void NotifyInitialLoadFinished();
// Helper function that completes bookkeeping tasks related to
// completed file transfer.
diff --git a/chrome/browser/chromeos/gdata/gdata_file_system_unittest.cc b/chrome/browser/chromeos/gdata/gdata_file_system_unittest.cc
index d0a1229..3d33680 100644
--- a/chrome/browser/chromeos/gdata/gdata_file_system_unittest.cc
+++ b/chrome/browser/chromeos/gdata/gdata_file_system_unittest.cc
@@ -895,6 +895,40 @@ class MockFindFileDelegate : public gdata::FindFileDelegate {
GDataFileBase*));
};
+void AsyncInitializationCallback(int* counter,
+ int expected_counter,
+ const FilePath& expected_file_path,
+ MessageLoop* message_loop,
+ base::PlatformFileError error,
+ const FilePath& directory_path,
+ GDataFileBase* file) {
+ LOG(INFO) << "here";
+ ASSERT_EQ(base::PLATFORM_FILE_OK, error);
+ EXPECT_EQ(expected_file_path, directory_path);
+ EXPECT_FALSE(file == NULL);
+
+ (*counter)++;
+ if (*counter >= expected_counter)
+ message_loop->Quit();
+}
+
+TEST_F(GDataFileSystemTest, DuplicatedAsyncInitialization) {
+ int counter = 0;
+ FindFileCallback callback = base::Bind(
+ &AsyncInitializationCallback,
+ &counter,
+ 2,
+ FilePath(FILE_PATH_LITERAL("gdata")),
+ &message_loop_);
+
+ file_system_->FindFileByPathAsync(
+ FilePath(FILE_PATH_LITERAL("gdata")), callback);
+ file_system_->FindFileByPathAsync(
+ FilePath(FILE_PATH_LITERAL("gdata")), callback);
+ message_loop_.Run(); // Wait to get our result
+ EXPECT_EQ(2, counter);
+}
+
TEST_F(GDataFileSystemTest, SearchRootDirectory) {
MockFindFileDelegate mock_find_file_delegate;
EXPECT_CALL(mock_find_file_delegate,
diff --git a/chrome/browser/chromeos/gdata/gdata_files.cc b/chrome/browser/chromeos/gdata/gdata_files.cc
index b416128a..2b80b5c 100644
--- a/chrome/browser/chromeos/gdata/gdata_files.cc
+++ b/chrome/browser/chromeos/gdata/gdata_files.cc
@@ -249,6 +249,10 @@ void GDataDirectory::RemoveChildren() {
}
bool GDataDirectory::NeedsRefresh() const {
+ // Already refreshing by someone else.
+ if (origin_ == REFRESHING)
+ return false;
+
// Refresh is needed for content read from disk cache or stale content.
if (origin_ == FROM_CACHE)
return true;
diff --git a/chrome/browser/chromeos/gdata/gdata_files.h b/chrome/browser/chromeos/gdata/gdata_files.h
index f37e8eb..5a5329b 100644
--- a/chrome/browser/chromeos/gdata/gdata_files.h
+++ b/chrome/browser/chromeos/gdata/gdata_files.h
@@ -36,6 +36,10 @@ typedef base::Callback<void(base::PlatformFileError error,
// Directory content origin.
enum ContentOrigin {
UNINITIALIZED,
+ // Directory content is currently loading from somewhere. needs to wait.
+ INITIALIZING,
+ // Directory content is initialized, but during refreshing.
+ REFRESHING,
// Directory content is initialized from disk cache.
FROM_CACHE,
// Directory content is initialized from the direct server response.