Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 "content/browser/indexed_db/indexed_db_backing_store.h" | 5 #include "content/browser/indexed_db/indexed_db_backing_store.h" |
| 6 | 6 |
| 7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
| 8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
| 9 #include "base/format_macros.h" | 9 #include "base/format_macros.h" |
| 10 #include "base/json/json_reader.h" | 10 #include "base/json/json_reader.h" |
| (...skipping 2142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2153 return s; | 2153 return s; |
| 2154 } | 2154 } |
| 2155 | 2155 |
| 2156 class IndexedDBBackingStore::Transaction::ChainedBlobWriterImpl | 2156 class IndexedDBBackingStore::Transaction::ChainedBlobWriterImpl |
| 2157 : public IndexedDBBackingStore::Transaction::ChainedBlobWriter { | 2157 : public IndexedDBBackingStore::Transaction::ChainedBlobWriter { |
| 2158 public: | 2158 public: |
| 2159 typedef IndexedDBBackingStore::Transaction::WriteDescriptorVec | 2159 typedef IndexedDBBackingStore::Transaction::WriteDescriptorVec |
| 2160 WriteDescriptorVec; | 2160 WriteDescriptorVec; |
| 2161 ChainedBlobWriterImpl( | 2161 ChainedBlobWriterImpl( |
| 2162 int64 database_id, | 2162 int64 database_id, |
| 2163 IndexedDBBackingStore* backingStore, | 2163 IndexedDBBackingStore* backing_store, |
| 2164 WriteDescriptorVec& blobs, | 2164 WriteDescriptorVec& blobs, |
| 2165 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback) | 2165 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback) |
| 2166 : waiting_for_callback_(false), | 2166 : waiting_for_callback_(false), |
| 2167 database_id_(database_id), | 2167 database_id_(database_id), |
| 2168 backing_store_(backingStore), | 2168 backing_store_(backing_store), |
| 2169 callback_(callback), | 2169 callback_(callback), |
| 2170 aborted_(false) { | 2170 aborted_(false) { |
| 2171 blobs_.swap(blobs); | 2171 blobs_.swap(blobs); |
| 2172 iter_ = blobs_.begin(); | 2172 iter_ = blobs_.begin(); |
| 2173 WriteNextFile(); | 2173 backing_store->task_runner()->PostTask( |
| 2174 FROM_HERE, base::Bind(&ChainedBlobWriterImpl::WriteNextFile, this)); | |
| 2174 } | 2175 } |
| 2175 | 2176 |
| 2176 virtual void set_delegate(scoped_ptr<FileWriterDelegate> delegate) OVERRIDE { | 2177 virtual void set_delegate(scoped_ptr<FileWriterDelegate> delegate) OVERRIDE { |
| 2177 delegate_.reset(delegate.release()); | 2178 delegate_.reset(delegate.release()); |
| 2178 } | 2179 } |
| 2179 | 2180 |
| 2180 virtual void ReportWriteCompletion(bool succeeded, | 2181 virtual void ReportWriteCompletion(bool succeeded, |
| 2181 int64 bytes_written) OVERRIDE { | 2182 int64 bytes_written) OVERRIDE { |
| 2182 // TODO(ericu): Check bytes_written against the blob's snapshot value. | |
| 2183 DCHECK(waiting_for_callback_); | 2183 DCHECK(waiting_for_callback_); |
| 2184 DCHECK(!succeeded || bytes_written >= 0); | 2184 DCHECK(!succeeded || bytes_written >= 0); |
| 2185 waiting_for_callback_ = false; | 2185 waiting_for_callback_ = false; |
| 2186 if (delegate_.get()) // Only present for Blob, not File. | 2186 if (delegate_.get()) // Only present for Blob, not File. |
| 2187 content::BrowserThread::DeleteSoon( | 2187 content::BrowserThread::DeleteSoon( |
| 2188 content::BrowserThread::IO, FROM_HERE, delegate_.release()); | 2188 content::BrowserThread::IO, FROM_HERE, delegate_.release()); |
| 2189 if (aborted_) { | 2189 if (aborted_) { |
| 2190 self_ref_ = NULL; | 2190 self_ref_ = NULL; |
| 2191 return; | 2191 return; |
| 2192 } | 2192 } |
| 2193 if (succeeded) | 2193 if (iter_->size() != -1 && iter_->size() != bytes_written) |
| 2194 succeeded = false; | |
| 2195 if (succeeded) { | |
| 2196 ++iter_; | |
| 2194 WriteNextFile(); | 2197 WriteNextFile(); |
| 2195 else | 2198 } else { |
| 2196 callback_->Run(false); | 2199 callback_->Run(false); |
| 2200 } | |
| 2197 } | 2201 } |
| 2198 | 2202 |
| 2199 virtual void Abort() OVERRIDE { | 2203 virtual void Abort() OVERRIDE { |
| 2200 if (!waiting_for_callback_) | 2204 if (!waiting_for_callback_) |
| 2201 return; | 2205 return; |
| 2202 self_ref_ = this; | 2206 self_ref_ = this; |
| 2203 aborted_ = true; | 2207 aborted_ = true; |
| 2204 } | 2208 } |
| 2205 | 2209 |
| 2206 private: | 2210 private: |
| 2207 virtual ~ChainedBlobWriterImpl() {} | 2211 virtual ~ChainedBlobWriterImpl() {} |
| 2208 | 2212 |
| 2209 void WriteNextFile() { | 2213 void WriteNextFile() { |
| 2210 DCHECK(!waiting_for_callback_); | 2214 DCHECK(!waiting_for_callback_); |
| 2211 DCHECK(!aborted_); | 2215 DCHECK(!aborted_); |
| 2212 if (iter_ == blobs_.end()) { | 2216 if (iter_ == blobs_.end()) { |
| 2213 DCHECK(!self_ref_); | 2217 DCHECK(!self_ref_); |
| 2214 callback_->Run(true); | 2218 callback_->Run(true); |
| 2215 return; | 2219 return; |
| 2216 } else { | 2220 } else { |
| 2217 if (!backing_store_->WriteBlobFile(database_id_, *iter_, this)) { | 2221 if (!backing_store_->WriteBlobFile(database_id_, *iter_, this)) { |
| 2218 callback_->Run(false); | 2222 callback_->Run(false); |
| 2219 return; | 2223 return; |
| 2220 } | 2224 } |
| 2221 waiting_for_callback_ = true; | 2225 waiting_for_callback_ = true; |
| 2222 ++iter_; | |
| 2223 } | 2226 } |
| 2224 } | 2227 } |
| 2225 | 2228 |
| 2226 bool waiting_for_callback_; | 2229 bool waiting_for_callback_; |
| 2227 scoped_refptr<ChainedBlobWriterImpl> self_ref_; | 2230 scoped_refptr<ChainedBlobWriterImpl> self_ref_; |
| 2228 WriteDescriptorVec blobs_; | 2231 WriteDescriptorVec blobs_; |
| 2229 WriteDescriptorVec::const_iterator iter_; | 2232 WriteDescriptorVec::const_iterator iter_; |
| 2230 int64 database_id_; | 2233 int64 database_id_; |
| 2231 IndexedDBBackingStore* backing_store_; | 2234 IndexedDBBackingStore* backing_store_; |
| 2232 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback_; | 2235 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback_; |
| 2233 scoped_ptr<FileWriterDelegate> delegate_; | 2236 scoped_ptr<FileWriterDelegate> delegate_; |
| 2234 bool aborted_; | 2237 bool aborted_; |
| 2235 | 2238 |
| 2236 DISALLOW_COPY_AND_ASSIGN(ChainedBlobWriterImpl); | 2239 DISALLOW_COPY_AND_ASSIGN(ChainedBlobWriterImpl); |
| 2237 }; | 2240 }; |
| 2238 | 2241 |
| 2239 class LocalWriteClosure : public FileWriterDelegate::DelegateWriteCallback, | 2242 class LocalWriteClosure : public FileWriterDelegate::DelegateWriteCallback, |
| 2240 public base::RefCounted<LocalWriteClosure> { | 2243 public base::RefCounted<LocalWriteClosure> { |
| 2241 public: | 2244 public: |
| 2242 LocalWriteClosure(IndexedDBBackingStore::Transaction::ChainedBlobWriter* | 2245 LocalWriteClosure(IndexedDBBackingStore::Transaction::ChainedBlobWriter* |
| 2243 chained_blob_writer, | 2246 chained_blob_writer, |
| 2244 base::TaskRunner* task_runner) | 2247 base::TaskRunner* task_runner) |
| 2245 : chained_blob_writer_(chained_blob_writer), | 2248 : chained_blob_writer_(chained_blob_writer), |
| 2246 task_runner_(task_runner), | 2249 task_runner_(task_runner), |
| 2247 bytes_written_(-1) {} | 2250 bytes_written_(0) {} |
| 2248 | 2251 |
| 2249 void Run(base::File::Error rv, | 2252 void Run(base::File::Error rv, |
| 2250 int64 bytes, | 2253 int64 bytes, |
| 2251 FileWriterDelegate::WriteProgressStatus write_status) { | 2254 FileWriterDelegate::WriteProgressStatus write_status) { |
| 2255 DCHECK_GE(bytes, 0); | |
| 2256 bytes_written_ += bytes; | |
| 2252 if (write_status == FileWriterDelegate::SUCCESS_IO_PENDING) | 2257 if (write_status == FileWriterDelegate::SUCCESS_IO_PENDING) |
| 2253 return; // We don't care about progress events. | 2258 return; // We don't care about progress events. |
| 2254 if (rv == base::File::FILE_OK) { | 2259 if (rv == base::File::FILE_OK) { |
| 2255 DCHECK_GE(bytes, 0); | |
| 2256 DCHECK_EQ(write_status, FileWriterDelegate::SUCCESS_COMPLETED); | 2260 DCHECK_EQ(write_status, FileWriterDelegate::SUCCESS_COMPLETED); |
| 2257 bytes_written_ = bytes; | |
| 2258 } else { | 2261 } else { |
| 2259 DCHECK(write_status == FileWriterDelegate::ERROR_WRITE_STARTED || | 2262 DCHECK(write_status == FileWriterDelegate::ERROR_WRITE_STARTED || |
| 2260 write_status == FileWriterDelegate::ERROR_WRITE_NOT_STARTED); | 2263 write_status == FileWriterDelegate::ERROR_WRITE_NOT_STARTED); |
| 2261 } | 2264 } |
| 2262 task_runner_->PostTask( | 2265 task_runner_->PostTask( |
| 2263 FROM_HERE, | 2266 FROM_HERE, |
| 2264 base::Bind(&LocalWriteClosure::callBlobCallbackOnIDBTaskRunner, | 2267 base::Bind(&LocalWriteClosure::callBlobCallbackOnIDBTaskRunner, |
| 2265 this, | 2268 this, |
| 2266 write_status == FileWriterDelegate::SUCCESS_COMPLETED)); | 2269 write_status == FileWriterDelegate::SUCCESS_COMPLETED)); |
| 2267 } | 2270 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2313 | 2316 |
| 2314 FilePath path = GetBlobFileName(database_id, descriptor.key()); | 2317 FilePath path = GetBlobFileName(database_id, descriptor.key()); |
| 2315 | 2318 |
| 2316 if (descriptor.is_file()) { | 2319 if (descriptor.is_file()) { |
| 2317 DCHECK(!descriptor.file_path().empty()); | 2320 DCHECK(!descriptor.file_path().empty()); |
| 2318 if (!base::CopyFile(descriptor.file_path(), path)) | 2321 if (!base::CopyFile(descriptor.file_path(), path)) |
| 2319 return false; | 2322 return false; |
| 2320 | 2323 |
| 2321 base::File::Info info; | 2324 base::File::Info info; |
| 2322 if (base::GetFileInfo(descriptor.file_path(), &info)) { | 2325 if (base::GetFileInfo(descriptor.file_path(), &info)) { |
| 2323 // TODO(ericu): Validate the snapshot date here. Expand WriteDescriptor | 2326 if (descriptor.size() != -1) { |
| 2324 // to include snapshot date and file size, and check both. | 2327 if (descriptor.size() != info.size) |
| 2328 return false; | |
| 2329 // The round-trip can be lossy; round to nearest millisecond. | |
|
jsbell
2014/06/18 23:26:10
This is because we've asked the filesystem for the
ericu
2014/06/18 23:28:44
I believe that's the case. I've hit this before i
| |
| 2330 int64 delta = (descriptor.last_modified() - | |
| 2331 info.last_modified).InMilliseconds(); | |
| 2332 if (std::abs(delta) > 1) | |
| 2333 return false; | |
| 2334 } | |
| 2325 if (!base::TouchFile(path, info.last_accessed, info.last_modified)) { | 2335 if (!base::TouchFile(path, info.last_accessed, info.last_modified)) { |
| 2326 // TODO(ericu): Complain quietly; timestamp's probably not vital. | 2336 // TODO(ericu): Complain quietly; timestamp's probably not vital. |
| 2327 } | 2337 } |
| 2328 } else { | 2338 } else { |
| 2329 // TODO(ericu): Complain quietly; timestamp's probably not vital. | 2339 // TODO(ericu): Complain quietly; timestamp's probably not vital. |
| 2330 } | 2340 } |
| 2331 | 2341 |
| 2332 task_runner_->PostTask( | 2342 task_runner_->PostTask( |
| 2333 FROM_HERE, | 2343 FROM_HERE, |
| 2334 base::Bind(&Transaction::ChainedBlobWriter::ReportWriteCompletion, | 2344 base::Bind(&Transaction::ChainedBlobWriter::ReportWriteCompletion, |
| (...skipping 1534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3869 int64 next_blob_key = -1; | 3879 int64 next_blob_key = -1; |
| 3870 bool result = GetBlobKeyGeneratorCurrentNumber( | 3880 bool result = GetBlobKeyGeneratorCurrentNumber( |
| 3871 pre_transaction.get(), database_id_, &next_blob_key); | 3881 pre_transaction.get(), database_id_, &next_blob_key); |
| 3872 if (!result || next_blob_key < 0) | 3882 if (!result || next_blob_key < 0) |
| 3873 return InternalInconsistencyStatus(); | 3883 return InternalInconsistencyStatus(); |
| 3874 BlobJournalEntryType journal_entry = | 3884 BlobJournalEntryType journal_entry = |
| 3875 std::make_pair(database_id_, next_blob_key); | 3885 std::make_pair(database_id_, next_blob_key); |
| 3876 journal.push_back(journal_entry); | 3886 journal.push_back(journal_entry); |
| 3877 if (info_iter->is_file()) { | 3887 if (info_iter->is_file()) { |
| 3878 new_files_to_write->push_back( | 3888 new_files_to_write->push_back( |
| 3879 WriteDescriptor(info_iter->file_path(), next_blob_key)); | 3889 WriteDescriptor(info_iter->file_path(), |
| 3890 next_blob_key, | |
| 3891 info_iter->size(), | |
| 3892 info_iter->last_modified())); | |
| 3880 } else { | 3893 } else { |
| 3881 new_files_to_write->push_back(WriteDescriptor( | 3894 new_files_to_write->push_back( |
| 3882 getURLFromUUID(info_iter->uuid()), next_blob_key)); | 3895 WriteDescriptor(getURLFromUUID(info_iter->uuid()), |
| 3896 next_blob_key, | |
| 3897 info_iter->size())); | |
| 3883 } | 3898 } |
| 3884 info_iter->set_key(next_blob_key); | 3899 info_iter->set_key(next_blob_key); |
| 3885 new_blob_keys.push_back(&*info_iter); | 3900 new_blob_keys.push_back(&*info_iter); |
| 3886 result = UpdateBlobKeyGeneratorCurrentNumber( | 3901 result = UpdateBlobKeyGeneratorCurrentNumber( |
| 3887 pre_transaction.get(), database_id_, next_blob_key + 1); | 3902 pre_transaction.get(), database_id_, next_blob_key + 1); |
| 3888 if (!result) | 3903 if (!result) |
| 3889 return InternalInconsistencyStatus(); | 3904 return InternalInconsistencyStatus(); |
| 3890 } | 3905 } |
| 3891 BlobEntryKey blob_entry_key; | 3906 BlobEntryKey blob_entry_key; |
| 3892 StringPiece key_piece(iter->second->key()); | 3907 StringPiece key_piece(iter->second->key()); |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4059 | 4074 |
| 4060 | 4075 |
| 4061 class IndexedDBBackingStore::Transaction::BlobWriteCallbackWrapper | 4076 class IndexedDBBackingStore::Transaction::BlobWriteCallbackWrapper |
| 4062 : public IndexedDBBackingStore::BlobWriteCallback { | 4077 : public IndexedDBBackingStore::BlobWriteCallback { |
| 4063 public: | 4078 public: |
| 4064 BlobWriteCallbackWrapper(IndexedDBBackingStore::Transaction* transaction, | 4079 BlobWriteCallbackWrapper(IndexedDBBackingStore::Transaction* transaction, |
| 4065 scoped_refptr<BlobWriteCallback> callback) | 4080 scoped_refptr<BlobWriteCallback> callback) |
| 4066 : transaction_(transaction), callback_(callback) {} | 4081 : transaction_(transaction), callback_(callback) {} |
| 4067 virtual void Run(bool succeeded) OVERRIDE { | 4082 virtual void Run(bool succeeded) OVERRIDE { |
| 4068 callback_->Run(succeeded); | 4083 callback_->Run(succeeded); |
| 4069 transaction_->chained_blob_writer_ = NULL; | 4084 if (succeeded) // Else it's already been deleted during rollback. |
| 4085 transaction_->chained_blob_writer_ = NULL; | |
| 4070 } | 4086 } |
| 4071 | 4087 |
| 4072 private: | 4088 private: |
| 4073 virtual ~BlobWriteCallbackWrapper() {} | 4089 virtual ~BlobWriteCallbackWrapper() {} |
| 4074 friend class base::RefCounted<IndexedDBBackingStore::BlobWriteCallback>; | 4090 friend class base::RefCounted<IndexedDBBackingStore::BlobWriteCallback>; |
| 4075 | 4091 |
| 4076 IndexedDBBackingStore::Transaction* transaction_; | 4092 IndexedDBBackingStore::Transaction* transaction_; |
| 4077 scoped_refptr<BlobWriteCallback> callback_; | 4093 scoped_refptr<BlobWriteCallback> callback_; |
| 4078 | 4094 |
| 4079 DISALLOW_COPY_AND_ASSIGN(BlobWriteCallbackWrapper); | 4095 DISALLOW_COPY_AND_ASSIGN(BlobWriteCallbackWrapper); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4206 record = it->second; | 4222 record = it->second; |
| 4207 } | 4223 } |
| 4208 DCHECK_EQ(record->object_store_id(), object_store_id); | 4224 DCHECK_EQ(record->object_store_id(), object_store_id); |
| 4209 record->SetBlobInfo(blob_info); | 4225 record->SetBlobInfo(blob_info); |
| 4210 record->SetHandles(handles); | 4226 record->SetHandles(handles); |
| 4211 DCHECK(!handles || !handles->size()); | 4227 DCHECK(!handles || !handles->size()); |
| 4212 } | 4228 } |
| 4213 | 4229 |
| 4214 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor( | 4230 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor( |
| 4215 const GURL& url, | 4231 const GURL& url, |
| 4216 int64_t key) | 4232 int64_t key, |
| 4217 : is_file_(false), url_(url), key_(key) {} | 4233 int64_t size) |
| 4234 : is_file_(false), url_(url), key_(key), size_(size) { | |
| 4235 } | |
| 4218 | 4236 |
| 4219 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor( | 4237 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor( |
| 4220 const FilePath& file_path, | 4238 const FilePath& file_path, |
| 4221 int64_t key) | 4239 int64_t key, |
| 4222 : is_file_(true), file_path_(file_path), key_(key) {} | 4240 int64_t size, |
| 4241 base::Time last_modified) | |
| 4242 : is_file_(true), | |
| 4243 file_path_(file_path), | |
| 4244 key_(key), | |
| 4245 size_(size), | |
| 4246 last_modified_(last_modified) { | |
| 4247 } | |
| 4223 | 4248 |
| 4224 } // namespace content | 4249 } // namespace content |
| OLD | NEW |