Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(221)

Side by Side Diff: content/browser/indexed_db/indexed_db_factory.cc

Issue 18023022: Blob support for IDB [Chromium] (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Settle on one name for the live blob journal. Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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_factory.h" 5 #include "content/browser/indexed_db/indexed_db_factory.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/strings/utf_string_conversions.h" 8 #include "base/strings/utf_string_conversions.h"
9 #include "base/time/time.h" 9 #include "base/time/time.h"
10 #include "content/browser/indexed_db/indexed_db_backing_store.h" 10 #include "content/browser/indexed_db/indexed_db_backing_store.h"
(...skipping 23 matching lines...) Expand all
34 34
35 // No grace period on a forced-close, as the initiator is 35 // No grace period on a forced-close, as the initiator is
36 // assuming the backing store will be released once all 36 // assuming the backing store will be released once all
37 // connections are closed. 37 // connections are closed.
38 ReleaseBackingStore(origin_url, forcedClose); 38 ReleaseBackingStore(origin_url, forcedClose);
39 } 39 }
40 40
41 void IndexedDBFactory::ReleaseBackingStore(const GURL& origin_url, 41 void IndexedDBFactory::ReleaseBackingStore(const GURL& origin_url,
42 bool immediate) { 42 bool immediate) {
43 // Only close if this is the last reference. 43 // Only close if this is the last reference.
44 if (!HasLastBackingStoreReference(origin_url)) 44 if (!HasLastBackingStoreReference(origin_url, immediate))
45 return; 45 return;
46 46
47 // If this factory does hold the last reference to the backing store, it can 47 // If this factory does hold the last reference to the backing store, it can
48 // be closed - but unless requested to close it immediately, keep it around 48 // be closed - but unless requested to close it immediately, keep it around
49 // for a short period so that a re-open is fast. 49 // for a short period so that a re-open is fast.
50 if (immediate) { 50 if (immediate) {
51 CloseBackingStore(origin_url); 51 CloseBackingStore(origin_url);
52 return; 52 return;
53 } 53 }
54 54
55 // Start a timer to close the backing store, unless something else opens it 55 // Start a timer to close the backing store, unless something else opens it
56 // in the mean time. 56 // in the mean time.
57 DCHECK(!backing_store_map_[origin_url]->close_timer()->IsRunning()); 57 DCHECK(!backing_store_map_[origin_url]->close_timer()->IsRunning());
58 backing_store_map_[origin_url]->close_timer()->Start( 58 backing_store_map_[origin_url]->close_timer()->Start(
59 FROM_HERE, 59 FROM_HERE,
60 base::TimeDelta::FromMilliseconds(kBackingStoreGracePeriodMs), 60 base::TimeDelta::FromMilliseconds(kBackingStoreGracePeriodMs),
61 base::Bind(&IndexedDBFactory::MaybeCloseBackingStore, this, origin_url)); 61 base::Bind(&IndexedDBFactory::MaybeCloseBackingStore, this, origin_url));
62 } 62 }
63 63
64 void IndexedDBFactory::MaybeCloseBackingStore(const GURL& origin_url) { 64 void IndexedDBFactory::MaybeCloseBackingStore(const GURL& origin_url) {
65 // Another reference may have opened since the maybe-close was posted, so it 65 // Another reference may have opened since the maybe-close was posted, so it
66 // is necessary to check again. 66 // is necessary to check again.
67 if (HasLastBackingStoreReference(origin_url)) 67 if (HasLastBackingStoreReference(origin_url, false))
68 CloseBackingStore(origin_url); 68 CloseBackingStore(origin_url);
69 } 69 }
70 70
71 void IndexedDBFactory::CloseBackingStore(const GURL& origin_url) { 71 void IndexedDBFactory::CloseBackingStore(const GURL& origin_url) {
72 IndexedDBBackingStoreMap::iterator it = backing_store_map_.find(origin_url); 72 IndexedDBBackingStoreMap::iterator it = backing_store_map_.find(origin_url);
73 DCHECK(it != backing_store_map_.end()); 73 DCHECK(it != backing_store_map_.end());
74 // Stop the timer (if it's running) - this may happen if the timer was started 74 // Stop the timer (if it's running) - this may happen if the timer was started
75 // and then a forced close occurs. 75 // and then a forced close occurs.
76 it->second->close_timer()->Stop(); 76 it->second->close_timer()->Stop();
77 backing_store_map_.erase(it); 77 backing_store_map_.erase(it);
78 } 78 }
79 79
80 bool IndexedDBFactory::HasLastBackingStoreReference(const GURL& origin_url) 80 bool IndexedDBFactory::HasLastBackingStoreReference(const GURL& origin_url,
81 const { 81 bool forcedClose) const {
82 IndexedDBBackingStore* ptr; 82 IndexedDBBackingStore* ptr;
83 { 83 {
84 // Scope so that the implicit scoped_refptr<> is freed. 84 // Scope so that the implicit scoped_refptr<> is freed.
85 IndexedDBBackingStoreMap::const_iterator it = 85 IndexedDBBackingStoreMap::const_iterator it =
86 backing_store_map_.find(origin_url); 86 backing_store_map_.find(origin_url);
87 DCHECK(it != backing_store_map_.end()); 87 DCHECK(it != backing_store_map_.end());
88 ptr = it->second.get(); 88 ptr = it->second.get();
89 } 89 }
90 if (ptr->HasOneRef())
91 return true;
92 if (!forcedClose)
93 return false;
94 ptr->active_blob_registry()->ForceShutdown();
jsbell 2013/12/03 00:10:03 Hrm, unfortunate placement (in a Has.... method).
jsbell 2013/12/03 00:11:24 ISTM this is a good reason to move away from relyi
ericu 2013/12/03 02:03:55 It's idempotent, but currently assumes that once i
ericu 2013/12/03 02:03:55 I'm fine with that too; this code I've put in feel
90 return ptr->HasOneRef(); 95 return ptr->HasOneRef();
91 } 96 }
92 97
93 void IndexedDBFactory::ContextDestroyed() { 98 void IndexedDBFactory::ContextDestroyed() {
94 // Timers on backing stores hold a reference to this factory. When the 99 // Timers on backing stores hold a reference to this factory. When the
95 // context (which nominally owns this factory) is destroyed during thread 100 // context (which nominally owns this factory) is destroyed during thread
96 // termination the timers must be stopped so that this factory and the 101 // termination the timers must be stopped so that this factory and the
97 // stores can be disposed of. 102 // stores can be disposed of.
98 for (IndexedDBBackingStoreMap::iterator it = backing_store_map_.begin(); 103 for (IndexedDBBackingStoreMap::iterator it = backing_store_map_.begin();
99 it != backing_store_map_.end(); 104 it != backing_store_map_.end();
100 ++it) 105 ++it)
101 it->second->close_timer()->Stop(); 106 it->second->close_timer()->Stop();
102 backing_store_map_.clear(); 107 backing_store_map_.clear();
103 context_ = NULL; 108 context_ = NULL;
104 } 109 }
105 110
106 void IndexedDBFactory::GetDatabaseNames( 111 void IndexedDBFactory::GetDatabaseNames(
107 scoped_refptr<IndexedDBCallbacks> callbacks, 112 scoped_refptr<IndexedDBCallbacks> callbacks,
108 const GURL& origin_url, 113 const GURL& origin_url,
109 const base::FilePath& data_directory) { 114 const base::FilePath& data_directory,
115 base::TaskRunner* task_runner) {
110 IDB_TRACE("IndexedDBFactory::GetDatabaseNames"); 116 IDB_TRACE("IndexedDBFactory::GetDatabaseNames");
111 // TODO(dgrogan): Plumb data_loss back to script eventually? 117 // TODO(dgrogan): Plumb data_loss back to script eventually?
112 blink::WebIDBDataLoss data_loss; 118 blink::WebIDBDataLoss data_loss;
113 std::string data_loss_message; 119 std::string data_loss_message;
114 bool disk_full; 120 bool disk_full;
115 scoped_refptr<IndexedDBBackingStore> backing_store = 121 scoped_refptr<IndexedDBBackingStore> backing_store =
116 OpenBackingStore(origin_url, 122 OpenBackingStore(origin_url,
117 data_directory, 123 data_directory,
124 NULL,
118 &data_loss, 125 &data_loss,
119 &data_loss_message, 126 &data_loss_message,
120 &disk_full); 127 &disk_full,
128 task_runner);
121 if (!backing_store) { 129 if (!backing_store) {
122 callbacks->OnError( 130 callbacks->OnError(
123 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, 131 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
124 "Internal error opening backing store for " 132 "Internal error opening backing store for "
125 "indexedDB.webkitGetDatabaseNames.")); 133 "indexedDB.webkitGetDatabaseNames."));
126 return; 134 return;
127 } 135 }
128 136
129 callbacks->OnSuccess(backing_store->GetDatabaseNames()); 137 callbacks->OnSuccess(backing_store->GetDatabaseNames());
130 } 138 }
131 139
132 void IndexedDBFactory::DeleteDatabase( 140 void IndexedDBFactory::DeleteDatabase(
133 const string16& name, 141 const string16& name,
142 net::URLRequestContext* request_context,
134 scoped_refptr<IndexedDBCallbacks> callbacks, 143 scoped_refptr<IndexedDBCallbacks> callbacks,
135 const GURL& origin_url, 144 const GURL& origin_url,
136 const base::FilePath& data_directory) { 145 const base::FilePath& data_directory,
146 base::TaskRunner* task_runner) {
137 IDB_TRACE("IndexedDBFactory::DeleteDatabase"); 147 IDB_TRACE("IndexedDBFactory::DeleteDatabase");
138 IndexedDBDatabase::Identifier unique_identifier(origin_url, name); 148 IndexedDBDatabase::Identifier unique_identifier(origin_url, name);
139 IndexedDBDatabaseMap::iterator it = database_map_.find(unique_identifier); 149 IndexedDBDatabaseMap::iterator it = database_map_.find(unique_identifier);
140 if (it != database_map_.end()) { 150 if (it != database_map_.end()) {
141 // If there are any connections to the database, directly delete the 151 // If there are any connections to the database, directly delete the
142 // database. 152 // database.
143 it->second->DeleteDatabase(callbacks); 153 it->second->DeleteDatabase(callbacks);
144 return; 154 return;
145 } 155 }
146 156
147 // TODO(dgrogan): Plumb data_loss back to script eventually? 157 // TODO(dgrogan): Plumb data_loss back to script eventually?
148 blink::WebIDBDataLoss data_loss; 158 blink::WebIDBDataLoss data_loss;
149 std::string data_loss_message; 159 std::string data_loss_message;
150 bool disk_full = false; 160 bool disk_full = false;
151 scoped_refptr<IndexedDBBackingStore> backing_store = 161 scoped_refptr<IndexedDBBackingStore> backing_store =
152 OpenBackingStore(origin_url, 162 OpenBackingStore(origin_url,
153 data_directory, 163 data_directory,
164 request_context,
154 &data_loss, 165 &data_loss,
155 &data_loss_message, 166 &data_loss_message,
156 &disk_full); 167 &disk_full,
168 task_runner);
157 if (!backing_store) { 169 if (!backing_store) {
158 callbacks->OnError( 170 callbacks->OnError(
159 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, 171 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
160 ASCIIToUTF16( 172 ASCIIToUTF16(
161 "Internal error opening backing store " 173 "Internal error opening backing store "
162 "for indexedDB.deleteDatabase."))); 174 "for indexedDB.deleteDatabase.")));
163 return; 175 return;
164 } 176 }
165 177
166 scoped_refptr<IndexedDBDatabase> database = 178 scoped_refptr<IndexedDBDatabase> database =
(...skipping 20 matching lines...) Expand all
187 } 199 }
188 200
189 bool IndexedDBFactory::IsBackingStoreOpenForTesting(const GURL& origin_url) 201 bool IndexedDBFactory::IsBackingStoreOpenForTesting(const GURL& origin_url)
190 const { 202 const {
191 return backing_store_map_.find(origin_url) != backing_store_map_.end(); 203 return backing_store_map_.find(origin_url) != backing_store_map_.end();
192 } 204 }
193 205
194 scoped_refptr<IndexedDBBackingStore> IndexedDBFactory::OpenBackingStore( 206 scoped_refptr<IndexedDBBackingStore> IndexedDBFactory::OpenBackingStore(
195 const GURL& origin_url, 207 const GURL& origin_url,
196 const base::FilePath& data_directory, 208 const base::FilePath& data_directory,
209 net::URLRequestContext* request_context,
197 blink::WebIDBDataLoss* data_loss, 210 blink::WebIDBDataLoss* data_loss,
198 std::string* data_loss_message, 211 std::string* data_loss_message,
199 bool* disk_full) { 212 bool* disk_full,
213 base::TaskRunner* task_runner) {
200 const bool open_in_memory = data_directory.empty(); 214 const bool open_in_memory = data_directory.empty();
201 215
202 IndexedDBBackingStoreMap::iterator it2 = backing_store_map_.find(origin_url); 216 IndexedDBBackingStoreMap::iterator it2 = backing_store_map_.find(origin_url);
203 if (it2 != backing_store_map_.end()) { 217 if (it2 != backing_store_map_.end()) {
204 it2->second->close_timer()->Stop(); 218 it2->second->close_timer()->Stop();
205 return it2->second; 219 return it2->second;
206 } 220 }
207 221
208 scoped_refptr<IndexedDBBackingStore> backing_store; 222 scoped_refptr<IndexedDBBackingStore> backing_store;
223 bool first_time = false;
209 if (open_in_memory) { 224 if (open_in_memory) {
225 // TODO(ericu): Support blobs in in-memory backends.
210 backing_store = IndexedDBBackingStore::OpenInMemory(origin_url); 226 backing_store = IndexedDBBackingStore::OpenInMemory(origin_url);
211 } else { 227 } else {
212 backing_store = IndexedDBBackingStore::Open(origin_url, 228 first_time = !backends_opened_since_boot_.count(origin_url);
229 backing_store = IndexedDBBackingStore::Open(this,
230 origin_url,
213 data_directory, 231 data_directory,
232 request_context,
214 data_loss, 233 data_loss,
215 data_loss_message, 234 data_loss_message,
216 disk_full); 235 disk_full,
236 task_runner,
237 first_time);
217 } 238 }
218 239
219 if (backing_store.get()) { 240 if (backing_store.get()) {
241 if (first_time)
242 backends_opened_since_boot_.insert(origin_url);
220 backing_store_map_[origin_url] = backing_store; 243 backing_store_map_[origin_url] = backing_store;
221 // If an in-memory database, bind lifetime to this factory instance. 244 // If an in-memory database, bind lifetime to this factory instance.
222 if (open_in_memory) 245 if (open_in_memory)
223 session_only_backing_stores_.insert(backing_store); 246 session_only_backing_stores_.insert(backing_store);
224 247
225 // All backing stores associated with this factory should be of the same 248 // All backing stores associated with this factory should be of the same
226 // type. 249 // type.
227 DCHECK(session_only_backing_stores_.empty() || open_in_memory); 250 DCHECK(session_only_backing_stores_.empty() != open_in_memory);
228 251
229 return backing_store; 252 return backing_store;
230 } 253 }
231 254
232 return 0; 255 return 0;
233 } 256 }
234 257
235 void IndexedDBFactory::Open( 258 void IndexedDBFactory::Open(
236 const string16& name, 259 const string16& name,
237 int64 version, 260 int64 version,
261 net::URLRequestContext* request_context,
238 int64 transaction_id, 262 int64 transaction_id,
239 scoped_refptr<IndexedDBCallbacks> callbacks, 263 scoped_refptr<IndexedDBCallbacks> callbacks,
240 scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks, 264 scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
241 const GURL& origin_url, 265 const GURL& origin_url,
242 const base::FilePath& data_directory) { 266 const base::FilePath& data_directory,
267 int child_process_id,
268 base::TaskRunner* task_runner) {
243 IDB_TRACE("IndexedDBFactory::Open"); 269 IDB_TRACE("IndexedDBFactory::Open");
244 scoped_refptr<IndexedDBDatabase> database; 270 scoped_refptr<IndexedDBDatabase> database;
245 IndexedDBDatabase::Identifier unique_identifier(origin_url, name); 271 IndexedDBDatabase::Identifier unique_identifier(origin_url, name);
246 IndexedDBDatabaseMap::iterator it = database_map_.find(unique_identifier); 272 IndexedDBDatabaseMap::iterator it = database_map_.find(unique_identifier);
247 blink::WebIDBDataLoss data_loss = 273 blink::WebIDBDataLoss data_loss =
248 blink::WebIDBDataLossNone; 274 blink::WebIDBDataLossNone;
249 std::string data_loss_message; 275 std::string data_loss_message;
250 bool disk_full = false; 276 bool disk_full = false;
251 if (it == database_map_.end()) { 277 if (it == database_map_.end()) {
252 scoped_refptr<IndexedDBBackingStore> backing_store = 278 scoped_refptr<IndexedDBBackingStore> backing_store =
253 OpenBackingStore(origin_url, 279 OpenBackingStore(origin_url,
254 data_directory, 280 data_directory,
281 request_context,
255 &data_loss, 282 &data_loss,
256 &data_loss_message, 283 &data_loss_message,
257 &disk_full); 284 &disk_full,
285 task_runner);
258 if (!backing_store) { 286 if (!backing_store) {
259 if (disk_full) { 287 if (disk_full) {
260 callbacks->OnError( 288 callbacks->OnError(
261 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionQuotaError, 289 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionQuotaError,
262 ASCIIToUTF16( 290 ASCIIToUTF16(
263 "Encountered full disk while opening " 291 "Encountered full disk while opening "
264 "backing store for indexedDB.open."))); 292 "backing store for indexedDB.open.")));
265 return; 293 return;
266 } 294 }
267 callbacks->OnError(IndexedDBDatabaseError( 295 callbacks->OnError(IndexedDBDatabaseError(
(...skipping 13 matching lines...) Expand all
281 return; 309 return;
282 } 310 }
283 311
284 database_map_[unique_identifier] = database; 312 database_map_[unique_identifier] = database;
285 } else { 313 } else {
286 database = it->second; 314 database = it->second;
287 } 315 }
288 316
289 database->OpenConnection(callbacks, 317 database->OpenConnection(callbacks,
290 database_callbacks, 318 database_callbacks,
319 child_process_id,
291 transaction_id, 320 transaction_id,
292 version, 321 version,
293 data_loss, 322 data_loss,
294 data_loss_message); 323 data_loss_message);
295 } 324 }
296 325
297 std::vector<IndexedDBDatabase*> IndexedDBFactory::GetOpenDatabasesForOrigin( 326 std::vector<IndexedDBDatabase*> IndexedDBFactory::GetOpenDatabasesForOrigin(
298 const GURL& origin_url) const { 327 const GURL& origin_url) const {
299 std::vector<IndexedDBDatabase*> result; 328 std::vector<IndexedDBDatabase*> result;
300 for (IndexedDBDatabaseMap::const_iterator it = database_map_.begin(); 329 for (IndexedDBDatabaseMap::const_iterator it = database_map_.begin();
301 it != database_map_.end(); 330 it != database_map_.end();
302 ++it) { 331 ++it) {
303 if (it->first.first == origin_url) 332 if (it->first.first == origin_url)
304 result.push_back(it->second.get()); 333 result.push_back(it->second.get());
305 } 334 }
306 return result; 335 return result;
307 } 336 }
308 337
309 } // namespace content 338 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/indexed_db/indexed_db_factory.h ('k') | content/browser/indexed_db/indexed_db_index_writer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698