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 |