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

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

Issue 265833003: drive: Stop checking free disk space in ResourceMetadata::Initialize (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix typo Created 6 years, 7 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
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 "chrome/browser/chromeos/drive/resource_metadata.h" 5 #include "chrome/browser/chromeos/drive/resource_metadata.h"
6 6
7 #include "base/guid.h" 7 #include "base/guid.h"
8 #include "base/rand_util.h" 8 #include "base/rand_util.h"
9 #include "base/strings/string_number_conversions.h" 9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/stringprintf.h" 10 #include "base/strings/stringprintf.h"
(...skipping 20 matching lines...) Expand all
31 // Returns a file name with a uniquifier appended. (e.g. "File (1).txt") 31 // Returns a file name with a uniquifier appended. (e.g. "File (1).txt")
32 std::string GetUniquifiedName(const std::string& name, int uniquifier) { 32 std::string GetUniquifiedName(const std::string& name, int uniquifier) {
33 base::FilePath name_path = base::FilePath::FromUTF8Unsafe(name); 33 base::FilePath name_path = base::FilePath::FromUTF8Unsafe(name);
34 name_path = name_path.InsertBeforeExtension( 34 name_path = name_path.InsertBeforeExtension(
35 base::StringPrintf(" (%d)", uniquifier)); 35 base::StringPrintf(" (%d)", uniquifier));
36 return name_path.AsUTF8Unsafe(); 36 return name_path.AsUTF8Unsafe();
37 } 37 }
38 38
39 // Returns true when there is no entry with the specified name under the parent 39 // Returns true when there is no entry with the specified name under the parent
40 // other than the specified entry. 40 // other than the specified entry.
41 bool EntryCanUseName(ResourceMetadataStorage* storage, 41 FileError EntryCanUseName(ResourceMetadataStorage* storage,
42 const std::string& parent_local_id, 42 const std::string& parent_local_id,
43 const std::string& local_id, 43 const std::string& local_id,
44 const std::string& base_name) { 44 const std::string& base_name,
45 const std::string existing_entry_id = storage->GetChild(parent_local_id, 45 bool* result) {
46 base_name); 46 std::string existing_entry_id;
47 return existing_entry_id.empty() || existing_entry_id == local_id; 47 FileError error = storage->GetChild(parent_local_id, base_name,
48 &existing_entry_id);
49 if (error == FILE_ERROR_OK)
50 *result = existing_entry_id == local_id;
51 else if (error == FILE_ERROR_NOT_FOUND)
52 *result = true;
53 else
54 return error;
55 return FILE_ERROR_OK;
48 } 56 }
49 57
50 } // namespace 58 } // namespace
51 59
52 ResourceMetadata::ResourceMetadata( 60 ResourceMetadata::ResourceMetadata(
53 ResourceMetadataStorage* storage, 61 ResourceMetadataStorage* storage,
54 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) 62 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner)
55 : blocking_task_runner_(blocking_task_runner), 63 : blocking_task_runner_(blocking_task_runner),
56 storage_(storage) { 64 storage_(storage) {
57 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 65 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
58 } 66 }
59 67
60 FileError ResourceMetadata::Initialize() { 68 FileError ResourceMetadata::Initialize() {
61 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); 69 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
62 70 return SetUpDefaultEntries();
63 if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
64 return FILE_ERROR_NO_LOCAL_SPACE;
65
66 if (!SetUpDefaultEntries())
67 return FILE_ERROR_FAILED;
68
69 return FILE_ERROR_OK;
70 } 71 }
71 72
72 void ResourceMetadata::Destroy() { 73 void ResourceMetadata::Destroy() {
73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 74 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
74 75
75 blocking_task_runner_->PostTask( 76 blocking_task_runner_->PostTask(
76 FROM_HERE, 77 FROM_HERE,
77 base::Bind(&ResourceMetadata::DestroyOnBlockingPool, 78 base::Bind(&ResourceMetadata::DestroyOnBlockingPool,
78 base::Unretained(this))); 79 base::Unretained(this)));
79 } 80 }
80 81
81 FileError ResourceMetadata::Reset() { 82 FileError ResourceMetadata::Reset() {
82 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); 83 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
83 84
84 if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path())) 85 if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
85 return FILE_ERROR_NO_LOCAL_SPACE; 86 return FILE_ERROR_NO_LOCAL_SPACE;
86 87
87 if (!storage_->SetLargestChangestamp(0)) 88 FileError error = storage_->SetLargestChangestamp(0);
88 return FILE_ERROR_FAILED; 89 if (error != FILE_ERROR_OK)
90 return error;
89 91
90 // Remove all root entries. 92 // Remove all root entries.
91 scoped_ptr<Iterator> it = GetIterator(); 93 scoped_ptr<Iterator> it = GetIterator();
92 for (; !it->IsAtEnd(); it->Advance()) { 94 for (; !it->IsAtEnd(); it->Advance()) {
93 if (it->GetValue().parent_local_id().empty()) { 95 if (it->GetValue().parent_local_id().empty()) {
94 if (!RemoveEntryRecursively(it->GetID())) 96 error = RemoveEntryRecursively(it->GetID());
95 return FILE_ERROR_FAILED; 97 if (error != FILE_ERROR_OK)
98 return error;
96 } 99 }
97 } 100 }
98 if (it->HasError()) 101 if (it->HasError())
99 return FILE_ERROR_FAILED; 102 return FILE_ERROR_FAILED;
100 103
101 if (!SetUpDefaultEntries()) 104 return SetUpDefaultEntries();
102 return FILE_ERROR_FAILED;
103
104 return FILE_ERROR_OK;
105 } 105 }
106 106
107 ResourceMetadata::~ResourceMetadata() { 107 ResourceMetadata::~ResourceMetadata() {
108 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); 108 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
109 } 109 }
110 110
111 bool ResourceMetadata::SetUpDefaultEntries() { 111 FileError ResourceMetadata::SetUpDefaultEntries() {
112 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); 112 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
113 113
114 // Initialize "/drive", "/drive/other", "drive/trash" and "drive/root". 114 // Initialize "/drive".
115 ResourceEntry entry; 115 ResourceEntry entry;
116 if (!storage_->GetEntry(util::kDriveGrandRootLocalId, &entry)) { 116 FileError error = storage_->GetEntry(util::kDriveGrandRootLocalId, &entry);
117 if (error == FILE_ERROR_NOT_FOUND) {
117 ResourceEntry root; 118 ResourceEntry root;
118 root.mutable_file_info()->set_is_directory(true); 119 root.mutable_file_info()->set_is_directory(true);
119 root.set_local_id(util::kDriveGrandRootLocalId); 120 root.set_local_id(util::kDriveGrandRootLocalId);
120 root.set_title(util::kDriveGrandRootDirName); 121 root.set_title(util::kDriveGrandRootDirName);
121 root.set_base_name(util::kDriveGrandRootDirName); 122 root.set_base_name(util::kDriveGrandRootDirName);
122 if (!storage_->PutEntry(root)) 123 error = storage_->PutEntry(root);
123 return false; 124 if (error != FILE_ERROR_OK)
124 } else if (!entry.resource_id().empty()) { 125 return error;
125 // Old implementations used kDriveGrandRootLocalId as a resource ID. 126 } else if (error == FILE_ERROR_OK) {
126 entry.clear_resource_id(); 127 if (!entry.resource_id().empty()) {
127 if (!storage_->PutEntry(entry)) 128 // Old implementations used kDriveGrandRootLocalId as a resource ID.
128 return false; 129 entry.clear_resource_id();
130 error = storage_->PutEntry(entry);
131 if (error != FILE_ERROR_OK)
132 return error;
133 }
134 } else {
135 return error;
129 } 136 }
130 if (!storage_->GetEntry(util::kDriveOtherDirLocalId, &entry)) { 137
138 // Initialize "/drive/other".
139 error = storage_->GetEntry(util::kDriveOtherDirLocalId, &entry);
140 if (error == FILE_ERROR_NOT_FOUND) {
131 ResourceEntry other_dir; 141 ResourceEntry other_dir;
132 other_dir.mutable_file_info()->set_is_directory(true); 142 other_dir.mutable_file_info()->set_is_directory(true);
133 other_dir.set_local_id(util::kDriveOtherDirLocalId); 143 other_dir.set_local_id(util::kDriveOtherDirLocalId);
134 other_dir.set_parent_local_id(util::kDriveGrandRootLocalId); 144 other_dir.set_parent_local_id(util::kDriveGrandRootLocalId);
135 other_dir.set_title(util::kDriveOtherDirName); 145 other_dir.set_title(util::kDriveOtherDirName);
136 if (!PutEntryUnderDirectory(other_dir)) 146 error = PutEntryUnderDirectory(other_dir);
137 return false; 147 if (error != FILE_ERROR_OK)
138 } else if (!entry.resource_id().empty()) { 148 return error;
139 // Old implementations used kDriveOtherDirLocalId as a resource ID. 149 } else if (error == FILE_ERROR_OK) {
140 entry.clear_resource_id(); 150 if (!entry.resource_id().empty()) {
141 if (!storage_->PutEntry(entry)) 151 // Old implementations used kDriveOtherDirLocalId as a resource ID.
142 return false; 152 entry.clear_resource_id();
153 error = storage_->PutEntry(entry);
154 if (error != FILE_ERROR_OK)
155 return error;
156 }
157 } else {
158 return error;
143 } 159 }
144 if (!storage_->GetEntry(util::kDriveTrashDirLocalId, &entry)) { 160
161 // Initialize "drive/trash".
162 error = storage_->GetEntry(util::kDriveTrashDirLocalId, &entry);
163 if (error == FILE_ERROR_NOT_FOUND) {
145 ResourceEntry trash_dir; 164 ResourceEntry trash_dir;
146 trash_dir.mutable_file_info()->set_is_directory(true); 165 trash_dir.mutable_file_info()->set_is_directory(true);
147 trash_dir.set_local_id(util::kDriveTrashDirLocalId); 166 trash_dir.set_local_id(util::kDriveTrashDirLocalId);
148 trash_dir.set_parent_local_id(util::kDriveGrandRootLocalId); 167 trash_dir.set_parent_local_id(util::kDriveGrandRootLocalId);
149 trash_dir.set_title(util::kDriveTrashDirName); 168 trash_dir.set_title(util::kDriveTrashDirName);
150 if (!PutEntryUnderDirectory(trash_dir)) 169 error = PutEntryUnderDirectory(trash_dir);
151 return false; 170 if (error != FILE_ERROR_OK)
171 return error;
172 } else if (error != FILE_ERROR_OK) {
173 return error;
152 } 174 }
153 if (storage_->GetChild(util::kDriveGrandRootLocalId, 175
154 util::kDriveMyDriveRootDirName).empty()) { 176 // Initialize "drive/root".
177 std::string child_id;
178 error = storage_->GetChild(
179 util::kDriveGrandRootLocalId, util::kDriveMyDriveRootDirName, &child_id);
180 if (error == FILE_ERROR_NOT_FOUND) {
155 ResourceEntry mydrive; 181 ResourceEntry mydrive;
156 mydrive.mutable_file_info()->set_is_directory(true); 182 mydrive.mutable_file_info()->set_is_directory(true);
157 mydrive.set_parent_local_id(util::kDriveGrandRootLocalId); 183 mydrive.set_parent_local_id(util::kDriveGrandRootLocalId);
158 mydrive.set_title(util::kDriveMyDriveRootDirName); 184 mydrive.set_title(util::kDriveMyDriveRootDirName);
159 185
160 std::string local_id; 186 std::string local_id;
161 if (AddEntry(mydrive, &local_id) != FILE_ERROR_OK) 187 error = AddEntry(mydrive, &local_id);
162 return false; 188 if (error != FILE_ERROR_OK)
189 return error;
190 } else if (error != FILE_ERROR_OK) {
191 return error;
163 } 192 }
164 return true; 193 return FILE_ERROR_OK;
165 } 194 }
166 195
167 void ResourceMetadata::DestroyOnBlockingPool() { 196 void ResourceMetadata::DestroyOnBlockingPool() {
168 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); 197 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
169 delete this; 198 delete this;
170 } 199 }
171 200
172 int64 ResourceMetadata::GetLargestChangestamp() { 201 int64 ResourceMetadata::GetLargestChangestamp() {
173 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); 202 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
174 return storage_->GetLargestChangestamp(); 203 int64 value = 0;
204 storage_->GetLargestChangestamp(&value);
205 return value;
175 } 206 }
176 207
177 FileError ResourceMetadata::SetLargestChangestamp(int64 value) { 208 FileError ResourceMetadata::SetLargestChangestamp(int64 value) {
178 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); 209 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
179 210
180 if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path())) 211 if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
181 return FILE_ERROR_NO_LOCAL_SPACE; 212 return FILE_ERROR_NO_LOCAL_SPACE;
182 213
183 return storage_->SetLargestChangestamp(value) ? 214 return storage_->SetLargestChangestamp(value);
184 FILE_ERROR_OK : FILE_ERROR_FAILED;
185 } 215 }
186 216
187 FileError ResourceMetadata::AddEntry(const ResourceEntry& entry, 217 FileError ResourceMetadata::AddEntry(const ResourceEntry& entry,
188 std::string* out_id) { 218 std::string* out_id) {
189 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); 219 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
190 DCHECK(entry.local_id().empty()); 220 DCHECK(entry.local_id().empty());
191 221
192 if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path())) 222 if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
193 return FILE_ERROR_NO_LOCAL_SPACE; 223 return FILE_ERROR_NO_LOCAL_SPACE;
194 224
195 ResourceEntry parent; 225 ResourceEntry parent;
196 if (!storage_->GetEntry(entry.parent_local_id(), &parent) || 226 FileError error = storage_->GetEntry(entry.parent_local_id(), &parent);
197 !parent.file_info().is_directory()) 227 if (error != FILE_ERROR_OK)
198 return FILE_ERROR_NOT_FOUND; 228 return error;
229 if (!parent.file_info().is_directory())
230 return FILE_ERROR_NOT_A_DIRECTORY;
199 231
200 // Multiple entries with the same resource ID should not be present. 232 // Multiple entries with the same resource ID should not be present.
201 std::string local_id; 233 std::string local_id;
202 ResourceEntry existing_entry; 234 ResourceEntry existing_entry;
203 if (!entry.resource_id().empty() && 235 if (!entry.resource_id().empty()) {
204 storage_->GetIdByResourceId(entry.resource_id(), &local_id) && 236 error = storage_->GetIdByResourceId(entry.resource_id(), &local_id);
205 storage_->GetEntry(local_id, &existing_entry)) 237 if (error == FILE_ERROR_OK)
206 return FILE_ERROR_EXISTS; 238 error = storage_->GetEntry(local_id, &existing_entry);
239
240 if (error == FILE_ERROR_OK)
241 return FILE_ERROR_EXISTS;
242 else if (error != FILE_ERROR_NOT_FOUND)
243 return error;
244 }
207 245
208 // Generate unique local ID when needed. 246 // Generate unique local ID when needed.
209 while (local_id.empty() || storage_->GetEntry(local_id, &existing_entry)) 247 // We don't check for ID collisions as its probability is extremely low.
248 if (local_id.empty())
210 local_id = base::GenerateGUID(); 249 local_id = base::GenerateGUID();
211 250
212 ResourceEntry new_entry(entry); 251 ResourceEntry new_entry(entry);
213 new_entry.set_local_id(local_id); 252 new_entry.set_local_id(local_id);
214 253
215 if (!PutEntryUnderDirectory(new_entry)) 254 error = PutEntryUnderDirectory(new_entry);
216 return FILE_ERROR_FAILED; 255 if (error != FILE_ERROR_OK)
256 return error;
217 257
218 *out_id = local_id; 258 *out_id = local_id;
219 return FILE_ERROR_OK; 259 return FILE_ERROR_OK;
220 } 260 }
221 261
222 FileError ResourceMetadata::RemoveEntry(const std::string& id) { 262 FileError ResourceMetadata::RemoveEntry(const std::string& id) {
223 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); 263 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
224 264
225 if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path())) 265 if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
226 return FILE_ERROR_NO_LOCAL_SPACE; 266 return FILE_ERROR_NO_LOCAL_SPACE;
227 267
228 // Disallow deletion of default entries. 268 // Disallow deletion of default entries.
229 if (id == util::kDriveGrandRootLocalId || 269 if (id == util::kDriveGrandRootLocalId ||
230 id == util::kDriveOtherDirLocalId || 270 id == util::kDriveOtherDirLocalId ||
231 id == util::kDriveTrashDirLocalId) 271 id == util::kDriveTrashDirLocalId)
232 return FILE_ERROR_ACCESS_DENIED; 272 return FILE_ERROR_ACCESS_DENIED;
233 273
234 ResourceEntry entry; 274 ResourceEntry entry;
235 if (!storage_->GetEntry(id, &entry)) 275 FileError error = storage_->GetEntry(id, &entry);
236 return FILE_ERROR_NOT_FOUND; 276 if (error != FILE_ERROR_OK)
277 return error;
237 278
238 if (!RemoveEntryRecursively(id)) 279 return RemoveEntryRecursively(id);
239 return FILE_ERROR_FAILED;
240 return FILE_ERROR_OK;
241 } 280 }
242 281
243 FileError ResourceMetadata::GetResourceEntryById(const std::string& id, 282 FileError ResourceMetadata::GetResourceEntryById(const std::string& id,
244 ResourceEntry* out_entry) { 283 ResourceEntry* out_entry) {
245 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); 284 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
246 DCHECK(!id.empty()); 285 DCHECK(!id.empty());
247 DCHECK(out_entry); 286 DCHECK(out_entry);
248 287
249 return storage_->GetEntry(id, out_entry) ? 288 return storage_->GetEntry(id, out_entry);
250 FILE_ERROR_OK : FILE_ERROR_NOT_FOUND;
251 } 289 }
252 290
253 FileError ResourceMetadata::GetResourceEntryByPath(const base::FilePath& path, 291 FileError ResourceMetadata::GetResourceEntryByPath(const base::FilePath& path,
254 ResourceEntry* out_entry) { 292 ResourceEntry* out_entry) {
255 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); 293 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
256 DCHECK(out_entry); 294 DCHECK(out_entry);
257 295
258 std::string id; 296 std::string id;
259 FileError error = GetIdByPath(path, &id); 297 FileError error = GetIdByPath(path, &id);
260 if (error != FILE_ERROR_OK) 298 if (error != FILE_ERROR_OK)
(...skipping 23 matching lines...) Expand all
284 322
285 ResourceEntry entry; 323 ResourceEntry entry;
286 FileError error = GetResourceEntryById(id, &entry); 324 FileError error = GetResourceEntryById(id, &entry);
287 if (error != FILE_ERROR_OK) 325 if (error != FILE_ERROR_OK)
288 return error; 326 return error;
289 327
290 if (!entry.file_info().is_directory()) 328 if (!entry.file_info().is_directory())
291 return FILE_ERROR_NOT_A_DIRECTORY; 329 return FILE_ERROR_NOT_A_DIRECTORY;
292 330
293 std::vector<std::string> children; 331 std::vector<std::string> children;
294 storage_->GetChildren(id, &children); 332 error = storage_->GetChildren(id, &children);
333 if (error != FILE_ERROR_OK)
334 return error;
295 335
296 ResourceEntryVector entries(children.size()); 336 ResourceEntryVector entries(children.size());
297 for (size_t i = 0; i < children.size(); ++i) { 337 for (size_t i = 0; i < children.size(); ++i) {
298 if (!storage_->GetEntry(children[i], &entries[i])) 338 error = storage_->GetEntry(children[i], &entries[i]);
299 return FILE_ERROR_FAILED; 339 if (error != FILE_ERROR_OK)
340 return error;
300 } 341 }
301 out_entries->swap(entries); 342 out_entries->swap(entries);
302 return FILE_ERROR_OK; 343 return FILE_ERROR_OK;
303 } 344 }
304 345
305 FileError ResourceMetadata::RefreshEntry(const ResourceEntry& entry) { 346 FileError ResourceMetadata::RefreshEntry(const ResourceEntry& entry) {
306 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); 347 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
307 348
308 if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path())) 349 if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
309 return FILE_ERROR_NO_LOCAL_SPACE; 350 return FILE_ERROR_NO_LOCAL_SPACE;
310 351
311 ResourceEntry old_entry; 352 ResourceEntry old_entry;
312 if (!storage_->GetEntry(entry.local_id(), &old_entry)) 353 FileError error = storage_->GetEntry(entry.local_id(), &old_entry);
313 return FILE_ERROR_NOT_FOUND; 354 if (error != FILE_ERROR_OK)
355 return error;
314 356
315 if (old_entry.parent_local_id().empty() || // Reject root. 357 if (old_entry.parent_local_id().empty() || // Reject root.
316 old_entry.file_info().is_directory() != // Reject incompatible input. 358 old_entry.file_info().is_directory() != // Reject incompatible input.
317 entry.file_info().is_directory()) 359 entry.file_info().is_directory())
318 return FILE_ERROR_INVALID_OPERATION; 360 return FILE_ERROR_INVALID_OPERATION;
319 361
320 if (!entry.resource_id().empty()) { 362 if (!entry.resource_id().empty()) {
321 // Multiple entries cannot share the same resource ID. 363 // Multiple entries cannot share the same resource ID.
322 std::string local_id; 364 std::string local_id;
323 FileError error = GetIdByResourceId(entry.resource_id(), &local_id); 365 FileError error = GetIdByResourceId(entry.resource_id(), &local_id);
324 switch (error) { 366 switch (error) {
325 case FILE_ERROR_OK: 367 case FILE_ERROR_OK:
326 if (local_id != entry.local_id()) 368 if (local_id != entry.local_id())
327 return FILE_ERROR_INVALID_OPERATION; 369 return FILE_ERROR_INVALID_OPERATION;
328 break; 370 break;
329 371
330 case FILE_ERROR_NOT_FOUND: 372 case FILE_ERROR_NOT_FOUND:
331 break; 373 break;
332 374
333 default: 375 default:
334 return error; 376 return error;
335 } 377 }
336 } 378 }
337 379
338 // Make sure that the new parent exists and it is a directory. 380 // Make sure that the new parent exists and it is a directory.
339 ResourceEntry new_parent; 381 ResourceEntry new_parent;
340 if (!storage_->GetEntry(entry.parent_local_id(), &new_parent)) 382 error = storage_->GetEntry(entry.parent_local_id(), &new_parent);
341 return FILE_ERROR_NOT_FOUND; 383 if (error != FILE_ERROR_OK)
384 return error;
342 385
343 if (!new_parent.file_info().is_directory()) 386 if (!new_parent.file_info().is_directory())
344 return FILE_ERROR_NOT_A_DIRECTORY; 387 return FILE_ERROR_NOT_A_DIRECTORY;
345 388
346 // Remove from the old parent and add it to the new parent with the new data. 389 // Remove from the old parent and add it to the new parent with the new data.
347 if (!PutEntryUnderDirectory(entry)) 390 return PutEntryUnderDirectory(entry);
348 return FILE_ERROR_FAILED;
349 return FILE_ERROR_OK;
350 } 391 }
351 392
352 void ResourceMetadata::GetSubDirectoriesRecursively( 393 void ResourceMetadata::GetSubDirectoriesRecursively(
353 const std::string& id, 394 const std::string& id,
354 std::set<base::FilePath>* sub_directories) { 395 std::set<base::FilePath>* sub_directories) {
355 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); 396 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
356 397
357 std::vector<std::string> children; 398 std::vector<std::string> children;
358 storage_->GetChildren(id, &children); 399 if (storage_->GetChildren(id, &children) != FILE_ERROR_OK)
400 return;
359 for (size_t i = 0; i < children.size(); ++i) { 401 for (size_t i = 0; i < children.size(); ++i) {
360 ResourceEntry entry; 402 ResourceEntry entry;
361 if (storage_->GetEntry(children[i], &entry) && 403 if (storage_->GetEntry(children[i], &entry) != FILE_ERROR_OK)
362 entry.file_info().is_directory()) { 404 return;
405 if (entry.file_info().is_directory()) {
363 sub_directories->insert(GetFilePath(children[i])); 406 sub_directories->insert(GetFilePath(children[i]));
364 GetSubDirectoriesRecursively(children[i], sub_directories); 407 GetSubDirectoriesRecursively(children[i], sub_directories);
365 } 408 }
366 } 409 }
367 } 410 }
368 411
369 std::string ResourceMetadata::GetChildId(const std::string& parent_local_id, 412 std::string ResourceMetadata::GetChildId(const std::string& parent_local_id,
370 const std::string& base_name) { 413 const std::string& base_name) {
371 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); 414 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
372 return storage_->GetChild(parent_local_id, base_name); 415 std::string child_local_id;
416 storage_->GetChild(parent_local_id, base_name, &child_local_id);
417 return child_local_id;
373 } 418 }
374 419
375 scoped_ptr<ResourceMetadata::Iterator> ResourceMetadata::GetIterator() { 420 scoped_ptr<ResourceMetadata::Iterator> ResourceMetadata::GetIterator() {
376 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); 421 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
377 422
378 return storage_->GetIterator(); 423 return storage_->GetIterator();
379 } 424 }
380 425
381 base::FilePath ResourceMetadata::GetFilePath(const std::string& id) { 426 base::FilePath ResourceMetadata::GetFilePath(const std::string& id) {
382 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); 427 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
383 428
384 base::FilePath path; 429 base::FilePath path;
385 ResourceEntry entry; 430 ResourceEntry entry;
386 if (storage_->GetEntry(id, &entry)) { 431 if (storage_->GetEntry(id, &entry) == FILE_ERROR_OK) {
387 if (!entry.parent_local_id().empty()) { 432 if (!entry.parent_local_id().empty()) {
388 path = GetFilePath(entry.parent_local_id()); 433 path = GetFilePath(entry.parent_local_id());
389 } else if (entry.local_id() != util::kDriveGrandRootLocalId) { 434 } else if (entry.local_id() != util::kDriveGrandRootLocalId) {
390 DVLOG(1) << "Entries not under the grand root don't have paths."; 435 DVLOG(1) << "Entries not under the grand root don't have paths.";
391 return base::FilePath(); 436 return base::FilePath();
392 } 437 }
393 path = path.Append(base::FilePath::FromUTF8Unsafe(entry.base_name())); 438 path = path.Append(base::FilePath::FromUTF8Unsafe(entry.base_name()));
394 } 439 }
395 return path; 440 return path;
396 } 441 }
397 442
398 FileError ResourceMetadata::GetIdByPath(const base::FilePath& file_path, 443 FileError ResourceMetadata::GetIdByPath(const base::FilePath& file_path,
399 std::string* out_id) { 444 std::string* out_id) {
400 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); 445 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
401 446
402 // Start from the root. 447 // Start from the root.
403 std::vector<base::FilePath::StringType> components; 448 std::vector<base::FilePath::StringType> components;
404 file_path.GetComponents(&components); 449 file_path.GetComponents(&components);
405 if (components.empty() || components[0] != util::kDriveGrandRootDirName) 450 if (components.empty() || components[0] != util::kDriveGrandRootDirName)
406 return FILE_ERROR_NOT_FOUND; 451 return FILE_ERROR_NOT_FOUND;
407 452
408 // Iterate over the remaining components. 453 // Iterate over the remaining components.
409 std::string id = util::kDriveGrandRootLocalId; 454 std::string id = util::kDriveGrandRootLocalId;
410 for (size_t i = 1; i < components.size(); ++i) { 455 for (size_t i = 1; i < components.size(); ++i) {
411 const std::string component = base::FilePath(components[i]).AsUTF8Unsafe(); 456 const std::string component = base::FilePath(components[i]).AsUTF8Unsafe();
412 id = storage_->GetChild(id, component); 457 std::string child_id;
413 if (id.empty()) 458 FileError error = storage_->GetChild(id, component, &child_id);
414 return FILE_ERROR_NOT_FOUND; 459 if (error != FILE_ERROR_OK)
460 return error;
461 id = child_id;
415 } 462 }
416 *out_id = id; 463 *out_id = id;
417 return FILE_ERROR_OK; 464 return FILE_ERROR_OK;
418 } 465 }
419 466
420 FileError ResourceMetadata::GetIdByResourceId(const std::string& resource_id, 467 FileError ResourceMetadata::GetIdByResourceId(const std::string& resource_id,
421 std::string* out_local_id) { 468 std::string* out_local_id) {
422 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); 469 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
423 470 return storage_->GetIdByResourceId(resource_id, out_local_id);
424 return storage_->GetIdByResourceId(resource_id, out_local_id) ?
425 FILE_ERROR_OK : FILE_ERROR_NOT_FOUND;
426 } 471 }
427 472
428 bool ResourceMetadata::PutEntryUnderDirectory(const ResourceEntry& entry) { 473 FileError ResourceMetadata::PutEntryUnderDirectory(const ResourceEntry& entry) {
429 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); 474 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
430 DCHECK(!entry.local_id().empty()); 475 DCHECK(!entry.local_id().empty());
431 DCHECK(!entry.parent_local_id().empty()); 476 DCHECK(!entry.parent_local_id().empty());
432 477
478 std::string base_name;
479 FileError error = GetDeduplicatedBaseName(entry, &base_name);
480 if (error != FILE_ERROR_OK)
481 return error;
433 ResourceEntry updated_entry(entry); 482 ResourceEntry updated_entry(entry);
434 updated_entry.set_base_name(GetDeduplicatedBaseName(updated_entry)); 483 updated_entry.set_base_name(base_name);
435 return storage_->PutEntry(updated_entry); 484 return storage_->PutEntry(updated_entry);
436 } 485 }
437 486
438 std::string ResourceMetadata::GetDeduplicatedBaseName( 487 FileError ResourceMetadata::GetDeduplicatedBaseName(
439 const ResourceEntry& entry) { 488 const ResourceEntry& entry,
489 std::string* base_name) {
440 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); 490 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
441 DCHECK(!entry.parent_local_id().empty()); 491 DCHECK(!entry.parent_local_id().empty());
442 DCHECK(!entry.title().empty()); 492 DCHECK(!entry.title().empty());
443 493
444 // The entry name may have been changed due to prior name de-duplication. 494 // The entry name may have been changed due to prior name de-duplication.
445 // We need to first restore the file name based on the title before going 495 // We need to first restore the file name based on the title before going
446 // through name de-duplication again when it is added to another directory. 496 // through name de-duplication again when it is added to another directory.
447 std::string base_name = entry.title(); 497 *base_name = entry.title();
448 if (entry.has_file_specific_info() && 498 if (entry.has_file_specific_info() &&
449 entry.file_specific_info().is_hosted_document()) { 499 entry.file_specific_info().is_hosted_document()) {
450 base_name += entry.file_specific_info().document_extension(); 500 *base_name += entry.file_specific_info().document_extension();
451 } 501 }
452 base_name = util::NormalizeFileName(base_name); 502 *base_name = util::NormalizeFileName(*base_name);
453 503
454 // If |base_name| is not used, just return it. 504 // If |base_name| is not used, just return it.
455 if (EntryCanUseName(storage_, entry.parent_local_id(), entry.local_id(), 505 bool can_use_name = false;
456 base_name)) 506 FileError error = EntryCanUseName(storage_, entry.parent_local_id(),
457 return base_name; 507 entry.local_id(), *base_name,
508 &can_use_name);
509 if (error != FILE_ERROR_OK || can_use_name)
510 return error;
458 511
459 // Find an unused number with binary search. 512 // Find an unused number with binary search.
460 int smallest_known_unused_modifier = 1; 513 int smallest_known_unused_modifier = 1;
461 while (true) { 514 while (true) {
462 if (EntryCanUseName(storage_, entry.parent_local_id(), entry.local_id(), 515 error = EntryCanUseName(storage_, entry.parent_local_id(), entry.local_id(),
463 GetUniquifiedName(base_name, 516 GetUniquifiedName(*base_name,
464 smallest_known_unused_modifier))) 517 smallest_known_unused_modifier),
518 &can_use_name);
519 if (error != FILE_ERROR_OK)
520 return error;
521 if (can_use_name)
465 break; 522 break;
466 523
467 const int delta = base::RandInt(1, smallest_known_unused_modifier); 524 const int delta = base::RandInt(1, smallest_known_unused_modifier);
468 if (smallest_known_unused_modifier <= INT_MAX - delta) { 525 if (smallest_known_unused_modifier <= INT_MAX - delta) {
469 smallest_known_unused_modifier += delta; 526 smallest_known_unused_modifier += delta;
470 } else { // No luck finding an unused number. Try again. 527 } else { // No luck finding an unused number. Try again.
471 smallest_known_unused_modifier = 1; 528 smallest_known_unused_modifier = 1;
472 } 529 }
473 } 530 }
474 531
475 int largest_known_used_modifier = 1; 532 int largest_known_used_modifier = 1;
476 while (smallest_known_unused_modifier - largest_known_used_modifier > 1) { 533 while (smallest_known_unused_modifier - largest_known_used_modifier > 1) {
477 const int modifier = largest_known_used_modifier + 534 const int modifier = largest_known_used_modifier +
478 (smallest_known_unused_modifier - largest_known_used_modifier) / 2; 535 (smallest_known_unused_modifier - largest_known_used_modifier) / 2;
479 536
480 if (EntryCanUseName(storage_, entry.parent_local_id(), entry.local_id(), 537 error = EntryCanUseName(storage_, entry.parent_local_id(), entry.local_id(),
481 GetUniquifiedName(base_name, modifier))) { 538 GetUniquifiedName(*base_name, modifier),
539 &can_use_name);
540 if (error != FILE_ERROR_OK)
541 return error;
542 if (can_use_name) {
482 smallest_known_unused_modifier = modifier; 543 smallest_known_unused_modifier = modifier;
483 } else { 544 } else {
484 largest_known_used_modifier = modifier; 545 largest_known_used_modifier = modifier;
485 } 546 }
486 } 547 }
487 return GetUniquifiedName(base_name, smallest_known_unused_modifier); 548 *base_name = GetUniquifiedName(*base_name, smallest_known_unused_modifier);
549 return FILE_ERROR_OK;
488 } 550 }
489 551
490 bool ResourceMetadata::RemoveEntryRecursively(const std::string& id) { 552 FileError ResourceMetadata::RemoveEntryRecursively(const std::string& id) {
491 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); 553 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
492 554
493 ResourceEntry entry; 555 ResourceEntry entry;
494 if (!storage_->GetEntry(id, &entry)) 556 FileError error = storage_->GetEntry(id, &entry);
495 return false; 557 if (error != FILE_ERROR_OK)
558 return error;
496 559
497 if (entry.file_info().is_directory()) { 560 if (entry.file_info().is_directory()) {
498 std::vector<std::string> children; 561 std::vector<std::string> children;
499 storage_->GetChildren(id, &children); 562 storage_->GetChildren(id, &children);
500 for (size_t i = 0; i < children.size(); ++i) { 563 for (size_t i = 0; i < children.size(); ++i) {
501 if (!RemoveEntryRecursively(children[i])) 564 error = RemoveEntryRecursively(children[i]);
502 return false; 565 if (error != FILE_ERROR_OK)
566 return error;
503 } 567 }
504 } 568 }
505 return storage_->RemoveEntry(id); 569 return storage_->RemoveEntry(id);
506 } 570 }
507 571
508 } // namespace internal 572 } // namespace internal
509 } // namespace drive 573 } // namespace drive
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/drive/resource_metadata.h ('k') | chrome/browser/chromeos/drive/resource_metadata_storage.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698