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

Side by Side Diff: chrome/browser/chromeos/gdata/gdata_wapi_feed_processor.cc

Issue 10829118: gdata: Move GDataWapiFeedParser to a set of new files (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix clang build for sure... Created 8 years, 4 months 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
« no previous file with comments | « chrome/browser/chromeos/gdata/gdata_wapi_feed_processor.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "base/metrics/histogram.h"
6 #include "chrome/browser/chromeos/gdata/gdata_files.h"
7 #include "chrome/browser/chromeos/gdata/gdata_wapi_feed_processor.h"
8 #include "content/public/browser/browser_thread.h"
9
10 using content::BrowserThread;
11
12 namespace gdata {
13
14 namespace {
15
16 // Recursively extracts the paths set of all sub-directories of |entry|.
17 void GetChildDirectoryPaths(GDataEntry* entry,
18 std::set<FilePath>* changed_dirs) {
19 GDataDirectory* dir = entry->AsGDataDirectory();
20 if (!dir)
21 return;
22
23 for (GDataDirectoryCollection::const_iterator it =
24 dir->child_directories().begin();
25 it != dir->child_directories().end(); ++it) {
26 GDataDirectory* child_dir = it->second;
27 changed_dirs->insert(child_dir->GetFilePath());
28 GetChildDirectoryPaths(child_dir, changed_dirs);
29 }
30 }
31
32 } // namespace
33
34 FeedToFileResourceMapUmaStats::FeedToFileResourceMapUmaStats()
35 : num_regular_files(0),
36 num_hosted_documents(0) {
37 }
38
39 FeedToFileResourceMapUmaStats::~FeedToFileResourceMapUmaStats() {
40 }
41
42 GDataWapiFeedProcessor::GDataWapiFeedProcessor(
43 GDataDirectoryService* directory_service)
44 : directory_service_(directory_service) {
45 }
46
47 GDataWapiFeedProcessor::~GDataWapiFeedProcessor() {
48 }
49
50 GDataFileError GDataWapiFeedProcessor::ApplyFeeds(
51 const std::vector<DocumentFeed*>& feed_list,
52 int start_changestamp,
53 int root_feed_changestamp,
54 std::set<FilePath>* changed_dirs) {
55 bool is_delta_feed = start_changestamp != 0;
56
57 directory_service_->set_origin(FROM_SERVER);
58
59 int delta_feed_changestamp = 0;
60 FeedToFileResourceMapUmaStats uma_stats;
61 FileResourceIdMap file_map;
62 GDataFileError error = FeedToFileResourceMap(feed_list,
63 &file_map,
64 &delta_feed_changestamp,
65 &uma_stats);
66 if (error != GDATA_FILE_OK)
67 return error;
68
69 ApplyFeedFromFileUrlMap(
70 is_delta_feed,
71 is_delta_feed ? delta_feed_changestamp : root_feed_changestamp,
72 &file_map,
73 changed_dirs);
74
75 // Shouldn't record histograms when processing delta feeds.
76 if (!is_delta_feed)
77 UpdateFileCountUmaHistograms(uma_stats);
78
79 return GDATA_FILE_OK;
80 }
81
82 void GDataWapiFeedProcessor::UpdateFileCountUmaHistograms(
83 const FeedToFileResourceMapUmaStats& uma_stats) const {
84 const int num_total_files =
85 uma_stats.num_hosted_documents + uma_stats.num_regular_files;
86 UMA_HISTOGRAM_COUNTS("GData.NumberOfRegularFiles",
87 uma_stats.num_regular_files);
88 UMA_HISTOGRAM_COUNTS("GData.NumberOfHostedDocuments",
89 uma_stats.num_hosted_documents);
90 UMA_HISTOGRAM_COUNTS("GData.NumberOfTotalFiles", num_total_files);
91 const std::vector<int> all_entry_kinds = DocumentEntry::GetAllEntryKinds();
92 for (FeedToFileResourceMapUmaStats::EntryKindToCountMap::const_iterator iter =
93 uma_stats.num_files_with_entry_kind.begin();
94 iter != uma_stats.num_files_with_entry_kind.end();
95 ++iter) {
96 const DocumentEntry::EntryKind kind = iter->first;
97 const int count = iter->second;
98 for (int i = 0; i < count; ++i) {
99 UMA_HISTOGRAM_CUSTOM_ENUMERATION(
100 "GData.EntryKind", kind, all_entry_kinds);
101 }
102 }
103 }
104
105 void GDataWapiFeedProcessor::ApplyFeedFromFileUrlMap(
106 bool is_delta_feed,
107 int feed_changestamp,
108 FileResourceIdMap* file_map,
109 std::set<FilePath>* changed_dirs) {
110 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
111 DCHECK(changed_dirs);
112
113 if (!is_delta_feed) { // Full update.
114 directory_service_->root()->RemoveChildren();
115 changed_dirs->insert(directory_service_->root()->GetFilePath());
116 }
117 directory_service_->set_largest_changestamp(feed_changestamp);
118
119 scoped_ptr<GDataDirectoryService> orphaned_dir_service(
120 new GDataDirectoryService);
121 // Go through all entries generated by the feed and apply them to the local
122 // snapshot of the file system.
123 for (FileResourceIdMap::iterator it = file_map->begin();
124 it != file_map->end();) {
125 // Ensure that the entry is deleted, unless the ownership is explicitly
126 // transferred by entry.release().
127 scoped_ptr<GDataEntry> entry(it->second);
128 DCHECK_EQ(it->first, entry->resource_id());
129 // Erase the entry so the deleted entry won't be referenced.
130 file_map->erase(it++);
131
132 GDataEntry* old_entry =
133 directory_service_->GetEntryByResourceId(entry->resource_id());
134 GDataDirectory* dest_dir = NULL;
135 if (entry->is_deleted()) { // Deleted file/directory.
136 DVLOG(1) << "Removing file " << entry->base_name();
137 if (!old_entry)
138 continue;
139
140 dest_dir = old_entry->parent();
141 if (!dest_dir) {
142 NOTREACHED();
143 continue;
144 }
145 RemoveEntryFromDirectoryAndCollectChangedDirectories(
146 dest_dir, old_entry, changed_dirs);
147 } else if (old_entry) { // Change or move of existing entry.
148 // Please note that entry rename is just a special case of change here
149 // since name is just one of the properties that can change.
150 DVLOG(1) << "Changed file " << entry->base_name();
151 dest_dir = old_entry->parent();
152 if (!dest_dir) {
153 NOTREACHED();
154 continue;
155 }
156 // Move children files over if we are dealing with directories.
157 if (old_entry->AsGDataDirectory() && entry->AsGDataDirectory()) {
158 entry->AsGDataDirectory()->TakeOverEntries(
159 old_entry->AsGDataDirectory());
160 }
161 // Remove the old instance of this entry.
162 RemoveEntryFromDirectoryAndCollectChangedDirectories(
163 dest_dir, old_entry, changed_dirs);
164 // Did we actually move the new file to another directory?
165 if (dest_dir->resource_id() != entry->parent_resource_id()) {
166 changed_dirs->insert(dest_dir->GetFilePath());
167 dest_dir = FindDirectoryForNewEntry(entry.get(),
168 *file_map,
169 orphaned_dir_service.get());
170 }
171 DCHECK(dest_dir);
172 AddEntryToDirectoryAndCollectChangedDirectories(
173 entry.release(),
174 dest_dir,
175 orphaned_dir_service.get(),
176 changed_dirs);
177 } else { // Adding a new file.
178 dest_dir = FindDirectoryForNewEntry(entry.get(),
179 *file_map,
180 orphaned_dir_service.get());
181 DCHECK(dest_dir);
182 AddEntryToDirectoryAndCollectChangedDirectories(
183 entry.release(),
184 dest_dir,
185 orphaned_dir_service.get(),
186 changed_dirs);
187 }
188
189 // Record changed directory if this was a delta feed and the parent
190 // directory is already properly rooted within its parent.
191 if (dest_dir && (dest_dir->parent() ||
192 dest_dir == directory_service_->root()) &&
193 dest_dir != orphaned_dir_service->root() && is_delta_feed) {
194 changed_dirs->insert(dest_dir->GetFilePath());
195 }
196 }
197 // All entry must be erased from the map.
198 DCHECK(file_map->empty());
199 }
200
201 // static
202 void GDataWapiFeedProcessor::AddEntryToDirectoryAndCollectChangedDirectories(
203 GDataEntry* entry,
204 GDataDirectory* directory,
205 GDataDirectoryService* orphaned_dir_service,
206 std::set<FilePath>* changed_dirs) {
207 directory->AddEntry(entry);
208 if (entry->AsGDataDirectory() && directory != orphaned_dir_service->root())
209 changed_dirs->insert(entry->GetFilePath());
210 }
211
212 // static
213 void GDataWapiFeedProcessor::
214 RemoveEntryFromDirectoryAndCollectChangedDirectories(
215 GDataDirectory* directory,
216 GDataEntry* entry,
217 std::set<FilePath>* changed_dirs) {
218 // Get the list of all sub-directory paths, so we can notify their listeners
219 // that they are smoked.
220 GetChildDirectoryPaths(entry, changed_dirs);
221 directory->RemoveEntry(entry);
222 }
223
224 GDataDirectory* GDataWapiFeedProcessor::FindDirectoryForNewEntry(
225 GDataEntry* new_entry,
226 const FileResourceIdMap& file_map,
227 GDataDirectoryService* orphaned_dir_service) {
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
229 GDataDirectory* dir = NULL;
230 // Added file.
231 const std::string& parent_id = new_entry->parent_resource_id();
232 if (parent_id.empty()) {
233 dir = directory_service_->root();
234 DVLOG(1) << "Root parent for " << new_entry->base_name();
235 } else {
236 GDataEntry* entry = directory_service_->GetEntryByResourceId(parent_id);
237 dir = entry ? entry->AsGDataDirectory() : NULL;
238 if (!dir) {
239 // The parent directory was also added with this set of feeds.
240 FileResourceIdMap::const_iterator find_iter =
241 file_map.find(parent_id);
242 dir = (find_iter != file_map.end() &&
243 find_iter->second) ?
244 find_iter->second->AsGDataDirectory() : NULL;
245 if (dir) {
246 DVLOG(1) << "Found parent for " << new_entry->base_name()
247 << " in file_map " << parent_id;
248 } else {
249 DVLOG(1) << "Adding orphan " << new_entry->GetFilePath().value();
250 dir = orphaned_dir_service->root();
251 }
252 }
253 }
254 return dir;
255 }
256
257 GDataFileError GDataWapiFeedProcessor::FeedToFileResourceMap(
258 const std::vector<DocumentFeed*>& feed_list,
259 FileResourceIdMap* file_map,
260 int* feed_changestamp,
261 FeedToFileResourceMapUmaStats* uma_stats) {
262 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
263 DCHECK(uma_stats);
264
265 GDataFileError error = GDATA_FILE_OK;
266 uma_stats->num_regular_files = 0;
267 uma_stats->num_hosted_documents = 0;
268 uma_stats->num_files_with_entry_kind.clear();
269 for (size_t i = 0; i < feed_list.size(); ++i) {
270 const DocumentFeed* feed = feed_list[i];
271
272 // Get upload url from the root feed. Links for all other collections will
273 // be handled in GDatadirectory::FromDocumentEntry();
274 if (i == 0) {
275 const Link* root_feed_upload_link =
276 feed->GetLinkByType(Link::RESUMABLE_CREATE_MEDIA);
277 if (root_feed_upload_link)
278 directory_service_->root()->set_upload_url(
279 root_feed_upload_link->href());
280 *feed_changestamp = feed->largest_changestamp();
281 DCHECK_GE(*feed_changestamp, 0);
282 }
283
284 for (ScopedVector<DocumentEntry>::const_iterator iter =
285 feed->entries().begin();
286 iter != feed->entries().end(); ++iter) {
287 DocumentEntry* doc = *iter;
288 GDataEntry* entry = GDataEntry::FromDocumentEntry(
289 NULL, doc, directory_service_);
290 // Some document entries don't map into files (i.e. sites).
291 if (!entry)
292 continue;
293 // Count the number of files.
294 GDataFile* as_file = entry->AsGDataFile();
295 if (as_file) {
296 if (as_file->is_hosted_document())
297 ++uma_stats->num_hosted_documents;
298 else
299 ++uma_stats->num_regular_files;
300 ++uma_stats->num_files_with_entry_kind[as_file->kind()];
301 }
302
303 FileResourceIdMap::iterator map_entry =
304 file_map->find(entry->resource_id());
305
306 // An entry with the same self link may already exist, so we need to
307 // release the existing GDataEntry instance before overwriting the
308 // entry with another GDataEntry instance.
309 if (map_entry != file_map->end()) {
310 LOG(WARNING) << "Found duplicate file "
311 << map_entry->second->base_name();
312
313 delete map_entry->second;
314 file_map->erase(map_entry);
315 }
316 file_map->insert(
317 std::pair<std::string, GDataEntry*>(entry->resource_id(), entry));
318 }
319 }
320
321 if (error != GDATA_FILE_OK) {
322 // If the code above fails to parse a feed, any GDataEntry instance
323 // added to |file_by_url| is not managed by a GDataDirectory instance,
324 // so we need to explicitly release them here.
325 STLDeleteValues(file_map);
326 }
327
328 return error;
329 }
330
331 } // namespace gdata
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/gdata/gdata_wapi_feed_processor.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698