Modified: trunk/Source/WebCore/Modules/indexeddb/IDBBackingStore.cpp (137222 => 137223)
--- trunk/Source/WebCore/Modules/indexeddb/IDBBackingStore.cpp 2012-12-11 00:17:53 UTC (rev 137222)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBBackingStore.cpp 2012-12-11 00:21:14 UTC (rev 137223)
@@ -68,6 +68,10 @@
IDBLevelDBBackingStoreReadErrorKeyExistsInIndex,
IDBLevelDBBackingStoreReadErrorVersionExists,
IDBLevelDBBackingStoreReadErrorDeleteObjectStore,
+ IDBLevelDBBackingStoreReadErrorSetMaxObjectStoreId,
+ IDBLevelDBBackingStoreReadErrorSetMaxIndexId,
+ IDBLevelDBBackingStoreReadErrorGetNewDatabaseId,
+ IDBLevelDBBackingStoreReadErrorGetNewVersionNumber,
IDBLevelDBBackingStoreInternalErrorMax,
};
static inline void recordInternalError(IDBLevelDBBackingStoreInternalErrorType type)
@@ -84,32 +88,20 @@
recordInternalError(type); \
} while (0)
-template <typename DBOrTransaction>
-static bool getBool(DBOrTransaction* db, const LevelDBSlice& key, bool& foundBool)
-{
- Vector<char> result;
- if (!db->get(key, result))
- return false;
-
- foundBool = decodeBool(result.begin(), result.end());
- return true;
-}
-
static void putBool(LevelDBTransaction* transaction, const LevelDBSlice& key, bool value)
{
transaction->put(key, encodeBool(value));
}
template <typename DBOrTransaction>
-static bool getInt(DBOrTransaction* db, const LevelDBSlice& key, int64_t& foundInt)
+static bool getInt(DBOrTransaction* db, const LevelDBSlice& key, int64_t& foundInt, bool& found)
{
Vector<char> result;
- bool found = false;
bool ok = db->safeGet(key, result, found);
- // FIXME: Notify the caller if !ok.
- ASSERT_UNUSED(ok, ok);
+ if (!ok)
+ return false;
if (!found)
- return false;
+ return true;
foundInt = decodeInt(result.begin(), result.end());
return true;
@@ -185,26 +177,42 @@
// 1 - Adds UserIntVersion to DatabaseMetaData.
// 2 - Adds DataVersion to to global metadata.
const int64_t latestKnownSchemaVersion = 2;
-static bool isSchemaKnown(LevelDBDatabase* db)
+WARN_UNUSED_RETURN static bool isSchemaKnown(LevelDBDatabase* db, bool& known)
{
int64_t dbSchemaVersion = 0;
- if (!getInt(db, SchemaVersionKey::encode(), dbSchemaVersion))
+ bool found = false;
+ bool ok = getInt(db, SchemaVersionKey::encode(), dbSchemaVersion, found);
+ if (!ok)
+ return false;
+ if (!found) {
+ known = true;
return true;
- if (dbSchemaVersion > latestKnownSchemaVersion)
- return false;
+ }
+ if (dbSchemaVersion > latestKnownSchemaVersion) {
+ known = false;
+ return true;
+ }
const uint32_t latestKnownDataVersion = SerializedScriptValue::wireFormatVersion();
int64_t dbDataVersion = 0;
- if (!getInt(db, DataVersionKey::encode(), dbDataVersion))
+ ok = getInt(db, DataVersionKey::encode(), dbDataVersion, found);
+ if (!ok)
+ return false;
+ if (!found) {
+ known = true;
return true;
+ }
- if (dbDataVersion > latestKnownDataVersion)
- return false;
+ if (dbDataVersion > latestKnownDataVersion) {
+ known = false;
+ return true;
+ }
+ known = true;
return true;
}
-static bool setUpMetadata(LevelDBDatabase* db, const String& origin)
+WARN_UNUSED_RETURN static bool setUpMetadata(LevelDBDatabase* db, const String& origin)
{
const uint32_t latestKnownDataVersion = SerializedScriptValue::wireFormatVersion();
const Vector<char> schemaVersionKey = SchemaVersionKey::encode();
@@ -214,7 +222,13 @@
int64_t dbSchemaVersion = 0;
int64_t dbDataVersion = 0;
- if (!getInt(transaction.get(), schemaVersionKey, dbSchemaVersion)) {
+ bool found = false;
+ bool ok = getInt(transaction.get(), schemaVersionKey, dbSchemaVersion, found);
+ if (!ok) {
+ InternalError(IDBLevelDBBackingStoreReadErrorSetupMetadata);
+ return false;
+ }
+ if (!found) {
// Initialize new backing store.
dbSchemaVersion = latestKnownSchemaVersion;
putInt(transaction.get(), schemaVersionKey, dbSchemaVersion);
@@ -231,10 +245,16 @@
OwnPtr<LevelDBIterator> it = db->createIterator();
for (it->seek(startKey); it->isValid() && compareKeys(it->key(), stopKey) < 0; it->next()) {
int64_t databaseId = 0;
- if (!getInt(transaction.get(), it->key(), databaseId)) {
+ found = false;
+ bool ok = getInt(transaction.get(), it->key(), databaseId, found);
+ if (!ok) {
InternalError(IDBLevelDBBackingStoreReadErrorSetupMetadata);
return false;
}
+ if (!found) {
+ InternalError(IDBLevelDBBackingStoreConsistencyError);
+ return false;
+ }
Vector<char> intVersionKey = DatabaseMetaDataKey::encode(databaseId, DatabaseMetaDataKey::UserIntVersion);
putVarInt(transaction.get(), intVersionKey, IDBDatabaseMetadata::DefaultIntVersion);
}
@@ -248,10 +268,16 @@
}
// All new values will be written using this serialization version.
- if (!getInt(transaction.get(), dataVersionKey, dbDataVersion)) {
- InternalError(IDBLevelDBBackingStoreReadError);
+ found = false;
+ ok = getInt(transaction.get(), dataVersionKey, dbDataVersion, found);
+ if (!ok) {
+ InternalError(IDBLevelDBBackingStoreReadErrorSetupMetadata);
return false;
}
+ if (!found) {
+ InternalError(IDBLevelDBBackingStoreConsistencyError);
+ return false;
+ }
if (dbDataVersion < latestKnownDataVersion) {
dbDataVersion = latestKnownDataVersion;
putInt(transaction.get(), dataVersionKey, dbDataVersion);
@@ -268,21 +294,26 @@
}
template <typename DBOrTransaction>
-static int64_t getMaxObjectStoreId(DBOrTransaction* db, int64_t databaseId)
+WARN_UNUSED_RETURN static bool getMaxObjectStoreId(DBOrTransaction* db, int64_t databaseId, int64_t& maxObjectStoreId)
{
const Vector<char> maxObjectStoreIdKey = DatabaseMetaDataKey::encode(databaseId, DatabaseMetaDataKey::MaxObjectStoreId);
- return getMaxObjectStoreId(db, maxObjectStoreIdKey);
+ bool ok = getMaxObjectStoreId(db, maxObjectStoreIdKey, maxObjectStoreId);
+ return ok;
}
template <typename DBOrTransaction>
-static int64_t getMaxObjectStoreId(DBOrTransaction* db, const Vector<char>& maxObjectStoreIdKey)
+WARN_UNUSED_RETURN static bool getMaxObjectStoreId(DBOrTransaction* db, const Vector<char>& maxObjectStoreIdKey, int64_t& maxObjectStoreId)
{
- int64_t maxObjectStoreId = -1;
- if (!getInt(db, maxObjectStoreIdKey, maxObjectStoreId))
+ maxObjectStoreId = -1;
+ bool found = false;
+ bool ok = getInt(db, maxObjectStoreIdKey, maxObjectStoreId, found);
+ if (!ok)
+ return false;
+ if (!found)
maxObjectStoreId = 0;
ASSERT(maxObjectStoreId >= 0);
- return maxObjectStoreId;
+ return true;
}
IDBBackingStore::IDBBackingStore(const String& identifier, IDBFactoryBackendImpl* factory, PassOwnPtr<LevelDBDatabase> db)
@@ -316,6 +347,7 @@
IDBLevelDBBackingStoreOpenCleanupDestroyFailed,
IDBLevelDBBackingStoreOpenCleanupReopenFailed,
IDBLevelDBBackingStoreOpenCleanupReopenSuccess,
+ IDBLevelDBBackingStoreOpenFailedIOErrCheckingSchema,
IDBLevelDBBackingStoreOpenMax,
};
@@ -340,10 +372,18 @@
String path = pathByAppendingComponent(pathBase, securityOrigin->databaseIdentifier() + ".indexeddb.leveldb");
db = LevelDBDatabase::open(path, comparator.get());
- if (db && !isSchemaKnown(db.get())) {
- LOG_ERROR("IndexedDB backing store had unknown schema, treating it as failure to open");
- HistogramSupport::histogramEnumeration("WebCore.IndexedDB.BackingStore.OpenStatus", IDBLevelDBBackingStoreOpenFailedUnknownSchema, IDBLevelDBBackingStoreOpenMax);
- db.clear();
+ if (db) {
+ bool known = false;
+ bool ok = isSchemaKnown(db.get(), known);
+ if (!ok) {
+ HistogramSupport::histogramEnumeration("WebCore.IndexedDB.BackingStore.OpenStatus", IDBLevelDBBackingStoreOpenFailedIOErrCheckingSchema, IDBLevelDBBackingStoreOpenMax);
+ return PassRefPtr<IDBBackingStore>();
+ }
+ if (!known) {
+ LOG_ERROR("IndexedDB backing store had unknown schema, treating it as failure to open");
+ HistogramSupport::histogramEnumeration("WebCore.IndexedDB.BackingStore.OpenStatus", IDBLevelDBBackingStoreOpenFailedUnknownSchema, IDBLevelDBBackingStoreOpenMax);
+ db.clear();
+ }
}
if (db)
@@ -409,11 +449,15 @@
const Vector<char> key = DatabaseNameKey::encode(m_identifier, name);
found = false;
- found = getInt(m_db.get(), key, metadata->id);
+ bool ok = getInt(m_db.get(), key, metadata->id, found);
+ if (!ok) {
+ InternalError(IDBLevelDBBackingStoreReadErrorGetIDBDatabaseMetaData);
+ return false;
+ }
if (!found)
return true;
- bool ok = getString(m_db.get(), DatabaseMetaDataKey::encode(metadata->id, DatabaseMetaDataKey::UserVersion), metadata->version, found);
+ ok = getString(m_db.get(), DatabaseMetaDataKey::encode(metadata->id, DatabaseMetaDataKey::UserVersion), metadata->version, found);
if (!ok) {
InternalError(IDBLevelDBBackingStoreReadErrorGetIDBDatabaseMetaData);
return false;
@@ -436,17 +480,28 @@
if (metadata->intVersion == IDBDatabaseMetadata::DefaultIntVersion)
metadata->intVersion = IDBDatabaseMetadata::NoIntVersion;
- metadata->maxObjectStoreId = getMaxObjectStoreId(m_db.get(), metadata->id);
+ ok = getMaxObjectStoreId(m_db.get(), metadata->id, metadata->maxObjectStoreId);
+ if (!ok) {
+ InternalError(IDBLevelDBBackingStoreReadErrorGetIDBDatabaseMetaData);
+ return false;
+ }
return true;
}
-static int64_t getNewDatabaseId(LevelDBDatabase* db)
+WARN_UNUSED_RETURN static bool getNewDatabaseId(LevelDBDatabase* db, int64_t& newId)
{
RefPtr<LevelDBTransaction> transaction = LevelDBTransaction::create(db);
+ newId = -1;
int64_t maxDatabaseId = -1;
- if (!getInt(transaction.get(), MaxDatabaseIdKey::encode(), maxDatabaseId))
+ bool found = false;
+ bool ok = getInt(transaction.get(), MaxDatabaseIdKey::encode(), maxDatabaseId, found);
+ if (!ok) {
+ InternalError(IDBLevelDBBackingStoreReadErrorGetNewDatabaseId);
+ return false;
+ }
+ if (!found)
maxDatabaseId = 0;
ASSERT(maxDatabaseId >= 0);
@@ -455,16 +510,18 @@
putInt(transaction.get(), MaxDatabaseIdKey::encode(), databaseId);
if (!transaction->commit()) {
InternalError(IDBLevelDBBackingStoreWriteError);
- return -1;
+ return false;
}
- return databaseId;
+ newId = databaseId;
+ return true;
}
bool IDBBackingStore::createIDBDatabaseMetaData(const String& name, const String& version, int64_t intVersion, int64_t& rowId)
{
- rowId = getNewDatabaseId(m_db.get());
- if (rowId < 0)
+ bool ok = getNewDatabaseId(m_db.get(), rowId);
+ if (!ok)
return false;
+ ASSERT(rowId >= 0);
if (intVersion == IDBDatabaseMetadata::NoIntVersion)
intVersion = IDBDatabaseMetadata::DefaultIntVersion;
@@ -634,10 +691,15 @@
return objectStores;
}
-static bool setMaxObjectStoreId(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId)
+WARN_UNUSED_RETURN static bool setMaxObjectStoreId(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId)
{
const Vector<char> maxObjectStoreIdKey = DatabaseMetaDataKey::encode(databaseId, DatabaseMetaDataKey::MaxObjectStoreId);
- int64_t maxObjectStoreId = getMaxObjectStoreId(transaction, maxObjectStoreIdKey);
+ int64_t maxObjectStoreId = -1;
+ bool ok = getMaxObjectStoreId(transaction, maxObjectStoreIdKey, maxObjectStoreId);
+ if (!ok) {
+ InternalError(IDBLevelDBBackingStoreReadErrorSetMaxObjectStoreId);
+ return false;
+ }
if (objectStoreId <= maxObjectStoreId) {
InternalError(IDBLevelDBBackingStoreConsistencyError);
@@ -732,12 +794,19 @@
return true;
}
-static int64_t getNewVersionNumber(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId)
+WARN_UNUSED_RETURN static bool getNewVersionNumber(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t& newVersionNumber)
{
const Vector<char> lastVersionKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::LastVersion);
+ newVersionNumber = -1;
int64_t lastVersion = -1;
- if (!getInt(transaction, lastVersionKey, lastVersion))
+ bool found = false;
+ bool ok = getInt(transaction, lastVersionKey, lastVersion, found);
+ if (!ok) {
+ InternalError(IDBLevelDBBackingStoreReadErrorGetNewVersionNumber);
+ return false;
+ }
+ if (!found)
lastVersion = 0;
ASSERT(lastVersion >= 0);
@@ -747,15 +816,20 @@
ASSERT(version > lastVersion); // FIXME: Think about how we want to handle the overflow scenario.
- return version;
+ newVersionNumber = version;
+ return true;
}
-void IDBBackingStore::putRecord(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, const IDBKey& key, const String& value, RecordIdentifier* recordIdentifier)
+bool IDBBackingStore::putRecord(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, const IDBKey& key, const String& value, RecordIdentifier* recordIdentifier)
{
IDB_TRACE("IDBBackingStore::putRecord");
ASSERT(key.isValid());
LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction);
- int64_t version = getNewVersionNumber(levelDBTransaction, databaseId, objectStoreId);
+ int64_t version = -1;
+ bool ok = getNewVersionNumber(levelDBTransaction, databaseId, objectStoreId, version);
+ if (!ok)
+ return false;
+ ASSERT(version >= 0);
const Vector<char> objectStoredataKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, key);
Vector<char> v;
@@ -768,6 +842,7 @@
levelDBTransaction->put(existsEntryKey, encodeInt(version));
recordIdentifier->reset(encodeIDBKey(key), version);
+ return true;
}
void IDBBackingStore::clearObjectStore(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId)
@@ -954,11 +1029,17 @@
return indexes;
}
-static bool setMaxIndexId(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId)
+WARN_UNUSED_RETURN static bool setMaxIndexId(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId)
{
int64_t maxIndexId = -1;
const Vector<char> maxIndexIdKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::MaxIndexId);
- if (!getInt(transaction, maxIndexIdKey, maxIndexId))
+ bool found = false;
+ bool ok = getInt(transaction, maxIndexIdKey, maxIndexId, found);
+ if (!ok) {
+ InternalError(IDBLevelDBBackingStoreReadErrorSetMaxIndexId);
+ return false;
+ }
+ if (!found)
maxIndexId = MinimumIndexId;
if (indexId <= maxIndexId) {