Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(373)

Side by Side Diff: chrome/browser/chromeos/drive/drive_feed_processor.cc

Issue 11293247: Make DriveFeedProcessor asynchronous. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: merge conflicts + feedback Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 <utility> 5 #include <utility>
6 6
7 #include "base/metrics/histogram.h" 7 #include "base/metrics/histogram.h"
8 #include "chrome/browser/chromeos/drive/document_entry_conversion.h" 8 #include "chrome/browser/chromeos/drive/document_entry_conversion.h"
9 #include "chrome/browser/chromeos/drive/drive_feed_processor.h" 9 #include "chrome/browser/chromeos/drive/drive_feed_processor.h"
10 #include "chrome/browser/chromeos/drive/drive_files.h" 10 #include "chrome/browser/chromeos/drive/drive_files.h"
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 // Go through all entries generated by the feed and apply them to the local 94 // Go through all entries generated by the feed and apply them to the local
95 // snapshot of the file system. 95 // snapshot of the file system.
96 ApplyNextEntryProtoAsync(); 96 ApplyNextEntryProtoAsync();
97 } 97 }
98 98
99 void DriveFeedProcessor::ApplyNextEntryProtoAsync() { 99 void DriveFeedProcessor::ApplyNextEntryProtoAsync() {
100 base::MessageLoopProxy::current()->PostTask( 100 base::MessageLoopProxy::current()->PostTask(
101 FROM_HERE, 101 FROM_HERE,
102 base::Bind(&DriveFeedProcessor::ApplyNextEntryProto, 102 base::Bind(&DriveFeedProcessor::ApplyNextEntryProto,
103 weak_ptr_factory_.GetWeakPtr())); 103 weak_ptr_factory_.GetWeakPtr()));
104
105 } 104 }
106 105
107 void DriveFeedProcessor::ApplyNextEntryProto() { 106 void DriveFeedProcessor::ApplyNextEntryProto() {
108 DCHECK(!on_complete_callback_.is_null()); 107 DCHECK(!on_complete_callback_.is_null());
109 108
110 if (entry_proto_map_.empty()) { 109 if (entry_proto_map_.empty()) {
111 // All entries have been processed. 110 // All entries have been processed.
112 on_complete_callback_.Run(); 111 on_complete_callback_.Run();
113 return; 112 return;
114 } 113 }
(...skipping 17 matching lines...) Expand all
132 weak_ptr_factory_.GetWeakPtr(), 131 weak_ptr_factory_.GetWeakPtr(),
133 parent_it)); 132 parent_it));
134 } else { 133 } else {
135 // Erase the entry so the deleted entry won't be referenced. 134 // Erase the entry so the deleted entry won't be referenced.
136 entry_proto_map_.erase(it); 135 entry_proto_map_.erase(it);
137 ApplyEntryProto(entry_proto); 136 ApplyEntryProto(entry_proto);
138 } 137 }
139 } 138 }
140 139
141 void DriveFeedProcessor::ApplyEntryProto(const DriveEntryProto& entry_proto) { 140 void DriveFeedProcessor::ApplyEntryProto(const DriveEntryProto& entry_proto) {
142 scoped_ptr<DriveEntry> entry = 141 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
143 resource_metadata_->CreateDriveEntryFromProto(entry_proto);
144 DCHECK(entry.get());
145 DriveEntry* old_entry =
146 resource_metadata_->GetEntryByResourceId(entry->resource_id());
147 142
148 if (entry->is_deleted()) { 143 // Lookup the entry.
149 // Deleted file/directory. 144 resource_metadata_->GetEntryInfoByResourceId(
150 DVLOG(1) << "Removing file " << entry->base_name(); 145 entry_proto.resource_id(),
151 if (old_entry) 146 base::Bind(&DriveFeedProcessor::ContinueApplyEntryProto,
152 RemoveEntryFromParent(old_entry); 147 weak_ptr_factory_.GetWeakPtr(),
153 } else if (old_entry) { 148 entry_proto));
154 // Change or move of existing entry. 149 }
155 // Please note that entry rename is just a special case of change here
156 // since name is just one of the properties that can change.
157 DVLOG(1) << "Changed file " << entry->base_name();
158 150
159 // Move children files over if we are dealing with directories. 151 void DriveFeedProcessor::ContinueApplyEntryProto(
160 if (old_entry->AsDriveDirectory() && entry->AsDriveDirectory()) { 152 const DriveEntryProto& entry_proto,
161 entry->AsDriveDirectory()->TakeOverEntries( 153 DriveFileError error,
162 old_entry->AsDriveDirectory()); 154 const FilePath& file_path,
155 scoped_ptr<DriveEntryProto> old_entry_proto) {
156 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
157
158 if (error == DRIVE_FILE_OK) {
159 if (entry_proto.deleted()) {
160 // Deleted file/directory.
161 RemoveEntryFromParent(entry_proto, file_path);
162 } else {
163 // Entry exists and needs to be refreshed.
164 RefreshEntryProto(entry_proto, file_path);
163 } 165 }
166 } else if (error == DRIVE_FILE_ERROR_NOT_FOUND && !entry_proto.deleted()) {
167 // Adding a new entry.
168 AddEntryToParent(entry_proto);
169 } else {
170 // Continue.
171 ApplyNextEntryProtoAsync();
172 }
173 }
164 174
165 // Remove the old instance of this entry. 175 void DriveFeedProcessor::RefreshEntryProto(const DriveEntryProto& entry_proto,
166 RemoveEntryFromParent(old_entry); 176 const FilePath& file_path) {
177 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
167 178
168 // Add to parent. 179 resource_metadata_->RefreshEntryProto(
169 AddEntryToParent(entry.release()); 180 entry_proto,
170 } else { 181 base::Bind(&DriveFeedProcessor::NotifyForRefreshEntryProto,
171 // Adding a new file. 182 weak_ptr_factory_.GetWeakPtr(),
172 AddEntryToParent(entry.release()); 183 file_path));
184 }
185
186 void DriveFeedProcessor::NotifyForRefreshEntryProto(
187 const FilePath& old_file_path,
188 DriveFileError error,
189 const FilePath& file_path,
190 scoped_ptr<DriveEntryProto> entry_proto) {
191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
192
193 DVLOG(1) << "NotifyForRefreshEntryProto " << file_path.value();
194 if (error == DRIVE_FILE_OK) {
195 // Notify old parent.
196 changed_dirs_.insert(old_file_path.DirName());
197
198 // Notify new parent.
199 changed_dirs_.insert(file_path.DirName());
200
201 // Notify self if entry is a directory.
202 if (entry_proto->file_info().is_directory()) {
203 // Notify new self.
204 changed_dirs_.insert(file_path);
205 // Notify old self.
206 changed_dirs_.insert(old_file_path);
207 }
173 } 208 }
174 209
175 // Process the next DriveEntryProto from the map.
176 ApplyNextEntryProtoAsync(); 210 ApplyNextEntryProtoAsync();
177 } 211 }
178 212
179 void DriveFeedProcessor::AddEntryToParent( 213 void DriveFeedProcessor::AddEntryToParent(const DriveEntryProto& entry_proto) {
180 DriveEntry* entry) { 214 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
215
216 resource_metadata_->AddEntryToParent(entry_proto,
217 base::Bind(&DriveFeedProcessor::NotifyForAddEntryToParent,
218 weak_ptr_factory_.GetWeakPtr(),
219 entry_proto.file_info().is_directory()));
220 }
221
222 void DriveFeedProcessor::NotifyForAddEntryToParent(bool is_directory,
223 DriveFileError error,
224 const FilePath& file_path) {
225 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
226
227 DVLOG(1) << "NotifyForAddEntryToParent " << file_path.value();
228 if (error == DRIVE_FILE_OK) {
229 // Notify if a directory has been created.
230 if (is_directory)
231 changed_dirs_.insert(file_path);
232
233 // Notify parent.
234 changed_dirs_.insert(file_path.DirName());
235 }
236
237 ApplyNextEntryProtoAsync();
238 }
239
240
241 void DriveFeedProcessor::RemoveEntryFromParent(
242 const DriveEntryProto& entry_proto,
243 const FilePath& file_path) {
244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
245 DCHECK(!file_path.empty());
246
247 if (!entry_proto.file_info().is_directory()) {
248 // No children if entry is a file.
249 OnGetChildrenForRemove(entry_proto,
250 file_path,
251 std::set<FilePath>());
252 } else {
253 // If entry is a directory, notify its children.
254 resource_metadata_->GetChildDirectories(
255 entry_proto.resource_id(),
256 base::Bind(&DriveFeedProcessor::OnGetChildrenForRemove,
257 weak_ptr_factory_.GetWeakPtr(),
258 entry_proto,
259 file_path));
260 }
261 }
262
263 void DriveFeedProcessor::OnGetChildrenForRemove(
264 const DriveEntryProto& entry_proto,
265 const FilePath& file_path,
266 const std::set<FilePath>& changed_directories) {
267 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
268 DCHECK(!file_path.empty());
269
270 resource_metadata_->RemoveEntryFromParent(
271 entry_proto.resource_id(),
272 base::Bind(&DriveFeedProcessor::NotifyForRemoveEntryFromParent,
273 weak_ptr_factory_.GetWeakPtr(),
274 entry_proto.file_info().is_directory(),
275 file_path,
276 changed_directories));
277 }
278
279 void DriveFeedProcessor::NotifyForRemoveEntryFromParent(
280 bool is_directory,
281 const FilePath& file_path,
282 const std::set<FilePath>& changed_directories,
283 DriveFileError error,
284 const FilePath& parent_path) {
285 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
286
287 DVLOG(1) << "NotifyForRemoveEntryFromParent " << file_path.value();
288 if (error == DRIVE_FILE_OK) {
289 // Notify parent.
290 changed_dirs_.insert(parent_path);
291
292 // Notify children, if any.
293 changed_dirs_.insert(changed_directories.begin(),
294 changed_directories.end());
295
296 // If entry is a directory, notify self.
297 if (is_directory)
298 changed_dirs_.insert(file_path);
299 }
300
301 // Continue.
302 ApplyNextEntryProtoAsync();
303 }
304
305 void DriveFeedProcessor::AddEntryToParentDeprecated(DriveEntry* entry) {
181 DriveDirectory* parent = ResolveParent(entry); 306 DriveDirectory* parent = ResolveParent(entry);
182 307
183 if (!parent) { // Orphan. 308 if (!parent) { // Orphan.
184 delete entry; 309 delete entry;
185 return; 310 return;
186 } 311 }
187 parent->AddEntry(entry); 312 parent->AddEntry(entry);
188 313
189 // Notify this directory that has been created. 314 // Notify this directory that has been created.
190 if (entry->AsDriveDirectory()) 315 if (entry->AsDriveDirectory())
191 changed_dirs_.insert(entry->GetFilePath()); 316 changed_dirs_.insert(entry->GetFilePath());
192 317
193 // Notify |parent| only if it already exists by checking if it is attached to 318 // Notify |parent| only if it already exists by checking if it is attached to
194 // the tree (has parent) or if it is root. The parent of |parent| may not 319 // the tree (has parent) or if it is root. The parent of |parent| may not
195 // exist here if it is about to be created later in the same feed. 320 // exist here if it is about to be created later in the same feed.
196 if (parent->parent() || parent == resource_metadata_->root()) 321 if (parent->parent() || parent == resource_metadata_->root())
197 changed_dirs_.insert(parent->GetFilePath()); 322 changed_dirs_.insert(parent->GetFilePath());
198 } 323 }
199 324
200 void DriveFeedProcessor::RemoveEntryFromParent( 325 void DriveFeedProcessor::RemoveEntryFromParent(DriveEntry* entry) {
201 DriveEntry* entry) {
202 DriveDirectory* parent = entry->parent(); 326 DriveDirectory* parent = entry->parent();
203 if (!parent) { 327 if (!parent) {
204 NOTREACHED(); 328 NOTREACHED();
205 return; 329 return;
206 } 330 }
207 331
208 DriveDirectory* dir = entry->AsDriveDirectory(); 332 DriveDirectory* dir = entry->AsDriveDirectory();
209 if (dir) { 333 // Notify all children of entry, if entry is a directory.
210 // We need to notify all children of entry if entry is a directory. 334 if (dir)
211 dir->GetChildDirectoryPaths(&changed_dirs_); 335 dir->GetChildDirectoryPaths(&changed_dirs_);
212 // Besides children, notify this removed directory too.
213 changed_dirs_.insert(dir->GetFilePath());
214 }
215 336
216 parent->RemoveEntry(entry); 337 parent->RemoveEntry(entry);
217 338
218 // Notify parent. 339 // Notify parent.
219 changed_dirs_.insert(parent->GetFilePath()); 340 changed_dirs_.insert(parent->GetFilePath());
220 } 341 }
221 342
222 DriveDirectory* DriveFeedProcessor::ResolveParent( 343 DriveDirectory* DriveFeedProcessor::ResolveParent(DriveEntry* new_entry) {
223 DriveEntry* new_entry) {
224 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 344 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
225 345
226 const std::string& parent_resource_id = new_entry->parent_resource_id(); 346 const std::string& parent_resource_id = new_entry->parent_resource_id();
227 if (parent_resource_id.empty()) { 347 if (parent_resource_id.empty()) {
228 DVLOG(1) << "Root parent for " << new_entry->base_name(); 348 DVLOG(1) << "Root parent for " << new_entry->base_name();
229 return resource_metadata_->root(); 349 return resource_metadata_->root();
230 } 350 }
231 351
232 DriveEntry* parent = 352 DriveEntry* parent =
233 resource_metadata_->GetEntryByResourceId(parent_resource_id); 353 resource_metadata_->GetEntryByResourceId(parent_resource_id);
(...skipping 26 matching lines...) Expand all
260 } 380 }
261 381
262 for (size_t j = 0; j < feed->entries().size(); ++j) { 382 for (size_t j = 0; j < feed->entries().size(); ++j) {
263 const google_apis::DocumentEntry* doc = feed->entries()[j]; 383 const google_apis::DocumentEntry* doc = feed->entries()[j];
264 DriveEntryProto entry_proto = ConvertDocumentEntryToDriveEntryProto(*doc); 384 DriveEntryProto entry_proto = ConvertDocumentEntryToDriveEntryProto(*doc);
265 // Some document entries don't map into files (i.e. sites). 385 // Some document entries don't map into files (i.e. sites).
266 if (entry_proto.resource_id().empty()) 386 if (entry_proto.resource_id().empty())
267 continue; 387 continue;
268 388
269 // Count the number of files. 389 // Count the number of files.
270 if (uma_stats && entry_proto.has_file_specific_info()) { 390 if (uma_stats && !entry_proto.file_info().is_directory()) {
271 uma_stats->IncrementNumFiles( 391 uma_stats->IncrementNumFiles(
272 entry_proto.file_specific_info().is_hosted_document()); 392 entry_proto.file_specific_info().is_hosted_document());
273 } 393 }
274 394
275 std::pair<DriveEntryProtoMap::iterator, bool> ret = entry_proto_map_. 395 std::pair<DriveEntryProtoMap::iterator, bool> ret = entry_proto_map_.
276 insert(std::make_pair(entry_proto.resource_id(), entry_proto)); 396 insert(std::make_pair(entry_proto.resource_id(), entry_proto));
277 DCHECK(ret.second); 397 DCHECK(ret.second);
278 if (!ret.second) 398 if (!ret.second)
279 LOG(WARNING) << "Found duplicate file " << entry_proto.base_name(); 399 LOG(WARNING) << "Found duplicate file " << entry_proto.base_name();
280 } 400 }
281 } 401 }
282 } 402 }
283 403
284 void DriveFeedProcessor::Clear() { 404 void DriveFeedProcessor::Clear() {
285 entry_proto_map_.clear(); 405 entry_proto_map_.clear();
286 changed_dirs_.clear(); 406 changed_dirs_.clear();
287 on_complete_callback_.Reset(); 407 on_complete_callback_.Reset();
288 } 408 }
289 409
290 } // namespace drive 410 } // namespace drive
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/drive/drive_feed_processor.h ('k') | chrome/browser/chromeos/drive/drive_resource_metadata.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698