OLD | NEW |
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/location.h" | 7 #include "base/location.h" |
8 #include "base/message_loop/message_loop_proxy.h" | 8 #include "base/message_loop/message_loop_proxy.h" |
9 #include "base/task_runner_util.h" | 9 #include "base/task_runner_util.h" |
10 #include "base/threading/thread_restrictions.h" | 10 #include "base/threading/thread_restrictions.h" |
11 #include "base/threading/worker_pool.h" | 11 #include "base/threading/worker_pool.h" |
12 #include "net/base/file_stream_context.h" | 12 #include "net/base/file_stream_context.h" |
13 #include "net/base/file_stream_net_log_parameters.h" | 13 #include "net/base/file_stream_net_log_parameters.h" |
14 #include "net/base/net_errors.h" | 14 #include "net/base/net_errors.h" |
15 | 15 |
16 namespace net { | 16 namespace net { |
17 | 17 |
18 FileStream::FileStream(NetLog* net_log, | 18 FileStream::FileStream(NetLog* net_log, |
19 const scoped_refptr<base::TaskRunner>& task_runner) | 19 const scoped_refptr<base::TaskRunner>& task_runner) |
20 /* To allow never opened stream to be destroyed on any thread we set flags | 20 /* To allow never opened stream to be destroyed on any thread we set flags |
21 as if stream was opened asynchronously. */ | 21 as if stream was opened asynchronously. */ |
22 : open_flags_(base::PLATFORM_FILE_ASYNC), | 22 : bound_net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_FILESTREAM)), |
23 bound_net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_FILESTREAM)), | |
24 context_(new Context(bound_net_log_, task_runner)) { | 23 context_(new Context(bound_net_log_, task_runner)) { |
25 bound_net_log_.BeginEvent(NetLog::TYPE_FILE_STREAM_ALIVE); | 24 bound_net_log_.BeginEvent(NetLog::TYPE_FILE_STREAM_ALIVE); |
26 } | 25 } |
27 | 26 |
28 FileStream::FileStream(NetLog* net_log) | 27 FileStream::FileStream(NetLog* net_log) |
29 /* To allow never opened stream to be destroyed on any thread we set flags | 28 /* To allow never opened stream to be destroyed on any thread we set flags |
30 as if stream was opened asynchronously. */ | 29 as if stream was opened asynchronously. */ |
31 : open_flags_(base::PLATFORM_FILE_ASYNC), | 30 : bound_net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_FILESTREAM)), |
32 bound_net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_FILESTREAM)), | |
33 context_(new Context(bound_net_log_, | 31 context_(new Context(bound_net_log_, |
34 base::WorkerPool::GetTaskRunner(true /* slow */))) { | 32 base::WorkerPool::GetTaskRunner(true /* slow */))) { |
35 bound_net_log_.BeginEvent(NetLog::TYPE_FILE_STREAM_ALIVE); | 33 bound_net_log_.BeginEvent(NetLog::TYPE_FILE_STREAM_ALIVE); |
36 } | 34 } |
37 | 35 |
38 FileStream::FileStream(base::PlatformFile file, | 36 FileStream::FileStream(base::PlatformFile file, |
39 int flags, | 37 int flags, |
40 NetLog* net_log, | 38 NetLog* net_log, |
41 const scoped_refptr<base::TaskRunner>& task_runner) | 39 const scoped_refptr<base::TaskRunner>& task_runner) |
42 : open_flags_(flags), | 40 : bound_net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_FILESTREAM)), |
43 bound_net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_FILESTREAM)), | 41 context_(new Context(base::File(file), flags, bound_net_log_, |
44 context_(new Context(file, bound_net_log_, open_flags_, task_runner)) { | 42 task_runner)) { |
45 bound_net_log_.BeginEvent(NetLog::TYPE_FILE_STREAM_ALIVE); | 43 bound_net_log_.BeginEvent(NetLog::TYPE_FILE_STREAM_ALIVE); |
46 } | 44 } |
47 | 45 |
48 FileStream::FileStream(base::PlatformFile file, int flags, NetLog* net_log) | 46 FileStream::FileStream(base::PlatformFile file, int flags, NetLog* net_log) |
49 : open_flags_(flags), | 47 : bound_net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_FILESTREAM)), |
50 bound_net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_FILESTREAM)), | 48 context_(new Context(base::File(file), flags, bound_net_log_, |
51 context_(new Context(file, | 49 base::WorkerPool::GetTaskRunner(true /* slow */))) { |
52 bound_net_log_, | 50 bound_net_log_.BeginEvent(NetLog::TYPE_FILE_STREAM_ALIVE); |
53 open_flags_, | 51 } |
| 52 |
| 53 FileStream::FileStream(base::File file, |
| 54 net::NetLog* net_log, |
| 55 const scoped_refptr<base::TaskRunner>& task_runner) |
| 56 : bound_net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_FILESTREAM)), |
| 57 context_(new Context(file.Pass(), bound_net_log_, task_runner)) { |
| 58 bound_net_log_.BeginEvent(NetLog::TYPE_FILE_STREAM_ALIVE); |
| 59 } |
| 60 |
| 61 FileStream::FileStream(base::File file, net::NetLog* net_log) |
| 62 : bound_net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_FILESTREAM)), |
| 63 context_(new Context(file.Pass(), bound_net_log_, |
54 base::WorkerPool::GetTaskRunner(true /* slow */))) { | 64 base::WorkerPool::GetTaskRunner(true /* slow */))) { |
55 bound_net_log_.BeginEvent(NetLog::TYPE_FILE_STREAM_ALIVE); | 65 bound_net_log_.BeginEvent(NetLog::TYPE_FILE_STREAM_ALIVE); |
56 } | 66 } |
57 | 67 |
58 FileStream::~FileStream() { | 68 FileStream::~FileStream() { |
59 if (!is_async()) { | 69 if (context_->async()) { |
60 base::ThreadRestrictions::AssertIOAllowed(); | 70 context_.release()->Orphan(); |
| 71 } else { |
61 context_->CloseSync(); | 72 context_->CloseSync(); |
62 context_.reset(); | 73 context_.reset(); |
63 } else { | |
64 context_.release()->Orphan(); | |
65 } | 74 } |
66 | 75 |
67 bound_net_log_.EndEvent(NetLog::TYPE_FILE_STREAM_ALIVE); | 76 bound_net_log_.EndEvent(NetLog::TYPE_FILE_STREAM_ALIVE); |
68 } | 77 } |
69 | 78 |
70 int FileStream::Open(const base::FilePath& path, int open_flags, | 79 int FileStream::Open(const base::FilePath& path, int open_flags, |
71 const CompletionCallback& callback) { | 80 const CompletionCallback& callback) { |
72 if (IsOpen()) { | 81 if (IsOpen()) { |
73 DLOG(FATAL) << "File is already open!"; | 82 DLOG(FATAL) << "File is already open!"; |
74 return ERR_UNEXPECTED; | 83 return ERR_UNEXPECTED; |
75 } | 84 } |
76 | 85 |
77 open_flags_ = open_flags; | 86 DCHECK(open_flags & base::File::FLAG_ASYNC); |
78 DCHECK(is_async()); | |
79 context_->OpenAsync(path, open_flags, callback); | 87 context_->OpenAsync(path, open_flags, callback); |
80 return ERR_IO_PENDING; | 88 return ERR_IO_PENDING; |
81 } | 89 } |
82 | 90 |
83 int FileStream::OpenSync(const base::FilePath& path, int open_flags) { | 91 int FileStream::OpenSync(const base::FilePath& path, int open_flags) { |
84 base::ThreadRestrictions::AssertIOAllowed(); | 92 base::ThreadRestrictions::AssertIOAllowed(); |
85 | 93 |
86 if (IsOpen()) { | 94 if (IsOpen()) { |
87 DLOG(FATAL) << "File is already open!"; | 95 DLOG(FATAL) << "File is already open!"; |
88 return ERR_UNEXPECTED; | 96 return ERR_UNEXPECTED; |
89 } | 97 } |
90 | 98 |
91 open_flags_ = open_flags; | 99 DCHECK(!context_->async()); |
92 DCHECK(!is_async()); | 100 return context_->OpenSync(path, open_flags); |
93 return context_->OpenSync(path, open_flags_); | |
94 } | 101 } |
95 | 102 |
96 int FileStream::Close(const CompletionCallback& callback) { | 103 int FileStream::Close(const CompletionCallback& callback) { |
97 DCHECK(is_async()); | 104 DCHECK(context_->async()); |
98 context_->CloseAsync(callback); | 105 context_->CloseAsync(callback); |
99 return ERR_IO_PENDING; | 106 return ERR_IO_PENDING; |
100 } | 107 } |
101 | 108 |
102 int FileStream::CloseSync() { | 109 int FileStream::CloseSync() { |
103 DCHECK(!is_async()); | 110 DCHECK(!context_->async()); |
104 base::ThreadRestrictions::AssertIOAllowed(); | 111 base::ThreadRestrictions::AssertIOAllowed(); |
105 context_->CloseSync(); | 112 context_->CloseSync(); |
106 return OK; | 113 return OK; |
107 } | 114 } |
108 | 115 |
109 bool FileStream::IsOpen() const { | 116 bool FileStream::IsOpen() const { |
110 return context_->file() != base::kInvalidPlatformFileValue; | 117 return context_->file().IsValid(); |
111 } | 118 } |
112 | 119 |
113 int FileStream::Seek(Whence whence, | 120 int FileStream::Seek(Whence whence, |
114 int64 offset, | 121 int64 offset, |
115 const Int64CompletionCallback& callback) { | 122 const Int64CompletionCallback& callback) { |
116 if (!IsOpen()) | 123 if (!IsOpen()) |
117 return ERR_UNEXPECTED; | 124 return ERR_UNEXPECTED; |
118 | 125 |
119 // Make sure we're async. | 126 // Make sure we're async. |
120 DCHECK(is_async()); | 127 DCHECK(context_->async()); |
121 context_->SeekAsync(whence, offset, callback); | 128 context_->SeekAsync(whence, offset, callback); |
122 return ERR_IO_PENDING; | 129 return ERR_IO_PENDING; |
123 } | 130 } |
124 | 131 |
125 int64 FileStream::SeekSync(Whence whence, int64 offset) { | 132 int64 FileStream::SeekSync(Whence whence, int64 offset) { |
126 base::ThreadRestrictions::AssertIOAllowed(); | 133 base::ThreadRestrictions::AssertIOAllowed(); |
127 | 134 |
128 if (!IsOpen()) | 135 if (!IsOpen()) |
129 return ERR_UNEXPECTED; | 136 return ERR_UNEXPECTED; |
130 | 137 |
131 // If we're in async, make sure we don't have a request in flight. | 138 // If we're in async, make sure we don't have a request in flight. |
132 DCHECK(!is_async() || !context_->async_in_progress()); | 139 DCHECK(!context_->async() || !context_->async_in_progress()); |
133 return context_->SeekSync(whence, offset); | 140 return context_->SeekSync(whence, offset); |
134 } | 141 } |
135 | 142 |
136 int64 FileStream::Available() { | 143 int64 FileStream::Available() { |
137 base::ThreadRestrictions::AssertIOAllowed(); | 144 base::ThreadRestrictions::AssertIOAllowed(); |
138 | 145 |
139 if (!IsOpen()) | 146 if (!IsOpen()) |
140 return ERR_UNEXPECTED; | 147 return ERR_UNEXPECTED; |
141 | 148 |
142 int64 cur_pos = SeekSync(FROM_CURRENT, 0); | 149 int64 cur_pos = SeekSync(FROM_CURRENT, 0); |
143 if (cur_pos < 0) | 150 if (cur_pos < 0) |
144 return cur_pos; | 151 return cur_pos; |
145 | 152 |
146 int64 size = context_->GetFileSize(); | 153 int64 size = context_->GetFileSize(); |
147 if (size < 0) | 154 if (size < 0) |
148 return size; | 155 return size; |
149 | 156 |
150 DCHECK_GE(size, cur_pos); | 157 DCHECK_GE(size, cur_pos); |
151 return size - cur_pos; | 158 return size - cur_pos; |
152 } | 159 } |
153 | 160 |
154 int FileStream::Read(IOBuffer* buf, | 161 int FileStream::Read(IOBuffer* buf, |
155 int buf_len, | 162 int buf_len, |
156 const CompletionCallback& callback) { | 163 const CompletionCallback& callback) { |
157 if (!IsOpen()) | 164 if (!IsOpen()) |
158 return ERR_UNEXPECTED; | 165 return ERR_UNEXPECTED; |
159 | 166 |
160 // read(..., 0) will return 0, which indicates end-of-file. | 167 // read(..., 0) will return 0, which indicates end-of-file. |
161 DCHECK_GT(buf_len, 0); | 168 DCHECK_GT(buf_len, 0); |
162 DCHECK(open_flags_ & base::PLATFORM_FILE_READ); | 169 DCHECK(context_->async()); |
163 DCHECK(is_async()); | |
164 | 170 |
165 return context_->ReadAsync(buf, buf_len, callback); | 171 return context_->ReadAsync(buf, buf_len, callback); |
166 } | 172 } |
167 | 173 |
168 int FileStream::ReadSync(char* buf, int buf_len) { | 174 int FileStream::ReadSync(char* buf, int buf_len) { |
169 base::ThreadRestrictions::AssertIOAllowed(); | 175 base::ThreadRestrictions::AssertIOAllowed(); |
170 | 176 |
171 if (!IsOpen()) | 177 if (!IsOpen()) |
172 return ERR_UNEXPECTED; | 178 return ERR_UNEXPECTED; |
173 | 179 |
174 DCHECK(!is_async()); | 180 DCHECK(!context_->async()); |
175 // read(..., 0) will return 0, which indicates end-of-file. | 181 // read(..., 0) will return 0, which indicates end-of-file. |
176 DCHECK_GT(buf_len, 0); | 182 DCHECK_GT(buf_len, 0); |
177 DCHECK(open_flags_ & base::PLATFORM_FILE_READ); | |
178 | 183 |
179 return context_->ReadSync(buf, buf_len); | 184 return context_->ReadSync(buf, buf_len); |
180 } | 185 } |
181 | 186 |
182 int FileStream::ReadUntilComplete(char *buf, int buf_len) { | 187 int FileStream::ReadUntilComplete(char *buf, int buf_len) { |
183 base::ThreadRestrictions::AssertIOAllowed(); | 188 base::ThreadRestrictions::AssertIOAllowed(); |
184 | 189 |
185 int to_read = buf_len; | 190 int to_read = buf_len; |
186 int bytes_total = 0; | 191 int bytes_total = 0; |
187 | 192 |
(...skipping 13 matching lines...) Expand all Loading... |
201 | 206 |
202 return bytes_total; | 207 return bytes_total; |
203 } | 208 } |
204 | 209 |
205 int FileStream::Write(IOBuffer* buf, | 210 int FileStream::Write(IOBuffer* buf, |
206 int buf_len, | 211 int buf_len, |
207 const CompletionCallback& callback) { | 212 const CompletionCallback& callback) { |
208 if (!IsOpen()) | 213 if (!IsOpen()) |
209 return ERR_UNEXPECTED; | 214 return ERR_UNEXPECTED; |
210 | 215 |
211 DCHECK(is_async()); | 216 DCHECK(context_->async()); |
212 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); | |
213 // write(..., 0) will return 0, which indicates end-of-file. | 217 // write(..., 0) will return 0, which indicates end-of-file. |
214 DCHECK_GT(buf_len, 0); | 218 DCHECK_GT(buf_len, 0); |
215 | 219 |
216 return context_->WriteAsync(buf, buf_len, callback); | 220 return context_->WriteAsync(buf, buf_len, callback); |
217 } | 221 } |
218 | 222 |
219 int FileStream::WriteSync(const char* buf, int buf_len) { | 223 int FileStream::WriteSync(const char* buf, int buf_len) { |
220 base::ThreadRestrictions::AssertIOAllowed(); | 224 base::ThreadRestrictions::AssertIOAllowed(); |
221 | 225 |
222 if (!IsOpen()) | 226 if (!IsOpen()) |
223 return ERR_UNEXPECTED; | 227 return ERR_UNEXPECTED; |
224 | 228 |
225 DCHECK(!is_async()); | 229 DCHECK(!context_->async()); |
226 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); | |
227 // write(..., 0) will return 0, which indicates end-of-file. | 230 // write(..., 0) will return 0, which indicates end-of-file. |
228 DCHECK_GT(buf_len, 0); | 231 DCHECK_GT(buf_len, 0); |
229 | 232 |
230 return context_->WriteSync(buf, buf_len); | 233 return context_->WriteSync(buf, buf_len); |
231 } | 234 } |
232 | 235 |
233 int64 FileStream::Truncate(int64 bytes) { | 236 int64 FileStream::Truncate(int64 bytes) { |
234 base::ThreadRestrictions::AssertIOAllowed(); | 237 base::ThreadRestrictions::AssertIOAllowed(); |
235 | 238 |
236 if (!IsOpen()) | 239 if (!IsOpen()) |
237 return ERR_UNEXPECTED; | 240 return ERR_UNEXPECTED; |
238 | 241 |
239 // We'd better be open for writing. | |
240 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); | |
241 | |
242 // Seek to the position to truncate from. | 242 // Seek to the position to truncate from. |
243 int64 seek_position = SeekSync(FROM_BEGIN, bytes); | 243 int64 seek_position = SeekSync(FROM_BEGIN, bytes); |
244 if (seek_position != bytes) | 244 if (seek_position != bytes) |
245 return ERR_UNEXPECTED; | 245 return ERR_UNEXPECTED; |
246 | 246 |
247 // And truncate the file. | 247 // And truncate the file. |
248 return context_->Truncate(bytes); | 248 return context_->Truncate(bytes); |
249 } | 249 } |
250 | 250 |
251 int FileStream::Flush(const CompletionCallback& callback) { | 251 int FileStream::Flush(const CompletionCallback& callback) { |
252 if (!IsOpen()) | 252 if (!IsOpen()) |
253 return ERR_UNEXPECTED; | 253 return ERR_UNEXPECTED; |
254 | 254 |
255 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); | |
256 // Make sure we're async. | 255 // Make sure we're async. |
257 DCHECK(is_async()); | 256 DCHECK(context_->async()); |
258 | 257 |
259 context_->FlushAsync(callback); | 258 context_->FlushAsync(callback); |
260 return ERR_IO_PENDING; | 259 return ERR_IO_PENDING; |
261 } | 260 } |
262 | 261 |
263 int FileStream::FlushSync() { | 262 int FileStream::FlushSync() { |
264 base::ThreadRestrictions::AssertIOAllowed(); | 263 base::ThreadRestrictions::AssertIOAllowed(); |
265 | 264 |
266 if (!IsOpen()) | 265 if (!IsOpen()) |
267 return ERR_UNEXPECTED; | 266 return ERR_UNEXPECTED; |
268 | 267 |
269 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); | |
270 return context_->FlushSync(); | 268 return context_->FlushSync(); |
271 } | 269 } |
272 | 270 |
273 void FileStream::EnableErrorStatistics() { | 271 void FileStream::EnableErrorStatistics() { |
274 context_->set_record_uma(true); | 272 context_->set_record_uma(true); |
275 } | 273 } |
276 | 274 |
277 void FileStream::SetBoundNetLogSource(const BoundNetLog& owner_bound_net_log) { | 275 void FileStream::SetBoundNetLogSource(const BoundNetLog& owner_bound_net_log) { |
278 if ((owner_bound_net_log.source().id == NetLog::Source::kInvalidId) && | 276 if ((owner_bound_net_log.source().id == NetLog::Source::kInvalidId) && |
279 (bound_net_log_.source().id == NetLog::Source::kInvalidId)) { | 277 (bound_net_log_.source().id == NetLog::Source::kInvalidId)) { |
280 // Both |BoundNetLog|s are invalid. | 278 // Both |BoundNetLog|s are invalid. |
281 return; | 279 return; |
282 } | 280 } |
283 | 281 |
284 // Should never connect to itself. | 282 // Should never connect to itself. |
285 DCHECK_NE(bound_net_log_.source().id, owner_bound_net_log.source().id); | 283 DCHECK_NE(bound_net_log_.source().id, owner_bound_net_log.source().id); |
286 | 284 |
287 bound_net_log_.AddEvent(NetLog::TYPE_FILE_STREAM_BOUND_TO_OWNER, | 285 bound_net_log_.AddEvent(NetLog::TYPE_FILE_STREAM_BOUND_TO_OWNER, |
288 owner_bound_net_log.source().ToEventParametersCallback()); | 286 owner_bound_net_log.source().ToEventParametersCallback()); |
289 | 287 |
290 owner_bound_net_log.AddEvent(NetLog::TYPE_FILE_STREAM_SOURCE, | 288 owner_bound_net_log.AddEvent(NetLog::TYPE_FILE_STREAM_SOURCE, |
291 bound_net_log_.source().ToEventParametersCallback()); | 289 bound_net_log_.source().ToEventParametersCallback()); |
292 } | 290 } |
293 | 291 |
294 base::PlatformFile FileStream::GetPlatformFileForTesting() { | 292 const base::File& FileStream::GetFileForTesting() const { |
295 return context_->file(); | 293 return context_->file(); |
296 } | 294 } |
297 | 295 |
298 } // namespace net | 296 } // namespace net |
OLD | NEW |