diff --git a/dom/cache/DBAction.cpp b/dom/cache/DBAction.cpp index f241ff97b6beb..2b9364cd97cc6 100644 --- a/dom/cache/DBAction.cpp +++ b/dom/cache/DBAction.cpp @@ -226,7 +226,7 @@ nsresult OpenDBConnection(const QuotaInfo& aQuotaInfo, nsIFile* aDBFile, } nsCOMPtr conn; - rv = ss->OpenDatabaseWithFileURL(dbFileUrl, EmptyCString(), getter_AddRefs(conn)); + rv = ss->OpenDatabaseWithFileURL(dbFileUrl, getter_AddRefs(conn)); if (rv == NS_ERROR_FILE_CORRUPTED) { NS_WARNING("Cache database corrupted. Recreating empty database."); @@ -239,7 +239,7 @@ nsresult OpenDBConnection(const QuotaInfo& aQuotaInfo, nsIFile* aDBFile, return rv; } - rv = ss->OpenDatabaseWithFileURL(dbFileUrl, EmptyCString(), getter_AddRefs(conn)); + rv = ss->OpenDatabaseWithFileURL(dbFileUrl, getter_AddRefs(conn)); } if (NS_WARN_IF(NS_FAILED(rv))) { return rv; @@ -258,7 +258,7 @@ nsresult OpenDBConnection(const QuotaInfo& aQuotaInfo, nsIFile* aDBFile, return rv; } - rv = ss->OpenDatabaseWithFileURL(dbFileUrl, EmptyCString(), getter_AddRefs(conn)); + rv = ss->OpenDatabaseWithFileURL(dbFileUrl, getter_AddRefs(conn)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp index 967568c2c83c8..4f27be600259d 100644 --- a/dom/indexedDB/ActorsParent.cpp +++ b/dom/indexedDB/ActorsParent.cpp @@ -3806,7 +3806,8 @@ nsresult UpgradeSchemaFrom25_0To26_0(mozIStorageConnection& aConnection) { } Result, nsresult> GetDatabaseFileURL( - nsIFile& aDatabaseFile, const int64_t aDirectoryLockId) { + nsIFile& aDatabaseFile, const int64_t aDirectoryLockId, + const uint32_t aTelemetryId) { MOZ_ASSERT(aDirectoryLockId >= -1); nsresult rv; @@ -3839,9 +3840,17 @@ Result, nsresult> GetDatabaseFileURL( ? "&directoryLockId="_ns + IntCString(aDirectoryLockId) : EmptyCString(); + nsAutoCString telemetryFilenameClause; + if (aTelemetryId) { + telemetryFilenameClause.AssignLiteral("&telemetryFilename=indexedDB-"); + telemetryFilenameClause.AppendInt(aTelemetryId); + telemetryFilenameClause.Append(NS_ConvertUTF16toUTF8(kSQLiteSuffix)); + } + nsCOMPtr result; rv = NS_MutateURI(mutator) - .SetQuery("cache=private"_ns + directoryLockIdClause) + .SetQuery("cache=private"_ns + directoryLockIdClause + + telemetryFilenameClause) .Finalize(result); if (NS_WARN_IF(NS_FAILED(rv))) { return Err(rv); @@ -3975,19 +3984,10 @@ struct StorageOpenTraits; template <> struct StorageOpenTraits { static Result>, nsresult> Open( - mozIStorageService& aStorageService, nsIFileURL& aFileURL, - const uint32_t aTelemetryId = 0) { - - nsAutoCString telemetryFilename; - if (aTelemetryId) { - telemetryFilename.AssignLiteral("indexedDB-"); - telemetryFilename.AppendInt(aTelemetryId); - telemetryFilename.Append(NS_ConvertUTF16toUTF8(kSQLiteSuffix)); - } - + mozIStorageService& aStorageService, nsIFileURL& aFileURL) { nsCOMPtr connection; nsresult rv = aStorageService.OpenDatabaseWithFileURL( - &aFileURL, telemetryFilename, getter_AddRefs(connection)); + &aFileURL, getter_AddRefs(connection)); return ValOrErr(std::move(connection), rv); } @@ -4001,8 +4001,7 @@ struct StorageOpenTraits { template <> struct StorageOpenTraits { static Result>, nsresult> Open( - mozIStorageService& aStorageService, nsIFile& aFile, - const uint32_t aTelemetryId = 0) { + mozIStorageService& aStorageService, nsIFile& aFile) { nsCOMPtr connection; nsresult rv = aStorageService.OpenUnsharedDatabase( &aFile, getter_AddRefs(connection)); @@ -4022,13 +4021,12 @@ struct StorageOpenTraits { template Result>, nsresult> OpenDatabaseAndHandleBusy(mozIStorageService& aStorageService, - FileOrURLType& aFileOrURL, - const uint32_t aTelemetryId = 0) { + FileOrURLType& aFileOrURL) { MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(!IsOnBackgroundThread()); auto connectionOrErr = - StorageOpenTraits::Open(aStorageService, aFileOrURL, aTelemetryId); + StorageOpenTraits::Open(aStorageService, aFileOrURL); if (connectionOrErr.isErr() && connectionOrErr.inspectErr() == NS_ERROR_STORAGE_BUSY) { @@ -4054,7 +4052,7 @@ OpenDatabaseAndHandleBusy(mozIStorageService& aStorageService, PR_Sleep(PR_MillisecondsToInterval(100)); connectionOrErr = - StorageOpenTraits::Open(aStorageService, aFileOrURL, aTelemetryId); + StorageOpenTraits::Open(aStorageService, aFileOrURL); if (!connectionOrErr.isErr() || connectionOrErr.inspectErr() != NS_ERROR_STORAGE_BUSY || TimeStamp::NowLoRes() - start > TimeDuration::FromSeconds(10)) { @@ -4083,7 +4081,7 @@ CreateStorageConnection(nsIFile& aDBFile, nsIFile& aFMDirectory, bool exists; auto dbFileUrlOrErr = - GetDatabaseFileURL(aDBFile, aDirectoryLockId); + GetDatabaseFileURL(aDBFile, aDirectoryLockId, aTelemetryId); if (NS_WARN_IF(dbFileUrlOrErr.isErr())) { return dbFileUrlOrErr.propagateErr(); } @@ -4097,7 +4095,7 @@ CreateStorageConnection(nsIFile& aDBFile, nsIFile& aFMDirectory, return Err(rv); } - auto connectionOrErr = OpenDatabaseAndHandleBusy(*ss, *dbFileUrl, aTelemetryId); + auto connectionOrErr = OpenDatabaseAndHandleBusy(*ss, *dbFileUrl); if (connectionOrErr.isErr()) { if (connectionOrErr.inspectErr() == NS_ERROR_FILE_CORRUPTED) { // If we're just opening the database during origin initialization, then @@ -4135,7 +4133,7 @@ CreateStorageConnection(nsIFile& aDBFile, nsIFile& aFMDirectory, } } - connectionOrErr = OpenDatabaseAndHandleBusy(*ss, *dbFileUrl, aTelemetryId); + connectionOrErr = OpenDatabaseAndHandleBusy(*ss, *dbFileUrl); } if (NS_WARN_IF(connectionOrErr.isErr())) { @@ -4550,7 +4548,7 @@ GetStorageConnection(nsIFile& aDatabaseFile, const int64_t aDirectoryLockId, } auto dbFileUrlOrErr = - GetDatabaseFileURL(aDatabaseFile, aDirectoryLockId); + GetDatabaseFileURL(aDatabaseFile, aDirectoryLockId, aTelemetryId); if (NS_WARN_IF(dbFileUrlOrErr.isErr())) { return dbFileUrlOrErr.propagateErr(); } @@ -4562,7 +4560,7 @@ GetStorageConnection(nsIFile& aDatabaseFile, const int64_t aDirectoryLockId, } auto connectionOrErr = - OpenDatabaseAndHandleBusy(*ss, *dbFileUrlOrErr.inspect(), aTelemetryId); + OpenDatabaseAndHandleBusy(*ss, *dbFileUrlOrErr.inspect()); if (NS_WARN_IF(connectionOrErr.isErr())) { return connectionOrErr.propagateErr(); } diff --git a/storage/mozIStorageService.idl b/storage/mozIStorageService.idl index 509ac38b22147..56d2a127ed22b 100644 --- a/storage/mozIStorageService.idl +++ b/storage/mozIStorageService.idl @@ -161,12 +161,8 @@ interface mozIStorageService : nsISupports { * * @param aURL * A nsIFileURL that represents the database that is to be opened. - * @param [optional] aTelemetryFilename - * The name to use for the database in telemetry. Only needed if the - * actual filename can contain sensitive information. */ - mozIStorageConnection openDatabaseWithFileURL(in nsIFileURL aFileURL, - [optional] in ACString aTelemetryFilename); + mozIStorageConnection openDatabaseWithFileURL(in nsIFileURL aFileURL); /* * Utilities diff --git a/storage/mozStorageAsyncStatementExecution.cpp b/storage/mozStorageAsyncStatementExecution.cpp index 971ea67399551..760df8f6b2bf1 100644 --- a/storage/mozStorageAsyncStatementExecution.cpp +++ b/storage/mozStorageAsyncStatementExecution.cpp @@ -122,8 +122,8 @@ bool AsyncExecuteStatements::bindExecuteAndProcessStatement( sqlite3_stmt* aStatement = nullptr; // This cannot fail; we are only called if it's available. - Unused << aData.getSqliteStatement(&aStatement); - MOZ_DIAGNOSTIC_ASSERT(aStatement, "bindExecuteAndProcessStatement called without an initialized statement"); + (void)aData.getSqliteStatement(&aStatement); + NS_ASSERTION(aStatement, "You broke the code; do not call here like that!"); BindingParamsArray* paramsArray(aData); // Iterate through all of our parameters, bind them, and execute. @@ -147,7 +147,7 @@ bool AsyncExecuteStatements::bindExecuteAndProcessStatement( // Advance our iterator, execute, and then process the statement. itr++; bool lastStatement = aLastStatement && itr == end; - continueProcessing = executeAndProcessStatement(aData, lastStatement); + continueProcessing = executeAndProcessStatement(aStatement, lastStatement); // Always reset our statement. (void)::sqlite3_reset(aStatement); @@ -157,18 +157,13 @@ bool AsyncExecuteStatements::bindExecuteAndProcessStatement( } bool AsyncExecuteStatements::executeAndProcessStatement( - StatementData& aData, bool aLastStatement) { + sqlite3_stmt* aStatement, bool aLastStatement) { mMutex.AssertNotCurrentThreadOwns(); - sqlite3_stmt* aStatement = nullptr; - // This cannot fail; we are only called if it's available. - Unused << aData.getSqliteStatement(&aStatement); - MOZ_DIAGNOSTIC_ASSERT(aStatement, "executeAndProcessStatement called without an initialized statement"); - // Execute our statement bool hasResults; do { - hasResults = executeStatement(aData); + hasResults = executeStatement(aStatement); // If we had an error, bail. if (mState == ERROR || mState == CANCELED) return false; @@ -213,16 +208,11 @@ bool AsyncExecuteStatements::executeAndProcessStatement( return true; } -bool AsyncExecuteStatements::executeStatement(StatementData& aData) { +bool AsyncExecuteStatements::executeStatement(sqlite3_stmt* aStatement) { mMutex.AssertNotCurrentThreadOwns(); Telemetry::AutoTimer finallySendExecutionDuration(mRequestStartDate); - sqlite3_stmt* aStatement = nullptr; - // This cannot fail; we are only called if it's available. - Unused << aData.getSqliteStatement(&aStatement); - MOZ_DIAGNOSTIC_ASSERT(aStatement, "executeStatement called without an initialized statement"); - bool busyRetry = false; while (true) { if (busyRetry) { @@ -245,16 +235,6 @@ bool AsyncExecuteStatements::executeStatement(StatementData& aData) { SQLiteMutexAutoLock lockedScope(mDBMutex); int rc = mConnection->stepStatement(mNativeConnection, aStatement); - - // Some errors are not fatal, and we can handle them and continue. - if (rc == SQLITE_BUSY) { - ::sqlite3_reset(aStatement); - busyRetry = true; - continue; - } - - aData.MaybeRecordQueryStatus(rc); - // Stop if we have no more results. if (rc == SQLITE_DONE) { Telemetry::Accumulate(Telemetry::MOZ_STORAGE_ASYNC_REQUESTS_SUCCESS, @@ -269,6 +249,13 @@ bool AsyncExecuteStatements::executeStatement(StatementData& aData) { return true; } + // Some errors are not fatal, and we can handle them and continue. + if (rc == SQLITE_BUSY) { + ::sqlite3_reset(aStatement); + busyRetry = true; + continue; + } + if (rc == SQLITE_INTERRUPT) { mState = CANCELED; return false; @@ -561,7 +548,7 @@ AsyncExecuteStatements::Run() { if (!bindExecuteAndProcessStatement(mStatements[i], finished)) break; } // Otherwise, just execute and process the statement. - else if (!executeAndProcessStatement(mStatements[i], finished)) { + else if (!executeAndProcessStatement(stmt, finished)) { break; } } diff --git a/storage/mozStorageAsyncStatementExecution.h b/storage/mozStorageAsyncStatementExecution.h index 2e68a50107a5c..6daebd6d7ac54 100644 --- a/storage/mozStorageAsyncStatementExecution.h +++ b/storage/mozStorageAsyncStatementExecution.h @@ -119,14 +119,14 @@ class AsyncExecuteStatements final : public Runnable, * * @pre mMutex is not held * - * @param aData - * The StatementData to execute, and then process. + * @param aStatement + * The statement to execute and then process. * @param aLastStatement * Indicates if this is the last statement or not. If it is, we have * to set the proper state. * @returns true if we should continue to process statements, false otherwise. */ - bool executeAndProcessStatement(StatementData& aData, + bool executeAndProcessStatement(sqlite3_stmt* aStatement, bool aLastStatement); /** @@ -134,11 +134,11 @@ class AsyncExecuteStatements final : public Runnable, * * @pre mMutex is not held * - * @param aData - * The StatementData to execute to completion. + * @param aStatement + * The statement to execute to completion. * @returns true if results were obtained, false otherwise. */ - bool executeStatement(StatementData& aData); + bool executeStatement(sqlite3_stmt* aStatement); /** * Builds a result set up with a row from a given statement. If we meet the diff --git a/storage/mozStorageConnection.cpp b/storage/mozStorageConnection.cpp index f4c8c89ce32c8..ebe719d044ad4 100644 --- a/storage/mozStorageConnection.cpp +++ b/storage/mozStorageConnection.cpp @@ -72,9 +72,6 @@ mozilla::LazyLogModule gStorageLog("mozStorage"); namespace mozilla::storage { using mozilla::dom::quota::QuotaObject; -using mozilla::Telemetry::AccumulateCategoricalKeyed; -using mozilla::Telemetry::LABELS_SQLITE_STORE_OPEN; -using mozilla::Telemetry::LABELS_SQLITE_STORE_QUERY; const char* GetVFSName(bool); @@ -562,103 +559,17 @@ nsIEventTarget* Connection::getAsyncExecutionTarget() { return mAsyncExecutionThread; } -void Connection::RecordOpenStatus(nsresult rv) { - nsCString histogramKey = mTelemetryFilename; - - if (histogramKey.IsEmpty()) { - histogramKey.AssignLiteral("unknown"); - } - - if (NS_SUCCEEDED(rv)) { - AccumulateCategoricalKeyed(histogramKey, LABELS_SQLITE_STORE_OPEN::success); - return; - } - - switch (rv) { - case NS_ERROR_FILE_CORRUPTED: - AccumulateCategoricalKeyed(histogramKey, LABELS_SQLITE_STORE_OPEN::corrupt); - break; - case NS_ERROR_STORAGE_IOERR: - AccumulateCategoricalKeyed(histogramKey, LABELS_SQLITE_STORE_OPEN::diskio); - break; - case NS_ERROR_FILE_ACCESS_DENIED: - case NS_ERROR_FILE_IS_LOCKED: - case NS_ERROR_FILE_READ_ONLY: - AccumulateCategoricalKeyed(histogramKey, LABELS_SQLITE_STORE_OPEN::access); - break; - case NS_ERROR_FILE_NO_DEVICE_SPACE: - AccumulateCategoricalKeyed(histogramKey, LABELS_SQLITE_STORE_OPEN::diskspace); - break; - default: - AccumulateCategoricalKeyed(histogramKey, LABELS_SQLITE_STORE_OPEN::failure); - } -} - -void Connection::RecordQueryStatus(int srv) { - nsCString histogramKey = mTelemetryFilename; - - if (histogramKey.IsEmpty()) { - histogramKey.AssignLiteral("unknown"); - } - - switch (srv) { - case SQLITE_OK: - case SQLITE_ROW: - case SQLITE_DONE: - - // Note that these are returned when we intentionally cancel a statement so they - // aren't indicating a failure. - case SQLITE_ABORT: - case SQLITE_INTERRUPT: - AccumulateCategoricalKeyed(histogramKey, LABELS_SQLITE_STORE_QUERY::success); - break; - case SQLITE_CORRUPT: - case SQLITE_NOTADB: - AccumulateCategoricalKeyed(histogramKey, LABELS_SQLITE_STORE_QUERY::corrupt); - break; - case SQLITE_PERM: - case SQLITE_CANTOPEN: - case SQLITE_LOCKED: - case SQLITE_READONLY: - AccumulateCategoricalKeyed(histogramKey, LABELS_SQLITE_STORE_QUERY::access); - break; - case SQLITE_IOERR: - case SQLITE_NOLFS: - AccumulateCategoricalKeyed(histogramKey, LABELS_SQLITE_STORE_QUERY::diskio); - break; - case SQLITE_FULL: - case SQLITE_TOOBIG: - AccumulateCategoricalKeyed(histogramKey, LABELS_SQLITE_STORE_OPEN::diskspace); - break; - case SQLITE_CONSTRAINT: - case SQLITE_RANGE: - case SQLITE_MISMATCH: - case SQLITE_MISUSE: - AccumulateCategoricalKeyed(histogramKey, LABELS_SQLITE_STORE_OPEN::misuse); - break; - case SQLITE_BUSY: - AccumulateCategoricalKeyed(histogramKey, LABELS_SQLITE_STORE_OPEN::busy); - break; - default: - AccumulateCategoricalKeyed(histogramKey, LABELS_SQLITE_STORE_QUERY::failure); - } -} - nsresult Connection::initialize() { NS_ASSERTION(!connectionReady(), "Initialize called on already opened database!"); MOZ_ASSERT(!mIgnoreLockingMode, "Can't ignore locking on an in-memory db."); AUTO_PROFILER_LABEL("Connection::initialize", OTHER); - mTelemetryFilename.AssignLiteral(":memory:"); - // in memory database requested, sqlite uses a magic file name int srv = ::sqlite3_open_v2(":memory:", &mDBConn, mFlags, GetVFSName(true)); if (srv != SQLITE_OK) { mDBConn = nullptr; - nsresult rv = convertResultCode(srv); - RecordOpenStatus(rv); - return rv; + return convertResultCode(srv); } #ifdef MOZ_SQLITE_FTS3_TOKENIZER @@ -672,7 +583,6 @@ nsresult Connection::initialize() { // database. nsresult rv = initializeInternal(); - RecordOpenStatus(rv); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; @@ -687,7 +597,6 @@ nsresult Connection::initialize(nsIFile* aDatabaseFile) { // Do not set mFileURL here since this is database does not have an associated // URL. mDatabaseFile = aDatabaseFile; - aDatabaseFile->GetNativeLeafName(mTelemetryFilename); nsAutoString path; nsresult rv = aDatabaseFile->GetPath(path); @@ -717,9 +626,7 @@ nsresult Connection::initialize(nsIFile* aDatabaseFile) { } if (srv != SQLITE_OK) { mDBConn = nullptr; - rv = convertResultCode(srv); - RecordOpenStatus(rv); - return rv; + return convertResultCode(srv); } rv = initializeInternal(); @@ -735,14 +642,12 @@ nsresult Connection::initialize(nsIFile* aDatabaseFile) { rv = initializeInternal(); } } - - RecordOpenStatus(rv); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } -nsresult Connection::initialize(nsIFileURL* aFileURL, const nsACString& aTelemetryFilename) { +nsresult Connection::initialize(nsIFileURL* aFileURL) { NS_ASSERTION(aFileURL, "Passed null file URL!"); NS_ASSERTION(!connectionReady(), "Initialize called on already opened database!"); @@ -756,12 +661,6 @@ nsresult Connection::initialize(nsIFileURL* aFileURL, const nsACString& aTelemet mFileURL = aFileURL; mDatabaseFile = databaseFile; - if (!aTelemetryFilename.IsEmpty()) { - mTelemetryFilename = aTelemetryFilename; - } else { - databaseFile->GetNativeLeafName(mTelemetryFilename); - } - nsAutoCString spec; rv = aFileURL->GetSpec(spec); NS_ENSURE_SUCCESS(rv, rv); @@ -771,13 +670,10 @@ nsresult Connection::initialize(nsIFileURL* aFileURL, const nsACString& aTelemet ::sqlite3_open_v2(spec.get(), &mDBConn, mFlags, GetVFSName(exclusive)); if (srv != SQLITE_OK) { mDBConn = nullptr; - rv = convertResultCode(srv); - RecordOpenStatus(rv); - return rv; + return convertResultCode(srv); } rv = initializeInternal(); - RecordOpenStatus(rv); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; @@ -796,7 +692,24 @@ nsresult Connection::initializeInternal() { "SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled"); #endif - MOZ_ASSERT(!mTelemetryFilename.IsEmpty(), "A telemetry filename should have been set by now."); + if (mFileURL) { + const char* dbPath = ::sqlite3_db_filename(mDBConn, "main"); + MOZ_ASSERT(dbPath); + + const char* telemetryFilename = + ::sqlite3_uri_parameter(dbPath, "telemetryFilename"); + if (telemetryFilename) { + if (NS_WARN_IF(*telemetryFilename == '\0')) { + return NS_ERROR_INVALID_ARG; + } + mTelemetryFilename = telemetryFilename; + } + } + + if (mTelemetryFilename.IsEmpty()) { + mTelemetryFilename = getFilename(); + MOZ_ASSERT(!mTelemetryFilename.IsEmpty()); + } // Properly wrap the database handle's mutex. sharedDBMutex.initWithMutex(sqlite3_db_mutex(mDBConn)); @@ -930,17 +843,12 @@ nsresult Connection::databaseElementExists( sqlite3_stmt* stmt; int srv = prepareStatement(mDBConn, query, &stmt); - if (srv != SQLITE_OK) { - RecordQueryStatus(srv); - return convertResultCode(srv); - } + if (srv != SQLITE_OK) return convertResultCode(srv); srv = stepStatement(mDBConn, stmt); // we just care about the return value from step (void)::sqlite3_finalize(stmt); - RecordQueryStatus(srv); - if (srv == SQLITE_ROW) { *_exists = true; return NS_OK; @@ -1160,7 +1068,11 @@ nsresult Connection::internalClose(sqlite3* aNativeConnection) { } nsCString Connection::getFilename() { - return mTelemetryFilename; + nsCString leafname(":memory:"); + if (mDatabaseFile) { + (void)mDatabaseFile->GetNativeLeafName(leafname); + } + return leafname; } int Connection::stepStatement(sqlite3* aNativeConnection, @@ -1277,7 +1189,6 @@ int Connection::executeSql(sqlite3* aNativeConnection, const char* aSqlString) { TimeStamp startTime = TimeStamp::Now(); int srv = ::sqlite3_exec(aNativeConnection, aSqlString, nullptr, nullptr, nullptr); - RecordQueryStatus(srv); // Report very slow SQL statements to Telemetry TimeDuration duration = TimeStamp::Now() - startTime; @@ -1532,7 +1443,7 @@ Connection::AsyncClone(bool aReadOnly, } nsresult Connection::initializeClone(Connection* aClone, bool aReadOnly) { - nsresult rv = mFileURL ? aClone->initialize(mFileURL, mTelemetryFilename) + nsresult rv = mFileURL ? aClone->initialize(mFileURL) : aClone->initialize(mDatabaseFile); if (NS_FAILED(rv)) { return rv; diff --git a/storage/mozStorageConnection.h b/storage/mozStorageConnection.h index 3aa12256548a5..837a9c9bde9cf 100644 --- a/storage/mozStorageConnection.h +++ b/storage/mozStorageConnection.h @@ -103,7 +103,7 @@ class Connection final : public mozIStorageConnection, * The nsIFileURL of the location of the database to open, or create if * it does not exist. */ - nsresult initialize(nsIFileURL* aFileURL, const nsACString& aTelemetryFilename); + nsresult initialize(nsIFileURL* aFileURL); /** * Same as initialize, but to be used on the async thread. @@ -305,25 +305,11 @@ class Connection final : public mozIStorageConnection, nsresult initializeClone(Connection* aClone, bool aReadOnly); - /** - * Records a status from a sqlite statement. - * - * @param srv The sqlite result for the failure or SQLITE_OK. - */ - void RecordQueryStatus(int srv); - private: ~Connection(); nsresult initializeInternal(); void initializeFailed(); - /** - * Records the status of an attempt to load a sqlite database to telemetry. - * - * @param rv The state of the load, success or failure. - */ - void RecordOpenStatus(nsresult rv); - /** * Sets the database into a closed state so no further actions can be * performed. diff --git a/storage/mozStoragePrivateHelpers.cpp b/storage/mozStoragePrivateHelpers.cpp index 4ba533b2cc807..1a5d478f1a37b 100644 --- a/storage/mozStoragePrivateHelpers.cpp +++ b/storage/mozStoragePrivateHelpers.cpp @@ -27,16 +27,6 @@ extern mozilla::LazyLogModule gStorageLog; namespace mozilla { namespace storage { -bool isErrorCode(int aSQLiteResultCode) { - // Drop off the extended result bits of the result code. - int rc = aSQLiteResultCode & 0xFF; - - if (rc == SQLITE_OK || rc == SQLITE_ROW || rc == SQLITE_DONE) { - return false; - } - return true; -} - nsresult convertResultCode(int aSQLiteResultCode) { // Drop off the extended result bits of the result code. int rc = aSQLiteResultCode & 0xFF; diff --git a/storage/mozStoragePrivateHelpers.h b/storage/mozStoragePrivateHelpers.h index 457ee1c1a3cfe..416c87feadb8b 100644 --- a/storage/mozStoragePrivateHelpers.h +++ b/storage/mozStoragePrivateHelpers.h @@ -32,15 +32,6 @@ namespace storage { //////////////////////////////////////////////////////////////////////////////// //// Functions -/** - * Returns true if the given SQLite result is an error of come kind. - * - * @param aSQLiteResultCode - * The SQLite return code to check. - * @returns true if the result represents an error. - */ -bool isErrorCode(int aSQLiteResultCode); - /** * Converts a SQLite return code to an nsresult return code. * diff --git a/storage/mozStorageService.cpp b/storage/mozStorageService.cpp index 4e0d97e0e956b..e8c4c3b37ba01 100644 --- a/storage/mozStorageService.cpp +++ b/storage/mozStorageService.cpp @@ -596,7 +596,6 @@ Service::OpenUnsharedDatabase(nsIFile* aDatabaseFile, NS_IMETHODIMP Service::OpenDatabaseWithFileURL(nsIFileURL* aFileURL, - const nsACString& aTelemetryFilename, mozIStorageConnection** _connection) { NS_ENSURE_ARG(aFileURL); @@ -606,7 +605,7 @@ Service::OpenDatabaseWithFileURL(nsIFileURL* aFileURL, SQLITE_OPEN_CREATE | SQLITE_OPEN_URI; RefPtr msc = new Connection(this, flags, Connection::SYNCHRONOUS); - nsresult rv = msc->initialize(aFileURL, aTelemetryFilename); + nsresult rv = msc->initialize(aFileURL); NS_ENSURE_SUCCESS(rv, rv); msc.forget(_connection); diff --git a/storage/mozStorageStatement.cpp b/storage/mozStorageStatement.cpp index 1c3f8fdbcac6e..d857c48164026 100644 --- a/storage/mozStorageStatement.cpp +++ b/storage/mozStorageStatement.cpp @@ -105,9 +105,7 @@ Statement::Statement() mParamCount(0), mResultColumnCount(0), mColumnNames(), - mExecuting(false), - mQueryStatusRecorded(false), - mHasExecuted(false) {} + mExecuting(false) {} nsresult Statement::initialize(Connection* aDBConnection, sqlite3* aNativeConnection, @@ -126,9 +124,6 @@ nsresult Statement::initialize(Connection* aDBConnection, ::sqlite3_errmsg(aNativeConnection))); MOZ_LOG(gStorageLog, LogLevel::Error, ("Statement was: '%s'", PromiseFlatCString(aSQLStatement).get())); - - aDBConnection->RecordQueryStatus(srv); - mQueryStatusRecorded = true; return NS_ERROR_FAILURE; } @@ -220,28 +215,6 @@ mozIStorageBindingParams* Statement::getParams() { return *mParamsArray->begin(); } -void Statement::MaybeRecordQueryStatus(int srv, bool isResetting) { - // If the statement hasn't been executed synchronously since it was last reset - // or created then there is no need to record anything. Asynchronous - // statements have their status tracked and recorded by StatementData. - if (!mHasExecuted) { - return; - } - - if (!isResetting && !isErrorCode(srv)) { - // Non-errors will be recorded when finalizing. - return; - } - - // We only record a status if no status has been recorded previously. - if (!mQueryStatusRecorded && mDBConnection) { - mDBConnection->RecordQueryStatus(srv); - } - - // Allow another status to be recorded if we are resetting this statement. - mQueryStatusRecorded = !isResetting; -} - Statement::~Statement() { (void)internalFinalize(true); } //////////////////////////////////////////////////////////////////////////////// @@ -277,7 +250,6 @@ int Statement::getAsyncStatement(sqlite3_stmt** _stmt) { int rc = mDBConnection->prepareStatement(mNativeConnection, sql, &mAsyncStatement); if (rc != SQLITE_OK) { - mDBConnection->RecordQueryStatus(rc); *_stmt = nullptr; return rc; } @@ -374,11 +346,6 @@ nsresult Statement::internalFinalize(bool aDestructing) { #endif // DEBUG } - // This will be a no-op if the status has already been recorded or if this - // statement has not been executed. Async statements have their status - // tracked and recorded in StatementData. - MaybeRecordQueryStatus(srv, true); - mDBStatement = nullptr; if (mAsyncStatement) { @@ -493,12 +460,6 @@ Statement::Reset() { mExecuting = false; - // This will be a no-op if the status has already been recorded or if this - // statement has not been executed. Async statements have their status - // tracked and recorded in StatementData. - MaybeRecordQueryStatus(SQLITE_OK, true); - mHasExecuted = false; - return NS_OK; } @@ -556,8 +517,6 @@ Statement::ExecuteStep(bool* _moreResults) { mParamsArray = nullptr; } int srv = mDBConnection->stepStatement(mNativeConnection, mDBStatement); - mHasExecuted = true; - MaybeRecordQueryStatus(srv); if (srv != SQLITE_ROW && srv != SQLITE_DONE && MOZ_LOG_TEST(gStorageLog, LogLevel::Debug)) { diff --git a/storage/mozStorageStatement.h b/storage/mozStorageStatement.h index e472a804c2d02..d6016503de9fd 100644 --- a/storage/mozStorageStatement.h +++ b/storage/mozStorageStatement.h @@ -76,26 +76,12 @@ class Statement final : public mozIStorageStatement, nsTArray mColumnNames; bool mExecuting; - // Tracks whether the status for this statement has been recorded since it was - // last reset or created. - bool mQueryStatusRecorded; - // Tracks whether this statement has been executed since it was last reset or - // created. - bool mHasExecuted; - /** * @return a pointer to the BindingParams object to use with our Bind* * method. */ mozIStorageBindingParams* getParams(); - /** - * Records a query status result in telemetry. If a result has already been - * recorded for this statement then this does nothing. Otherwise the result - * is recorded if it is an error or if this is the final result. - */ - void MaybeRecordQueryStatus(int srv, bool isResetting = false); - /** * Holds the array of parameters to bind to this statement when we execute * it asynchronously. diff --git a/storage/mozStorageStatementData.h b/storage/mozStorageStatementData.h index 1008496671c19..f336e7375a72f 100644 --- a/storage/mozStorageStatementData.h +++ b/storage/mozStorageStatementData.h @@ -15,7 +15,6 @@ #include "mozStorageBindingParamsArray.h" #include "mozStorageConnection.h" #include "StorageBaseStatementInternal.h" -#include "mozStoragePrivateHelpers.h" struct sqlite3_stmt; @@ -29,18 +28,16 @@ class StatementData { StorageBaseStatementInternal* aStatementOwner) : mStatement(aStatement), mParamsArray(aParamsArray), - mQueryStatusRecorded(false), mStatementOwner(aStatementOwner) { MOZ_ASSERT(mStatementOwner, "Must have a statement owner!"); } StatementData(const StatementData& aSource) : mStatement(aSource.mStatement), mParamsArray(aSource.mParamsArray), - mQueryStatusRecorded(false), mStatementOwner(aSource.mStatementOwner) { MOZ_ASSERT(mStatementOwner, "Must have a statement owner!"); } - StatementData() : mStatement(nullptr), mQueryStatusRecorded(false) {} + StatementData() : mStatement(nullptr) {} ~StatementData() { // We need to ensure that mParamsArray is released on the main thread, // as the binding arguments may be XPConnect values, which are safe @@ -56,7 +53,6 @@ class StatementData { inline int getSqliteStatement(sqlite3_stmt** _stmt) { if (!mStatement) { int rc = mStatementOwner->getAsyncStatement(&mStatement); - MaybeRecordQueryStatus(rc); NS_ENSURE_TRUE(rc == SQLITE_OK, rc); } *_stmt = mStatement; @@ -78,10 +74,6 @@ class StatementData { (void)::sqlite3_reset(mStatement); (void)::sqlite3_clear_bindings(mStatement); mStatement = nullptr; - - if (!mQueryStatusRecorded) { - mStatementOwner->getOwner()->RecordQueryStatus(SQLITE_OK); - } } } @@ -116,19 +108,9 @@ class StatementData { return mParamsArray ? mParamsArray->length() : 1; } - void MaybeRecordQueryStatus(int srv) { - if (mQueryStatusRecorded || !isErrorCode(srv)) { - return; - } - - mStatementOwner->getOwner()->RecordQueryStatus(srv); - mQueryStatusRecorded = true; - } - private: sqlite3_stmt* mStatement; RefPtr mParamsArray; - bool mQueryStatusRecorded; /** * We hold onto a reference of the statement's owner so it doesn't get diff --git a/storage/test/unit/baddataDB.sqlite b/storage/test/unit/baddataDB.sqlite deleted file mode 100644 index 5b2f9da3d6980..0000000000000 Binary files a/storage/test/unit/baddataDB.sqlite and /dev/null differ diff --git a/storage/test/unit/goodDB.sqlite b/storage/test/unit/goodDB.sqlite deleted file mode 100644 index b06884672fa98..0000000000000 Binary files a/storage/test/unit/goodDB.sqlite and /dev/null differ diff --git a/storage/test/unit/head_storage.js b/storage/test/unit/head_storage.js index b19075270b4a4..0e00e6ba734cd 100644 --- a/storage/test/unit/head_storage.js +++ b/storage/test/unit/head_storage.js @@ -10,31 +10,12 @@ var { AppConstants } = ChromeUtils.import( "resource://gre/modules/AppConstants.jsm" ); -const { TelemetryTestUtils } = ChromeUtils.import( - "resource://testing-common/TelemetryTestUtils.jsm" -); - -const OPEN_HISTOGRAM = "SQLITE_STORE_OPEN"; -const QUERY_HISTOGRAM = "SQLITE_STORE_QUERY"; - -const TELEMETRY_VALUES = { - success: 0, - failure: 1, - access: 2, - diskio: 3, - corrupt: 4, - busy: 5, - misuse: 6, - diskspace: 7, -}; - do_get_profile(); var gDBConn = null; -const TEST_DB_NAME = "test_storage.sqlite"; function getTestDB() { var db = Services.dirsvc.get("ProfD", Ci.nsIFile); - db.append(TEST_DB_NAME); + db.append("test_storage.sqlite"); return db; } @@ -114,10 +95,6 @@ function asyncCleanup() { function getOpenedDatabase() { if (!gDBConn) { gDBConn = Services.storage.openDatabase(getTestDB()); - - // Clear out counts for any queries that occured while opening the database. - TelemetryTestUtils.getAndClearKeyedHistogram(OPEN_HISTOGRAM); - TelemetryTestUtils.getAndClearKeyedHistogram(QUERY_HISTOGRAM); } return gDBConn; } diff --git a/storage/test/unit/test_statement_executeAsync.js b/storage/test/unit/test_statement_executeAsync.js index 5cd87747dcff9..ecb56efbb69b8 100644 --- a/storage/test/unit/test_statement_executeAsync.js +++ b/storage/test/unit/test_statement_executeAsync.js @@ -179,34 +179,16 @@ function execAsync(aStmt, aOptions, aResults) { * error synchronously (and is tested elsewhere). */ function test_illegal_sql_async_deferred() { - let histogram = TelemetryTestUtils.getAndClearKeyedHistogram(QUERY_HISTOGRAM); - // gibberish let stmt = makeTestStatement("I AM A ROBOT. DO AS I SAY."); execAsync(stmt, { error: Ci.mozIStorageError.ERROR }); stmt.finalize(); - TelemetryTestUtils.assertKeyedHistogramValue( - histogram, - TEST_DB_NAME, - TELEMETRY_VALUES.failure, - 1 - ); - histogram.clear(); - // legal SQL syntax, but with semantics issues. stmt = makeTestStatement("SELECT destination FROM funkytown"); execAsync(stmt, { error: Ci.mozIStorageError.ERROR }); stmt.finalize(); - TelemetryTestUtils.assertKeyedHistogramValue( - histogram, - TEST_DB_NAME, - TELEMETRY_VALUES.failure, - 1 - ); - histogram.clear(); - run_next_test(); } test_illegal_sql_async_deferred.asyncOnly = true; @@ -215,8 +197,6 @@ function test_create_table() { // Ensure our table doesn't exist Assert.ok(!getOpenedDatabase().tableExists("test")); - let histogram = TelemetryTestUtils.getAndClearKeyedHistogram(QUERY_HISTOGRAM); - var stmt = makeTestStatement( "CREATE TABLE test (" + "id INTEGER, " + @@ -229,34 +209,18 @@ function test_create_table() { execAsync(stmt); stmt.finalize(); - TelemetryTestUtils.assertKeyedHistogramValue( - histogram, - TEST_DB_NAME, - TELEMETRY_VALUES.success, - 1 - ); - histogram.clear(); - // Check that the table has been created Assert.ok(getOpenedDatabase().tableExists("test")); - histogram.clear(); - // Verify that it's created correctly (this will throw if it wasn't) let checkStmt = getOpenedDatabase().createStatement( "SELECT id, string, number, nuller, blober FROM test" ); checkStmt.finalize(); - - // Nothing has executed so the histogram should be empty. - Assert.ok(!histogram.snapshot().values); - run_next_test(); } function test_add_data() { - let histogram = TelemetryTestUtils.getAndClearKeyedHistogram(QUERY_HISTOGRAM); - var stmt = makeTestStatement( "INSERT INTO test (id, string, number, nuller, blober) " + "VALUES (?, ?, ?, ?, ?)" @@ -270,35 +234,16 @@ function test_add_data() { execAsync(stmt); stmt.finalize(); - TelemetryTestUtils.assertKeyedHistogramValue( - histogram, - TEST_DB_NAME, - TELEMETRY_VALUES.success, - 1 - ); - histogram.clear(); - // Check that the result is in the table verifyQuery( "SELECT string, number, nuller, blober FROM test WHERE id = ?", INTEGER, [TEXT, REAL, null, BLOB] ); - - TelemetryTestUtils.assertKeyedHistogramValue( - histogram, - TEST_DB_NAME, - TELEMETRY_VALUES.success, - 1 - ); - histogram.clear(); - run_next_test(); } function test_get_data() { - let histogram = TelemetryTestUtils.getAndClearKeyedHistogram(QUERY_HISTOGRAM); - var stmt = makeTestStatement( "SELECT string, number, nuller, blober, id FROM test WHERE id = ?" ); @@ -363,21 +308,10 @@ function test_get_data() { }, ]); stmt.finalize(); - - TelemetryTestUtils.assertKeyedHistogramValue( - histogram, - TEST_DB_NAME, - TELEMETRY_VALUES.success, - 1 - ); - histogram.clear(); - run_next_test(); } function test_tuple_out_of_bounds() { - let histogram = TelemetryTestUtils.getAndClearKeyedHistogram(QUERY_HISTOGRAM); - var stmt = makeTestStatement("SELECT string FROM test"); execAsync(stmt, {}, [ function(tuple) { @@ -414,15 +348,6 @@ function test_tuple_out_of_bounds() { }, ]); stmt.finalize(); - - TelemetryTestUtils.assertKeyedHistogramValue( - histogram, - TEST_DB_NAME, - TELEMETRY_VALUES.success, - 1 - ); - histogram.clear(); - run_next_test(); } @@ -525,21 +450,10 @@ function test_cancellation_after_execution() { * handleResult to get called multiple times) and not comprehensive. */ function test_double_execute() { - let histogram = TelemetryTestUtils.getAndClearKeyedHistogram(QUERY_HISTOGRAM); - var stmt = makeTestStatement("SELECT 1"); execAsync(stmt, null, 1); execAsync(stmt, null, 1); stmt.finalize(); - - TelemetryTestUtils.assertKeyedHistogramValue( - histogram, - TEST_DB_NAME, - TELEMETRY_VALUES.success, - 2 - ); - histogram.clear(); - run_next_test(); } diff --git a/storage/test/unit/test_storage_service.js b/storage/test/unit/test_storage_service.js index ccfe4eaae2a43..ce4f64d8ecb35 100644 --- a/storage/test/unit/test_storage_service.js +++ b/storage/test/unit/test_storage_service.js @@ -42,78 +42,36 @@ function test_openUnsharedDatabase_null_file() { function test_openDatabase_file_DNE() { // the file should be created after calling - - let histogram = TelemetryTestUtils.getAndClearKeyedHistogram(OPEN_HISTOGRAM); - var db = getTestDB(); Assert.ok(!db.exists()); Services.storage.openDatabase(db); Assert.ok(db.exists()); - - TelemetryTestUtils.assertKeyedHistogramValue( - histogram, - db.leafName, - TELEMETRY_VALUES.success, - 1 - ); } function test_openDatabase_file_exists() { // it should already exist from our last test - - let histogram = TelemetryTestUtils.getAndClearKeyedHistogram(OPEN_HISTOGRAM); - var db = getTestDB(); Assert.ok(db.exists()); Services.storage.openDatabase(db); Assert.ok(db.exists()); - - TelemetryTestUtils.assertKeyedHistogramValue( - histogram, - db.leafName, - TELEMETRY_VALUES.success, - 1 - ); } function test_corrupt_db_throws_with_openDatabase() { - let histogram = TelemetryTestUtils.getAndClearKeyedHistogram(OPEN_HISTOGRAM); - - let db = getCorruptDB(); - try { - getDatabase(db); + getDatabase(getCorruptDB()); do_throw("should not be here"); } catch (e) { Assert.equal(Cr.NS_ERROR_FILE_CORRUPTED, e.result); } - - TelemetryTestUtils.assertKeyedHistogramValue( - histogram, - db.leafName, - TELEMETRY_VALUES.corrupt, - 1 - ); } function test_fake_db_throws_with_openDatabase() { - let histogram = TelemetryTestUtils.getAndClearKeyedHistogram(OPEN_HISTOGRAM); - - let db = getFakeDB(); - try { - getDatabase(db); + getDatabase(getFakeDB()); do_throw("should not be here"); } catch (e) { Assert.equal(Cr.NS_ERROR_FILE_CORRUPTED, e.result); } - - TelemetryTestUtils.assertKeyedHistogramValue( - histogram, - db.leafName, - TELEMETRY_VALUES.corrupt, - 1 - ); } function test_backup_not_new_filename() { @@ -155,106 +113,6 @@ function test_backup_new_folder() { parentDir.remove(true); } -function test_openDatabase_directory() { - let dir = getTestDB().parent; - dir.append("test_storage_temp"); - if (dir.exists()) { - dir.remove(true); - } - dir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755); - Assert.ok(dir.exists()); - - let histogram = TelemetryTestUtils.getAndClearKeyedHistogram(OPEN_HISTOGRAM); - - try { - getDatabase(dir); - do_throw("should not be here"); - } catch (e) { - Assert.equal(Cr.NS_ERROR_FILE_ACCESS_DENIED, e.result); - } - - TelemetryTestUtils.assertKeyedHistogramValue( - histogram, - dir.leafName, - TELEMETRY_VALUES.access, - 1 - ); - - dir.remove(true); -} - -function test_read_gooddb() { - let file = do_get_file("goodDB.sqlite"); - let db = getDatabase(file); - - let histogram = TelemetryTestUtils.getAndClearKeyedHistogram(QUERY_HISTOGRAM); - - db.executeSimpleSQL("SELECT * FROM Foo;"); - - TelemetryTestUtils.assertKeyedHistogramValue( - histogram, - file.leafName, - TELEMETRY_VALUES.success, - 1 - ); - - histogram.clear(); - - let stmt = db.createStatement("SELECT id from Foo"); - - while (true) { - if (!stmt.executeStep()) { - break; - } - } - - stmt.finalize(); - - // A single statement should count as a single access. - TelemetryTestUtils.assertKeyedHistogramValue( - histogram, - file.leafName, - TELEMETRY_VALUES.success, - 1 - ); -} - -function test_read_baddb() { - let file = do_get_file("baddataDB.sqlite"); - let db = getDatabase(file); - - let histogram = TelemetryTestUtils.getAndClearKeyedHistogram(QUERY_HISTOGRAM); - - Assert.throws( - () => db.executeSimpleSQL("SELECT * FROM Foo"), - /NS_ERROR_FILE_CORRUPTED/, - "Executing sql should fail." - ); - - TelemetryTestUtils.assertKeyedHistogramValue( - histogram, - file.leafName, - TELEMETRY_VALUES.corrupt, - 1 - ); - - histogram.clear(); - - let stmt = db.createStatement("SELECT * FROM Foo"); - Assert.throws( - () => stmt.executeStep(), - /NS_ERROR_FILE_CORRUPTED/, - "Executing a statement should fail." - ); - - TelemetryTestUtils.assertKeyedHistogramValue( - histogram, - file.leafName, - TELEMETRY_VALUES.corrupt, - 1 - ); -} - var tests = [ test_openSpecialDatabase_invalid_arg, test_openDatabase_null_file, @@ -266,9 +124,6 @@ var tests = [ test_backup_not_new_filename, test_backup_new_filename, test_backup_new_folder, - test_openDatabase_directory, - test_read_gooddb, - test_read_baddb, ]; function run_test() { diff --git a/storage/test/unit/xpcshell.ini b/storage/test/unit/xpcshell.ini index 80baaab282f6f..fde21a4add665 100644 --- a/storage/test/unit/xpcshell.ini +++ b/storage/test/unit/xpcshell.ini @@ -1,10 +1,8 @@ [DEFAULT] head = head_storage.js support-files = - baddataDB.sqlite corruptDB.sqlite fakeDB.sqlite - goodDB.sqlite locale_collation.txt vacuumParticipant.js vacuumParticipant.manifest diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index 94732b117f401..559ee61a5ab68 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -15442,47 +15442,5 @@ "alert_emails": ["jmathies@mozilla.com", "chsiang@mozilla.com"], "bug_numbers": [1653073, 1656355], "releaseChannelCollection": "opt-out" - }, - "SQLITE_STORE_OPEN": { - "record_in_processes": ["main"], - "products": ["firefox"], - "alert_emails": ["dtownsend@mozilla.com", "mbonardo@mozilla.com"], - "expires_in_version": "never", - "kind": "categorical", - "keyed": true, - "releaseChannelCollection": "opt-out", - "bug_numbers": [1635489], - "description": "The result of attempting to open a sqlite file.", - "labels": [ - "success", - "failure", - "access", - "diskio", - "corrupt", - "busy", - "misuse", - "diskspace" - ] - }, - "SQLITE_STORE_QUERY": { - "record_in_processes": ["main"], - "products": ["firefox"], - "alert_emails": ["dtownsend@mozilla.com", "mbonardo@mozilla.com"], - "expires_in_version": "never", - "kind": "categorical", - "keyed": true, - "releaseChannelCollection": "opt-out", - "bug_numbers": [1635489], - "description": "The result of attempting to query a sqlite file.", - "labels": [ - "success", - "failure", - "access", - "diskio", - "corrupt", - "busy", - "misuse", - "diskspace" - ] } }