--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/sql/SRC/Server/SqlSrvConfig.cpp Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,470 @@
+// Copyright (c) 2007-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:
+//
+#include <f32file.h>
+#include <f32file64.h>
+#include "SqlSrvConfig.h"
+#include "SqlSrvUtil.h"
+
+/**
+Initializes TSqlSrvConfigParams data members with their default values.
+*/
+TSqlSrvConfigParams::TSqlSrvConfigParams() :
+ iCacheSize(TSqlSrvConfigParams::KConfigPrmValueNotSet),
+ iPageSize(TSqlSrvConfigParams::KConfigPrmValueNotSet),
+ iDbEncoding(TSqlSrvConfigParams::EEncNotSet),
+ iSoftHeapLimitKb(TSqlSrvConfigParams::KConfigPrmValueNotSet),
+ iCompactionMode(ESqlCompactionNotSet),
+ iFreePageThresholdKb(TSqlSrvConfigParams::KConfigPrmValueNotSet)
+ {
+ }
+
+/**
+"Object initialization" method.
+Opens and reads the SQL server configuration file (if it exists).
+Initializes TSqlSrvConfig data members using the data from the config file.
+If the configuration file does not exist, TSqlSrvConfig data members stay unchanged,
+except:
+ - the soft heap limit, which default value is TSqlSrvConfigParams::KDefaultSoftHeapLimit;
+ - the free pages threshold, which default value is KSqlCompactFreePageThreshold;
+
+@param aFs File session
+@param aFileName Config file name
+@leave KErrEof No valid config string found in the configuration file;
+ Note that the function may also leave with some other system-wide error codes.
+*/
+void TSqlSrvConfig::InitL(RFs& aFs, const TDesC& aFileName)
+ {
+ if(::FileExists(aFs, aFileName))
+ {
+ TBuf8<KSqlSrvMaxConfigStrLen> configFileStr;
+ //Step 1: get the config string from the config file and store the string in configFileStr
+ TSqlSrvConfig::GetConfigStringFromFileL(aFs, aFileName, configFileStr);
+ //Step 2: extract config file parameters from the string (configFileStr) and store them in iConfigFileParams
+ TSqlSrvConfig::ExtractConfigParamsFromStringL(configFileStr, iConfigFileParams);
+ }
+ //If the soft heap limit is not set from the file or the file does not exist - then set the soft heap limit with the default value
+ if(iConfigFileParams.iSoftHeapLimitKb == TSqlSrvConfigParams::KConfigPrmValueNotSet)
+ {
+ iConfigFileParams.iSoftHeapLimitKb = TSqlSrvConfigParams::KDefaultSoftHeapLimitKb;
+ }
+ //If the free page threshold is not set from the file or the file does not exist - then set the free page threshold with the default value
+ if(iConfigFileParams.iFreePageThresholdKb == TSqlSrvConfigParams::KConfigPrmValueNotSet)
+ {
+ iConfigFileParams.iFreePageThresholdKb = KSqlCompactFreePageThresholdKb;
+ }
+ }
+
+/**
+Parses the config string parameter (aConfigStr), extracts configuration parameters values and
+and initialises with them aConfigParams data members.
+The config string format is: "PARAM1=VALUE1;PARAM2=VALUE2;..."
+If there is unknown parameter "name=value" pair in the config string, it will be skipped - not reported as an error.
+In a case of a leave, the old content of aConfigStr is preserved.
+The rules for TSqlSrvConfigParams data members initialization are described in TSqlSrvConfig class' comments.
+
+@see TSqlSrvConfig
+@param aConfigStr the config descriptor
+@param aConfigParams Output argument, config parameters will be stored there.
+@leave KErrArgument if the config is not good or the config string contains "soft heap limit" parameter/value pair.
+@leave KErrArgument if the config is not good or the config string contains "free page threshold" parameter/value pair.
+*/
+void TSqlSrvConfig::GetConfigParamsL(const TDesC8& aConfigStr, TSqlSrvConfigParams& aConfigParams) const
+ {
+ TSqlSrvConfigParams tmpConfigParams;
+ //Step 1: extract configuration parameters from aConfigStr, store them in tmpConfigParams.
+ TSqlSrvConfig::ExtractConfigParamsFromStringL(aConfigStr, tmpConfigParams);
+ if(tmpConfigParams.iSoftHeapLimitKb != TSqlSrvConfigParams::KConfigPrmValueNotSet ||
+ tmpConfigParams.iFreePageThresholdKb != TSqlSrvConfigParams::KConfigPrmValueNotSet)
+ {//It is not allowed the soft heap limit to be set from a config string, only from the SQL server config file.
+ //It is not allowed the free page threshold to be set from a config string, only from the SQL server config file.
+ __SQLLEAVE(KErrArgument);
+ }
+ //Step 2: store tmpConfigParams in aConfigParams.
+ aConfigParams = tmpConfigParams;
+ //Step 3: replace each "not set" parameter in aConfigParams with the related parameter value from iConfigFileParams (the config file).
+ if(aConfigParams.iPageSize == TSqlSrvConfigParams::KConfigPrmValueNotSet)
+ {
+ aConfigParams.iPageSize = iConfigFileParams.iPageSize;
+ }
+ if(aConfigParams.iDbEncoding == TSqlSrvConfigParams::EEncNotSet)
+ {
+ aConfigParams.iDbEncoding = iConfigFileParams.iDbEncoding;
+ }
+ if(aConfigParams.iCompactionMode == ESqlCompactionNotSet)
+ {
+ aConfigParams.iCompactionMode = iConfigFileParams.iCompactionMode;
+ }
+ //Step 4: set the soft heap limit.
+ aConfigParams.iSoftHeapLimitKb = iConfigFileParams.iSoftHeapLimitKb;
+ //Step 5: set the free page threshold.
+ aConfigParams.iFreePageThresholdKb = iConfigFileParams.iFreePageThresholdKb;
+ //Step 6: assert the parameter values.
+ __SQLASSERT(aConfigParams.iPageSize == TSqlSrvConfigParams::KConfigPrmValueNotSet || aConfigParams.iPageSize >= 0, ESqlPanicInternalError);
+ __SQLASSERT(aConfigParams.iCacheSize == TSqlSrvConfigParams::KConfigPrmValueNotSet || aConfigParams.iCacheSize >= 0, ESqlPanicInternalError);
+ __SQLASSERT(aConfigParams.iDbEncoding == TSqlSrvConfigParams::EEncNotSet ||
+ aConfigParams.iDbEncoding == TSqlSrvConfigParams::EEncUtf8 ||
+ aConfigParams.iDbEncoding == TSqlSrvConfigParams::EEncUtf16, ESqlPanicInternalError);
+ __SQLASSERT(aConfigParams.iSoftHeapLimitKb == TSqlSrvConfigParams::KConfigPrmValueNotSet ||
+ (aConfigParams.iSoftHeapLimitKb >= TSqlSrvConfigParams::KMinSoftHeapLimitKb &&
+ aConfigParams.iSoftHeapLimitKb <= TSqlSrvConfigParams::KMaxSoftHeapLimitKb), ESqlPanicInternalError);
+ __SQLASSERT(aConfigParams.iCompactionMode == ESqlCompactionNotSet || aConfigParams.iCompactionMode == ESqlCompactionManual ||
+ aConfigParams.iCompactionMode == ESqlCompactionBackground || aConfigParams.iCompactionMode == ESqlCompactionAuto, ESqlPanicInternalError);
+ __SQLASSERT(aConfigParams.iFreePageThresholdKb == TSqlSrvConfigParams::KConfigPrmValueNotSet ||
+ aConfigParams.iFreePageThresholdKb >= 0, ESqlPanicInternalError);
+ }
+
+//The function opeans the aFileName config file and reads the config string, storring it in aConfigStr argument.
+//Preconditions:
+// - The config file does exist;
+// - It is a file, containing 16-bit strings;
+// - aConfigStr max size is at least KSqlSrvMaxConfigStrLen bytes;
+//The function may leave if some of the file I/O operations (open file, read file) fails.
+void TSqlSrvConfig::GetConfigStringFromFileL(RFs& aFs, const TDesC& aFileName, TDes8& aConfigStr)
+ {
+ __SQLASSERT(aConfigStr.MaxLength() >= KSqlSrvMaxConfigStrLen, ESqlPanicBadArgument);
+ RFile64 cfgFile;
+ CleanupClosePushL(cfgFile);
+ __SQLLEAVE_IF_ERROR(cfgFile.Open(aFs, aFileName, EFileRead));
+ TFileText cfgFileReader;
+ cfgFileReader.Set(cfgFile);
+ TBuf<KSqlSrvMaxConfigStrLen> buf;
+ TBool cfgLineFound = EFalse;
+ TInt err = KErrNone;
+ //Read the configuration file line by line until get the first "non-comment" line.
+ while((err = cfgFileReader.Read(buf)) == KErrNone)
+ {
+ buf.TrimAll();
+ if(buf.Length() == 0 || buf.Locate('#') == 0) //'#' means - this line is a comment
+ {
+ continue;
+ }
+ cfgLineFound = ETrue;
+ break;
+ }
+ CleanupStack::PopAndDestroy(&cfgFile);
+ if(err != KErrEof)
+ {//The "read configuration file" operation has failed with "err" (if err != KErrNone)
+ __SQLLEAVE_IF_ERROR(err);
+ }
+ if(!cfgLineFound)
+ {//End of config file reached - no valid configuration line found.
+ __SQLLEAVE(KErrEof);
+ }
+ __SQLASSERT(err == KErrNone || err == KErrEof, ESqlPanicInternalError);
+ aConfigStr.Copy(buf);
+ }
+
+//Parses the config string parameter (aConfigStr) and stores the extracted configuration parameter values in the aConfigParams argument.
+//The config string format is: "PARAM1=VALUE1;PARAM2=VALUE2;..."
+//If there is unknown parameter name in the config string, it will be skipped - not reported as an error.
+//The function will leave with KErrArgument in a case of a bad config string (bad parameter values).
+void TSqlSrvConfig::ExtractConfigParamsFromStringL(const TDesC8& aConfigStr, TSqlSrvConfigParams& aConfigParams)
+ {
+ //Search iteratively the config string for "PARAM=VALUE;" pairs. If such pair is found, extract the parameter name and
+ //parameter value. Adjust the string start ptr to point to the rest of the string.
+ for(TPtrC8 ptr(aConfigStr);ptr.Length()>0;)
+ {
+ TPtrC8 prmName(KNullDesC8);
+ TPtrC8 prmValue(KNullDesC8);
+ if(TSqlSrvConfig::ExtractParamValuePairL(ptr, prmName, prmValue))
+ {
+ TSqlSrvConfig::ExtractParamValueL(prmName, prmValue, aConfigParams);
+ }
+ }
+ //Assert the extracted parameter values.
+ __SQLASSERT(aConfigParams.iPageSize == TSqlSrvConfigParams::KConfigPrmValueNotSet || aConfigParams.iPageSize >= 0, ESqlPanicInternalError);
+ __SQLASSERT(aConfigParams.iCacheSize == TSqlSrvConfigParams::KConfigPrmValueNotSet || aConfigParams.iCacheSize >= 0, ESqlPanicInternalError);
+ __SQLASSERT(aConfigParams.iDbEncoding == TSqlSrvConfigParams::EEncNotSet ||
+ aConfigParams.iDbEncoding == TSqlSrvConfigParams::EEncUtf8 ||
+ aConfigParams.iDbEncoding == TSqlSrvConfigParams::EEncUtf16, ESqlPanicInternalError);
+ __SQLASSERT(aConfigParams.iSoftHeapLimitKb == TSqlSrvConfigParams::KConfigPrmValueNotSet ||
+ (aConfigParams.iSoftHeapLimitKb >= TSqlSrvConfigParams::KMinSoftHeapLimitKb &&
+ aConfigParams.iSoftHeapLimitKb <= TSqlSrvConfigParams::KMaxSoftHeapLimitKb), ESqlPanicInternalError);
+ __SQLASSERT(aConfigParams.iCompactionMode == ESqlCompactionNotSet || aConfigParams.iCompactionMode == ESqlCompactionManual ||
+ aConfigParams.iCompactionMode == ESqlCompactionBackground || aConfigParams.iCompactionMode == ESqlCompactionAuto, ESqlPanicInternalError);
+ __SQLASSERT(aConfigParams.iFreePageThresholdKb == TSqlSrvConfigParams::KConfigPrmValueNotSet ||
+ aConfigParams.iFreePageThresholdKb >= 0, ESqlPanicInternalError);
+ }
+
+//The function searches aConfigStr arguments for "PARAM=VALUE;" pair. If such pair is found, then
+//aParamName is set to point to the parameter name, aParamValue is set to point to the parameter value,
+//aConfigStr is set to point to the rest of the config string (skipping the just found "param=value;" pair).
+//The function leaves with KErrArgument in case of a bad config string.
+//The function returns false if a ";" string is found instead of a "param=value;" pair.
+//When the function returns true, it means that aParamName and aParamValue arguments are set to point to the
+//parameter name and parameter value.
+TBool TSqlSrvConfig::ExtractParamValuePairL(TPtrC8& aConfigStr, TPtrC8& aParamName, TPtrC8& aParamValue)
+ {
+ const TChar KSemiColon(';');
+ const TChar KAssignment('=');
+ TInt pos = aConfigStr.Locate(KSemiColon);
+ TPtrC8 prmText(KNullDesC8);
+ if(pos < 0)
+ {
+ pos = aConfigStr.Length() - 1;
+ prmText.Set(TSqlSrvConfig::TrimAndConstructPtr(aConfigStr.Ptr(), aConfigStr.Length()));
+ }
+ else
+ {
+ prmText.Set(TSqlSrvConfig::TrimAndConstructPtr(aConfigStr.Ptr(), pos));
+ }
+ //Set aConfigStr to the "point" right after the last found ';'
+ if(pos == aConfigStr.Length() - 1)
+ {
+ aConfigStr.Set(NULL, 0);
+ }
+ else
+ {
+ aConfigStr.Set(aConfigStr.Ptr() + pos + 1, aConfigStr.Length() - (pos + 1));
+ }
+ if(prmText.Length() == 0)
+ {//Empty ";"
+ return EFalse;
+ }
+ //Find the parameter name and parameter value
+ pos = prmText.Locate(KAssignment);
+ if(pos < 0 || pos >= (prmText.Length() - 1))
+ {
+ __SQLLEAVE(KErrArgument);
+ }
+ //we've got now prmText pointing to a " PARAM = VALUE " string.
+ aParamName.Set(TSqlSrvConfig::TrimAndConstructPtr(prmText.Ptr(), pos));
+ aParamValue.Set(TSqlSrvConfig::TrimAndConstructPtr(prmText.Ptr() + pos + 1, prmText.Length() - (pos + 1)));
+ return ETrue;
+ }
+
+//The function compares aParamName argument against a set of predefined parameter names and if one of them is matched,
+//then the function converts aParamValue argument to a numerical value and assigns it to the corresponding aConfigParams data member.
+//The function may leave with KErrArgument, if the parameter value is invalid.
+void TSqlSrvConfig::ExtractParamValueL(const TDesC8& aParamName, const TDesC8& aParamValue, TSqlSrvConfigParams& aConfigParams)
+ {
+ if(aParamName.CompareF(KCacheSize) == 0)
+ {
+ aConfigParams.iCacheSize = TSqlSrvConfig::GetCacheSizeL(aParamValue);
+ }
+ else if(aParamName.CompareF(KPageSize) == 0)
+ {
+ aConfigParams.iPageSize = TSqlSrvConfig::GetPageSizeL(aParamValue);
+ }
+ else if(aParamName.CompareF(KEncoding) == 0)
+ {
+ aConfigParams.iDbEncoding = TSqlSrvConfig::GetEncoding(aParamValue);
+ }
+ else if(aParamName.CompareF(KSoftHeapLimitKb) == 0)
+ {
+ aConfigParams.iSoftHeapLimitKb = TSqlSrvConfig::GetSoftHeapLimitL(aParamValue);
+ }
+ else if(aParamName.CompareF(KCompactionMode) == 0)
+ {
+ aConfigParams.iCompactionMode = TSqlSrvConfig::GetCompactionModeL(aParamValue);
+ }
+ else if(aParamName.CompareF(KFreePageThresholdKb) == 0)
+ {
+ aConfigParams.iFreePageThresholdKb = TSqlSrvConfig::GetFreePageThresholdL(aParamValue);
+ }
+ //else
+ // {
+ // Unrecognized parameter/value pair - no problem, skip it.
+ // }
+ }
+
+//The function converts aParamValue to a numerical value (the cache size in pages) and returns it.
+//If the converted numerical value is less than 0, the function leaves with KErrArgument.
+TInt TSqlSrvConfig::GetCacheSizeL(const TDesC8& aParamValue)
+ {
+ TLex8 lex(aParamValue);
+ TInt cacheSize = TSqlSrvConfigParams::KConfigPrmValueNotSet;
+ TInt err = lex.Val(cacheSize);
+ if(err != KErrNone || cacheSize < 0) //The correct check is for "<=0", but it has to be backward
+ { //compatible with the previous implementation
+ __SQLLEAVE(KErrArgument);
+ }
+ return cacheSize;
+ }
+
+//The function converts aParamValue to a numerical value (the page size in bytes) and returns it.
+//If the converted numerical value is less than 0, the function leaves with KErrArgument.
+TInt TSqlSrvConfig::GetPageSizeL(const TDesC8& aParamValue)
+ {
+ TLex8 lex(aParamValue);
+ TInt pageSize = TSqlSrvConfigParams::KConfigPrmValueNotSet;
+ TInt err = lex.Val(pageSize);
+ if(err != KErrNone || pageSize < 0) //The correct check is for "<0", "power of 2", "between 512 and 32768",
+ { //but it has to be backward compatible with the previous implementation
+ __SQLLEAVE(KErrArgument);
+ }
+ return pageSize;
+ }
+
+//The function converts aParamValue to a numerical value (the database encoding) and returns it.
+TSqlSrvConfigParams::TDbEncoding TSqlSrvConfig::GetEncoding(const TDesC8& aParamValue)
+ {
+ TSqlSrvConfigParams::TDbEncoding encoding = TSqlSrvConfigParams::EEncNotSet;
+ if(aParamValue.CompareF(KUTF8) == 0 || aParamValue.CompareF(KUTF8Q) == 0)
+ {
+ encoding = TSqlSrvConfigParams::EEncUtf8;
+ }
+ else if(aParamValue.CompareF(KUTF16) == 0 || aParamValue.CompareF(KUTF16Q) == 0)
+ {
+ encoding = TSqlSrvConfigParams::EEncUtf16;
+ }
+ //else
+ // {
+ // Invalid encoding - bypass it in order to be compatible with the previous implementation
+ // }
+ return encoding;
+ }
+
+//The function converts aParamValue to a numerical value (the soft heap limit in Kb) and returns it.
+TInt TSqlSrvConfig::GetSoftHeapLimitL(const TDesC8& aParamValue)
+ {
+ TLex8 lex(aParamValue);
+ TInt softHeapLimitKb = TSqlSrvConfigParams::KConfigPrmValueNotSet;
+ TInt err = lex.Val(softHeapLimitKb);
+ if(err != KErrNone || softHeapLimitKb < 0 ||
+ (softHeapLimitKb < TSqlSrvConfigParams::KMinSoftHeapLimitKb || softHeapLimitKb > TSqlSrvConfigParams::KMaxSoftHeapLimitKb))
+ {
+ __SQLLEAVE(KErrArgument);
+ }
+ return softHeapLimitKb;
+ }
+
+//The function converts aParamValue to a numerical value (the database compaction mode) and returns it.
+TSqlCompactionMode TSqlSrvConfig::GetCompactionModeL(const TDesC8& aParamValue)
+ {
+ TSqlCompactionMode compactionMode = ESqlCompactionNotSet;
+ if(aParamValue.CompareF(KManual) == 0)
+ {
+ compactionMode = ESqlCompactionManual;
+ }
+ else if(aParamValue.CompareF(KBackground) == 0)
+ {
+ compactionMode = ESqlCompactionBackground;
+ }
+ else if(aParamValue.CompareF(KAuto) == 0 || aParamValue.CompareF(KSynchronous) == 0)
+ {
+ compactionMode = ESqlCompactionAuto;
+ }
+ //else
+ // {
+ // Invalid compaction mode
+ // }
+ return compactionMode;
+ }
+
+//The function converts aParamValue to a numerical value (the free page threshold in pages) and returns it.
+TInt TSqlSrvConfig::GetFreePageThresholdL(const TDesC8& aParamValue)
+ {
+ TLex8 lex(aParamValue);
+ TInt freePageThreshold = 0;
+ TInt err = lex.Val(freePageThreshold);
+ if(err != KErrNone || freePageThreshold < 0)
+ {
+ __SQLLEAVE(KErrArgument);
+ }
+ return freePageThreshold;
+ }
+
+
+//The function searches aStr for leading and trailing whitespace
+//characters, then creates and returns TPtrC object which points to the
+//aStr content without leading and trailing whitespace characters.
+TPtrC8 TSqlSrvConfig::TrimAndConstructPtr(const TUint8* aStr, TInt aLength)
+ {
+ __SQLASSERT(aStr != NULL, ESqlPanicBadArgument);
+ __SQLASSERT(aLength >= 0, ESqlPanicBadArgument);
+ //Trim left
+ for(;aLength>0;--aLength,++aStr)
+ {
+ if(!TChar(*aStr).IsSpace())
+ {
+ break;
+ }
+ }
+ //Trim right
+ for(const TUint8* p=aStr+aLength-1;aLength>0;--aLength,--p)
+ {
+ if(!TChar(*p).IsSpace())
+ {
+ break;
+ }
+ }
+ return TPtrC8(aStr, aLength);
+ }
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+CDbConfigFiles* CDbConfigFiles::NewL(const CDir& aDirEntries)
+ {
+ CDbConfigFiles* self = new(ELeave) CDbConfigFiles();
+ CleanupStack::PushL(self);
+ self->ConstructL(aDirEntries);
+ CleanupStack::Pop();
+ return self;
+ }
+
+CDbConfigFiles::CDbConfigFiles()
+ {
+ }
+
+void CDbConfigFiles::ConstructL(const CDir& aDirEntries)
+ {
+ StoreFileNamesL(aDirEntries);
+ }
+
+CDbConfigFiles::~CDbConfigFiles()
+ {
+ iConfigFileNames.ResetAndDestroy();
+ }
+
+//Stores the names of the given database configuration files.
+//These files were found in the server's private data cage on
+//the Z: drive and begin with the prefix 'cfg'
+void CDbConfigFiles::StoreFileNamesL(const CDir& aDirEntries)
+ {
+ //Store the file names in reverse alphabetical order so that
+ //in FindConfigFile() if there is more than one version of the same
+ //config file (which there shouldn't be) then the highest version
+ //will be returned
+ for(TInt i = aDirEntries.Count() - 1; i >= 0; --i)
+ {
+ const TEntry& entry = aDirEntries[i];
+ if(!entry.IsDir())
+ {
+ HBufC* filename = entry.iName.AllocLC();
+ iConfigFileNames.AppendL(filename);
+ CleanupStack::Pop(); // filename
+ }
+ }
+ }
+
+//Finds the configuration file corresponding to the given database, if one exists.
+//The database filename including the extension is passed as a parameter - for example,
+//[12345678]a.db. Note that if more than one version of a configuration file exists
+//for the given database (which shouldn't happen) - for example, cfg[12345678]a.db.01
+//and cfg[12345678]a.db.02 - then the highest version will be returned
+HBufC* CDbConfigFiles::FindConfigFile(const TDesC& aDbFilename) const
+ {
+ TInt count = iConfigFileNames.Count();
+ for(TInt i = 0; i < count; ++i)
+ {
+ TInt offset = iConfigFileNames[i]->Des().FindF(aDbFilename);
+ if(KErrNotFound != offset)
+ {
+ return iConfigFileNames[i];
+ }
+ }
+ return NULL;
+ }