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

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

Issue 10378066: SessionStorageDatabase: Allow writing data into a shallow copy. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Code review. Created 8 years, 7 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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 // exist. 75 // exist.
76 const bool kOkIfExists = true; 76 const bool kOkIfExists = true;
77 if (!CreateNamespace(namespace_id, kOkIfExists, &batch)) 77 if (!CreateNamespace(namespace_id, kOkIfExists, &batch))
78 return false; 78 return false;
79 79
80 std::string map_id; 80 std::string map_id;
81 bool exists; 81 bool exists;
82 if (!GetMapForArea(namespace_id, origin, &exists, &map_id)) 82 if (!GetMapForArea(namespace_id, origin, &exists, &map_id))
83 return false; 83 return false;
84 if (exists) { 84 if (exists) {
85 // We shouldn't write data into a shallow copy. If this is a shallow copy,
86 // it's a caller error (not an inconsistency in the database).
87 int64 ref_count; 85 int64 ref_count;
88 if (!GetMapRefCount(map_id, &ref_count)) 86 if (!GetMapRefCount(map_id, &ref_count))
89 return false; 87 return false;
90 if (!CallerErrorCheck(ref_count == 1)) 88 if (ref_count > 1) {
91 return false; 89 if (!DeepCopyArea(namespace_id, origin, !clear_all_first,
92 90 &map_id, &batch))
93 if (clear_all_first) { 91 return false;
92 }
93 else if (clear_all_first) {
94 if (!ClearMap(map_id, &batch)) 94 if (!ClearMap(map_id, &batch))
95 return false; 95 return false;
96 } 96 }
97 } else { 97 } else {
98 // Map doesn't exist, create it now if needed. 98 // Map doesn't exist, create it now if needed.
99 if (!changes.empty()) { 99 if (!changes.empty()) {
100 if (!CreateMapForArea(namespace_id, origin, &map_id, &batch)) 100 if (!CreateMapForArea(namespace_id, origin, &map_id, &batch))
101 return false; 101 return false;
102 } 102 }
103 } 103 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 const std::string& origin = it->first; 144 const std::string& origin = it->first;
145 const std::string& map_id = it->second; 145 const std::string& map_id = it->second;
146 if (!IncreaseMapRefCount(map_id, &batch)) 146 if (!IncreaseMapRefCount(map_id, &batch))
147 return false; 147 return false;
148 AddAreaToNamespace(new_namespace_id, origin, map_id, &batch); 148 AddAreaToNamespace(new_namespace_id, origin, map_id, &batch);
149 } 149 }
150 leveldb::Status s = db_->Write(leveldb::WriteOptions(), &batch); 150 leveldb::Status s = db_->Write(leveldb::WriteOptions(), &batch);
151 return DatabaseErrorCheck(s.ok()); 151 return DatabaseErrorCheck(s.ok());
152 } 152 }
153 153
154 bool SessionStorageDatabase::DeepCopyArea(int64 namespace_id,
155 const GURL& origin) {
156 // Example, data before deep copy:
157 // | namespace-1 (1 = namespace id) | dummy |
158 // | namespace-1-origin1 | 1 (mapid) |
159 // | namespace-2 | dummy |
160 // | namespace-2-origin1 | 1 (mapid) << references the same map
161 // | map-1 | 2 (refcount) |
162 // | map-1-a | b |
163
164 // Example, data after deep copy copy:
165 // | namespace-1 (1 = namespace id) | dummy |
166 // | namespace-1-origin1 | 1 (mapid) |
167 // | namespace-2 | dummy |
168 // | namespace-2-origin1 | 2 (mapid) << references the new map
169 // | map-1 | 1 (dec. refcount) |
170 // | map-1-a | b |
171 // | map-2 | 1 (refcount) |
172 // | map-2-a | b |
173
174 if (!LazyOpen(true))
175 return false;
176
177 std::string old_map_id;
178 bool exists;
179 if (!GetMapForArea(namespace_id, origin, &exists, &old_map_id))
180 return false;
181
182 // If the area doesn't exist, or if it's not a shallow copy, it's a caller
183 // error.
184 if (!CallerErrorCheck(exists))
185 return false;
186 int64 ref_count;
187 if (!GetMapRefCount(old_map_id, &ref_count))
188 return false;
189 if (!CallerErrorCheck(ref_count > 1))
190 return false;
191
192 leveldb::WriteBatch batch;
193 std::string new_map_id;
194 if (!CreateMapForArea(namespace_id, origin, &new_map_id, &batch))
195 return false;
196
197 // Copy the values in the map.
198 ValuesMap values;
199 if (!ReadMap(old_map_id, &values, false))
200 return false;
201 WriteValuesToMap(new_map_id, values, &batch);
202
203 if (!DecreaseMapRefCount(old_map_id, 1, &batch))
204 return false;
205
206 leveldb::Status s = db_->Write(leveldb::WriteOptions(), &batch);
207 return DatabaseErrorCheck(s.ok());
208 }
209
210 bool SessionStorageDatabase::DeleteArea(int64 namespace_id, 154 bool SessionStorageDatabase::DeleteArea(int64 namespace_id,
211 const GURL& origin) { 155 const GURL& origin) {
212 if (!LazyOpen(false)) { 156 if (!LazyOpen(false)) {
213 // No need to create the database if it doesn't exist. 157 // No need to create the database if it doesn't exist.
214 return true; 158 return true;
215 } 159 }
216 leveldb::WriteBatch batch; 160 leveldb::WriteBatch batch;
217 if (!DeleteArea(namespace_id, origin.spec(), &batch)) 161 if (!DeleteArea(namespace_id, origin.spec(), &batch))
218 return false; 162 return false;
219 leveldb::Status s = db_->Write(leveldb::WriteOptions(), &batch); 163 leveldb::Status s = db_->Write(leveldb::WriteOptions(), &batch);
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after
596 bool SessionStorageDatabase::ClearMap(const std::string& map_id, 540 bool SessionStorageDatabase::ClearMap(const std::string& map_id,
597 leveldb::WriteBatch* batch) { 541 leveldb::WriteBatch* batch) {
598 ValuesMap values; 542 ValuesMap values;
599 if (!ReadMap(map_id, &values, true)) 543 if (!ReadMap(map_id, &values, true))
600 return false; 544 return false;
601 for (ValuesMap::const_iterator it = values.begin(); it != values.end(); ++it) 545 for (ValuesMap::const_iterator it = values.begin(); it != values.end(); ++it)
602 batch->Delete(MapKey(map_id, UTF16ToUTF8(it->first))); 546 batch->Delete(MapKey(map_id, UTF16ToUTF8(it->first)));
603 return true; 547 return true;
604 } 548 }
605 549
550 bool SessionStorageDatabase::DeepCopyArea(
551 int64 namespace_id, const GURL& origin, bool copy_data,
552 std::string* map_id, leveldb::WriteBatch* batch) {
553 // Example, data before deep copy:
554 // | namespace-1 (1 = namespace id) | dummy |
555 // | namespace-1-origin1 | 1 (mapid) |
556 // | namespace-2 | dummy |
557 // | namespace-2-origin1 | 1 (mapid) << references the same map
558 // | map-1 | 2 (refcount) |
559 // | map-1-a | b |
560
561 // Example, data after deep copy copy:
562 // | namespace-1 (1 = namespace id) | dummy |
563 // | namespace-1-origin1 | 1 (mapid) |
564 // | namespace-2 | dummy |
565 // | namespace-2-origin1 | 2 (mapid) << references the new map
566 // | map-1 | 1 (dec. refcount) |
567 // | map-1-a | b |
568 // | map-2 | 1 (refcount) |
569 // | map-2-a | b |
570
571 // Read the values from the old map here. If we don't need to copy the data,
572 // this can stay empty.
573 ValuesMap values;
574 if (copy_data && !ReadMap(*map_id, &values, false))
575 return false;
576 if (!DecreaseMapRefCount(*map_id, 1, batch))
577 return false;
578 // Create a new map (this will also break the association to the old map) and
579 // write the old data into it. This will write the id of the created map into
580 // |map_id|.
581 if (!CreateMapForArea(namespace_id, origin, map_id, batch))
582 return false;
583 WriteValuesToMap(*map_id, values, batch);
584 return true;
585 }
586
606 std::string SessionStorageDatabase::NamespaceStartKey( 587 std::string SessionStorageDatabase::NamespaceStartKey(
607 const std::string& namespace_id_str) { 588 const std::string& namespace_id_str) {
608 return base::StringPrintf("namespace-%s", namespace_id_str.c_str()); 589 return base::StringPrintf("namespace-%s", namespace_id_str.c_str());
609 } 590 }
610 591
611 std::string SessionStorageDatabase::NamespaceStartKey(int64 namespace_id, 592 std::string SessionStorageDatabase::NamespaceStartKey(int64 namespace_id,
612 int64 namespace_offset) { 593 int64 namespace_offset) {
613 return NamespaceStartKey(NamespaceIdStr(namespace_id, namespace_offset)); 594 return NamespaceStartKey(NamespaceIdStr(namespace_id, namespace_offset));
614 } 595 }
615 596
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
649 630
650 const char* SessionStorageDatabase::NextNamespaceIdKey() { 631 const char* SessionStorageDatabase::NextNamespaceIdKey() {
651 return "next-namespace-id"; 632 return "next-namespace-id";
652 } 633 }
653 634
654 const char* SessionStorageDatabase::NextMapIdKey() { 635 const char* SessionStorageDatabase::NextMapIdKey() {
655 return "next-map-id"; 636 return "next-map-id";
656 } 637 }
657 638
658 } // namespace dom_storage 639 } // namespace dom_storage
OLDNEW
« no previous file with comments | « webkit/dom_storage/session_storage_database.h ('k') | webkit/dom_storage/session_storage_database_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698