diff --git a/storage/public/mozIStorageConnection.idl b/storage/public/mozIStorageConnection.idl index 48c5ecbbabd..d61d5189c49 100644 --- a/storage/public/mozIStorageConnection.idl +++ b/storage/public/mozIStorageConnection.idl @@ -361,13 +361,17 @@ interface mozIStorageConnection : nsISupports { /** * Controls SQLITE_FCNTL_CHUNK_SIZE setting in sqlite. This helps avoid fragmentation - * by growing/shrinking the database file in SQLITE_FCNTL_CHUNK_SIZE increments. + * by growing/shrinking the database file in SQLITE_FCNTL_CHUNK_SIZE increments. To + * conserve memory on systems short on storage space, this function will have no effect + * on mobile devices or if less than 100MB of space is left available. * * @param aIncrement * The database file will grow in multiples of chunkSize. * @param aDatabaseName * Sqlite database name. "" means pass NULL for zDbName to sqlite3_file_control. * See http://sqlite.org/c3ref/file_control.html for more details. + * @throws NS_ERROR_FILE_TOO_BIG + * If the system is short on storage space. */ void setGrowthIncrement(in PRInt32 aIncrement, in AUTF8String aDatabaseName); }; diff --git a/storage/src/mozStorageConnection.cpp b/storage/src/mozStorageConnection.cpp index acf6dc24536..5f8d8e7c623 100644 --- a/storage/src/mozStorageConnection.cpp +++ b/storage/src/mozStorageConnection.cpp @@ -47,9 +47,9 @@ #include "nsIMutableArray.h" #include "nsHashSets.h" #include "nsAutoPtr.h" -#include "nsIFile.h" #include "nsIMemoryReporter.h" #include "nsThreadUtils.h" +#include "nsILocalFile.h" #include "mozIStorageAggregateFunction.h" #include "mozIStorageCompletionCallback.h" @@ -70,6 +70,8 @@ #include "prlog.h" #include "prprf.h" +#define BYTES_PER_MEBIBYTE 1048576 + #ifdef PR_LOGGING PRLogModuleInfo* gStorageLog = nsnull; #endif @@ -1245,6 +1247,16 @@ Connection::SetGrowthIncrement(PRInt32 aChunkSize, const nsACString &aDatabaseNa // so don't preallocate space. This is also not effective // on log structured file systems used by Android devices #if !defined(ANDROID) && !defined(MOZ_PLATFORM_MAEMO) + // Don't preallocate if less than 100MiB is available. + nsCOMPtr localFile = do_QueryInterface(mDatabaseFile); + NS_ENSURE_STATE(localFile); + PRInt64 bytesAvailable; + nsresult rv = localFile->GetDiskSpaceAvailable(&bytesAvailable); + NS_ENSURE_SUCCESS(rv, rv); + if (bytesAvailable < 100 * BYTES_PER_MEBIBYTE) { + return NS_ERROR_FILE_TOO_BIG; + } + (void)::sqlite3_file_control(mDBConn, aDatabaseName.Length() ? nsPromiseFlatCString(aDatabaseName).get() : NULL, SQLITE_FCNTL_CHUNK_SIZE,