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

Side by Side Diff: chrome/common/important_file_writer.cc

Issue 6713032: Provide lazy CommitPendingWrites in addition to eager SavePersistentPrefs. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: for test Created 9 years, 9 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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/common/important_file_writer.h" 5 #include "chrome/common/important_file_writer.h"
6 6
7 #include <stdio.h> 7 #include <stdio.h>
8 8
9 #include <string> 9 #include <string>
10 10
11 #include "base/file_path.h" 11 #include "base/file_path.h"
12 #include "base/file_util.h" 12 #include "base/file_util.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/message_loop_proxy.h" 14 #include "base/message_loop_proxy.h"
15 #include "base/string_number_conversions.h" 15 #include "base/string_number_conversions.h"
16 #include "base/task.h" 16 #include "base/task.h"
17 #include "base/threading/thread.h" 17 #include "base/threading/thread.h"
18 #include "base/time.h" 18 #include "base/time.h"
19 #include "content/browser/browser_thread.h"
20 #include "content/common/notification_service.h"
19 21
20 using base::TimeDelta; 22 using base::TimeDelta;
21 23
22 namespace { 24 namespace {
23 25
24 const int kDefaultCommitIntervalMs = 10000; 26 const int kDefaultCommitIntervalMs = 10000;
25 27
26 class WriteToDiskTask : public Task { 28 class CommitNotificationTask: public Task {
27 public: 29 public:
28 WriteToDiskTask(const FilePath& path, const std::string& data) 30 CommitNotificationTask(bool success, NotificationSource source)
29 : path_(path), 31 : success_(success),
30 data_(data) { 32 source_(source) {
31 } 33 }
32 34
33 virtual void Run() { 35 virtual void Run() {
36 // At this moment we do not send notification in case of failure but we may
37 // want to send it including additional information in details.
38 if (success_ && NotificationService::current()) {
39 NotificationService::current()->Notify(
40 NotificationType::PREF_COMMITTED,
41 source_,
42 NotificationService::NoDetails());
43 }
44 }
45
46 private:
47 bool success_;
48 NotificationSource source_;
49 };
50
51 class WriteToDiskTask : public Task {
52 public:
53 WriteToDiskTask(const FilePath& path,
54 const std::string& data,
55 NotificationSource source)
56 : path_(path),
57 data_(data),
58 source_(source) {
59 }
60
61 virtual void Run() {
34 // Write the data to a temp file then rename to avoid data loss if we crash 62 // Write the data to a temp file then rename to avoid data loss if we crash
35 // while writing the file. Ensure that the temp file is on the same volume 63 // while writing the file. Ensure that the temp file is on the same volume
36 // as target file, so it can be moved in one step, and that the temp file 64 // as target file, so it can be moved in one step, and that the temp file
37 // is securely created. 65 // is securely created.
38 FilePath tmp_file_path; 66 FilePath tmp_file_path;
39 FILE* tmp_file = file_util::CreateAndOpenTemporaryFileInDir( 67 FILE* tmp_file = file_util::CreateAndOpenTemporaryFileInDir(
40 path_.DirName(), &tmp_file_path); 68 path_.DirName(), &tmp_file_path);
41 if (!tmp_file) { 69 if (!tmp_file) {
42 LogFailure("could not create temporary file"); 70 LogFailure("could not create temporary file");
43 return; 71 return;
(...skipping 10 matching lines...) Expand all
54 base::Uint64ToString(bytes_written)); 82 base::Uint64ToString(bytes_written));
55 file_util::Delete(tmp_file_path, false); 83 file_util::Delete(tmp_file_path, false);
56 return; 84 return;
57 } 85 }
58 86
59 if (!file_util::ReplaceFile(tmp_file_path, path_)) { 87 if (!file_util::ReplaceFile(tmp_file_path, path_)) {
60 LogFailure("could not rename temporary file"); 88 LogFailure("could not rename temporary file");
61 file_util::Delete(tmp_file_path, false); 89 file_util::Delete(tmp_file_path, false);
62 return; 90 return;
63 } 91 }
92 #if defined(OS_CHROMEOS)
93 BrowserThread::PostTask(
94 BrowserThread::UI, FROM_HERE,
95 new CommitNotificationTask(true, source_));
96 #endif
64 } 97 }
65 98
66 private: 99 private:
67 void LogFailure(const std::string& message) { 100 void LogFailure(const std::string& message) {
68 PLOG(WARNING) << "failed to write " << path_.value() 101 PLOG(WARNING) << "failed to write " << path_.value()
69 << ": " << message; 102 << ": " << message;
70 } 103 }
71 104
72 const FilePath path_; 105 const FilePath path_;
73 const std::string data_; 106 const std::string data_;
107 const NotificationSource source_;
74 108
75 DISALLOW_COPY_AND_ASSIGN(WriteToDiskTask); 109 DISALLOW_COPY_AND_ASSIGN(WriteToDiskTask);
76 }; 110 };
77 111
78 } // namespace 112 } // namespace
79 113
80 ImportantFileWriter::ImportantFileWriter( 114 ImportantFileWriter::ImportantFileWriter(
81 const FilePath& path, base::MessageLoopProxy* file_message_loop_proxy) 115 const FilePath& path, base::MessageLoopProxy* file_message_loop_proxy)
82 : path_(path), 116 : path_(path),
83 file_message_loop_proxy_(file_message_loop_proxy), 117 file_message_loop_proxy_(file_message_loop_proxy),
84 serializer_(NULL), 118 serializer_(NULL),
85 commit_interval_(TimeDelta::FromMilliseconds( 119 commit_interval_(TimeDelta::FromMilliseconds(
86 kDefaultCommitIntervalMs)) { 120 kDefaultCommitIntervalMs)),
121 source_(NotificationService::AllSources()) {
87 DCHECK(CalledOnValidThread()); 122 DCHECK(CalledOnValidThread());
88 DCHECK(file_message_loop_proxy_.get()); 123 DCHECK(file_message_loop_proxy_.get());
89 } 124 }
90 125
91 ImportantFileWriter::~ImportantFileWriter() { 126 ImportantFileWriter::~ImportantFileWriter() {
92 // We're usually a member variable of some other object, which also tends 127 // We're usually a member variable of some other object, which also tends
93 // to be our serializer. It may not be safe to call back to the parent object 128 // to be our serializer. It may not be safe to call back to the parent object
94 // being destructed. 129 // being destructed.
95 DCHECK(!HasPendingWrite()); 130 DCHECK(!HasPendingWrite());
96 } 131 }
97 132
98 bool ImportantFileWriter::HasPendingWrite() const { 133 bool ImportantFileWriter::HasPendingWrite() const {
99 DCHECK(CalledOnValidThread()); 134 DCHECK(CalledOnValidThread());
100 return timer_.IsRunning(); 135 return timer_.IsRunning();
101 } 136 }
102 137
103 void ImportantFileWriter::WriteNow(const std::string& data) { 138 void ImportantFileWriter::WriteNow(const std::string& data) {
104 DCHECK(CalledOnValidThread()); 139 DCHECK(CalledOnValidThread());
105 140
106 if (HasPendingWrite()) 141 if (HasPendingWrite())
107 timer_.Stop(); 142 timer_.Stop();
108 143
109 if (!file_message_loop_proxy_->PostTask(FROM_HERE, 144 if (!file_message_loop_proxy_->PostTask(
110 new WriteToDiskTask(path_, data))) { 145 FROM_HERE, new WriteToDiskTask(path_, data, source_))) {
111 // Posting the task to background message loop is not expected 146 // Posting the task to background message loop is not expected
112 // to fail, but if it does, avoid losing data and just hit the disk 147 // to fail, but if it does, avoid losing data and just hit the disk
113 // on the current thread. 148 // on the current thread.
114 NOTREACHED(); 149 NOTREACHED();
115 150
116 WriteToDiskTask write_task(path_, data); 151 WriteToDiskTask write_task(path_, data, source_);
117 write_task.Run(); 152 write_task.Run();
118 } 153 }
119 } 154 }
120 155
121 void ImportantFileWriter::ScheduleWrite(DataSerializer* serializer) { 156 void ImportantFileWriter::ScheduleWrite(DataSerializer* serializer) {
122 DCHECK(CalledOnValidThread()); 157 DCHECK(CalledOnValidThread());
123 158
124 DCHECK(serializer); 159 DCHECK(serializer);
125 serializer_ = serializer; 160 serializer_ = serializer;
126 161
(...skipping 13 matching lines...) Expand all
140 DCHECK(serializer_); 175 DCHECK(serializer_);
141 std::string data; 176 std::string data;
142 if (serializer_->SerializeData(&data)) { 177 if (serializer_->SerializeData(&data)) {
143 WriteNow(data); 178 WriteNow(data);
144 } else { 179 } else {
145 LOG(WARNING) << "failed to serialize data to be saved in " 180 LOG(WARNING) << "failed to serialize data to be saved in "
146 << path_.value(); 181 << path_.value();
147 } 182 }
148 serializer_ = NULL; 183 serializer_ = NULL;
149 } 184 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698