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

Side by Side Diff: webkit/dom_storage/session_storage_database.cc

Issue 9963107: Persist sessionStorage on disk. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Code review. Created 8 years, 6 months 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) 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 "webkit/dom_storage/session_storage_database.h" 5 #include "webkit/dom_storage/session_storage_database.h"
6 6
7 #include "base/file_util.h" 7 #include "base/file_util.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/stringprintf.h" 9 #include "base/stringprintf.h"
10 #include "base/string_number_conversions.h" 10 #include "base/string_number_conversions.h"
(...skipping 14 matching lines...) Expand all
25 // | namespace- | dummy (start of namespace-* keys) | 25 // | namespace- | dummy (start of namespace-* keys) |
26 // | namespace-1- (1 = namespace id)| dummy (start of namespace-1-* keys)| 26 // | namespace-1- (1 = namespace id)| dummy (start of namespace-1-* keys)|
27 // | namespace-1-origin1 | 1 (mapid) | 27 // | namespace-1-origin1 | 1 (mapid) |
28 // | namespace-1-origin2 | 2 | 28 // | namespace-1-origin2 | 2 |
29 // | namespace-2- | dummy | 29 // | namespace-2- | dummy |
30 // | namespace-2-origin1 | 1 (shallow copy) | 30 // | namespace-2-origin1 | 1 (shallow copy) |
31 // | namespace-2-origin2 | 2 (shallow copy) | 31 // | namespace-2-origin2 | 2 (shallow copy) |
32 // | namespace-3- | dummy | 32 // | namespace-3- | dummy |
33 // | namespace-3-origin1 | 3 (deep copy) | 33 // | namespace-3-origin1 | 3 (deep copy) |
34 // | namespace-3-origin2 | 2 (shallow copy) | 34 // | namespace-3-origin2 | 2 (shallow copy) |
35 // | next-namespace-id | 4 |
36 // | next-map-id | 4 | 35 // | next-map-id | 4 |
37 36
38 namespace dom_storage { 37 namespace dom_storage {
39 38
40 SessionStorageDatabase::SessionStorageDatabase(const FilePath& file_path) 39 SessionStorageDatabase::SessionStorageDatabase(const FilePath& file_path)
41 : file_path_(file_path), 40 : file_path_(file_path),
42 db_error_(false), 41 db_error_(false),
43 is_inconsistent_(false), 42 is_inconsistent_(false) {
44 namespace_offset_(0) {
45 } 43 }
46 44
47 SessionStorageDatabase::~SessionStorageDatabase() { 45 SessionStorageDatabase::~SessionStorageDatabase() {
48 } 46 }
49 47
50 void SessionStorageDatabase::ReadAreaValues(int64 namespace_id, 48 void SessionStorageDatabase::ReadAreaValues(const std::string& namespace_id,
51 const GURL& origin, 49 const GURL& origin,
52 ValuesMap* result) { 50 ValuesMap* result) {
53 // We don't create a database if it doesn't exist. In that case, there is 51 // We don't create a database if it doesn't exist. In that case, there is
54 // nothing to be added to the result. 52 // nothing to be added to the result.
55 if (!LazyOpen(false)) 53 if (!LazyOpen(false))
56 return; 54 return;
57 std::string map_id; 55 std::string map_id;
58 bool exists; 56 bool exists;
59 if (!GetMapForArea(namespace_id, origin, &exists, &map_id)) 57 if (!GetMapForArea(namespace_id, origin.spec(), &exists, &map_id))
60 return; 58 return;
61 if (exists) 59 if (exists)
62 ReadMap(map_id, result, false); 60 ReadMap(map_id, result, false);
63 } 61 }
64 62
65 bool SessionStorageDatabase::CommitAreaChanges(int64 namespace_id, 63 bool SessionStorageDatabase::CommitAreaChanges(const std::string& namespace_id,
66 const GURL& origin, 64 const GURL& origin,
67 bool clear_all_first, 65 bool clear_all_first,
68 const ValuesMap& changes) { 66 const ValuesMap& changes) {
69 // Even if |changes| is empty, we need to write the appropriate placeholders 67 // Even if |changes| is empty, we need to write the appropriate placeholders
70 // in the database, so that it can be later shallow-copied succssfully. 68 // in the database, so that it can be later shallow-copied succssfully.
71 if (!LazyOpen(true)) 69 if (!LazyOpen(true))
72 return false; 70 return false;
73 71
74 leveldb::WriteBatch batch; 72 leveldb::WriteBatch batch;
75 // Ensure that the keys "namespace-" "namespace-N" (see the schema above) 73 // Ensure that the keys "namespace-" "namespace-N" (see the schema above)
76 // exist. 74 // exist.
77 const bool kOkIfExists = true; 75 const bool kOkIfExists = true;
78 if (!CreateNamespace(namespace_id, kOkIfExists, &batch)) 76 if (!CreateNamespace(namespace_id, kOkIfExists, &batch))
79 return false; 77 return false;
80 78
81 std::string map_id; 79 std::string map_id;
82 bool exists; 80 bool exists;
83 if (!GetMapForArea(namespace_id, origin, &exists, &map_id)) 81 if (!GetMapForArea(namespace_id, origin.spec(), &exists, &map_id))
84 return false; 82 return false;
85 if (exists) { 83 if (exists) {
86 int64 ref_count; 84 int64 ref_count;
87 if (!GetMapRefCount(map_id, &ref_count)) 85 if (!GetMapRefCount(map_id, &ref_count))
88 return false; 86 return false;
89 if (ref_count > 1) { 87 if (ref_count > 1) {
90 if (!DeepCopyArea(namespace_id, origin, !clear_all_first, 88 if (!DeepCopyArea(namespace_id, origin, !clear_all_first,
91 &map_id, &batch)) 89 &map_id, &batch))
92 return false; 90 return false;
93 } 91 }
94 else if (clear_all_first) { 92 else if (clear_all_first) {
95 if (!ClearMap(map_id, &batch)) 93 if (!ClearMap(map_id, &batch))
96 return false; 94 return false;
97 } 95 }
98 } else { 96 } else {
99 // Map doesn't exist, create it now if needed. 97 // Map doesn't exist, create it now if needed.
100 if (!changes.empty()) { 98 if (!changes.empty()) {
101 if (!CreateMapForArea(namespace_id, origin, &map_id, &batch)) 99 if (!CreateMapForArea(namespace_id, origin, &map_id, &batch))
102 return false; 100 return false;
103 } 101 }
104 } 102 }
105 103
106 WriteValuesToMap(map_id, changes, &batch); 104 WriteValuesToMap(map_id, changes, &batch);
107 105
108 leveldb::Status s = db_->Write(leveldb::WriteOptions(), &batch); 106 leveldb::Status s = db_->Write(leveldb::WriteOptions(), &batch);
109 return DatabaseErrorCheck(s.ok()); 107 return DatabaseErrorCheck(s.ok());
110 } 108 }
111 109
112 bool SessionStorageDatabase::CloneNamespace(int64 namespace_id, 110 bool SessionStorageDatabase::CloneNamespace(
113 int64 new_namespace_id) { 111 const std::string& namespace_id, const std::string& new_namespace_id) {
114 // Go through all origins in the namespace |namespace_id|, create placeholders 112 // Go through all origins in the namespace |namespace_id|, create placeholders
115 // for them in |new_namespace_id|, and associate them with the existing maps. 113 // for them in |new_namespace_id|, and associate them with the existing maps.
116 114
117 // Example, data before shallow copy: 115 // Example, data before shallow copy:
118 // | map-1- | 1 (refcount) | 116 // | map-1- | 1 (refcount) |
119 // | map-1-a | b | 117 // | map-1-a | b |
120 // | namespace-1- (1 = namespace id)| dummy | 118 // | namespace-1- (1 = namespace id)| dummy |
121 // | namespace-1-origin1 | 1 (mapid) | 119 // | namespace-1-origin1 | 1 (mapid) |
122 120
123 // Example, data after shallow copy: 121 // Example, data after shallow copy:
(...skipping 21 matching lines...) Expand all
145 const std::string& origin = it->first; 143 const std::string& origin = it->first;
146 const std::string& map_id = it->second; 144 const std::string& map_id = it->second;
147 if (!IncreaseMapRefCount(map_id, &batch)) 145 if (!IncreaseMapRefCount(map_id, &batch))
148 return false; 146 return false;
149 AddAreaToNamespace(new_namespace_id, origin, map_id, &batch); 147 AddAreaToNamespace(new_namespace_id, origin, map_id, &batch);
150 } 148 }
151 leveldb::Status s = db_->Write(leveldb::WriteOptions(), &batch); 149 leveldb::Status s = db_->Write(leveldb::WriteOptions(), &batch);
152 return DatabaseErrorCheck(s.ok()); 150 return DatabaseErrorCheck(s.ok());
153 } 151 }
154 152
155 bool SessionStorageDatabase::DeleteArea(int64 namespace_id, 153 bool SessionStorageDatabase::DeleteArea(const std::string& namespace_id,
156 const GURL& origin) { 154 const GURL& origin) {
157 if (!LazyOpen(false)) { 155 if (!LazyOpen(false)) {
158 // No need to create the database if it doesn't exist. 156 // No need to create the database if it doesn't exist.
159 return true; 157 return true;
160 } 158 }
161 leveldb::WriteBatch batch; 159 leveldb::WriteBatch batch;
162 if (!DeleteArea(namespace_id, origin.spec(), &batch)) 160 if (!DeleteAreaHelper(namespace_id, origin.spec(), &batch))
163 return false; 161 return false;
164 leveldb::Status s = db_->Write(leveldb::WriteOptions(), &batch); 162 leveldb::Status s = db_->Write(leveldb::WriteOptions(), &batch);
165 return DatabaseErrorCheck(s.ok()); 163 return DatabaseErrorCheck(s.ok());
166 } 164 }
167 165
168 bool SessionStorageDatabase::DeleteNamespace(int64 namespace_id) { 166 bool SessionStorageDatabase::DeleteNamespace(const std::string& namespace_id) {
169 if (!LazyOpen(false)) { 167 if (!LazyOpen(false)) {
170 // No need to create the database if it doesn't exist. 168 // No need to create the database if it doesn't exist.
171 return true; 169 return true;
172 } 170 }
173 // Itereate through the areas in the namespace. 171 // Itereate through the areas in the namespace.
174 leveldb::WriteBatch batch; 172 leveldb::WriteBatch batch;
175 std::map<std::string, std::string> areas; 173 std::map<std::string, std::string> areas;
176 if (!GetAreasInNamespace(namespace_id, &areas)) 174 if (!GetAreasInNamespace(namespace_id, &areas))
177 return false; 175 return false;
178 for (std::map<std::string, std::string>::const_iterator it = areas.begin(); 176 for (std::map<std::string, std::string>::const_iterator it = areas.begin();
179 it != areas.end(); ++it) { 177 it != areas.end(); ++it) {
180 const std::string& origin = it->first; 178 const std::string& origin = it->first;
181 if (!DeleteArea(namespace_id, origin, &batch)) 179 if (!DeleteAreaHelper(namespace_id, origin, &batch))
182 return false; 180 return false;
183 } 181 }
184 batch.Delete(NamespaceStartKey(namespace_id, namespace_offset_)); 182 batch.Delete(NamespaceStartKey(namespace_id));
185 leveldb::Status s = db_->Write(leveldb::WriteOptions(), &batch); 183 leveldb::Status s = db_->Write(leveldb::WriteOptions(), &batch);
186 return DatabaseErrorCheck(s.ok()); 184 return DatabaseErrorCheck(s.ok());
187 } 185 }
188 186
187 bool SessionStorageDatabase::ReadNamespaceIds(
188 std::vector<std::string>* namespace_ids) {
189 if (!LazyOpen(true))
190 return false;
191
192 std::string namespace_prefix = NamespacePrefix();
193 scoped_ptr<leveldb::Iterator> it(db_->NewIterator(leveldb::ReadOptions()));
194 it->Seek(namespace_prefix);
195 if (it->status().IsNotFound())
196 return true;
197
198 if (!DatabaseErrorCheck(it->status().ok()))
199 return false;
200
201 // Skip the dummy entry "namespace-" and iterate the namespaces.
202 std::string current_namespace_start_key;
203 for (it->Next(); it->Valid(); it->Next()) {
204 std::string key = it->key().ToString();
205 if (key.find(namespace_prefix) != 0) {
206 // Iterated past the "namespace-" keys.
207 break;
208 }
209 // For each namespace, the first key is "namespace-<namespaceid>-", and the
210 // subsequent keys are "namespace-<namespaceid>-<origin>". Read the unique
211 // "<namespaceid>" parts from the keys.
212 if (current_namespace_start_key.empty() ||
213 key.substr(0, current_namespace_start_key.length()) !=
214 current_namespace_start_key) {
215 // The key is of the form "namespace-<namespaceid>-" for a new
216 // <namespaceid>.
217 current_namespace_start_key = key;
218 namespace_ids->push_back(
219 key.substr(namespace_prefix.length(),
220 key.length() - namespace_prefix.length()));
221 }
222 }
223 return true;
224 }
225
189 bool SessionStorageDatabase::LazyOpen(bool create_if_needed) { 226 bool SessionStorageDatabase::LazyOpen(bool create_if_needed) {
190 base::AutoLock auto_lock(db_lock_); 227 base::AutoLock auto_lock(db_lock_);
191 if (db_error_ || is_inconsistent_) { 228 if (db_error_ || is_inconsistent_) {
192 // Don't try to open a database that we know has failed already. 229 // Don't try to open a database that we know has failed already.
193 return false; 230 return false;
194 } 231 }
195 if (IsOpen()) 232 if (IsOpen())
196 return true; 233 return true;
197 234
198 if (!create_if_needed && 235 if (!create_if_needed &&
(...skipping 18 matching lines...) Expand all
217 s = TryToOpen(&db); 254 s = TryToOpen(&db);
218 if (!s.ok()) { 255 if (!s.ok()) {
219 LOG(WARNING) << "Failed to open leveldb in " << file_path_.value() 256 LOG(WARNING) << "Failed to open leveldb in " << file_path_.value()
220 << ", error: " << s.ToString(); 257 << ", error: " << s.ToString();
221 DCHECK(db == NULL); 258 DCHECK(db == NULL);
222 db_error_ = true; 259 db_error_ = true;
223 return false; 260 return false;
224 } 261 }
225 } 262 }
226 db_.reset(db); 263 db_.reset(db);
227 264 return true;
228 return GetNextNamespaceId(&namespace_offset_);
229 } 265 }
230 266
231 leveldb::Status SessionStorageDatabase::TryToOpen(leveldb::DB** db) { 267 leveldb::Status SessionStorageDatabase::TryToOpen(leveldb::DB** db) {
232 leveldb::Options options; 268 leveldb::Options options;
233 // The directory exists but a valid leveldb database might not exist inside it 269 // The directory exists but a valid leveldb database might not exist inside it
234 // (e.g., a subset of the needed files might be missing). Handle this 270 // (e.g., a subset of the needed files might be missing). Handle this
235 // situation gracefully by creating the database now. 271 // situation gracefully by creating the database now.
236 options.create_if_missing = true; 272 options.create_if_missing = true;
237 #if defined(OS_WIN) 273 #if defined(OS_WIN)
238 return leveldb::DB::Open(options, WideToUTF8(file_path_.value()), db); 274 return leveldb::DB::Open(options, WideToUTF8(file_path_.value()), db);
(...skipping 26 matching lines...) Expand all
265 301
266 bool SessionStorageDatabase::DatabaseErrorCheck(bool ok) { 302 bool SessionStorageDatabase::DatabaseErrorCheck(bool ok) {
267 if (ok) 303 if (ok)
268 return true; 304 return true;
269 base::AutoLock auto_lock(db_lock_); 305 base::AutoLock auto_lock(db_lock_);
270 db_error_ = true; 306 db_error_ = true;
271 // TODO(marja): Error handling. 307 // TODO(marja): Error handling.
272 return false; 308 return false;
273 } 309 }
274 310
275 bool SessionStorageDatabase::CreateNamespace(int64 namespace_id, 311 bool SessionStorageDatabase::CreateNamespace(const std::string& namespace_id,
276 bool ok_if_exists, 312 bool ok_if_exists,
277 leveldb::WriteBatch* batch) { 313 leveldb::WriteBatch* batch) {
278 leveldb::Slice namespace_prefix = NamespacePrefix(); 314 leveldb::Slice namespace_prefix = NamespacePrefix();
279 std::string dummy; 315 std::string dummy;
280 leveldb::Status s = db_->Get(leveldb::ReadOptions(), namespace_prefix, 316 leveldb::Status s = db_->Get(leveldb::ReadOptions(), namespace_prefix,
281 &dummy); 317 &dummy);
282 if (!DatabaseErrorCheck(s.ok() || s.IsNotFound())) 318 if (!DatabaseErrorCheck(s.ok() || s.IsNotFound()))
283 return false; 319 return false;
284 if (s.IsNotFound()) 320 if (s.IsNotFound())
285 batch->Put(namespace_prefix, ""); 321 batch->Put(namespace_prefix, "");
286 322
287 std::string namespace_start_key = 323 std::string namespace_start_key = NamespaceStartKey(namespace_id);
288 NamespaceStartKey(namespace_id, namespace_offset_);
289 s = db_->Get(leveldb::ReadOptions(), namespace_start_key, &dummy); 324 s = db_->Get(leveldb::ReadOptions(), namespace_start_key, &dummy);
290 if (!DatabaseErrorCheck(s.ok() || s.IsNotFound())) 325 if (!DatabaseErrorCheck(s.ok() || s.IsNotFound()))
291 return false; 326 return false;
292 if (s.IsNotFound()) { 327 if (s.IsNotFound()) {
293 batch->Put(namespace_start_key, ""); 328 batch->Put(namespace_start_key, "");
294 return UpdateNextNamespaceId(namespace_id, batch); 329 return true;
295 } 330 }
296 return CallerErrorCheck(ok_if_exists); 331 return CallerErrorCheck(ok_if_exists);
297 } 332 }
298 333
299 bool SessionStorageDatabase::GetNextNamespaceId(int64* next_namespace_id) {
300 std::string next_namespace_id_string;
301 leveldb::Status s = db_->Get(leveldb::ReadOptions(), NextNamespaceIdKey(),
302 &next_namespace_id_string);
303 if (!DatabaseErrorCheck(s.ok() || s.IsNotFound()))
304 return false;
305 if (s.IsNotFound()) {
306 *next_namespace_id = 0;
307 return true;
308 }
309 bool conversion_ok =
310 base::StringToInt64(next_namespace_id_string, next_namespace_id);
311 return ConsistencyCheck(conversion_ok);
312 }
313
314 bool SessionStorageDatabase::UpdateNextNamespaceId(int64 namespace_id,
315 leveldb::WriteBatch* batch) {
316 int64 next_namespace_id;
317 if (!GetNextNamespaceId(&next_namespace_id))
318 return false;
319 if (next_namespace_id < namespace_id + namespace_offset_ + 1) {
320 next_namespace_id = namespace_id + namespace_offset_ + 1;
321 batch->Put(NextNamespaceIdKey(), base::Int64ToString(next_namespace_id));
322 }
323 return true;
324 }
325
326 bool SessionStorageDatabase::GetAreasInNamespace( 334 bool SessionStorageDatabase::GetAreasInNamespace(
327 int64 namespace_id, 335 const std::string& namespace_id,
328 std::map<std::string, std::string>* areas) { 336 std::map<std::string, std::string>* areas) {
329 return GetAreasInNamespace(NamespaceIdStr(namespace_id, namespace_offset_), 337 std::string namespace_start_key = NamespaceStartKey(namespace_id);
330 areas);
331 }
332
333 bool SessionStorageDatabase::GetAreasInNamespace(
334 const std::string& namespace_id_str,
335 std::map<std::string, std::string>* areas) {
336 std::string namespace_start_key = NamespaceStartKey(namespace_id_str);
337 scoped_ptr<leveldb::Iterator> it(db_->NewIterator(leveldb::ReadOptions())); 338 scoped_ptr<leveldb::Iterator> it(db_->NewIterator(leveldb::ReadOptions()));
338 it->Seek(namespace_start_key); 339 it->Seek(namespace_start_key);
339 if (it->status().IsNotFound()) { 340 if (it->status().IsNotFound()) {
340 // The namespace_start_key is not found when the namespace doesn't contain 341 // The namespace_start_key is not found when the namespace doesn't contain
341 // any areas. We don't need to do anything. 342 // any areas. We don't need to do anything.
342 return true; 343 return true;
343 } 344 }
344 if (!DatabaseErrorCheck(it->status().ok())) 345 if (!DatabaseErrorCheck(it->status().ok()))
345 return false; 346 return false;
346 347
347 // Skip the dummy entry "namespace-<namespaceid>-" and iterate the origins. 348 // Skip the dummy entry "namespace-<namespaceid>-" and iterate the origins.
348 for (it->Next(); it->Valid(); it->Next()) { 349 for (it->Next(); it->Valid(); it->Next()) {
349 std::string key = it->key().ToString(); 350 std::string key = it->key().ToString();
350 if (key.find(namespace_start_key) != 0) { 351 if (key.find(namespace_start_key) != 0) {
351 // Iterated past the origins for this namespace. 352 // Iterated past the origins for this namespace.
352 break; 353 break;
353 } 354 }
354 std::string origin = key.substr(namespace_start_key.length()); 355 std::string origin = key.substr(namespace_start_key.length());
355 std::string map_id = it->value().ToString(); 356 std::string map_id = it->value().ToString();
356 (*areas)[origin] = map_id; 357 (*areas)[origin] = map_id;
357 } 358 }
358 return true; 359 return true;
359 } 360 }
360 361
361 void SessionStorageDatabase::AddAreaToNamespace(int64 namespace_id, 362 void SessionStorageDatabase::AddAreaToNamespace(const std::string& namespace_id,
362 const std::string& origin, 363 const std::string& origin,
363 const std::string& map_id, 364 const std::string& map_id,
364 leveldb::WriteBatch* batch) { 365 leveldb::WriteBatch* batch) {
365 std::string namespace_key = NamespaceKey( 366 std::string namespace_key = NamespaceKey(namespace_id, origin);
366 NamespaceIdStr(namespace_id, namespace_offset_), origin);
367 batch->Put(namespace_key, map_id); 367 batch->Put(namespace_key, map_id);
368 } 368 }
369 369
370 bool SessionStorageDatabase::DeleteArea(int64 namespace_id, 370 bool SessionStorageDatabase::DeleteAreaHelper(
371 const std::string& origin, 371 const std::string& namespace_id,
372 leveldb::WriteBatch* batch) { 372 const std::string& origin,
373 return DeleteArea(NamespaceIdStr(namespace_id, namespace_offset_), 373 leveldb::WriteBatch* batch) {
374 origin, batch);
375 }
376
377 bool SessionStorageDatabase::DeleteArea(const std::string& namespace_id_str,
378 const std::string& origin,
379 leveldb::WriteBatch* batch) {
380 std::string map_id; 374 std::string map_id;
381 bool exists; 375 bool exists;
382 if (!GetMapForArea(namespace_id_str, origin, &exists, &map_id)) 376 if (!GetMapForArea(namespace_id, origin, &exists, &map_id))
383 return false; 377 return false;
384 if (!exists) 378 if (!exists)
385 return true; // Nothing to delete. 379 return true; // Nothing to delete.
386 if (!DecreaseMapRefCount(map_id, 1, batch)) 380 if (!DecreaseMapRefCount(map_id, 1, batch))
387 return false; 381 return false;
388 std::string namespace_key = NamespaceKey(namespace_id_str, origin); 382 std::string namespace_key = NamespaceKey(namespace_id, origin);
389 batch->Delete(namespace_key); 383 batch->Delete(namespace_key);
390 return true; 384 return true;
391 } 385 }
392 386
393 bool SessionStorageDatabase::GetMapForArea(int64 namespace_id, 387 bool SessionStorageDatabase::GetMapForArea(const std::string& namespace_id,
394 const GURL& origin,
395 bool* exists,
396 std::string* map_id) {
397 return GetMapForArea(
398 base::Int64ToString(namespace_id + namespace_offset_),
399 origin.spec(), exists, map_id);
400 }
401
402 bool SessionStorageDatabase::GetMapForArea(const std::string& namespace_id_str,
403 const std::string& origin, 388 const std::string& origin,
404 bool* exists, std::string* map_id) { 389 bool* exists, std::string* map_id) {
405 std::string namespace_key = NamespaceKey(namespace_id_str, origin); 390 std::string namespace_key = NamespaceKey(namespace_id, origin);
406 leveldb::Status s = db_->Get(leveldb::ReadOptions(), namespace_key, map_id); 391 leveldb::Status s = db_->Get(leveldb::ReadOptions(), namespace_key, map_id);
407 if (s.IsNotFound()) { 392 if (s.IsNotFound()) {
408 *exists = false; 393 *exists = false;
409 return true; 394 return true;
410 } 395 }
411 *exists = true; 396 *exists = true;
412 return DatabaseErrorCheck(s.ok()); 397 return DatabaseErrorCheck(s.ok());
413 } 398 }
414 399
415 bool SessionStorageDatabase::CreateMapForArea(int64 namespace_id, 400 bool SessionStorageDatabase::CreateMapForArea(const std::string& namespace_id,
416 const GURL& origin, 401 const GURL& origin,
417 std::string* map_id, 402 std::string* map_id,
418 leveldb::WriteBatch* batch) { 403 leveldb::WriteBatch* batch) {
419 leveldb::Slice next_map_id_key = NextMapIdKey(); 404 leveldb::Slice next_map_id_key = NextMapIdKey();
420 leveldb::Status s = db_->Get(leveldb::ReadOptions(), next_map_id_key, map_id); 405 leveldb::Status s = db_->Get(leveldb::ReadOptions(), next_map_id_key, map_id);
421 if (!DatabaseErrorCheck(s.ok() || s.IsNotFound())) 406 if (!DatabaseErrorCheck(s.ok() || s.IsNotFound()))
422 return false; 407 return false;
423 int64 next_map_id = 0; 408 int64 next_map_id = 0;
424 if (s.IsNotFound()) { 409 if (s.IsNotFound()) {
425 *map_id = "0"; 410 *map_id = "0";
426 } else { 411 } else {
427 bool conversion_ok = base::StringToInt64(*map_id, &next_map_id); 412 bool conversion_ok = base::StringToInt64(*map_id, &next_map_id);
428 if (!ConsistencyCheck(conversion_ok)) 413 if (!ConsistencyCheck(conversion_ok))
429 return false; 414 return false;
430 } 415 }
431 batch->Put(next_map_id_key, base::Int64ToString(++next_map_id)); 416 batch->Put(next_map_id_key, base::Int64ToString(++next_map_id));
432 std::string namespace_key = 417 std::string namespace_key = NamespaceKey(namespace_id, origin.spec());
433 NamespaceKey(namespace_id, namespace_offset_, origin);
434 batch->Put(namespace_key, *map_id); 418 batch->Put(namespace_key, *map_id);
435 batch->Put(MapRefCountKey(*map_id), "1"); 419 batch->Put(MapRefCountKey(*map_id), "1");
436 return true; 420 return true;
437 } 421 }
438 422
439 bool SessionStorageDatabase::ReadMap(const std::string& map_id, 423 bool SessionStorageDatabase::ReadMap(const std::string& map_id,
440 ValuesMap* result, 424 ValuesMap* result,
441 bool only_keys) { 425 bool only_keys) {
442 scoped_ptr<leveldb::Iterator> it(db_->NewIterator(leveldb::ReadOptions())); 426 scoped_ptr<leveldb::Iterator> it(db_->NewIterator(leveldb::ReadOptions()));
443 std::string map_start_key = MapRefCountKey(map_id); 427 std::string map_start_key = MapRefCountKey(map_id);
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
535 leveldb::WriteBatch* batch) { 519 leveldb::WriteBatch* batch) {
536 ValuesMap values; 520 ValuesMap values;
537 if (!ReadMap(map_id, &values, true)) 521 if (!ReadMap(map_id, &values, true))
538 return false; 522 return false;
539 for (ValuesMap::const_iterator it = values.begin(); it != values.end(); ++it) 523 for (ValuesMap::const_iterator it = values.begin(); it != values.end(); ++it)
540 batch->Delete(MapKey(map_id, UTF16ToUTF8(it->first))); 524 batch->Delete(MapKey(map_id, UTF16ToUTF8(it->first)));
541 return true; 525 return true;
542 } 526 }
543 527
544 bool SessionStorageDatabase::DeepCopyArea( 528 bool SessionStorageDatabase::DeepCopyArea(
545 int64 namespace_id, const GURL& origin, bool copy_data, 529 const std::string& namespace_id, const GURL& origin, bool copy_data,
546 std::string* map_id, leveldb::WriteBatch* batch) { 530 std::string* map_id, leveldb::WriteBatch* batch) {
547 // Example, data before deep copy: 531 // Example, data before deep copy:
548 // | namespace-1- (1 = namespace id)| dummy | 532 // | namespace-1- (1 = namespace id)| dummy |
549 // | namespace-1-origin1 | 1 (mapid) | 533 // | namespace-1-origin1 | 1 (mapid) |
550 // | namespace-2- | dummy | 534 // | namespace-2- | dummy |
551 // | namespace-2-origin1 | 1 (mapid) << references the same map 535 // | namespace-2-origin1 | 1 (mapid) << references the same map
552 // | map-1- | 2 (refcount) | 536 // | map-1- | 2 (refcount) |
553 // | map-1-a | b | 537 // | map-1-a | b |
554 538
555 // Example, data after deep copy copy: 539 // Example, data after deep copy copy:
(...skipping 16 matching lines...) Expand all
572 // Create a new map (this will also break the association to the old map) and 556 // Create a new map (this will also break the association to the old map) and
573 // write the old data into it. This will write the id of the created map into 557 // write the old data into it. This will write the id of the created map into
574 // |map_id|. 558 // |map_id|.
575 if (!CreateMapForArea(namespace_id, origin, map_id, batch)) 559 if (!CreateMapForArea(namespace_id, origin, map_id, batch))
576 return false; 560 return false;
577 WriteValuesToMap(*map_id, values, batch); 561 WriteValuesToMap(*map_id, values, batch);
578 return true; 562 return true;
579 } 563 }
580 564
581 std::string SessionStorageDatabase::NamespaceStartKey( 565 std::string SessionStorageDatabase::NamespaceStartKey(
582 const std::string& namespace_id_str) { 566 const std::string& namespace_id) {
583 return base::StringPrintf("namespace-%s-", namespace_id_str.c_str()); 567 return base::StringPrintf("namespace-%s-", namespace_id.c_str());
584 }
585
586 std::string SessionStorageDatabase::NamespaceStartKey(int64 namespace_id,
587 int64 namespace_offset) {
588 return NamespaceStartKey(NamespaceIdStr(namespace_id, namespace_offset));
589 } 568 }
590 569
591 std::string SessionStorageDatabase::NamespaceKey( 570 std::string SessionStorageDatabase::NamespaceKey(
592 const std::string& namespace_id_str, const std::string& origin) { 571 const std::string& namespace_id, const std::string& origin) {
593 return base::StringPrintf("namespace-%s-%s", namespace_id_str.c_str(), 572 return base::StringPrintf("namespace-%s-%s", namespace_id.c_str(),
594 origin.c_str()); 573 origin.c_str());
595 } 574 }
596 575
597 std::string SessionStorageDatabase::NamespaceKey(
598 int64 namespace_id, int64 namespace_offset, const GURL& origin) {
599 return NamespaceKey(NamespaceIdStr(namespace_id, namespace_offset),
600 origin.spec());
601 }
602
603 std::string SessionStorageDatabase::NamespaceIdStr(int64 namespace_id,
604 int64 namespace_offset) {
605 return base::Int64ToString(namespace_id + namespace_offset);
606 }
607
608 const char* SessionStorageDatabase::NamespacePrefix() { 576 const char* SessionStorageDatabase::NamespacePrefix() {
609 return "namespace-"; 577 return "namespace-";
610 } 578 }
611 579
612 std::string SessionStorageDatabase::MapRefCountKey(const std::string& map_id) { 580 std::string SessionStorageDatabase::MapRefCountKey(const std::string& map_id) {
613 return base::StringPrintf("map-%s-", map_id.c_str()); 581 return base::StringPrintf("map-%s-", map_id.c_str());
614 } 582 }
615 583
616 std::string SessionStorageDatabase::MapKey(const std::string& map_id, 584 std::string SessionStorageDatabase::MapKey(const std::string& map_id,
617 const std::string& key) { 585 const std::string& key) {
618 return base::StringPrintf("map-%s-%s", map_id.c_str(), key.c_str()); 586 return base::StringPrintf("map-%s-%s", map_id.c_str(), key.c_str());
619 } 587 }
620 588
621 const char* SessionStorageDatabase::NextNamespaceIdKey() {
622 return "next-namespace-id";
623 }
624
625 const char* SessionStorageDatabase::NextMapIdKey() { 589 const char* SessionStorageDatabase::NextMapIdKey() {
626 return "next-map-id"; 590 return "next-map-id";
627 } 591 }
628 592
629 } // namespace dom_storage 593 } // namespace dom_storage
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698