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

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: Normalize expected file path Created 8 years, 2 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 } // namespace
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 bool db_disabled_;
53
54 DISALLOW_COPY_AND_ASSIGN(TrackerDB);
55 };
56
57 // LocalFileChangeTracker ------------------------------------------------------
58
12 LocalFileChangeTracker::LocalFileChangeTracker( 59 LocalFileChangeTracker::LocalFileChangeTracker(
13 LocalFileSyncStatus* sync_status, 60 LocalFileSyncStatus* sync_status,
61 const FilePath& profile_path,
14 base::SequencedTaskRunner* file_task_runner) 62 base::SequencedTaskRunner* file_task_runner)
15 : sync_status_(sync_status), 63 : sync_status_(sync_status),
16 file_task_runner_(file_task_runner) {} 64 file_task_runner_(file_task_runner),
65 tracker_db_(new TrackerDB(profile_path)) {}
17 66
18 LocalFileChangeTracker::~LocalFileChangeTracker() { 67 LocalFileChangeTracker::~LocalFileChangeTracker() {
19 // file_task_runner_->PostTask(FROM_HERE, base::Bind(&DropDatabase)); 68 if (tracker_db_.get())
20 // TODO(kinuko): implement. 69 file_task_runner_->DeleteSoon(FROM_HERE, tracker_db_.release());
21 } 70 }
22 71
23 void LocalFileChangeTracker::OnStartUpdate(const FileSystemURL& url) { 72 void LocalFileChangeTracker::OnStartUpdate(const FileSystemURL& url) {
24 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); 73 DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
25 // TODO(kinuko): we may want to reduce the number of this call if 74 // TODO(kinuko): we may want to reduce the number of this call if
26 // the URL is already marked dirty. 75 // the URL is already marked dirty.
27 MarkDirtyOnDatabase(url); 76 MarkDirtyOnDatabase(url);
28 } 77 }
29 78
30 void LocalFileChangeTracker::OnEndUpdate(const FileSystemURL& url) { 79 void LocalFileChangeTracker::OnEndUpdate(const FileSystemURL& url) {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 } 145 }
97 146
98 void LocalFileChangeTracker::CollectLastDirtyChanges(FileChangeMap* changes) { 147 void LocalFileChangeTracker::CollectLastDirtyChanges(FileChangeMap* changes) {
99 // TODO(kinuko): implement. 148 // TODO(kinuko): implement.
100 NOTREACHED(); 149 NOTREACHED();
101 } 150 }
102 151
103 void LocalFileChangeTracker::RecordChange( 152 void LocalFileChangeTracker::RecordChange(
104 const FileSystemURL& url, const FileChange& change) { 153 const FileSystemURL& url, const FileChange& change) {
105 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); 154 DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
155 // TODO(nhiroki): propagate the error code (see http://crbug.com/152127).
156 MarkDirtyOnDatabase(url);
106 changes_[url].Update(change); 157 changes_[url].Update(change);
107 } 158 }
108 159
109 void LocalFileChangeTracker::MarkDirtyOnDatabase(const FileSystemURL& url) { 160 void LocalFileChangeTracker::MarkDirtyOnDatabase(const FileSystemURL& url) {
110 // TODO(kinuko): implement. 161 tracker_db_->MarkDirty(SerializeExternalFileSystemURL(url));
111 } 162 }
112 163
113 void LocalFileChangeTracker::ClearDirtyOnDatabase(const FileSystemURL& url) { 164 void LocalFileChangeTracker::ClearDirtyOnDatabase(const FileSystemURL& url) {
114 // TODO(kinuko): implement. 165 tracker_db_->ClearDirty(SerializeExternalFileSystemURL(url));
166 }
167
168 std::string LocalFileChangeTracker::SerializeExternalFileSystemURL(
169 const FileSystemURL& url) {
170 return GetFileSystemRootURI(url.origin(), kFileSystemTypeExternal).spec() +
171 url.filesystem_id() + "/" + url.path().AsUTF8Unsafe();
172 }
173
174 bool LocalFileChangeTracker::DeserializeExternalFileSystemURL(
175 const std::string& serialized_url, FileSystemURL* url) {
176 *url = FileSystemURL(GURL(serialized_url));
177 return url->is_valid();
178 }
179
180 // TrackerDB -------------------------------------------------------------------
181
182 LocalFileChangeTracker::TrackerDB::TrackerDB(const FilePath& profile_path)
183 : profile_path_(profile_path),
184 db_disabled_(false) {}
185
186 bool LocalFileChangeTracker::TrackerDB::Init(RecoveryOption recovery_option) {
187 if (db_.get())
188 return true;
189
190 std::string path = FilePathToString(profile_path_.Append(kDatabaseName));
191 leveldb::Options options;
192 options.create_if_missing = true;
193 leveldb::DB* db;
194 leveldb::Status status = leveldb::DB::Open(options, path, &db);
195 if (status.ok()) {
196 db_.reset(db);
197 return true;
198 }
199
200 HandleError(FROM_HERE, status);
201 if (!status.IsCorruption())
202 return false;
203
204 switch (recovery_option) {
205 case FAIL_ON_CORRUPTION:
206 return false;
207 case REPAIR_ON_CORRUPTION:
208 return Repair(path);
209 }
210 NOTREACHED();
211 return false;
212 }
213
214 bool LocalFileChangeTracker::TrackerDB::Repair(const std::string& db_path) {
215 DCHECK(!db_.get());
216 LOG(WARNING) << "Attempting to repair TrackerDB.";
217
218 if (leveldb::RepairDB(db_path, leveldb::Options()).ok() &&
219 Init(FAIL_ON_CORRUPTION)) {
220 // TODO(nhiroki): perform some consistency checks between TrackerDB and
221 // syncable file system.
222 LOG(WARNING) << "Repairing TrackerDB completed.";
223 return true;
224 }
225
226 LOG(WARNING) << "Failed to repair TrackerDB.";
227 return false;
228 }
229
230 // TODO(nhiroki): factor out the common methods into somewhere else.
231 void LocalFileChangeTracker::TrackerDB::HandleError(
232 const tracked_objects::Location& from_here,
233 const leveldb::Status& status) {
234 LOG(ERROR) << "LocalFileChangeTracker::TrackerDB failed at: "
235 << from_here.ToString() << " with error: " << status.ToString();
236 }
237
238 bool LocalFileChangeTracker::TrackerDB::MarkDirty(const std::string& url) {
239 if (db_disabled_)
240 return false;
241
242 if (!Init(REPAIR_ON_CORRUPTION)) {
243 db_disabled_ = true;
244 db_.reset();
245 return false;
246 }
247
248 leveldb::Status status = db_->Put(leveldb::WriteOptions(), url, kMark);
249 if (!status.ok()) {
250 HandleError(FROM_HERE, status);
251 db_disabled_ = true;
252 db_.reset();
253 return false;
254 }
255 return true;
256 }
257
258 bool LocalFileChangeTracker::TrackerDB::ClearDirty(const std::string& url) {
259 if (db_disabled_)
260 return false;
261
262 // Should not reach here before initializing the database. The database should
263 // be cleared after read, and should be initialized during read if
264 // uninitialized.
265 DCHECK(db_.get());
266
267 leveldb::Status status = db_->Delete(leveldb::WriteOptions(), url);
268 if (!status.ok() && !status.IsNotFound()) {
269 HandleError(FROM_HERE, status);
270 db_disabled_ = true;
271 db_.reset();
272 return false;
273 }
274 return true;
115 } 275 }
116 276
117 } // namespace fileapi 277 } // namespace fileapi
OLDNEW
« no previous file with comments | « webkit/fileapi/syncable/local_file_change_tracker.h ('k') | webkit/fileapi/syncable/local_file_change_tracker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698