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

Side by Side Diff: net/base/file_stream.cc

Issue 10701050: net: Implement canceling of all async operations in FileStream. (Closed) Base URL: https://src.chromium.org/chrome/trunk/src/
Patch Set: 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
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 "net/base/file_stream.h" 5 #include "net/base/file_stream.h"
6 6
7 #include "base/threading/thread_restrictions.h"
8 #include "net/base/net_errors.h"
9
10 #if defined(OS_WIN)
11 #include "net/base/file_stream_win.h"
12 #elif defined(OS_POSIX)
13 #include "net/base/file_stream_posix.h"
14 #endif
15
7 namespace net { 16 namespace net {
8 17
9 FileStream::FileStream(net::NetLog* net_log) 18 FileStream::FileStream(net::NetLog* net_log)
10 : impl_(net_log) { 19 : open_flags_(0),
11 } 20 bound_net_log_(net::BoundNetLog::Make(net_log,
12 21 net::NetLog::SOURCE_FILESTREAM)),
13 FileStream::FileStream( 22 context_(new Context(bound_net_log_)) {
14 base::PlatformFile file, int flags, net::NetLog* net_log) 23 bound_net_log_.BeginEvent(net::NetLog::TYPE_FILE_STREAM_ALIVE);
15 : impl_(file, flags, net_log) { 24 }
25
26 FileStream::FileStream(base::PlatformFile file, int flags, net::NetLog* net_log)
27 : open_flags_(flags),
28 bound_net_log_(net::BoundNetLog::Make(net_log,
29 net::NetLog::SOURCE_FILESTREAM)),
30 context_(new Context(file, bound_net_log_, open_flags_)) {
31 bound_net_log_.BeginEvent(net::NetLog::TYPE_FILE_STREAM_ALIVE);
16 } 32 }
17 33
18 FileStream::~FileStream() { 34 FileStream::~FileStream() {
35 if (IsOpen() && !is_async())
36 CloseSync();
willchan no longer on Chromium 2012/09/05 00:15:48 Can you change this to: if (IsOpen() && !is_async(
37 context_.release()->Orphan();
38
39 bound_net_log_.EndEvent(net::NetLog::TYPE_FILE_STREAM_ALIVE);
19 } 40 }
20 41
21 void FileStream::Close(const CompletionCallback& callback) { 42 void FileStream::Close(const CompletionCallback& callback) {
22 impl_.Close(callback); 43 DCHECK(is_async());
44 context_->CloseAsync(callback);
23 } 45 }
24 46
25 void FileStream::CloseSync() { 47 void FileStream::CloseSync() {
26 impl_.CloseSync(); 48 // CloseSync() should be called on the correct thread even if it eventually
willchan no longer on Chromium 2012/09/05 00:15:48 I think this comment is unnecessary.
49 // ends up not doing any file operations.
50 base::ThreadRestrictions::AssertIOAllowed();
51
52 // TODO(satorux): Replace the following async stuff with a
53 // DCHECK(is_async()) once all async clients are migrated to
54 // use Close(). crbug.com/114783
55 if (!context_->async_in_progress()) {
56 context_->CloseSync();
57 } else {
58 Context* old_context = context_.release();
59 context_.reset(new Context(bound_net_log_));
60 context_->set_record_uma(old_context->record_uma());
61 old_context->Orphan();
62 }
27 } 63 }
28 64
29 int FileStream::Open(const FilePath& path, int open_flags, 65 int FileStream::Open(const FilePath& path, int open_flags,
30 const CompletionCallback& callback) { 66 const CompletionCallback& callback) {
31 return impl_.Open(path, open_flags, callback); 67 if (IsOpen()) {
68 DLOG(FATAL) << "File is already open!";
69 return ERR_UNEXPECTED;
70 }
71
72 open_flags_ = open_flags;
73 DCHECK(is_async());
74 context_->OpenAsync(path, open_flags, callback);
75 return ERR_IO_PENDING;
32 } 76 }
33 77
34 int FileStream::OpenSync(const FilePath& path, int open_flags) { 78 int FileStream::OpenSync(const FilePath& path, int open_flags) {
35 return impl_.OpenSync(path, open_flags); 79 base::ThreadRestrictions::AssertIOAllowed();
80
81 if (IsOpen()) {
82 DLOG(FATAL) << "File is already open!";
83 return ERR_UNEXPECTED;
84 }
85
86 open_flags_ = open_flags;
87 // TODO(satorux): Put a DCHECK once all async clients are migrated
88 // to use Open(). crbug.com/114783
89 //
90 // DCHECK(!is_async());
91 return context_->OpenSync(path, open_flags_);
36 } 92 }
37 93
38 bool FileStream::IsOpen() const { 94 bool FileStream::IsOpen() const {
39 return impl_.IsOpen(); 95 return context_->file() != base::kInvalidPlatformFileValue;
40 } 96 }
41 97
42 int FileStream::Seek(Whence whence, int64 offset, 98 int FileStream::Seek(Whence whence,
99 int64 offset,
43 const Int64CompletionCallback& callback) { 100 const Int64CompletionCallback& callback) {
44 return impl_.Seek(whence, offset, callback); 101 if (!IsOpen())
102 return ERR_UNEXPECTED;
103
104 // Make sure we're async.
105 DCHECK(is_async());
106 context_->SeekAsync(whence, offset, callback);
107 return ERR_IO_PENDING;
45 } 108 }
46 109
47 int64 FileStream::SeekSync(Whence whence, int64 offset) { 110 int64 FileStream::SeekSync(Whence whence, int64 offset) {
48 return impl_.SeekSync(whence, offset); 111 base::ThreadRestrictions::AssertIOAllowed();
112
113 if (!IsOpen())
114 return ERR_UNEXPECTED;
115
116 // If we're in async, make sure we don't have a request in flight.
117 DCHECK(!is_async() || !context_->async_in_progress());
118 return context_->SeekSync(whence, offset);
49 } 119 }
50 120
51 int64 FileStream::Available() { 121 int64 FileStream::Available() {
52 return impl_.Available(); 122 base::ThreadRestrictions::AssertIOAllowed();
53 } 123
54 124 if (!IsOpen())
55 int FileStream::Read( 125 return ERR_UNEXPECTED;
56 IOBuffer* in_buf, int buf_len, const CompletionCallback& callback) { 126
57 return impl_.Read(in_buf, buf_len, callback); 127 int64 cur_pos = SeekSync(FROM_CURRENT, 0);
128 if (cur_pos < 0)
129 return cur_pos;
130
131 int64 size = context_->GetFileSize();
132 if (size < 0)
133 return size;
134
135 DCHECK_GT(size, cur_pos);
136 return size - cur_pos;
137 }
138
139 int FileStream::Read(IOBuffer* buf,
140 int buf_len,
141 const CompletionCallback& callback) {
142 if (!IsOpen())
143 return ERR_UNEXPECTED;
144
145 // read(..., 0) will return 0, which indicates end-of-file.
146 DCHECK_GT(buf_len, 0);
147 DCHECK(open_flags_ & base::PLATFORM_FILE_READ);
148 DCHECK(is_async());
149
150 return context_->ReadAsync(buf, buf_len, callback);
58 } 151 }
59 152
60 int FileStream::ReadSync(char* buf, int buf_len) { 153 int FileStream::ReadSync(char* buf, int buf_len) {
61 return impl_.ReadSync(buf, buf_len); 154 base::ThreadRestrictions::AssertIOAllowed();
155
156 if (!IsOpen())
157 return ERR_UNEXPECTED;
158
159 DCHECK(!is_async());
160 // read(..., 0) will return 0, which indicates end-of-file.
161 DCHECK_GT(buf_len, 0);
162 DCHECK(open_flags_ & base::PLATFORM_FILE_READ);
163
164 return context_->ReadSync(buf, buf_len);
62 } 165 }
63 166
64 int FileStream::ReadUntilComplete(char *buf, int buf_len) { 167 int FileStream::ReadUntilComplete(char *buf, int buf_len) {
65 return impl_.ReadUntilComplete(buf, buf_len); 168 int to_read = buf_len;
66 } 169 int bytes_total = 0;
67 170
68 int FileStream::Write( 171 do {
69 IOBuffer* buf, int buf_len, const CompletionCallback& callback) { 172 int bytes_read = ReadSync(buf, to_read);
70 return impl_.Write(buf, buf_len, callback); 173 if (bytes_read <= 0) {
174 if (bytes_total == 0)
175 return bytes_read;
176
177 return bytes_total;
178 }
179
180 bytes_total += bytes_read;
181 buf += bytes_read;
182 to_read -= bytes_read;
183 } while (bytes_total < buf_len);
184
185 return bytes_total;
186 }
187
188 int FileStream::Write(IOBuffer* buf,
189 int buf_len,
190 const CompletionCallback& callback) {
191 if (!IsOpen())
192 return ERR_UNEXPECTED;
193
194 DCHECK(is_async());
195 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE);
196 // write(..., 0) will return 0, which indicates end-of-file.
197 DCHECK_GT(buf_len, 0);
198
199 return context_->WriteAsync(buf, buf_len, callback);
71 } 200 }
72 201
73 int FileStream::WriteSync(const char* buf, int buf_len) { 202 int FileStream::WriteSync(const char* buf, int buf_len) {
74 return impl_.WriteSync(buf, buf_len); 203 base::ThreadRestrictions::AssertIOAllowed();
204
205 if (!IsOpen())
206 return ERR_UNEXPECTED;
207
208 DCHECK(!is_async());
209 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE);
210 // write(..., 0) will return 0, which indicates end-of-file.
211 DCHECK_GT(buf_len, 0);
212
213 return context_->WriteSync(buf, buf_len);
75 } 214 }
76 215
77 int64 FileStream::Truncate(int64 bytes) { 216 int64 FileStream::Truncate(int64 bytes) {
78 return impl_.Truncate(bytes); 217 base::ThreadRestrictions::AssertIOAllowed();
218
219 if (!IsOpen())
220 return ERR_UNEXPECTED;
221
222 // We'd better be open for writing.
223 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE);
224
225 // Seek to the position to truncate from.
226 int64 seek_position = SeekSync(FROM_BEGIN, bytes);
227 if (seek_position != bytes)
228 return ERR_UNEXPECTED;
229
230 // And truncate the file.
231 return context_->Truncate(bytes);
79 } 232 }
80 233
81 int FileStream::Flush() { 234 int FileStream::Flush() {
82 return impl_.Flush(); 235 base::ThreadRestrictions::AssertIOAllowed();
236
237 if (!IsOpen())
238 return ERR_UNEXPECTED;
239
240 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE);
241 return context_->Flush();
83 } 242 }
84 243
85 void FileStream::EnableErrorStatistics() { 244 void FileStream::EnableErrorStatistics() {
86 impl_.EnableErrorStatistics(); 245 context_->set_record_uma(true);
87 } 246 }
88 247
89 void FileStream::SetBoundNetLogSource( 248 void FileStream::SetBoundNetLogSource(
90 const net::BoundNetLog& owner_bound_net_log) { 249 const net::BoundNetLog& owner_bound_net_log) {
91 impl_.SetBoundNetLogSource(owner_bound_net_log); 250 if ((owner_bound_net_log.source().id == net::NetLog::Source::kInvalidId) &&
251 (bound_net_log_.source().id == net::NetLog::Source::kInvalidId)) {
252 // Both |BoundNetLog|s are invalid.
253 return;
254 }
255
256 // Should never connect to itself.
257 DCHECK_NE(bound_net_log_.source().id, owner_bound_net_log.source().id);
258
259 bound_net_log_.AddEvent(
260 net::NetLog::TYPE_FILE_STREAM_BOUND_TO_OWNER,
261 owner_bound_net_log.source().ToEventParametersCallback());
262
263 owner_bound_net_log.AddEvent(
264 net::NetLog::TYPE_FILE_STREAM_SOURCE,
265 bound_net_log_.source().ToEventParametersCallback());
92 } 266 }
93 267
94 base::PlatformFile FileStream::GetPlatformFileForTesting() { 268 base::PlatformFile FileStream::GetPlatformFileForTesting() {
95 return impl_.GetPlatformFileForTesting(); 269 return context_->file();
96 } 270 }
97 271
98 } // namespace net 272 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698