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() { |