--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/sqlite3api/OsLayer/os_symbian_emul.cpp Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,293 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// The Symbian OS porting layer - multi-threaded implementation.
+// Platform dependend implementation of the static mutexes and the file session API.
+//
+//
+
+/**
+ @file
+*/
+#include "os_symbian.h"
+#include <pls.h>
+#include <e32std.h>
+
+#ifdef SQLITE_OS_SYMBIAN
+
+const TUid KSqliteUid = {0x10285A79};//See UID3 in SQLite3.mmp file - it should be the same
+
+/**
+This class describes an object that serves as a container for SQLite global variables
+that are stored in an allocated WSD buffer.
+The global variables are organised in a map, where the pointer to the initial global variable value
+is used as a key.
+A hash table is used to speed-up the key search.
+A single TWsdMap object is created and stored in the process local storage - TPls.
+
+@see TPls
+
+@internalComponent
+*/
+NONSHARABLE_CLASS(TWsdMap)
+ {
+ /**
+ Hash table entry.
+ */
+ struct TPair
+ {
+ const TUint8* iKey; //Global variable - key (a pointer the initial variable value)
+ TUint8* iData; //Global variable - data
+ };
+
+public:
+ enum {KBufferSize = 4096}; //WSD buffer size in bytes
+ enum {KMaxEntries = 37}; //Max No. of entries in the hash table - prime number
+
+ TWsdMap() :
+ iNext(iBuffer),
+ iSize(0)
+ {
+ Mem::FillZ(iTable, sizeof(iTable));
+ }
+ /**
+ Performs a search in the map for a global variable with aKey key.
+ If there is no such variable in the map, the variable will be added and the new variable will be initialized
+ with the data of aLength length, pointed by aKey.
+ @param aKey Global variable key
+ @param aLength Global variable data length in bytes
+ @return Pointer to the global variable (located in the WSD buffer)
+ @panic SqliteMt 9 The global variables map is full
+ @panic SqliteMt 10 There is no space in the WSD buffer for the new variable
+ */
+ TUint8* Find(const TUint8* aKey, TInt aLength)
+ {
+ TInt idx = Hash((TUint)aKey);
+ TInt cnt = 0;
+ while(iTable[idx].iKey != aKey && iTable[idx].iKey != NULL && ++cnt < KMaxEntries)
+ {
+ idx = ++idx % KMaxEntries;
+ }
+ __ASSERT_ALWAYS(cnt < KMaxEntries, User::Panic(KPanicCategory, EPanicMaxKeysExceeded));
+ if(!iTable[idx].iKey)
+ {
+ Add(idx, aKey, aLength);
+ }
+ return iTable[idx].iData;
+ }
+
+private:
+ /**
+ Hash function. Calculates the index of the global variable key in the hash table.
+ @param aKey Global variable key (casted "const TUint8*" to "TUint")
+ @return Hash table index
+ */
+ TUint Hash(TUint aKey) const
+ {
+ return (aKey * (aKey + 3)) % KMaxEntries;
+ }
+ /**
+ Adds a new global variable to the WSD buffer and initializes a new entry in the hash table for the key.
+ @param aIdx The entry index in the hash table
+ @param aKey Global variable key
+ @param aLength Global variable data length in bytes
+ @panic SqliteMt 10 There is no space in the WSD buffer for the new variable
+ */
+ void Add(TInt aIdx, const TUint8* aKey, TInt aLength)
+ {
+ __ASSERT_ALWAYS((iSize + aLength) <= KBufferSize, User::Panic(KPanicCategory, EPanicBufferSizeExceeded));
+ //Add new entry to the hash table and the intial value to the WSD buffer
+ iTable[aIdx].iKey = aKey;
+ iTable[aIdx].iData = iNext;
+ iNext = Mem::Copy(iNext, aKey, aLength);
+ iSize += aLength;
+ //////////////// DEBUG prints /////////////////
+ //for(TInt i=0;i<KMaxEntries;++i)
+ // {
+ // RDebug::Print(_L("%d %X %X %d\r\n"), i, (TUint)iTable[i].iKey, (TUint)iTable[i].iData, Hash((TUint)iTable[i].iKey));
+ // }
+ }
+
+private:
+ TUint8 iBuffer[KBufferSize]; //WSD buffer
+ TUint8* iNext; //Points to the next entry in the buffer
+ TInt iSize; //Amount of buffer currently allocated in bytes
+ TPair iTable[KMaxEntries]; //Hash table matching the address of global varaibles to the address of the values in the WSD buffer
+
+ };
+
+/**
+"Process local storage" structure, used for managing SQLite global variables.
+
+@see TStaticFs
+@see TStaticMutex
+@see TWsdMap
+@see PlsInitialize
+
+@internalComponent
+*/
+NONSHARABLE_STRUCT(TPls)
+ {
+ TStaticFs iStaticFs;
+ TStaticMutex iStaticMutex[KStaticMutexCount];
+ TWsdMap iWsdMap;
+ sqlite3_vfs iVfsApi;
+ };
+
+/**
+This is a callback function used by the Pls() call to get the process local storage initialized.
+The function initializes the TPls data members.
+
+@param aPls A pointer to the process local storage.
+@return KErrNone The process local storage has been successfully initialized.
+
+@panic SqliteMt 1 Failed to connect the RFs
+@panic SqliteMt 2 Failed to create the static mutexes
+@panic SqliteMt 4 Null aPls parameter value
+
+@internalComponent
+*/
+static TInt PlsInitialize(TPls* aPls)
+ {
+ __ASSERT_ALWAYS(aPls != NULL, User::Panic(KPanicCategory, EPanicNullPls1));
+ //Global RFs object
+ TInt err = aPls->iStaticFs.Connect();
+ __ASSERT_ALWAYS(err == KErrNone , User::Panic(KPanicCategory, EPanicFsCreationError));
+ //Static mutexes
+ for(TInt i=0;i<(sizeof(aPls->iStaticMutex)/sizeof(aPls->iStaticMutex[0])) && err==KErrNone;++i)
+ {
+ err = aPls->iStaticMutex[i].Create();
+ }
+ __ASSERT_ALWAYS(err == KErrNone , User::Panic(KPanicCategory, EPanicMutexCreationError));
+ //WSD map
+ //...already initialized by its constructor
+ //sqlite3_vfs object
+ aPls->iVfsApi.iVersion = 1;
+ aPls->iVfsApi.szOsFile = sizeof(TDbFile);
+ aPls->iVfsApi.mxPathname = KMaxFileName;
+ aPls->iVfsApi.pNext = NULL;
+ aPls->iVfsApi.zName = "SymbianSqliteMt";
+ aPls->iVfsApi.pAppData = NULL;
+ aPls->iVfsApi.xOpen = &TVfs::Open;
+ aPls->iVfsApi.xDelete = &TVfs::Delete;
+ aPls->iVfsApi.xAccess = &TVfs::Access;
+ aPls->iVfsApi.xFullPathname = &TVfs::FullPathName;
+ aPls->iVfsApi.xDlOpen = NULL;
+ aPls->iVfsApi.xDlError = NULL;
+ aPls->iVfsApi.xDlSym = NULL;
+ aPls->iVfsApi.xDlClose = NULL;
+ aPls->iVfsApi.xRandomness = &TVfs::Randomness;
+ aPls->iVfsApi.xSleep = &TVfs::Sleep;
+ aPls->iVfsApi.xCurrentTime = &TVfs::CurrentTime;
+ aPls->iVfsApi.xGetLastError = &TVfs::GetLastError;
+
+ return KErrNone;
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////// TStaticFs /////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+TStaticFs::TStaticFs()
+ {
+ }
+
+/**
+Returns a reference to the already created RFs object that is located in the process local storage.
+
+@return RFs reference
+
+@panic SqliteMt 3 Invalid RFs handle
+@panic SqliteMt 5 Process local storage initialization failure
+*/
+RFs& TStaticFs::Fs()
+ {
+ TPls* pls = ::Pls(KSqliteUid, &PlsInitialize);
+ __ASSERT_ALWAYS(pls != 0, User::Panic(KPanicCategory, EPanicNullPls2));
+ __ASSERT_DEBUG(pls->iStaticFs.iFs.Handle() != KNullHandle, User::Panic(KPanicCategory, EPanicInvalidFs));
+ return pls->iStaticFs.iFs;
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////// TStaticMutex //////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+TStaticMutex::TStaticMutex()
+ {
+ }
+
+sqlite3_mutex* StaticMutex(TInt aType)
+ {
+ TPls* pls = ::Pls(KSqliteUid, &PlsInitialize);
+ __ASSERT_ALWAYS(pls != 0, User::Panic(KPanicCategory, EPanicNullPls3));
+ __ASSERT_ALWAYS((TUint)aType < (sizeof(pls->iStaticMutex)/sizeof(pls->iStaticMutex[0])), User::Panic(KPanicCategory, EPanicInvalidMutexType));
+ return &pls->iStaticMutex[aType];
+ }
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////// sqlite3_wsd /////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+The implementation of this function does not do anything special apart from checking that the requested WSD buffer size and
+global variables count (WSD entries) are not bigger than the max TWsdMap buffer size and max TWsdMap entry count.
+
+@param aWsdBufSize SQLite expects the size of the WSD buffer to be "aWsdBufSize" bytes
+@param aWsdEntryCount SQLite can place in the WSD buffer up to "aWsdEntryCount" global variables.
+
+@panic SqliteMt 12 The requested WSD buffer is too big. Bigger than TWsdMap::KBufferSize.
+@panic SqliteMt 13 The requested global variables count is too big. Bigger than TWsdMap::KMaxEntries.
+
+@see TWsdMap
+*/
+int sqlite3_wsd_init(int aWsdBufSize, int aWsdEntryCount)
+ {
+ __ASSERT_ALWAYS(aWsdBufSize <= TWsdMap::KBufferSize, User::Panic(KPanicCategory, EPanicWsdBufSize));
+ __ASSERT_ALWAYS(aWsdEntryCount <= TWsdMap::KMaxEntries, User::Panic(KPanicCategory, EPanicWsdEntryCount));
+ return SQLITE_OK;
+ }
+
+/**
+Performs a search in the WSD map (in the process local storage) for a global variable identified by the aKey parameter.
+
+@param aKey Global variable key
+@param aLength Global variable data length in bytes
+@return Pointer to the global variable data
+
+@panic SqliteMt 11 Process local storage initialization failure
+
+@see TWsdMap
+@see TPls
+*/
+void* sqlite3_wsd_find(void* aKey, int aLength)
+ {
+ __ASSERT_ALWAYS(aKey != NULL, User::Panic(KPanicCategory, EPanicNullKey));
+ return ::Pls(KSqliteUid, &PlsInitialize)->iWsdMap.Find(static_cast <const TUint8*> (aKey), aLength);
+ }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////// sqlite3_vfs ///////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+sqlite3_vfs* VfsApi()
+ {
+ TPls* pls = ::Pls(KSqliteUid, &PlsInitialize);
+ __ASSERT_ALWAYS(pls != 0, User::Panic(KPanicCategory, EPanicNullPls4));
+ return &pls->iVfsApi;
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#endif SQLITE_OS_SYMBIAN