| 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 |