sl@0: // Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: #include "SqlAssert.h" sl@0: #include "sqlite3.h" sl@0: #include "SqliteSymbian.h" //TSqlFreePageCallback sl@0: #include "SqlSrvUtil.h" sl@0: #include "SqlSrvStatementUtil.h" sl@0: #include "SqlCompactConn.h" sl@0: #include "OstTraceDefinitions.h" sl@0: #ifdef OST_TRACE_COMPILER_IN_USE sl@0: #include "SqlCompactConnTraces.h" sl@0: #endif sl@0: #include "SqlTraceDef.h" sl@0: sl@0: /** sl@0: Creates a new CSqlCompactConn instance. sl@0: sl@0: @param aFullName The full database name, including the path. sl@0: @param aFreePageCallback A reference to an object containing the free pages threshold and the callback sl@0: that needs to be called when the free page count reaches or is above the threshold. sl@0: aFreePageCallback.iThreshold must be set to be in Kb. sl@0: If the function call completes successfully and the free pages space is above the threshold, sl@0: the aFreePageCallback.iThreshold will be set to contain the free pages count. sl@0: Otherwise aFreePageCallback.iThreshold will be initialized with zero. sl@0: sl@0: @return A pointer to the created CSqlCompactConn instance sl@0: sl@0: @leave KErrNoMemory, an out of memory condition has occurred, sl@0: KErrArgument, invalid data in the aFreePageCallback object; sl@0: Note that the function may also leave with some other database specific sl@0: errors categorised as ESqlDbError, and other system-wide error codes. sl@0: sl@0: @panic SqlDb 4 In _DEBUG mode. Too short or too long database name (aFullName parameter) sl@0: @panic SqlDb 4 In _DEBUG mode. Invalid aFreePageCallback content. sl@0: */ sl@0: CSqlCompactConn* CSqlCompactConn::NewL(const TDesC& aFullName, TSqlFreePageCallback& aFreePageCallback) sl@0: { sl@0: SQL_TRACE_COMPACT(OstTraceExt1(TRACE_INTERNALS, CSQLCOMPACTCONN_NEWLC_ENTRY, "Entry;0;CSqlCompactConn::NewL;aFullName=%S", __SQLPRNSTR(aFullName))); sl@0: __ASSERT_DEBUG(aFullName.Length() > 0 && aFullName.Length() <= KMaxFileName, __SQLPANIC2(ESqlPanicBadArgument)); sl@0: __ASSERT_DEBUG(aFreePageCallback.IsValid(), __SQLPANIC2(ESqlPanicBadArgument)); sl@0: CSqlCompactConn* self = new (ELeave) CSqlCompactConn; sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aFullName, aFreePageCallback); sl@0: CleanupStack::Pop(self); sl@0: SQL_TRACE_COMPACT(OstTraceExt2(TRACE_INTERNALS, CSQLCOMPACTCONN_NEWLC_EXIT, "Exit;0x%X;CSqlCompactConn::NewL;aFullName=%S", (TUint)self, __SQLPRNSTR(aFullName))); sl@0: return self; sl@0: } sl@0: sl@0: /** sl@0: Destroys the CSqlCompactConn instance. sl@0: */ sl@0: CSqlCompactConn::~CSqlCompactConn() sl@0: { sl@0: SQL_TRACE_COMPACT(OstTrace1(TRACE_INTERNALS, CSQLCOMPACTCONN_CSQLCOMPACTCONN2, "0x%X;CSqlCompactConn::~CSqlCompactConn", (TUint)this)); sl@0: ::CloseDbHandle(iHandle); sl@0: } sl@0: sl@0: /** sl@0: Implements MSqlCompactConn::Release(). sl@0: Destroys the CSqlCompactConn instance. sl@0: */ sl@0: void CSqlCompactConn::Release() sl@0: { sl@0: SQLCOMPACTCONN_INVARIANT(); sl@0: delete this; sl@0: } sl@0: sl@0: /** sl@0: Implements MSqlCompactConn::Compact(). sl@0: sl@0: Compacts the database making an attempt to remove the specified amount of free pages. sl@0: sl@0: @param aPageCount The amount of free pages to be removed. sl@0: @param aProcessedPageCount Output parameter. The actual count of the removed free pages will be stored there. sl@0: @param aLength Desired length of the compaction in milliseconds. sl@0: @return KErrNoMemory, an out of memory condition has occurred; sl@0: Note that the function may also return some other database specific sl@0: errors categorised as ESqlDbError, and other system-wide error codes. sl@0: sl@0: @panic SqlDb 4 In _DEBUG mode. Negative aPageCount value. sl@0: @panic SqlDb 4 In _DEBUG mode. Negative aLength value. sl@0: */ sl@0: TInt CSqlCompactConn::Compact(TInt aPageCount, TInt& aProcessedPageCount, TInt aLength) sl@0: { sl@0: __ASSERT_DEBUG(aPageCount >= 0, __SQLPANIC(ESqlPanicBadArgument)); sl@0: __ASSERT_DEBUG(aLength >= 0, __SQLPANIC(ESqlPanicBadArgument)); sl@0: SQLCOMPACTCONN_INVARIANT(); sl@0: TInt err = ::DbCompact(iHandle, KNullDesC, aPageCount, aProcessedPageCount, aLength); sl@0: SQLCOMPACTCONN_INVARIANT(); sl@0: return err; sl@0: } sl@0: sl@0: /** sl@0: Initializes the CSqlCompactConn instance establishing a connection with the database to be compacted. sl@0: Registers the passed "free page" callback. sl@0: sl@0: Note: The free page threshold data member of the callback is in Kb. sl@0: The function implementation will convert that threshold to pages and pass it to the OS porting layer. sl@0: sl@0: @param aFullName The full database name, including the path. sl@0: @param aFreePageCallback Input/Output parameter. A reference to an object containing the free pages threshold and sl@0: the callback that needs to be called when the free page count reaches or is above the threshold. sl@0: aFreePageCallback.iThreshold must be set to be in Kb. sl@0: If the function call completes successfully and the free pages space is above the threshold, sl@0: the aFreePageCallback.iThreshold will be set to contain the free pages count. sl@0: Otherwise aFreePageCallback.iThreshold will be initialized with zero. sl@0: sl@0: @leave KErrNoMemory, an out of memory condition has occurred, sl@0: KErrArgument, invalid data in the aFreePageCallback object; sl@0: Note that the function may also leave with some other database specific sl@0: errors categorised as ESqlDbError, and other system-wide error codes. sl@0: sl@0: @panic SqlDb 4 In _DEBUG mode. Too short or too long database name (aFullName parameter) sl@0: @panic SqlDb 4 In _DEBUG mode. Invalid aFreePageCallback content. sl@0: @panic SqlDb 7 In _DEBUG mode. The database connection has been already established (not null db handle). sl@0: */ sl@0: void CSqlCompactConn::ConstructL(const TDesC& aFullName, TSqlFreePageCallback& aFreePageCallback) sl@0: { sl@0: __ASSERT_DEBUG(aFullName.Length() > 0 && aFullName.Length() <= KMaxFileName, __SQLPANIC(ESqlPanicBadArgument)); sl@0: __ASSERT_DEBUG(aFreePageCallback.IsValid(), __SQLPANIC(ESqlPanicBadArgument)); sl@0: __ASSERT_DEBUG(!iHandle, __SQLPANIC(ESqlPanicInternalError)); sl@0: sl@0: TBuf8 fname; sl@0: (void)::UTF16ToUTF8Z(aFullName, fname);//The file is first open by the main connection. sl@0: //The conversion here should always succeed. sl@0: //Even in a case of a conversion failure, the next line will report a failure. sl@0: __SQLLEAVE_IF_ERROR(::CreateDbHandle8(fname, iHandle)); sl@0: sl@0: TInt pageSize = PageSizeL(); sl@0: TInt64 freePageThresholdKb = aFreePageCallback.iThreshold;//"TInt64" because the calculation of the pages may cause an overflow on the next line sl@0: aFreePageCallback.iThreshold = (freePageThresholdKb * 1024) / pageSize;//the threshold can be 0 sl@0: sl@0: TBuf8 dbName; sl@0: dbName.Copy(KMainDb8); sl@0: TInt err = sqlite3_file_control(iHandle, (const char *)dbName.PtrZ(), KSqlFcntlRegisterFreePageCallback, &aFreePageCallback); sl@0: __SQLLEAVE_IF_ERROR(::Sql2OsErrCode(err, sqlite3SymbianLastOsError())); sl@0: sl@0: TInt64 freePageCount = FreePageCountL();//"TInt64" because the calculation of the free space may cause an overflow on the next line sl@0: TInt freePageSpaceKb = (freePageCount * pageSize) / 1024; sl@0: //Set iThreshold with the free pages count, if right now the database has free space above the threshold. sl@0: aFreePageCallback.iThreshold = freePageSpaceKb >= freePageThresholdKb ? freePageCount : 0; sl@0: } sl@0: sl@0: /** sl@0: Retrieves the database free pages count. sl@0: sl@0: @leave KErrNoMemory, an out of memory condition has occurred; sl@0: Note that the function may also return some other database specific sl@0: errors categorised as ESqlDbError, and other system-wide error codes. sl@0: sl@0: @return Free pages count sl@0: */ sl@0: TInt CSqlCompactConn::FreePageCountL() sl@0: { sl@0: SQLCOMPACTCONN_INVARIANT(); sl@0: TInt freePageCount = 0; sl@0: __SQLLEAVE_IF_ERROR(::DbFreePageCount(iHandle, KNullDesC, freePageCount)); sl@0: SQLCOMPACTCONN_INVARIANT(); sl@0: return freePageCount; sl@0: } sl@0: sl@0: /** sl@0: Retrieves the database page size in bytes. sl@0: sl@0: @leave KErrNoMemory, an out of memory condition has occurred; sl@0: Note that the function may also return some other database specific sl@0: errors categorised as ESqlDbError, and other system-wide error codes. sl@0: sl@0: @return Page size sl@0: */ sl@0: TInt CSqlCompactConn::PageSizeL() sl@0: { sl@0: SQLCOMPACTCONN_INVARIANT(); sl@0: TInt pageSize = 0; sl@0: __SQLLEAVE_IF_ERROR(::DbPageSize(iHandle, KNullDesC, pageSize)); sl@0: SQLCOMPACTCONN_INVARIANT(); sl@0: return pageSize; sl@0: } sl@0: sl@0: #ifdef _DEBUG sl@0: /** sl@0: CSqlCompactConn invariant. sl@0: */ sl@0: void CSqlCompactConn::Invariant() const sl@0: { sl@0: __ASSERT_ALWAYS(iHandle != NULL, __SQLPANIC(ESqlPanicInternalError)); sl@0: } sl@0: #endif//_DEBUG sl@0: sl@0: /** sl@0: A factory function for CSqlCompactConn. sl@0: sl@0: @param aFullName The full name of the database to be compacted (including the path). sl@0: @param aFreePageCallback A reference to an object containing the free pages threshold and the callback sl@0: that needs to be called when the free page count reaches or is above the threshold. sl@0: aFreePageCallback.iThreshold must be set to be in Kb. sl@0: If the function call completes successfully and the free pages space is above the threshold, sl@0: the aFreePageCallback.iThreshold will be set to contain the free pages count. sl@0: Otherwise aFreePageCallback.iThreshold will be initialized with zero. sl@0: sl@0: @return A pointer to the created MSqlCompactConn interface. sl@0: sl@0: @leave KErrNoMemory, an out of memory condition has occurred, sl@0: KErrArgument, invalid data in the aFreePageCallback object; sl@0: Note that the function may also leave with some other database specific sl@0: errors categorised as ESqlDbError, and other system-wide error codes. sl@0: sl@0: @see MSqlCompactConn sl@0: @see CSqlCompactConn sl@0: sl@0: @internalComponent sl@0: sl@0: @panic SqlDb 4 In _DEBUG mode. Too short or too long database name (aFullName parameter) sl@0: @panic SqlDb 4 In _DEBUG mode. Invalid aFreePageCallback content. sl@0: */ sl@0: MSqlCompactConn* SqlCreateCompactConnL(const TDesC& aFullName, TSqlFreePageCallback& aFreePageCallback) sl@0: { sl@0: __ASSERT_DEBUG(aFullName.Length() > 0 && aFullName.Length() <= KMaxFileName, __SQLPANIC2(ESqlPanicBadArgument)); sl@0: __ASSERT_DEBUG(aFreePageCallback.IsValid(), __SQLPANIC2(ESqlPanicBadArgument)); sl@0: return CSqlCompactConn::NewL(aFullName, aFreePageCallback); sl@0: }