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