persistentstorage/sqlite3api/OsLayer/os_symbian_emul.cpp
changeset 0 08ec8eefde2f
child 23 26645d81f48d
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // The Symbian OS porting layer - multi-threaded implementation. 
       
    15 // Platform dependend implementation of the static mutexes and the file session API.
       
    16 // 
       
    17 //
       
    18 
       
    19 /**
       
    20  @file
       
    21 */
       
    22 #include "os_symbian.h"
       
    23 #include <pls.h>
       
    24 #include <e32std.h>
       
    25 
       
    26 #ifdef SQLITE_OS_SYMBIAN
       
    27 
       
    28 const TUid KSqliteUid = {0x10285A79};//See UID3 in SQLite3.mmp file - it should be the same
       
    29 
       
    30 /**
       
    31 This class describes an object that serves as a container for SQLite global variables
       
    32 that are stored in an allocated WSD buffer.
       
    33 The global variables are organised in a map, where the pointer to the initial global variable value
       
    34 is used as a key.
       
    35 A hash table is used to speed-up the key search.
       
    36 A single TWsdMap object is created and stored in the process local storage - TPls.
       
    37 
       
    38 @see TPls
       
    39 
       
    40 @internalComponent
       
    41 */
       
    42 NONSHARABLE_CLASS(TWsdMap)
       
    43 	{
       
    44 	/**
       
    45 	Hash table entry.
       
    46 	*/
       
    47 	struct TPair
       
    48 		{
       
    49 		const TUint8* 	iKey;	//Global variable - key (a pointer the initial variable value)
       
    50 		TUint8* 		iData;	//Global variable - data
       
    51 		};
       
    52 		
       
    53 public:
       
    54 	enum {KBufferSize = 4096};		//WSD buffer size in bytes
       
    55 	enum {KMaxEntries = 37}; 		//Max No. of entries in the hash table - prime number
       
    56 	
       
    57 	TWsdMap() :
       
    58 		iNext(iBuffer),
       
    59 		iSize(0)
       
    60 		{
       
    61 		Mem::FillZ(iTable, sizeof(iTable));
       
    62 		}	
       
    63 	/**
       
    64 	Performs a search in the map for a global variable with aKey key.
       
    65 	If there is no such variable in the map, the variable will be added and the new variable will be initialized
       
    66 	with the data of aLength length, pointed by aKey.
       
    67 	@param aKey    Global variable key
       
    68 	@param aLength Global variable data length in bytes
       
    69 	@return Pointer to the global variable (located in the WSD buffer)
       
    70 	@panic SqliteMt  9 The global variables map is full
       
    71 	@panic SqliteMt 10 There is no space in the WSD buffer for the new variable
       
    72 	*/		
       
    73 	TUint8* Find(const TUint8* aKey, TInt aLength)
       
    74 		{
       
    75 		TInt idx = Hash((TUint)aKey);
       
    76 		TInt cnt = 0;
       
    77 		while(iTable[idx].iKey != aKey && iTable[idx].iKey != NULL && ++cnt < KMaxEntries)
       
    78 			{
       
    79 			idx = ++idx % KMaxEntries;
       
    80 			}
       
    81 		__ASSERT_ALWAYS(cnt < KMaxEntries, User::Panic(KPanicCategory, EPanicMaxKeysExceeded));
       
    82 		if(!iTable[idx].iKey)
       
    83 			{
       
    84 			Add(idx, aKey, aLength);
       
    85 			}
       
    86 		return iTable[idx].iData;
       
    87 		}
       
    88 		
       
    89 private:	
       
    90 	/**
       
    91 	Hash function. Calculates the index of the global variable key in the hash table.
       
    92 	@param aKey Global variable key (casted "const TUint8*" to "TUint")
       
    93 	@return Hash table index
       
    94 	*/	
       
    95 	TUint Hash(TUint aKey) const
       
    96 		{
       
    97 		return (aKey * (aKey + 3)) % KMaxEntries;
       
    98 		}
       
    99 	/**
       
   100 	Adds a new global variable to the WSD buffer and initializes a new entry in the hash table for the key.
       
   101 	@param aIdx    The entry index in the hash table
       
   102 	@param aKey    Global variable key
       
   103 	@param aLength Global variable data length in bytes
       
   104 	@panic SqliteMt 10 There is no space in the WSD buffer for the new variable
       
   105 	*/
       
   106 	void Add(TInt aIdx, const TUint8* aKey, TInt aLength)
       
   107 		{
       
   108 		__ASSERT_ALWAYS((iSize + aLength) <= KBufferSize, User::Panic(KPanicCategory, EPanicBufferSizeExceeded));
       
   109 		//Add new entry to the hash table and the intial value to the WSD buffer
       
   110 		iTable[aIdx].iKey = aKey;
       
   111 		iTable[aIdx].iData = iNext;
       
   112 		iNext = Mem::Copy(iNext, aKey, aLength);
       
   113 		iSize += aLength;
       
   114 		//////////////// DEBUG prints   /////////////////
       
   115 		//for(TInt i=0;i<KMaxEntries;++i)	
       
   116 		//	{
       
   117 		//	RDebug::Print(_L("%d %X %X %d\r\n"), i, (TUint)iTable[i].iKey, (TUint)iTable[i].iData, Hash((TUint)iTable[i].iKey));	
       
   118 		//	}
       
   119 		}
       
   120 		
       
   121 private:
       
   122 	TUint8	iBuffer[KBufferSize]; 	//WSD buffer
       
   123 	TUint8*	iNext; 					//Points to the next entry in the buffer	
       
   124 	TInt	iSize;  				//Amount of buffer currently allocated in bytes
       
   125 	TPair	iTable[KMaxEntries];	//Hash table matching the address of global varaibles to the address of the values in the WSD buffer	 
       
   126 		
       
   127 	};
       
   128 
       
   129 /**
       
   130 "Process local storage" structure, used for managing SQLite global variables.
       
   131 
       
   132 @see TStaticFs 
       
   133 @see TStaticMutex
       
   134 @see TWsdMap
       
   135 @see PlsInitialize
       
   136 
       
   137 @internalComponent
       
   138 */
       
   139 NONSHARABLE_STRUCT(TPls)
       
   140 	{
       
   141 	TStaticFs		iStaticFs;
       
   142 	TStaticMutex 	iStaticMutex[KStaticMutexCount];
       
   143 	TWsdMap			iWsdMap;
       
   144 	sqlite3_vfs		iVfsApi;
       
   145 	};
       
   146 
       
   147 /**
       
   148 This is a callback function used by the Pls() call to get the process local storage initialized.
       
   149 The function initializes the TPls data members.
       
   150 
       
   151 @param aPls A pointer to the process local storage.
       
   152 @return KErrNone The process local storage has been successfully initialized.
       
   153 
       
   154 @panic SqliteMt 1 Failed to connect the RFs
       
   155 @panic SqliteMt 2 Failed to create the static mutexes
       
   156 @panic SqliteMt 4 Null aPls parameter value
       
   157 
       
   158 @internalComponent
       
   159 */
       
   160 static TInt PlsInitialize(TPls* aPls)
       
   161 	{
       
   162 	__ASSERT_ALWAYS(aPls != NULL, User::Panic(KPanicCategory, EPanicNullPls1));
       
   163 	//Global RFs object
       
   164 	TInt err = aPls->iStaticFs.Connect();
       
   165 	__ASSERT_ALWAYS(err == KErrNone , User::Panic(KPanicCategory, EPanicFsCreationError));
       
   166 	//Static mutexes
       
   167 	for(TInt i=0;i<(sizeof(aPls->iStaticMutex)/sizeof(aPls->iStaticMutex[0])) && err==KErrNone;++i)
       
   168 		{
       
   169 		err = aPls->iStaticMutex[i].Create();
       
   170 		}
       
   171 	__ASSERT_ALWAYS(err == KErrNone , User::Panic(KPanicCategory, EPanicMutexCreationError));
       
   172 	//WSD map
       
   173 	//...already initialized by its constructor
       
   174 	//sqlite3_vfs object	
       
   175 	aPls->iVfsApi.iVersion 		= 1;
       
   176 	aPls->iVfsApi.szOsFile 		= sizeof(TDbFile);
       
   177 	aPls->iVfsApi.mxPathname 	= KMaxFileName;
       
   178 	aPls->iVfsApi.pNext 		= NULL;
       
   179 	aPls->iVfsApi.zName 		= "SymbianSqliteMt";
       
   180 	aPls->iVfsApi.pAppData 		= NULL;
       
   181 	aPls->iVfsApi.xOpen 		= &TVfs::Open;
       
   182 	aPls->iVfsApi.xDelete 		= &TVfs::Delete;
       
   183 	aPls->iVfsApi.xAccess 		= &TVfs::Access;
       
   184 	aPls->iVfsApi.xFullPathname	= &TVfs::FullPathName;
       
   185 	aPls->iVfsApi.xDlOpen 		= NULL;
       
   186 	aPls->iVfsApi.xDlError 		= NULL;
       
   187 	aPls->iVfsApi.xDlSym 		= NULL;
       
   188 	aPls->iVfsApi.xDlClose 		= NULL;
       
   189 	aPls->iVfsApi.xRandomness 	= &TVfs::Randomness;
       
   190 	aPls->iVfsApi.xSleep 		= &TVfs::Sleep;
       
   191 	aPls->iVfsApi.xCurrentTime 	= &TVfs::CurrentTime;
       
   192 	aPls->iVfsApi.xGetLastError	= &TVfs::GetLastError;
       
   193 	
       
   194 	return KErrNone;
       
   195 	}
       
   196 
       
   197 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   198 //////////////////////////  TStaticFs  /////////////////////////////////////////////////////////////////////////////////////////
       
   199 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   200 
       
   201 TStaticFs::TStaticFs()
       
   202 	{
       
   203 	}
       
   204 
       
   205 /**
       
   206 Returns a reference to the already created RFs object that is located in the process local storage.
       
   207 
       
   208 @return RFs reference
       
   209 
       
   210 @panic SqliteMt 3 Invalid RFs handle
       
   211 @panic SqliteMt 5 Process local storage initialization failure
       
   212 */
       
   213 RFs& TStaticFs::Fs()
       
   214 	{
       
   215 	TPls* pls = ::Pls(KSqliteUid, &PlsInitialize);
       
   216 	__ASSERT_ALWAYS(pls != 0, User::Panic(KPanicCategory, EPanicNullPls2));
       
   217 	__ASSERT_DEBUG(pls->iStaticFs.iFs.Handle() != KNullHandle, User::Panic(KPanicCategory, EPanicInvalidFs));
       
   218 	return pls->iStaticFs.iFs;
       
   219 	}
       
   220 
       
   221 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   222 //////////////////////////  TStaticMutex  //////////////////////////////////////////////////////////////////////////////////////
       
   223 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   224 
       
   225 TStaticMutex::TStaticMutex()
       
   226 	{
       
   227 	}
       
   228 
       
   229 sqlite3_mutex* StaticMutex(TInt aType)
       
   230 	{
       
   231 	TPls* pls = ::Pls(KSqliteUid, &PlsInitialize);
       
   232 	__ASSERT_ALWAYS(pls != 0, User::Panic(KPanicCategory, EPanicNullPls3));
       
   233 	__ASSERT_ALWAYS((TUint)aType < (sizeof(pls->iStaticMutex)/sizeof(pls->iStaticMutex[0])), User::Panic(KPanicCategory, EPanicInvalidMutexType));
       
   234 	return &pls->iStaticMutex[aType];
       
   235 	}
       
   236 
       
   237 
       
   238 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   239 ////////////////////////    sqlite3_wsd    /////////////////////////////////////////////////////////////////////////////////////
       
   240 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   241 
       
   242 /**
       
   243 The implementation of this function does not do anything special apart from checking that the requested WSD buffer size and
       
   244 global variables count (WSD entries) are not bigger than the max TWsdMap buffer size and max TWsdMap entry count.
       
   245 
       
   246 @param aWsdBufSize    SQLite expects the size of the WSD buffer to be "aWsdBufSize" bytes
       
   247 @param aWsdEntryCount SQLite can place in the WSD buffer up to "aWsdEntryCount" global variables.
       
   248 
       
   249 @panic SqliteMt 12 The requested WSD buffer is too big. Bigger than TWsdMap::KBufferSize.
       
   250 @panic SqliteMt 13 The requested global variables count is too big. Bigger than TWsdMap::KMaxEntries.
       
   251 
       
   252 @see TWsdMap
       
   253 */
       
   254 int sqlite3_wsd_init(int aWsdBufSize, int aWsdEntryCount)
       
   255 	{
       
   256 	__ASSERT_ALWAYS(aWsdBufSize <= TWsdMap::KBufferSize, User::Panic(KPanicCategory, EPanicWsdBufSize));
       
   257 	__ASSERT_ALWAYS(aWsdEntryCount <= TWsdMap::KMaxEntries, User::Panic(KPanicCategory, EPanicWsdEntryCount));
       
   258 	return SQLITE_OK;	
       
   259 	}
       
   260 
       
   261 /**
       
   262 Performs a search in the WSD map (in the process local storage) for a global variable identified by the aKey parameter.
       
   263 
       
   264 @param aKey    Global variable key
       
   265 @param aLength Global variable data length in bytes
       
   266 @return        Pointer to the global variable data
       
   267 
       
   268 @panic SqliteMt 11 Process local storage initialization failure
       
   269 
       
   270 @see TWsdMap
       
   271 @see TPls
       
   272 */
       
   273 void* sqlite3_wsd_find(void* aKey, int aLength)
       
   274 	{
       
   275 	__ASSERT_ALWAYS(aKey != NULL, User::Panic(KPanicCategory, EPanicNullKey));
       
   276 	return ::Pls(KSqliteUid, &PlsInitialize)->iWsdMap.Find(static_cast <const TUint8*> (aKey), aLength);
       
   277 	}
       
   278 
       
   279 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   280 //////////////////////////  sqlite3_vfs     ///////////////////////////////////////////////////////////////////////////////////
       
   281 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   282 
       
   283 sqlite3_vfs* VfsApi()
       
   284 	{
       
   285 	TPls* pls = ::Pls(KSqliteUid, &PlsInitialize);
       
   286 	__ASSERT_ALWAYS(pls != 0, User::Panic(KPanicCategory, EPanicNullPls4));
       
   287 	return &pls->iVfsApi;
       
   288 	}
       
   289 
       
   290 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   291 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   292 
       
   293 #endif SQLITE_OS_SYMBIAN