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

Side by Side Diff: webkit/fileapi/syncable/local_file_change_tracker.cc

Issue 10966003: Add LocalFileChangeTracker database to record non-synced dirty files (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix Created 8 years, 3 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 "webkit/fileapi/syncable/local_file_change_tracker.h" 5 #include "webkit/fileapi/syncable/local_file_change_tracker.h"
6 6
7 #include "base/location.h"
8 #include "base/logging.h"
7 #include "base/sequenced_task_runner.h" 9 #include "base/sequenced_task_runner.h"
10 #include "third_party/leveldatabase/src/include/leveldb/db.h"
11 #include "webkit/fileapi/file_system_util.h"
8 #include "webkit/fileapi/syncable/local_file_sync_status.h" 12 #include "webkit/fileapi/syncable/local_file_sync_status.h"
9 13
14 namespace {
15 const FilePath::CharType kDatabaseName[] =
16 FILE_PATH_LITERAL("LocalFileChangeTracker");
17 const char kMark[] = "d";
18 }
19
10 namespace fileapi { 20 namespace fileapi {
11 21
22 // A database class that stores local file changes in a local database. This
23 // object must be destructed on file_task_runner.
24 class LocalFileChangeTracker::TrackerDB {
25 public:
26 explicit TrackerDB(const FilePath& profile_path);
27
28 bool MarkDirty(const std::string& url);
29 bool ClearDirty(const std::string& url);
30
31 private:
32 enum InitStatus {
33 INIT_STATUS_OK = 0,
34 INIT_STATUS_CORRUPTION,
35 INIT_STATUS_IO_ERROR,
36 INIT_STATUS_UNKNOWN_ERROR,
37 INIT_STATUS_MAX,
38 };
39
40 enum RecoveryOption {
41 REPAIR_ON_CORRUPTION,
42 FAIL_ON_CORRUPTION,
43 };
44
45 bool Init(RecoveryOption recovery_option);
46 bool Repair(const std::string& db_path);
47 void HandleError(const tracked_objects::Location& from_here,
48 const leveldb::Status& status);
49
50 const FilePath profile_path_;
51 scoped_ptr<leveldb::DB> db_;
52 base::Time last_reported_time_;
53 bool db_disabled_;
54
55 DISALLOW_COPY_AND_ASSIGN(TrackerDB);
56 };
57
58 // LocalFileChangeTracker ------------------------------------------------------
59
12 LocalFileChangeTracker::LocalFileChangeTracker( 60 LocalFileChangeTracker::LocalFileChangeTracker(
13 LocalFileSyncStatus* sync_status, 61 LocalFileSyncStatus* sync_status,
62 const FilePath& profile_path,
14 base::SequencedTaskRunner* file_task_runner) 63 base::SequencedTaskRunner* file_task_runner)
15 : sync_status_(sync_status), 64 : sync_status_(sync_status),
16 file_task_runner_(file_task_runner) {} 65 file_task_runner_(file_task_runner),
66 tracker_db_(new TrackerDB(profile_path)) {}
17 67
18 LocalFileChangeTracker::~LocalFileChangeTracker() { 68 LocalFileChangeTracker::~LocalFileChangeTracker() {
19 // file_task_runner_->PostTask(FROM_HERE, base::Bind(&DropDatabase)); 69 if (tracker_db_.get())
20 // TODO(kinuko): implement. 70 file_task_runner_->DeleteSoon(FROM_HERE, tracker_db_.release());
21 } 71 }
22 72
23 void LocalFileChangeTracker::OnStartUpdate(const FileSystemURL& url) { 73 void LocalFileChangeTracker::OnStartUpdate(const FileSystemURL& url) {
24 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); 74 DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
25 // TODO(kinuko): we may want to reduce the number of this call if 75 // TODO(kinuko): we may want to reduce the number of this call if
26 // the URL is already marked dirty. 76 // the URL is already marked dirty.
27 MarkDirtyOnDatabase(url); 77 MarkDirtyOnDatabase(url);
28 } 78 }
29 79
30 void LocalFileChangeTracker::OnEndUpdate(const FileSystemURL& url) { 80 void LocalFileChangeTracker::OnEndUpdate(const FileSystemURL& url) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 NOTREACHED(); 150 NOTREACHED();
101 } 151 }
102 152
103 void LocalFileChangeTracker::RecordChange( 153 void LocalFileChangeTracker::RecordChange(
104 const FileSystemURL& url, const FileChange& change) { 154 const FileSystemURL& url, const FileChange& change) {
105 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); 155 DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
106 changes_[url].Update(change); 156 changes_[url].Update(change);
107 } 157 }
108 158
109 void LocalFileChangeTracker::MarkDirtyOnDatabase(const FileSystemURL& url) { 159 void LocalFileChangeTracker::MarkDirtyOnDatabase(const FileSystemURL& url) {
110 // TODO(kinuko): implement. 160 tracker_db_->MarkDirty(SerializeExternalFileSystemURL(url));
111 } 161 }
112 162
113 void LocalFileChangeTracker::ClearDirtyOnDatabase(const FileSystemURL& url) { 163 void LocalFileChangeTracker::ClearDirtyOnDatabase(const FileSystemURL& url) {
114 // TODO(kinuko): implement. 164 tracker_db_->ClearDirty(SerializeExternalFileSystemURL(url));
165 }
166
167 std::string LocalFileChangeTracker::SerializeExternalFileSystemURL(
168 const FileSystemURL& url) {
169 return GetFileSystemRootURI(url.origin(), kFileSystemTypeExternal).spec() +
170 url.filesystem_id() + "/" + url.path().AsUTF8Unsafe();
171 }
172
173 FileSystemURL LocalFileChangeTracker::DeserializeExternalFileSystemURL(
174 const std::string& url) {
175 return FileSystemURL(GURL(url));
176 }
177
178 // TrackerDB -------------------------------------------------------------------
179
180 LocalFileChangeTracker::TrackerDB::TrackerDB(const FilePath& profile_path)
181 : profile_path_(profile_path),
182 db_disabled_(false) {}
183
184 bool LocalFileChangeTracker::TrackerDB::Init(RecoveryOption recovery_option) {
185 if (db_.get())
186 return true;
187
188 std::string path = FilePathToString(profile_path_.Append(kDatabaseName));
189 leveldb::Options options;
190 options.create_if_missing = true;
191 leveldb::DB* db;
192 leveldb::Status status = leveldb::DB::Open(options, path, &db);
193 if (status.ok()) {
194 db_.reset(db);
195 return true;
196 }
197
198 HandleError(FROM_HERE, status);
199 if (!status.IsCorruption())
200 return false;
201
202 switch (recovery_option) {
203 case FAIL_ON_CORRUPTION:
204 return false;
205 case REPAIR_ON_CORRUPTION:
206 return Repair(path);
207 }
208 NOTREACHED();
209 return false;
210 }
211
212 bool LocalFileChangeTracker::TrackerDB::Repair(const std::string& db_path) {
213 DCHECK(!db_.get());
214 LOG(WARNING) << "Attempting to repair TrackerDB.";
215
216 if (leveldb::RepairDB(db_path, leveldb::Options()).ok() &&
217 Init(FAIL_ON_CORRUPTION)) {
218 // TODO(nhiroki): perform some consistency checks between TrackerDB and
219 // cloud-backed file system.
220 LOG(WARNING) << "Repairing TrackerDB completed.";
221 return true;
222 }
223
224 LOG(WARNING) << "Failed to repair TrackerDB.";
225 return false;
226 }
227
228 // TODO(nhiroki): factor out the common methods into somewhere else.
229 void LocalFileChangeTracker::TrackerDB::HandleError(
230 const tracked_objects::Location& from_here,
231 const leveldb::Status& status) {
232 LOG(ERROR) << "LocalFileChangeTracker::TrackerDB failed at: "
233 << from_here.ToString() << " with error: " << status.ToString();
234 }
235
236 bool LocalFileChangeTracker::TrackerDB::MarkDirty(const std::string& url) {
237 if (db_disabled_)
238 return false;
239
240 if (!Init(REPAIR_ON_CORRUPTION)) {
241 db_disabled_ = true;
tzik 2012/09/21 04:16:32 Could you reset db_ to NULL here?
nhiroki 2012/09/21 06:21:09 Done.
242 return false;
243 }
244
245 leveldb::Status status = db_->Put(leveldb::WriteOptions(), url, kMark);
246 if (!status.ok()) {
247 HandleError(FROM_HERE, status);
248 db_disabled_ = true;
tzik 2012/09/21 04:16:32 ditto
nhiroki 2012/09/21 06:21:09 Done.
249 return false;
250 }
251 return true;
252 }
253
254 bool LocalFileChangeTracker::TrackerDB::ClearDirty(const std::string& url) {
255 if (db_disabled_)
256 return false;
257
258 if (!Init(REPAIR_ON_CORRUPTION)) {
259 db_disabled_ = true;
tzik 2012/09/21 04:16:32 ditto
nhiroki 2012/09/21 06:21:09 Done.
260 return false;
261 }
262
263 leveldb::Status status = db_->Delete(leveldb::WriteOptions(), url);
264 if (!status.ok() && !status.IsNotFound()) {
265 HandleError(FROM_HERE, status);
266 db_disabled_ = true;
tzik 2012/09/21 04:16:32 ditto
nhiroki 2012/09/21 06:21:09 Done.
267 return false;
268 }
269 return true;
115 } 270 }
116 271
117 } // namespace fileapi 272 } // namespace fileapi
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698