OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |