diff -r 000000000000 -r 6474c204b198 dom/indexedDB/DatabaseInfo.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dom/indexedDB/DatabaseInfo.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,269 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "DatabaseInfo.h" + +#include "nsDataHashtable.h" +#include "nsThreadUtils.h" + +USING_INDEXEDDB_NAMESPACE + +namespace { + +typedef nsDataHashtable + DatabaseHash; + +DatabaseHash* gDatabaseHash = nullptr; + +PLDHashOperator +EnumerateObjectStoreNames(const nsAString& aKey, + ObjectStoreInfo* aData, + void* aUserArg) +{ + nsTArray* array = static_cast*>(aUserArg); + if (!array->InsertElementSorted(aData->name)) { + NS_ERROR("Out of memory?"); + return PL_DHASH_STOP; + } + return PL_DHASH_NEXT; +} + +PLDHashOperator +CloneObjectStoreInfo(const nsAString& aKey, + ObjectStoreInfo* aData, + void* aUserArg) +{ + ObjectStoreInfoHash* hash = static_cast(aUserArg); + + nsRefPtr newInfo(new ObjectStoreInfo(*aData)); + + hash->Put(aKey, newInfo); + + return PL_DHASH_NEXT; +} + +} + +DatabaseInfo::~DatabaseInfo() +{ + // Clones are never in the hash. + if (!cloned) { + DatabaseInfo::Remove(id); + } +} + +ObjectStoreInfo::ObjectStoreInfo(ObjectStoreInfo& aOther) +: nextAutoIncrementId(aOther.nextAutoIncrementId), + comittedAutoIncrementId(aOther.comittedAutoIncrementId) +{ + *static_cast(this) = + static_cast(aOther); + + // Doesn't copy the refcount + MOZ_COUNT_CTOR(ObjectStoreInfo); +} + +#ifdef NS_BUILD_REFCNT_LOGGING + +IndexInfo::IndexInfo() +: id(INT64_MIN), + keyPath(0), + unique(false), + multiEntry(false) +{ + MOZ_COUNT_CTOR(IndexInfo); +} + +IndexInfo::IndexInfo(const IndexInfo& aOther) +: name(aOther.name), + id(aOther.id), + keyPath(aOther.keyPath), + unique(aOther.unique), + multiEntry(aOther.multiEntry) +{ + MOZ_COUNT_CTOR(IndexInfo); +} + +IndexInfo::~IndexInfo() +{ + MOZ_COUNT_DTOR(IndexInfo); +} + +ObjectStoreInfo::ObjectStoreInfo() +: nextAutoIncrementId(0), + comittedAutoIncrementId(0) +{ + MOZ_COUNT_CTOR(ObjectStoreInfo); +} + +ObjectStoreInfo::~ObjectStoreInfo() +{ + MOZ_COUNT_DTOR(ObjectStoreInfo); +} + +IndexUpdateInfo::IndexUpdateInfo() +: indexId(0), + indexUnique(false) +{ + MOZ_COUNT_CTOR(IndexUpdateInfo); +} + +IndexUpdateInfo::IndexUpdateInfo(const IndexUpdateInfo& aOther) +: indexId(aOther.indexId), + indexUnique(aOther.indexUnique), + value(aOther.value) +{ + MOZ_COUNT_CTOR(IndexUpdateInfo); +} + +IndexUpdateInfo::~IndexUpdateInfo() +{ + MOZ_COUNT_DTOR(IndexUpdateInfo); +} + +#endif /* NS_BUILD_REFCNT_LOGGING */ + +// static +bool +DatabaseInfo::Get(const nsACString& aId, + DatabaseInfo** aInfo) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(!aId.IsEmpty(), "Bad id!"); + + if (gDatabaseHash && + gDatabaseHash->Get(aId, aInfo)) { + NS_IF_ADDREF(*aInfo); + return true; + } + return false; +} + +// static +bool +DatabaseInfo::Put(DatabaseInfo* aInfo) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(aInfo, "Null pointer!"); + + if (!gDatabaseHash) { + nsAutoPtr databaseHash(new DatabaseHash()); + gDatabaseHash = databaseHash.forget(); + } + + if (gDatabaseHash->Get(aInfo->id, nullptr)) { + NS_ERROR("Already know about this database!"); + return false; + } + + gDatabaseHash->Put(aInfo->id, aInfo); + + return true; +} + +// static +void +DatabaseInfo::Remove(const nsACString& aId) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + + if (gDatabaseHash) { + gDatabaseHash->Remove(aId); + + if (!gDatabaseHash->Count()) { + delete gDatabaseHash; + gDatabaseHash = nullptr; + } + } +} + +bool +DatabaseInfo::GetObjectStoreNames(nsTArray& aNames) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + + aNames.Clear(); + if (objectStoreHash) { + objectStoreHash->EnumerateRead(EnumerateObjectStoreNames, &aNames); + } + return true; +} + +bool +DatabaseInfo::ContainsStoreName(const nsAString& aName) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + + return objectStoreHash && objectStoreHash->Get(aName, nullptr); +} + +ObjectStoreInfo* +DatabaseInfo::GetObjectStore(const nsAString& aName) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + + if (objectStoreHash) { + return objectStoreHash->GetWeak(aName); + } + + return nullptr; +} + +bool +DatabaseInfo::PutObjectStore(ObjectStoreInfo* aInfo) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(aInfo, "Null pointer!"); + + if (!objectStoreHash) { + nsAutoPtr hash(new ObjectStoreInfoHash()); + objectStoreHash = hash.forget(); + } + + if (objectStoreHash->Get(aInfo->name, nullptr)) { + NS_ERROR("Already have an entry for this objectstore!"); + return false; + } + + objectStoreHash->Put(aInfo->name, aInfo); + return true; +} + +void +DatabaseInfo::RemoveObjectStore(const nsAString& aName) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(GetObjectStore(aName), "Don't know about this one!"); + + if (objectStoreHash) { + objectStoreHash->Remove(aName); + } +} + +already_AddRefed +DatabaseInfo::Clone() +{ + nsRefPtr dbInfo(new DatabaseInfo()); + + dbInfo->cloned = true; + dbInfo->name = name; + dbInfo->group = group; + dbInfo->origin = origin; + dbInfo->version = version; + dbInfo->persistenceType = persistenceType; + dbInfo->id = id; + dbInfo->filePath = filePath; + dbInfo->nextObjectStoreId = nextObjectStoreId; + dbInfo->nextIndexId = nextIndexId; + + if (objectStoreHash) { + dbInfo->objectStoreHash = new ObjectStoreInfoHash(); + objectStoreHash->EnumerateRead(CloneObjectStoreInfo, + dbInfo->objectStoreHash); + } + + return dbInfo.forget(); +}