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: // The Symbian OS porting layer - multi-threaded implementation. sl@0: // Platform dependend implementation of the static mutexes and the file session API. sl@0: // sl@0: // sl@0: sl@0: /** sl@0: @file sl@0: */ sl@0: #include "os_symbian.h" sl@0: #include sl@0: #include sl@0: #include "SqliteUtil.h" sl@0: #include "OstTraceDefinitions.h" sl@0: #ifdef OST_TRACE_COMPILER_IN_USE sl@0: #include "os_symbian_emulTraces.h" sl@0: #endif sl@0: #include "SqliteTraceDef.h" sl@0: sl@0: #ifdef SQLITE_OS_SYMBIAN sl@0: sl@0: const TUid KSqliteUid = {0x10285A79};//See UID3 in SQLite3.mmp file - it should be the same sl@0: sl@0: /** sl@0: This class describes an object that serves as a container for SQLite global variables sl@0: that are stored in an allocated WSD buffer. sl@0: The global variables are organised in a map, where the pointer to the initial global variable value sl@0: is used as a key. sl@0: A hash table is used to speed-up the key search. sl@0: A single TWsdMap object is created and stored in the process local storage - TPls. sl@0: sl@0: @see TPls sl@0: sl@0: @internalComponent sl@0: */ sl@0: NONSHARABLE_CLASS(TWsdMap) sl@0: { sl@0: /** sl@0: Hash table entry. sl@0: */ sl@0: struct TPair sl@0: { sl@0: const TUint8* iKey; //Global variable - key (a pointer the initial variable value) sl@0: TUint8* iData; //Global variable - data sl@0: }; sl@0: sl@0: public: sl@0: enum {KBufferSize = 4096}; //WSD buffer size in bytes sl@0: enum {KMaxEntries = 37}; //Max No. of entries in the hash table - prime number sl@0: sl@0: TWsdMap() : sl@0: iNext(iBuffer), sl@0: iSize(0) sl@0: { sl@0: Mem::FillZ(iTable, sizeof(iTable)); sl@0: } sl@0: /** sl@0: Performs a search in the map for a global variable with aKey key. sl@0: If there is no such variable in the map, the variable will be added and the new variable will be initialized sl@0: with the data of aLength length, pointed by aKey. sl@0: @param aKey Global variable key sl@0: @param aLength Global variable data length in bytes sl@0: @return Pointer to the global variable (located in the WSD buffer) sl@0: @panic SqliteMt 9 The global variables map is full sl@0: @panic SqliteMt 10 There is no space in the WSD buffer for the new variable sl@0: */ sl@0: TUint8* Find(const TUint8* aKey, TInt aLength) sl@0: { sl@0: TInt idx = Hash((TUint)aKey); sl@0: TInt cnt = 0; sl@0: while(iTable[idx].iKey != aKey && iTable[idx].iKey != NULL && ++cnt < KMaxEntries) sl@0: { sl@0: idx = ++idx % KMaxEntries; sl@0: } sl@0: __ASSERT_ALWAYS(cnt < KMaxEntries, __SQLITEPANIC2(ESqliteOsPanicMaxKeysExceeded)); sl@0: if(!iTable[idx].iKey) sl@0: { sl@0: Add(idx, aKey, aLength); sl@0: } sl@0: return iTable[idx].iData; sl@0: } sl@0: sl@0: private: sl@0: /** sl@0: Hash function. Calculates the index of the global variable key in the hash table. sl@0: @param aKey Global variable key (casted "const TUint8*" to "TUint") sl@0: @return Hash table index sl@0: */ sl@0: TUint Hash(TUint aKey) const sl@0: { sl@0: return (aKey * (aKey + 3)) % KMaxEntries; sl@0: } sl@0: /** sl@0: Adds a new global variable to the WSD buffer and initializes a new entry in the hash table for the key. sl@0: @param aIdx The entry index in the hash table sl@0: @param aKey Global variable key sl@0: @param aLength Global variable data length in bytes sl@0: @panic SqliteMt 10 There is no space in the WSD buffer for the new variable sl@0: */ sl@0: void Add(TInt aIdx, const TUint8* aKey, TInt aLength) sl@0: { sl@0: __ASSERT_ALWAYS((iSize + aLength) <= KBufferSize, __SQLITEPANIC2(ESqliteOsPanicBufferSizeExceeded)); sl@0: //Add new entry to the hash table and the intial value to the WSD buffer sl@0: iTable[aIdx].iKey = aKey; sl@0: iTable[aIdx].iData = iNext; sl@0: iNext = Mem::Copy(iNext, aKey, aLength); sl@0: iSize += aLength; sl@0: //////////////// DEBUG prints ///////////////// sl@0: //for(TInt i=0;iiStaticFs.Connect(); sl@0: SQLITE_TRACE_OS(OstTrace1(TRACE_INTERNALS, PLSINITIALIZE1, "OS;0;PlsInitialize;iStaticFs.Connect() err=%d", err)); sl@0: __ASSERT_ALWAYS(err == KErrNone, __SQLITEPANIC2(ESqliteOsPanicFsCreationError)); sl@0: //Static mutexes sl@0: TInt idx = 0; sl@0: for(;idx<(sizeof(aPls->iStaticMutex)/sizeof(aPls->iStaticMutex[0])) && err==KErrNone;++idx) sl@0: { sl@0: err = aPls->iStaticMutex[idx].Create(); sl@0: } sl@0: SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, PLSINITIALIZE2, "OS;0;PlsInitialize;iStaticMutex[%d].Create() err=%d", idx, err)); sl@0: __ASSERT_ALWAYS(err == KErrNone , __SQLITEPANIC2(ESqliteOsPanicMutexCreationError)); sl@0: //WSD map sl@0: //...already initialized by its constructor sl@0: //sqlite3_vfs object sl@0: aPls->iVfsApi.iVersion = 1; sl@0: aPls->iVfsApi.szOsFile = sizeof(TDbFile); sl@0: aPls->iVfsApi.mxPathname = KMaxFileName; sl@0: aPls->iVfsApi.pNext = NULL; sl@0: aPls->iVfsApi.zName = "SymbianSqliteMt"; sl@0: aPls->iVfsApi.pAppData = NULL; sl@0: aPls->iVfsApi.xOpen = &TVfs::Open; sl@0: aPls->iVfsApi.xDelete = &TVfs::Delete; sl@0: aPls->iVfsApi.xAccess = &TVfs::Access; sl@0: aPls->iVfsApi.xFullPathname = &TVfs::FullPathName; sl@0: aPls->iVfsApi.xDlOpen = NULL; sl@0: aPls->iVfsApi.xDlError = NULL; sl@0: aPls->iVfsApi.xDlSym = NULL; sl@0: aPls->iVfsApi.xDlClose = NULL; sl@0: aPls->iVfsApi.xRandomness = &TVfs::Randomness; sl@0: aPls->iVfsApi.xSleep = &TVfs::Sleep; sl@0: aPls->iVfsApi.xCurrentTime = &TVfs::CurrentTime; sl@0: aPls->iVfsApi.xGetLastError = &TVfs::GetLastError; sl@0: sl@0: SQLITE_TRACE_OS(OstTrace0(TRACE_INTERNALS, PLSINITIALIZE_EXIT, "OS-Exit;0;PlsInitialize")); sl@0: return KErrNone; sl@0: } sl@0: sl@0: //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// sl@0: ////////////////////////// TStaticFs ///////////////////////////////////////////////////////////////////////////////////////// sl@0: //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: TStaticFs::TStaticFs() sl@0: { sl@0: } sl@0: sl@0: /** sl@0: Returns a reference to the already created RFs object that is located in the process local storage. sl@0: sl@0: @return RFs reference sl@0: sl@0: @panic SqliteMt 3 Invalid RFs handle sl@0: @panic SqliteMt 5 Process local storage initialization failure sl@0: */ sl@0: RFs& TStaticFs::Fs() sl@0: { sl@0: TPls* pls = ::Pls(KSqliteUid, &PlsInitialize); sl@0: __ASSERT_ALWAYS(pls != 0, __SQLITEPANIC2(ESqliteOsPanicNullPls2)); sl@0: __ASSERT_DEBUG(pls->iStaticFs.iFs.Handle() != KNullHandle, __SQLITEPANIC2(ESqliteOsPanicInvalidFs)); sl@0: return pls->iStaticFs.iFs; sl@0: } sl@0: sl@0: //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// sl@0: ////////////////////////// TStaticMutex ////////////////////////////////////////////////////////////////////////////////////// sl@0: //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: TStaticMutex::TStaticMutex() sl@0: { sl@0: } sl@0: sl@0: sqlite3_mutex* StaticMutex(TInt aType) sl@0: { sl@0: TPls* pls = ::Pls(KSqliteUid, &PlsInitialize); sl@0: __ASSERT_ALWAYS(pls != 0, __SQLITEPANIC2(ESqliteOsPanicNullPls3)); sl@0: __ASSERT_ALWAYS((TUint)aType < (sizeof(pls->iStaticMutex)/sizeof(pls->iStaticMutex[0])), __SQLITEPANIC2(ESqliteOsPanicInvalidMutexType)); sl@0: return &pls->iStaticMutex[aType]; sl@0: } sl@0: sl@0: sl@0: //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// sl@0: //////////////////////// sqlite3_wsd ///////////////////////////////////////////////////////////////////////////////////// sl@0: //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: /** sl@0: The implementation of this function does not do anything special apart from checking that the requested WSD buffer size and sl@0: global variables count (WSD entries) are not bigger than the max TWsdMap buffer size and max TWsdMap entry count. sl@0: sl@0: @param aWsdBufSize SQLite expects the size of the WSD buffer to be "aWsdBufSize" bytes sl@0: @param aWsdEntryCount SQLite can place in the WSD buffer up to "aWsdEntryCount" global variables. sl@0: sl@0: @panic SqliteMt 12 The requested WSD buffer is too big. Bigger than TWsdMap::KBufferSize. sl@0: @panic SqliteMt 13 The requested global variables count is too big. Bigger than TWsdMap::KMaxEntries. sl@0: sl@0: @see TWsdMap sl@0: */ sl@0: int sqlite3_wsd_init(int aWsdBufSize, int aWsdEntryCount) sl@0: { sl@0: __ASSERT_ALWAYS(aWsdBufSize <= TWsdMap::KBufferSize, __SQLITEPANIC2(ESqliteOsPanicWsdBufSize)); sl@0: __ASSERT_ALWAYS(aWsdEntryCount <= TWsdMap::KMaxEntries, __SQLITEPANIC2(ESqliteOsPanicWsdEntryCount)); sl@0: return SQLITE_OK; sl@0: } sl@0: sl@0: /** sl@0: Performs a search in the WSD map (in the process local storage) for a global variable identified by the aKey parameter. sl@0: sl@0: @param aKey Global variable key sl@0: @param aLength Global variable data length in bytes sl@0: @return Pointer to the global variable data sl@0: sl@0: @panic SqliteMt 11 Process local storage initialization failure sl@0: sl@0: @see TWsdMap sl@0: @see TPls sl@0: */ sl@0: void* sqlite3_wsd_find(void* aKey, int aLength) sl@0: { sl@0: __ASSERT_ALWAYS(aKey != NULL, __SQLITEPANIC2(ESqliteOsPanicNullKey)); sl@0: return ::Pls(KSqliteUid, &PlsInitialize)->iWsdMap.Find(static_cast (aKey), aLength); sl@0: } sl@0: sl@0: /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// sl@0: ////////////////////////// sqlite3_vfs /////////////////////////////////////////////////////////////////////////////////// sl@0: /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: sqlite3_vfs* VfsApi() sl@0: { sl@0: TPls* pls = ::Pls(KSqliteUid, &PlsInitialize); sl@0: __ASSERT_ALWAYS(pls != 0, __SQLITEPANIC2(ESqliteOsPanicNullPls4)); sl@0: return &pls->iVfsApi; sl@0: } sl@0: sl@0: //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// sl@0: //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: #endif SQLITE_OS_SYMBIAN