1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/persistentstorage/sqlite3api/OsLayer/os_symbian_emul.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,304 @@
1.4 +// Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// The Symbian OS porting layer - multi-threaded implementation.
1.18 +// Platform dependend implementation of the static mutexes and the file session API.
1.19 +//
1.20 +//
1.21 +
1.22 +/**
1.23 + @file
1.24 +*/
1.25 +#include "os_symbian.h"
1.26 +#include <pls.h>
1.27 +#include <e32std.h>
1.28 +#include "SqliteUtil.h"
1.29 +#include "OstTraceDefinitions.h"
1.30 +#ifdef OST_TRACE_COMPILER_IN_USE
1.31 +#include "os_symbian_emulTraces.h"
1.32 +#endif
1.33 +#include "SqliteTraceDef.h"
1.34 +
1.35 +#ifdef SQLITE_OS_SYMBIAN
1.36 +
1.37 +const TUid KSqliteUid = {0x10285A79};//See UID3 in SQLite3.mmp file - it should be the same
1.38 +
1.39 +/**
1.40 +This class describes an object that serves as a container for SQLite global variables
1.41 +that are stored in an allocated WSD buffer.
1.42 +The global variables are organised in a map, where the pointer to the initial global variable value
1.43 +is used as a key.
1.44 +A hash table is used to speed-up the key search.
1.45 +A single TWsdMap object is created and stored in the process local storage - TPls.
1.46 +
1.47 +@see TPls
1.48 +
1.49 +@internalComponent
1.50 +*/
1.51 +NONSHARABLE_CLASS(TWsdMap)
1.52 + {
1.53 + /**
1.54 + Hash table entry.
1.55 + */
1.56 + struct TPair
1.57 + {
1.58 + const TUint8* iKey; //Global variable - key (a pointer the initial variable value)
1.59 + TUint8* iData; //Global variable - data
1.60 + };
1.61 +
1.62 +public:
1.63 + enum {KBufferSize = 4096}; //WSD buffer size in bytes
1.64 + enum {KMaxEntries = 37}; //Max No. of entries in the hash table - prime number
1.65 +
1.66 + TWsdMap() :
1.67 + iNext(iBuffer),
1.68 + iSize(0)
1.69 + {
1.70 + Mem::FillZ(iTable, sizeof(iTable));
1.71 + }
1.72 + /**
1.73 + Performs a search in the map for a global variable with aKey key.
1.74 + If there is no such variable in the map, the variable will be added and the new variable will be initialized
1.75 + with the data of aLength length, pointed by aKey.
1.76 + @param aKey Global variable key
1.77 + @param aLength Global variable data length in bytes
1.78 + @return Pointer to the global variable (located in the WSD buffer)
1.79 + @panic SqliteMt 9 The global variables map is full
1.80 + @panic SqliteMt 10 There is no space in the WSD buffer for the new variable
1.81 + */
1.82 + TUint8* Find(const TUint8* aKey, TInt aLength)
1.83 + {
1.84 + TInt idx = Hash((TUint)aKey);
1.85 + TInt cnt = 0;
1.86 + while(iTable[idx].iKey != aKey && iTable[idx].iKey != NULL && ++cnt < KMaxEntries)
1.87 + {
1.88 + idx = ++idx % KMaxEntries;
1.89 + }
1.90 + __ASSERT_ALWAYS(cnt < KMaxEntries, __SQLITEPANIC2(ESqliteOsPanicMaxKeysExceeded));
1.91 + if(!iTable[idx].iKey)
1.92 + {
1.93 + Add(idx, aKey, aLength);
1.94 + }
1.95 + return iTable[idx].iData;
1.96 + }
1.97 +
1.98 +private:
1.99 + /**
1.100 + Hash function. Calculates the index of the global variable key in the hash table.
1.101 + @param aKey Global variable key (casted "const TUint8*" to "TUint")
1.102 + @return Hash table index
1.103 + */
1.104 + TUint Hash(TUint aKey) const
1.105 + {
1.106 + return (aKey * (aKey + 3)) % KMaxEntries;
1.107 + }
1.108 + /**
1.109 + Adds a new global variable to the WSD buffer and initializes a new entry in the hash table for the key.
1.110 + @param aIdx The entry index in the hash table
1.111 + @param aKey Global variable key
1.112 + @param aLength Global variable data length in bytes
1.113 + @panic SqliteMt 10 There is no space in the WSD buffer for the new variable
1.114 + */
1.115 + void Add(TInt aIdx, const TUint8* aKey, TInt aLength)
1.116 + {
1.117 + __ASSERT_ALWAYS((iSize + aLength) <= KBufferSize, __SQLITEPANIC2(ESqliteOsPanicBufferSizeExceeded));
1.118 + //Add new entry to the hash table and the intial value to the WSD buffer
1.119 + iTable[aIdx].iKey = aKey;
1.120 + iTable[aIdx].iData = iNext;
1.121 + iNext = Mem::Copy(iNext, aKey, aLength);
1.122 + iSize += aLength;
1.123 + //////////////// DEBUG prints /////////////////
1.124 + //for(TInt i=0;i<KMaxEntries;++i)
1.125 + // {
1.126 + // RDebug::Print(_L("%d %X %X %d\r\n"), i, (TUint)iTable[i].iKey, (TUint)iTable[i].iData, Hash((TUint)iTable[i].iKey));
1.127 + // }
1.128 + }
1.129 +
1.130 +private:
1.131 + TUint8 iBuffer[KBufferSize]; //WSD buffer
1.132 + TUint8* iNext; //Points to the next entry in the buffer
1.133 + TInt iSize; //Amount of buffer currently allocated in bytes
1.134 + TPair iTable[KMaxEntries]; //Hash table matching the address of global varaibles to the address of the values in the WSD buffer
1.135 +
1.136 + };
1.137 +
1.138 +/**
1.139 +"Process local storage" structure, used for managing SQLite global variables.
1.140 +
1.141 +@see TStaticFs
1.142 +@see TStaticMutex
1.143 +@see TWsdMap
1.144 +@see PlsInitialize
1.145 +
1.146 +@internalComponent
1.147 +*/
1.148 +NONSHARABLE_STRUCT(TPls)
1.149 + {
1.150 + TStaticFs iStaticFs;
1.151 + TStaticMutex iStaticMutex[KStaticMutexCount];
1.152 + TWsdMap iWsdMap;
1.153 + sqlite3_vfs iVfsApi;
1.154 + };
1.155 +
1.156 +/**
1.157 +This is a callback function used by the Pls() call to get the process local storage initialized.
1.158 +The function initializes the TPls data members.
1.159 +
1.160 +@param aPls A pointer to the process local storage.
1.161 +@return KErrNone The process local storage has been successfully initialized.
1.162 +
1.163 +@panic SqliteMt 1 Failed to connect the RFs
1.164 +@panic SqliteMt 2 Failed to create the static mutexes
1.165 +@panic SqliteMt 4 Null aPls parameter value
1.166 +
1.167 +@internalComponent
1.168 +*/
1.169 +static TInt PlsInitialize(TPls* aPls)
1.170 + {
1.171 + SQLITE_TRACE_OS(OstTrace0(TRACE_INTERNALS, PLSINITIALIZE_ENTRY, "OS-Entry;0;PlsInitialize"));
1.172 + __ASSERT_ALWAYS(aPls != NULL, __SQLITEPANIC2(ESqliteOsPanicNullPls1));
1.173 + //Global RFs object
1.174 + TInt err = aPls->iStaticFs.Connect();
1.175 + SQLITE_TRACE_OS(OstTrace1(TRACE_INTERNALS, PLSINITIALIZE1, "OS;0;PlsInitialize;iStaticFs.Connect() err=%d", err));
1.176 + __ASSERT_ALWAYS(err == KErrNone, __SQLITEPANIC2(ESqliteOsPanicFsCreationError));
1.177 + //Static mutexes
1.178 + TInt idx = 0;
1.179 + for(;idx<(sizeof(aPls->iStaticMutex)/sizeof(aPls->iStaticMutex[0])) && err==KErrNone;++idx)
1.180 + {
1.181 + err = aPls->iStaticMutex[idx].Create();
1.182 + }
1.183 + SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, PLSINITIALIZE2, "OS;0;PlsInitialize;iStaticMutex[%d].Create() err=%d", idx, err));
1.184 + __ASSERT_ALWAYS(err == KErrNone , __SQLITEPANIC2(ESqliteOsPanicMutexCreationError));
1.185 + //WSD map
1.186 + //...already initialized by its constructor
1.187 + //sqlite3_vfs object
1.188 + aPls->iVfsApi.iVersion = 1;
1.189 + aPls->iVfsApi.szOsFile = sizeof(TDbFile);
1.190 + aPls->iVfsApi.mxPathname = KMaxFileName;
1.191 + aPls->iVfsApi.pNext = NULL;
1.192 + aPls->iVfsApi.zName = "SymbianSqliteMt";
1.193 + aPls->iVfsApi.pAppData = NULL;
1.194 + aPls->iVfsApi.xOpen = &TVfs::Open;
1.195 + aPls->iVfsApi.xDelete = &TVfs::Delete;
1.196 + aPls->iVfsApi.xAccess = &TVfs::Access;
1.197 + aPls->iVfsApi.xFullPathname = &TVfs::FullPathName;
1.198 + aPls->iVfsApi.xDlOpen = NULL;
1.199 + aPls->iVfsApi.xDlError = NULL;
1.200 + aPls->iVfsApi.xDlSym = NULL;
1.201 + aPls->iVfsApi.xDlClose = NULL;
1.202 + aPls->iVfsApi.xRandomness = &TVfs::Randomness;
1.203 + aPls->iVfsApi.xSleep = &TVfs::Sleep;
1.204 + aPls->iVfsApi.xCurrentTime = &TVfs::CurrentTime;
1.205 + aPls->iVfsApi.xGetLastError = &TVfs::GetLastError;
1.206 +
1.207 + SQLITE_TRACE_OS(OstTrace0(TRACE_INTERNALS, PLSINITIALIZE_EXIT, "OS-Exit;0;PlsInitialize"));
1.208 + return KErrNone;
1.209 + }
1.210 +
1.211 +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1.212 +////////////////////////// TStaticFs /////////////////////////////////////////////////////////////////////////////////////////
1.213 +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1.214 +
1.215 +TStaticFs::TStaticFs()
1.216 + {
1.217 + }
1.218 +
1.219 +/**
1.220 +Returns a reference to the already created RFs object that is located in the process local storage.
1.221 +
1.222 +@return RFs reference
1.223 +
1.224 +@panic SqliteMt 3 Invalid RFs handle
1.225 +@panic SqliteMt 5 Process local storage initialization failure
1.226 +*/
1.227 +RFs& TStaticFs::Fs()
1.228 + {
1.229 + TPls* pls = ::Pls(KSqliteUid, &PlsInitialize);
1.230 + __ASSERT_ALWAYS(pls != 0, __SQLITEPANIC2(ESqliteOsPanicNullPls2));
1.231 + __ASSERT_DEBUG(pls->iStaticFs.iFs.Handle() != KNullHandle, __SQLITEPANIC2(ESqliteOsPanicInvalidFs));
1.232 + return pls->iStaticFs.iFs;
1.233 + }
1.234 +
1.235 +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1.236 +////////////////////////// TStaticMutex //////////////////////////////////////////////////////////////////////////////////////
1.237 +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1.238 +
1.239 +TStaticMutex::TStaticMutex()
1.240 + {
1.241 + }
1.242 +
1.243 +sqlite3_mutex* StaticMutex(TInt aType)
1.244 + {
1.245 + TPls* pls = ::Pls(KSqliteUid, &PlsInitialize);
1.246 + __ASSERT_ALWAYS(pls != 0, __SQLITEPANIC2(ESqliteOsPanicNullPls3));
1.247 + __ASSERT_ALWAYS((TUint)aType < (sizeof(pls->iStaticMutex)/sizeof(pls->iStaticMutex[0])), __SQLITEPANIC2(ESqliteOsPanicInvalidMutexType));
1.248 + return &pls->iStaticMutex[aType];
1.249 + }
1.250 +
1.251 +
1.252 +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1.253 +//////////////////////// sqlite3_wsd /////////////////////////////////////////////////////////////////////////////////////
1.254 +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1.255 +
1.256 +/**
1.257 +The implementation of this function does not do anything special apart from checking that the requested WSD buffer size and
1.258 +global variables count (WSD entries) are not bigger than the max TWsdMap buffer size and max TWsdMap entry count.
1.259 +
1.260 +@param aWsdBufSize SQLite expects the size of the WSD buffer to be "aWsdBufSize" bytes
1.261 +@param aWsdEntryCount SQLite can place in the WSD buffer up to "aWsdEntryCount" global variables.
1.262 +
1.263 +@panic SqliteMt 12 The requested WSD buffer is too big. Bigger than TWsdMap::KBufferSize.
1.264 +@panic SqliteMt 13 The requested global variables count is too big. Bigger than TWsdMap::KMaxEntries.
1.265 +
1.266 +@see TWsdMap
1.267 +*/
1.268 +int sqlite3_wsd_init(int aWsdBufSize, int aWsdEntryCount)
1.269 + {
1.270 + __ASSERT_ALWAYS(aWsdBufSize <= TWsdMap::KBufferSize, __SQLITEPANIC2(ESqliteOsPanicWsdBufSize));
1.271 + __ASSERT_ALWAYS(aWsdEntryCount <= TWsdMap::KMaxEntries, __SQLITEPANIC2(ESqliteOsPanicWsdEntryCount));
1.272 + return SQLITE_OK;
1.273 + }
1.274 +
1.275 +/**
1.276 +Performs a search in the WSD map (in the process local storage) for a global variable identified by the aKey parameter.
1.277 +
1.278 +@param aKey Global variable key
1.279 +@param aLength Global variable data length in bytes
1.280 +@return Pointer to the global variable data
1.281 +
1.282 +@panic SqliteMt 11 Process local storage initialization failure
1.283 +
1.284 +@see TWsdMap
1.285 +@see TPls
1.286 +*/
1.287 +void* sqlite3_wsd_find(void* aKey, int aLength)
1.288 + {
1.289 + __ASSERT_ALWAYS(aKey != NULL, __SQLITEPANIC2(ESqliteOsPanicNullKey));
1.290 + return ::Pls(KSqliteUid, &PlsInitialize)->iWsdMap.Find(static_cast <const TUint8*> (aKey), aLength);
1.291 + }
1.292 +
1.293 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1.294 +////////////////////////// sqlite3_vfs ///////////////////////////////////////////////////////////////////////////////////
1.295 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1.296 +
1.297 +sqlite3_vfs* VfsApi()
1.298 + {
1.299 + TPls* pls = ::Pls(KSqliteUid, &PlsInitialize);
1.300 + __ASSERT_ALWAYS(pls != 0, __SQLITEPANIC2(ESqliteOsPanicNullPls4));
1.301 + return &pls->iVfsApi;
1.302 + }
1.303 +
1.304 +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1.305 +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1.306 +
1.307 +#endif SQLITE_OS_SYMBIAN