| 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 66e502f9a54be7ad6aef8da3f453fc3063f1ca2f..6661bd5a3d85b85387cc0bcc038b72269d71200e 100644
|
| --- a/webkit/dom_storage/session_storage_database.cc
|
| +++ b/webkit/dom_storage/session_storage_database.cc
|
| @@ -41,7 +41,19 @@ SessionStorageDatabase::SessionStorageDatabase(const FilePath& file_path)
|
| : file_path_(file_path),
|
| db_error_(false),
|
| is_inconsistent_(false),
|
| - namespace_offset_(0) {
|
| + next_namespace_id_(0),
|
| + next_negative_namespace_id_(-1) {
|
| +}
|
| +
|
| +SessionStorageDatabase::SessionStorageDatabase(
|
| + const FilePath& file_path,
|
| + const SessionStorageAssociatedCallback& associated_callback)
|
| + : file_path_(file_path),
|
| + db_error_(false),
|
| + is_inconsistent_(false),
|
| + next_namespace_id_(0),
|
| + next_negative_namespace_id_(-1),
|
| + associated_callback_(associated_callback) {
|
| }
|
|
|
| SessionStorageDatabase::~SessionStorageDatabase() {
|
| @@ -159,7 +171,7 @@ bool SessionStorageDatabase::DeleteArea(int64 namespace_id,
|
| return true;
|
| }
|
| leveldb::WriteBatch batch;
|
| - if (!DeleteArea(namespace_id, origin.spec(), &batch))
|
| + if (!DeleteAreaHelper(namespace_id, origin.spec(), &batch))
|
| return false;
|
| leveldb::Status s = db_->Write(leveldb::WriteOptions(), &batch);
|
| return DatabaseErrorCheck(s.ok());
|
| @@ -178,14 +190,68 @@ bool SessionStorageDatabase::DeleteNamespace(int64 namespace_id) {
|
| for (std::map<std::string, std::string>::const_iterator it = areas.begin();
|
| it != areas.end(); ++it) {
|
| const std::string& origin = it->first;
|
| - if (!DeleteArea(namespace_id, origin, &batch))
|
| + if (!DeleteAreaHelper(namespace_id, origin, &batch))
|
| return false;
|
| }
|
| - batch.Delete(NamespaceStartKey(namespace_id, namespace_offset_));
|
| + batch.Delete(NamespaceStartKey(namespace_id));
|
| leveldb::Status s = db_->Write(leveldb::WriteOptions(), &batch);
|
| return DatabaseErrorCheck(s.ok());
|
| }
|
|
|
| +bool SessionStorageDatabase::ReadNamespaceIds(
|
| + std::vector<int64>* namespace_ids) {
|
| + if (!LazyOpen(true))
|
| + return false;
|
| +
|
| + std::string namespace_prefix = NamespacePrefix();
|
| + scoped_ptr<leveldb::Iterator> it(db_->NewIterator(leveldb::ReadOptions()));
|
| + it->Seek(namespace_prefix);
|
| + if (it->status().IsNotFound())
|
| + return true;
|
| +
|
| + if (!DatabaseErrorCheck(it->status().ok()))
|
| + return false;
|
| +
|
| + // Skip the dummy entry "namespace-" and iterate the namespaces.
|
| + for (it->Next(); it->Valid(); it->Next()) {
|
| + std::string key = it->key().ToString();
|
| + if (key.find(namespace_prefix) != 0) {
|
| + // Iterated past the "namespace-" keys.
|
| + break;
|
| + }
|
| + size_t second_dash = key.find('-', namespace_prefix.length());
|
| + if (second_dash != std::string::npos)
|
| + continue;
|
| +
|
| + // The key is of the form "namespace-<namespaceid>".
|
| + std::string namespace_id_str = key.substr(namespace_prefix.length());
|
| + int64 real_namespace_id;
|
| + bool conversion_ok =
|
| + base::StringToInt64(namespace_id_str, &real_namespace_id);
|
| + if (!ConsistencyCheck(conversion_ok))
|
| + return false;
|
| + std::map<int64, int64>::const_iterator it =
|
| + real_id_to_id_.find(real_namespace_id);
|
| + if (it != real_id_to_id_.end()) {
|
| + namespace_ids->push_back(it->second);
|
| + } else {
|
| + // There is no known upper layer ID for this namespace. Create one. (The
|
| + // upper layer will only create positive IDs, so this won't overlap with
|
| + // the IDs created by it.)
|
| + int64 upper_layer_id = next_negative_namespace_id_--;
|
| + AssociateNamespaceId(upper_layer_id, real_namespace_id);
|
| + namespace_ids->push_back(upper_layer_id);
|
| + }
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +void SessionStorageDatabase::AssociateNamespaceId(int64 namespace_id,
|
| + int64 real_id) {
|
| + id_to_real_id_[namespace_id] = real_id;
|
| + real_id_to_id_[real_id] = namespace_id;
|
| +}
|
| +
|
| bool SessionStorageDatabase::LazyOpen(bool create_if_needed) {
|
| base::AutoLock auto_lock(db_lock_);
|
| if (db_error_ || is_inconsistent_) {
|
| @@ -224,8 +290,7 @@ bool SessionStorageDatabase::LazyOpen(bool create_if_needed) {
|
| }
|
| }
|
| db_.reset(db);
|
| -
|
| - return GetNextNamespaceId(&namespace_offset_);
|
| + return GetNextNamespaceId(&next_namespace_id_);
|
| }
|
|
|
| leveldb::Status SessionStorageDatabase::TryToOpen(leveldb::DB** db) {
|
| @@ -284,8 +349,7 @@ bool SessionStorageDatabase::CreateNamespace(int64 namespace_id,
|
| if (s.IsNotFound())
|
| batch->Put(namespace_prefix, "");
|
|
|
| - std::string namespace_start_key =
|
| - NamespaceStartKey(namespace_id, namespace_offset_);
|
| + std::string namespace_start_key = NamespaceStartKey(namespace_id);
|
| s = db_->Get(leveldb::ReadOptions(), namespace_start_key, &dummy);
|
| if (!DatabaseErrorCheck(s.ok() || s.IsNotFound()))
|
| return false;
|
| @@ -316,8 +380,11 @@ bool SessionStorageDatabase::UpdateNextNamespaceId(int64 namespace_id,
|
| int64 next_namespace_id;
|
| if (!GetNextNamespaceId(&next_namespace_id))
|
| return false;
|
| - if (next_namespace_id < namespace_id + namespace_offset_ + 1) {
|
| - next_namespace_id = namespace_id + namespace_offset_ + 1;
|
| + int64 real_id;
|
| + if (!GetRealId(namespace_id, &real_id))
|
| + return false;
|
| + if (next_namespace_id < real_id + 1) {
|
| + next_namespace_id = real_id + 1;
|
| batch->Put(NextNamespaceIdKey(), base::Int64ToString(next_namespace_id));
|
| }
|
| return true;
|
| @@ -326,8 +393,7 @@ bool SessionStorageDatabase::UpdateNextNamespaceId(int64 namespace_id,
|
| bool SessionStorageDatabase::GetAreasInNamespace(
|
| int64 namespace_id,
|
| std::map<std::string, std::string>* areas) {
|
| - return GetAreasInNamespace(NamespaceIdStr(namespace_id, namespace_offset_),
|
| - areas);
|
| + return GetAreasInNamespace(NamespaceIdStr(namespace_id), areas);
|
| }
|
|
|
| bool SessionStorageDatabase::GetAreasInNamespace(
|
| @@ -352,8 +418,8 @@ bool SessionStorageDatabase::GetAreasInNamespace(
|
| break;
|
| }
|
| size_t second_dash = key.find('-', namespace_start_key.length());
|
| - if (!ConsistencyCheck(second_dash != std::string::npos))
|
| - return false;
|
| + if (second_dash == std::string::npos)
|
| + break;
|
| std::string origin = key.substr(second_dash + 1);
|
| std::string map_id = it->value().ToString();
|
| (*areas)[origin] = map_id;
|
| @@ -365,21 +431,21 @@ void SessionStorageDatabase::AddAreaToNamespace(int64 namespace_id,
|
| const std::string& origin,
|
| const std::string& map_id,
|
| leveldb::WriteBatch* batch) {
|
| - std::string namespace_key = NamespaceKey(
|
| - NamespaceIdStr(namespace_id, namespace_offset_), origin);
|
| + std::string namespace_key =
|
| + NamespaceKey(NamespaceIdStr(namespace_id), origin);
|
| batch->Put(namespace_key, map_id);
|
| }
|
|
|
| -bool SessionStorageDatabase::DeleteArea(int64 namespace_id,
|
| - const std::string& origin,
|
| - leveldb::WriteBatch* batch) {
|
| - return DeleteArea(NamespaceIdStr(namespace_id, namespace_offset_),
|
| - origin, batch);
|
| +bool SessionStorageDatabase::DeleteAreaHelper(int64 namespace_id,
|
| + const std::string& origin,
|
| + leveldb::WriteBatch* batch) {
|
| + return DeleteAreaHelper(NamespaceIdStr(namespace_id), origin, batch);
|
| }
|
|
|
| -bool SessionStorageDatabase::DeleteArea(const std::string& namespace_id_str,
|
| - const std::string& origin,
|
| - leveldb::WriteBatch* batch) {
|
| +bool SessionStorageDatabase::DeleteAreaHelper(
|
| + const std::string& namespace_id_str,
|
| + const std::string& origin,
|
| + leveldb::WriteBatch* batch) {
|
| std::string map_id;
|
| bool exists;
|
| if (!GetMapForArea(namespace_id_str, origin, &exists, &map_id))
|
| @@ -397,9 +463,11 @@ bool SessionStorageDatabase::GetMapForArea(int64 namespace_id,
|
| const GURL& origin,
|
| bool* exists,
|
| std::string* map_id) {
|
| - return GetMapForArea(
|
| - base::Int64ToString(namespace_id + namespace_offset_),
|
| - origin.spec(), exists, map_id);
|
| + int64 real_id;
|
| + if (!GetRealId(namespace_id, &real_id))
|
| + return false;
|
| + return GetMapForArea(base::Int64ToString(real_id), origin.spec(),
|
| + exists, map_id);
|
| }
|
|
|
| bool SessionStorageDatabase::GetMapForArea(const std::string& namespace_id_str,
|
| @@ -432,8 +500,7 @@ bool SessionStorageDatabase::CreateMapForArea(int64 namespace_id,
|
| return false;
|
| }
|
| batch->Put(next_map_id_key, base::Int64ToString(++next_map_id));
|
| - std::string namespace_key =
|
| - NamespaceKey(namespace_id, namespace_offset_, origin);
|
| + std::string namespace_key = NamespaceKey(namespace_id, origin);
|
| batch->Put(namespace_key, *map_id);
|
| batch->Put(MapRefCountKey(*map_id), "1");
|
| return true;
|
| @@ -584,14 +651,36 @@ bool SessionStorageDatabase::DeepCopyArea(
|
| return true;
|
| }
|
|
|
| +bool SessionStorageDatabase::AllocateNamespaceId(int64* namespace_id) {
|
| + if (!LazyOpen(true))
|
| + return false;
|
| + *namespace_id = next_namespace_id_++;
|
| + // The next namespace id field in the db will be increased when data is
|
| + // actually written to the namespace.
|
| + return true;
|
| +}
|
| +
|
| +bool SessionStorageDatabase::GetRealId(int64 namespace_id, int64* real_id) {
|
| + std::map<int64, int64>::const_iterator it = id_to_real_id_.find(namespace_id);
|
| + if (it != id_to_real_id_.end()) {
|
| + *real_id = it->second;
|
| + return true;
|
| + }
|
| + if (!AllocateNamespaceId(real_id))
|
| + return false;
|
| + if (!associated_callback_.is_null())
|
| + associated_callback_.Run(namespace_id, *real_id);
|
| + AssociateNamespaceId(namespace_id, *real_id);
|
| + return true;
|
| +}
|
| +
|
| std::string SessionStorageDatabase::NamespaceStartKey(
|
| const std::string& namespace_id_str) {
|
| return base::StringPrintf("namespace-%s", namespace_id_str.c_str());
|
| }
|
|
|
| -std::string SessionStorageDatabase::NamespaceStartKey(int64 namespace_id,
|
| - int64 namespace_offset) {
|
| - return NamespaceStartKey(NamespaceIdStr(namespace_id, namespace_offset));
|
| +std::string SessionStorageDatabase::NamespaceStartKey(int64 namespace_id) {
|
| + return NamespaceStartKey(NamespaceIdStr(namespace_id));
|
| }
|
|
|
| std::string SessionStorageDatabase::NamespaceKey(
|
| @@ -600,15 +689,16 @@ std::string SessionStorageDatabase::NamespaceKey(
|
| origin.c_str());
|
| }
|
|
|
| -std::string SessionStorageDatabase::NamespaceKey(
|
| - int64 namespace_id, int64 namespace_offset, const GURL& origin) {
|
| - return NamespaceKey(NamespaceIdStr(namespace_id, namespace_offset),
|
| - origin.spec());
|
| +std::string SessionStorageDatabase::NamespaceKey(int64 namespace_id,
|
| + const GURL& origin) {
|
| + return NamespaceKey(NamespaceIdStr(namespace_id), origin.spec());
|
| }
|
|
|
| -std::string SessionStorageDatabase::NamespaceIdStr(int64 namespace_id,
|
| - int64 namespace_offset) {
|
| - return base::Int64ToString(namespace_id + namespace_offset);
|
| +std::string SessionStorageDatabase::NamespaceIdStr(int64 namespace_id) {
|
| + int64 real_id;
|
| + if (!GetRealId(namespace_id, &real_id))
|
| + return "";
|
| + return base::Int64ToString(real_id);
|
| }
|
|
|
| const char* SessionStorageDatabase::NamespacePrefix() {
|
|
|