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

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

Issue 7695014: ImportantFileWriter: Flush the data before closing the (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 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 | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 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
(...skipping 18 matching lines...) Expand all
29 : path_(path), 29 : path_(path),
30 data_(data) { 30 data_(data) {
31 } 31 }
32 32
33 virtual void Run() { 33 virtual void Run() {
34 // Write the data to a temp file then rename to avoid data loss if we crash 34 // 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 35 // 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 36 // as target file, so it can be moved in one step, and that the temp file
37 // is securely created. 37 // is securely created.
38 FilePath tmp_file_path; 38 FilePath tmp_file_path;
39 FILE* tmp_file = file_util::CreateAndOpenTemporaryFileInDir( 39 if (!file_util::CreateTemporaryFileInDir(path_.DirName(), &tmp_file_path)) {
40 path_.DirName(), &tmp_file_path);
41 if (!tmp_file) {
42 LogFailure("could not create temporary file"); 40 LogFailure("could not create temporary file");
43 return; 41 return;
44 } 42 }
45 43
46 size_t bytes_written = fwrite(data_.data(), 1, data_.length(), tmp_file); 44 int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE;
47 if (!file_util::CloseFile(tmp_file)) { 45 base::PlatformFile tmp_file =
46 base::CreatePlatformFile(tmp_file_path, flags, NULL, NULL);
Scott Hess - ex-Googler 2011/08/23 00:54:38 I would prefer if you could not introduce a race c
rvargas (doing something else) 2011/08/23 01:41:52 I was writing the code with some posix specific ve
Scott Hess - ex-Googler 2011/08/23 19:23:57 The rename case is a very good point! I won't dig
47 if (tmp_file == base::kInvalidPlatformFileValue) {
48 LogFailure("could not open temporary file");
49 return;
50 }
51
52 CHECK_LE(data_.length(), static_cast<size_t>(kint32max));
53 int bytes_written = base::WritePlatformFile(
54 tmp_file, 0, data_.data(), static_cast<int>(data_.length()));
Scott Hess - ex-Googler 2011/08/23 19:27:17 BTW ... AFAICT the POSIX version of this function
rvargas (doing something else) 2011/08/23 23:36:58 In that case, line 63 should detect the error and
55 base::FlushPlatformFile(tmp_file); // Ignore return value.
Scott Hess - ex-Googler 2011/08/23 00:54:38 Would it be reasonable to wire up something like f
rvargas (doing something else) 2011/08/23 01:41:52 Not sure. I can make fflush do the right thing on
Scott Hess - ex-Googler 2011/08/23 19:23:57 OK, that's all I wanted to hear - I hate having mu
56
57 if (!base::ClosePlatformFile(tmp_file)) {
48 LogFailure("failed to close temporary file"); 58 LogFailure("failed to close temporary file");
49 file_util::Delete(tmp_file_path, false); 59 file_util::Delete(tmp_file_path, false);
50 return; 60 return;
51 } 61 }
52 if (bytes_written < data_.length()) { 62
63 if (bytes_written < static_cast<int>(data_.length())) {
53 LogFailure("error writing, bytes_written=" + 64 LogFailure("error writing, bytes_written=" +
54 base::Uint64ToString(bytes_written)); 65 base::IntToString(bytes_written));
55 file_util::Delete(tmp_file_path, false); 66 file_util::Delete(tmp_file_path, false);
56 return; 67 return;
57 } 68 }
58 69
59 if (!file_util::ReplaceFile(tmp_file_path, path_)) { 70 if (!file_util::ReplaceFile(tmp_file_path, path_)) {
60 LogFailure("could not rename temporary file"); 71 LogFailure("could not rename temporary file");
61 file_util::Delete(tmp_file_path, false); 72 file_util::Delete(tmp_file_path, false);
62 return; 73 return;
63 } 74 }
64 } 75 }
(...skipping 30 matching lines...) Expand all
95 DCHECK(!HasPendingWrite()); 106 DCHECK(!HasPendingWrite());
96 } 107 }
97 108
98 bool ImportantFileWriter::HasPendingWrite() const { 109 bool ImportantFileWriter::HasPendingWrite() const {
99 DCHECK(CalledOnValidThread()); 110 DCHECK(CalledOnValidThread());
100 return timer_.IsRunning(); 111 return timer_.IsRunning();
101 } 112 }
102 113
103 void ImportantFileWriter::WriteNow(const std::string& data) { 114 void ImportantFileWriter::WriteNow(const std::string& data) {
104 DCHECK(CalledOnValidThread()); 115 DCHECK(CalledOnValidThread());
116 if (data.length() > static_cast<size_t>(kint32max)) {
117 NOTREACHED();
118 return;
119 }
105 120
106 if (HasPendingWrite()) 121 if (HasPendingWrite())
107 timer_.Stop(); 122 timer_.Stop();
108 123
109 if (!file_message_loop_proxy_->PostTask( 124 if (!file_message_loop_proxy_->PostTask(
110 FROM_HERE, new WriteToDiskTask(path_, data))) { 125 FROM_HERE, new WriteToDiskTask(path_, data))) {
111 // Posting the task to background message loop is not expected 126 // 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 127 // to fail, but if it does, avoid losing data and just hit the disk
113 // on the current thread. 128 // on the current thread.
114 NOTREACHED(); 129 NOTREACHED();
(...skipping 25 matching lines...) Expand all
140 DCHECK(serializer_); 155 DCHECK(serializer_);
141 std::string data; 156 std::string data;
142 if (serializer_->SerializeData(&data)) { 157 if (serializer_->SerializeData(&data)) {
143 WriteNow(data); 158 WriteNow(data);
144 } else { 159 } else {
145 LOG(WARNING) << "failed to serialize data to be saved in " 160 LOG(WARNING) << "failed to serialize data to be saved in "
146 << path_.value(); 161 << path_.value();
147 } 162 }
148 serializer_ = NULL; 163 serializer_ = NULL;
149 } 164 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698