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

Unified 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 (pkasting) Created 8 years, 4 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 side-by-side diff with in-line comments
Download patch
Index: webkit/dom_storage/session_storage_database.cc
diff --git a/webkit/dom_storage/session_storage_database.cc b/webkit/dom_storage/session_storage_database.cc
index 0f01db70778f2f2ba0fc43785121b34d76397d9a..da3fb4b952d2369c35f720ec3837ee1a15768a27 100644
--- a/webkit/dom_storage/session_storage_database.cc
+++ b/webkit/dom_storage/session_storage_database.cc
@@ -52,12 +52,20 @@ void SessionStorageDatabase::ReadAreaValues(const std::string& namespace_id,
// nothing to be added to the result.
if (!LazyOpen(false))
return;
+
+ // While ReadAreaValues is in progress, another thread can call
+ // CommitAreaChanges. CommitAreaChanges might update map ref count key while
+ // this thread is iterating over the map ref count key. To protect the reading
+ // operation, create a snapshot and read from it.
+ leveldb::ReadOptions options;
+ options.snapshot = db_->GetSnapshot();
+
std::string map_id;
bool exists;
- if (!GetMapForArea(namespace_id, origin.spec(), &exists, &map_id))
- return;
- if (exists)
- ReadMap(map_id, result, false);
+ if (GetMapForArea(namespace_id, origin.spec(), options, &exists, &map_id) &&
+ exists)
+ ReadMap(map_id, options, result, false);
+ db_->ReleaseSnapshot(options.snapshot);
}
bool SessionStorageDatabase::CommitAreaChanges(const std::string& namespace_id,
@@ -78,7 +86,8 @@ bool SessionStorageDatabase::CommitAreaChanges(const std::string& namespace_id,
std::string map_id;
bool exists;
- if (!GetMapForArea(namespace_id, origin.spec(), &exists, &map_id))
+ if (!GetMapForArea(namespace_id, origin.spec(), leveldb::ReadOptions(),
+ &exists, &map_id))
return false;
if (exists) {
int64 ref_count;
@@ -192,7 +201,9 @@ bool SessionStorageDatabase::ReadNamespaceIds(
std::string namespace_prefix = NamespacePrefix();
scoped_ptr<leveldb::Iterator> it(db_->NewIterator(leveldb::ReadOptions()));
it->Seek(namespace_prefix);
- if (it->status().IsNotFound())
+ // If the key is not found, the status of the iterator won't be IsNotFound(),
+ // but the iterator will be invalid.
+ if (!it->Valid())
return true;
if (!DatabaseErrorCheck(it->status().ok()))
@@ -223,6 +234,17 @@ bool SessionStorageDatabase::ReadNamespaceIds(
return true;
}
+bool SessionStorageDatabase::ReadOriginsInNamespace(
+ const std::string& namespace_id, std::vector<GURL>* origins) {
+ std::map<std::string, std::string> areas;
+ if (!GetAreasInNamespace(namespace_id, &areas))
+ return false;
+ for (std::map<std::string, std::string>::const_iterator it = areas.begin();
+ it != areas.end(); ++it)
+ origins->push_back(GURL(it->first));
+ return true;
+}
+
bool SessionStorageDatabase::LazyOpen(bool create_if_needed) {
base::AutoLock auto_lock(db_lock_);
if (db_error_ || is_inconsistent_) {
@@ -337,7 +359,9 @@ bool SessionStorageDatabase::GetAreasInNamespace(
std::string namespace_start_key = NamespaceStartKey(namespace_id);
scoped_ptr<leveldb::Iterator> it(db_->NewIterator(leveldb::ReadOptions()));
it->Seek(namespace_start_key);
- if (it->status().IsNotFound()) {
+ // If the key is not found, the status of the iterator won't be IsNotFound(),
+ // but the iterator will be invalid.
+ if (!it->Valid()) {
// The namespace_start_key is not found when the namespace doesn't contain
// any areas. We don't need to do anything.
return true;
@@ -373,7 +397,8 @@ bool SessionStorageDatabase::DeleteAreaHelper(
leveldb::WriteBatch* batch) {
std::string map_id;
bool exists;
- if (!GetMapForArea(namespace_id, origin, &exists, &map_id))
+ if (!GetMapForArea(namespace_id, origin, leveldb::ReadOptions(), &exists,
+ &map_id))
return false;
if (!exists)
return true; // Nothing to delete.
@@ -386,9 +411,10 @@ bool SessionStorageDatabase::DeleteAreaHelper(
bool SessionStorageDatabase::GetMapForArea(const std::string& namespace_id,
const std::string& origin,
+ const leveldb::ReadOptions& options,
bool* exists, std::string* map_id) {
std::string namespace_key = NamespaceKey(namespace_id, origin);
- leveldb::Status s = db_->Get(leveldb::ReadOptions(), namespace_key, map_id);
+ leveldb::Status s = db_->Get(options, namespace_key, map_id);
if (s.IsNotFound()) {
*exists = false;
return true;
@@ -421,13 +447,16 @@ bool SessionStorageDatabase::CreateMapForArea(const std::string& namespace_id,
}
bool SessionStorageDatabase::ReadMap(const std::string& map_id,
+ const leveldb::ReadOptions& options,
ValuesMap* result,
bool only_keys) {
- scoped_ptr<leveldb::Iterator> it(db_->NewIterator(leveldb::ReadOptions()));
+ scoped_ptr<leveldb::Iterator> it(db_->NewIterator(options));
std::string map_start_key = MapRefCountKey(map_id);
it->Seek(map_start_key);
- // The map needs to exist, otherwise we have a stale map_id in the database.
- if (!ConsistencyCheck(!it->status().IsNotFound()))
+ // If the key is not found, the status of the iterator won't be IsNotFound(),
+ // but the iterator will be invalid. The map needs to exist, otherwise we have
+ // a stale map_id in the database.
+ if (!ConsistencyCheck(it->Valid()))
return false;
if (!DatabaseErrorCheck(it->status().ok()))
return false;
@@ -518,7 +547,7 @@ bool SessionStorageDatabase::DecreaseMapRefCount(const std::string& map_id,
bool SessionStorageDatabase::ClearMap(const std::string& map_id,
leveldb::WriteBatch* batch) {
ValuesMap values;
- if (!ReadMap(map_id, &values, true))
+ if (!ReadMap(map_id, leveldb::ReadOptions(), &values, true))
return false;
for (ValuesMap::const_iterator it = values.begin(); it != values.end(); ++it)
batch->Delete(MapKey(map_id, UTF16ToUTF8(it->first)));
@@ -549,7 +578,7 @@ bool SessionStorageDatabase::DeepCopyArea(
// Read the values from the old map here. If we don't need to copy the data,
// this can stay empty.
ValuesMap values;
- if (copy_data && !ReadMap(*map_id, &values, false))
+ if (copy_data && !ReadMap(*map_id, leveldb::ReadOptions(), &values, false))
return false;
if (!DecreaseMapRefCount(*map_id, 1, batch))
return false;
« 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