/*!---------------------------------------------------------------------
  @file           RTEConf_ParameterAccessKernelInterface.cpp
  @author         RobinW
  @brief          RTE configuration parameters:  class for kernel configurable parameter access
  
  first created  2000-03-22  17:49

\if EMIT_LICENCE
    ========== licence begin  GPL
    Copyright (c) 2000-2005 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end

\endif
---------------------------------------------------------------------*/

/*PTS 1115041*/

/*===========================================================================*
 *  INCLUDES                                                                 *
 *===========================================================================*/


#include "SAPDBCommon/SAPDB_Types.hpp"
#include "RunTime/RTE_Types.hpp"
#include "RunTime/Configuration/RTEConf_ParameterAccessKernelInterface.h"
#include "gsp11.h"
#include "heo11.h"
#include "RunTime/Configuration/RTEConf_BuildParamFileName.h"

#include "RunTime/RTE_Message.hpp"
#include "SAPDBCommon/SAPDB_ToString.hpp"

#include "SAPDBCommon/Tracing/SAPDBTrace_Topic.hpp"
#include "SAPDBCommon/Tracing/SAPDBTrace_Usage.hpp"

extern SAPDBTrace_Topic Runtime_Trace;

#include "geo50_0.h"    // KGS
#include "SAPDBCommon/SAPDB_sprintf.h"
#include "SAPDBCommon/SAPDB_string.h"

#ifdef _WIN32           /* & if $OSSPEC = WIN32*/
#include "gos00k.h"     /* nocheck */
#else                   /* & else*/
#include "gen81.h"      /* nocheck */
#endif                  /* & endif*/

#include <math.h>       /* nocheck */

#include "RunTime/Configuration/RTEConf_ParameterAccessKernelInterface.hpp"
#include "RunTime/MemoryManagement/RTEMem_SystemPageCache.hpp"

#include "KernelCommon/ParameterNames/KernelParam_IOManager.hpp"
#include "KernelCommon/ParameterNames/KernelParam_Converter.hpp"
#include "KernelCommon/ParameterNames/KernelParam_RunTime.h"

#ifndef _WIN32
#include "RunTime/RTE_saveUNIXcalls.h"  /* nocheck */
#endif

/*===========================================================================*
 *  DEFINES                                                                  *
 *===========================================================================*/

#define SIZE_OF_NUMBER_BUFFER_  256

#define MAX_TASKCLUSTER_PARTS 10

#define MAX_EXCLUSIVE     250
#define MAX_REGIONS       40
#define ACT_PARAM_VERSION 0

#define MIN_DISP_LOOPS     1

#define UNKNOWN_PARAMETER_MESSAGE "unknown parameter found in XParam file: "

#define XP_V_UPDATE_OFFLINE 0
#define XP_V_UPDATE_ONLINE  1

#define XP_V_SET_TASKCLUSTER  0
#define XP_V_SET_DEVSP_NAME   1
#define XP_V_SET_DEVSP_SIZE   2
#define XP_V_SET_M_DEVSP_NAME 3
#define XP_V_SET_VOLUME_MODE  4
#define XP_V_SET_HS_NODE_NAME 5  
#define XP_V_SET_FILE_SYSTEM_ACCESS_TYPE 6

#define XP_V_BOOL_Y   0  /* Bool type (TRUE if Y or y) (for YES   */
#define XP_V_BOOL_N   1  /* Bool type (TRUE if N or n) (for NO)   */
#define XP_V_BOOL_A   2  /* Bool type (TRUE if A or a) (for AUTO) */
#define XP_V_BOOL_S   3  /* Bool type (TRUE if S or s) (for STACK) */
#define XP_V_LONG     4  /* Signed Long type */
#define XP_V_ULONG    5  /* Unsigned Long type */
#define XP_V_REGIONS  6  /* Unsigned Long Region Count */
#define XP_V_STRING   7  /* Any String type */
#define XP_V_IGNORED  8  /* Accepted, but ignored */
#define XP_V_CRYPT    9  /* Crypted Password */
#define XP_V_SPECIAL_STRING  10 /* String Parameter with side effect */
#define XP_V_SPECIAL_LONG    11 /* Long Parameter with side effect */
#define XP_V_SPECIAL_ULONG   12 /* Unsigned Long Parameter with side effect */
#define XP_V_SPECIAL_SPECIAL 13 /* Other Parameter with side effect */

#define XP_PARAM_CHANGED        "__PARAM_CHANGED___"

#ifdef WIN32
#define LAST_SYSTEM_ERROR_          ((SAPDB_ULong)GetLastError())
#else
#define LAST_SYSTEM_ERROR_          errno
#endif

/*===========================================================================*
 *  MACROS                                                                   *
 *===========================================================================*/

#define ALLOCATE_ARRAY(TypeOfElement,NumberOfElements)                          \
    (TypeOfElement *)AllocateMemory(sizeof(TypeOfElement) * (NumberOfElements))

#define DEALLOCATE_MEMORY(address)                                              \
{                                                                               \
    RTEMem_RteAllocator::Instance().Deallocate((void *)(address));              \
    address = NULL;                                                             \
}                                                                   
  
#define XP_PTR(_x,_t) (((SAPDB_Byte *)_x)+_t->offset)

#define RTE_NUMBER_OF_ELEMENTS_IN_XPARAM_TABLE1 \
	(sizeof(RteXparamTable1)/sizeof(struct xparam_strncmp_table))

#define XP_SZ_OFF(_x)  sizeof(((RTE_XPARAM_REC *)0)->_x), \
							((size_t)&(((RTE_XPARAM_REC *)0)->_x))

#define RTE_NUMBER_OF_ELEMENTS_IN_XPARAM_TABLE2 \
	(sizeof(RteXparamTable2)/sizeof(struct xparam_strcmp_table))

/*===========================================================================*
 *  LOCAL CLASSES, STRUCTURES, TYPES, UNIONS ...                             *
 *===========================================================================*/

/*!
  @brief small helper class for sorted parmameter dump
 */
class  RTEConf_ParameterNameValuePair
{
public:
    RTEConf_ParameterNameValuePair( SAPDB_Char *name
                                  , SAPDB_Char *value )
                                  : m_Name(name)
                                  , m_Value(value)
                                  , m_Prev(0)
                                  , m_Next(0)
    {
    }

    void Enqueue(RTEConf_ParameterNameValuePair *prev, RTEConf_ParameterNameValuePair *next)
    {
        m_Prev = prev;
        if ( prev )
        {
            prev->SetNext(this);
            m_Prev = prev;
        }
        m_Next = next;
        if ( next )
        {
            next->SetPrev(this);
        }
    }

    /*!
      @brief compare stored name with given name

      Name comparison is done case insensitive and leading underscores are ignored

      @param name [in] name to compare
      @return 0 if identical, -1 if stored name lexicographic smaller, +1 if stored name lexicographic larger
     */
    SAPDB_Int NameCompare(SAPDB_Char const *name)
    {
        SAPDB_Char *storedName = (SAPDB_Char *)m_Name;

        while ( *name && *name == '_' )
        {
            ++name;
        }

        while ( *storedName && *storedName == '_' )
        {
            ++storedName;
        }

        while ( *storedName && *name )
        {
            SAPDB_Int delta = (((SAPDB_Int)toupper(*storedName)) - ((SAPDB_Int)toupper(*name)));

            if ( delta > 0 )
            {
                return 1;
            }
            else if (  delta < 0 )
            {
                return -1;

            }
            else
            {
                ++storedName;
                ++name;
            }
        }
        return ( *name ? 1 : -1 );
    }

    RTEConf_ParameterNameValuePair *GetPrev()          { return m_Prev; }
    RTEConf_ParameterNameValuePair *GetNext()          { return m_Next; }


    void Show()
    {
        RTE_Message( SAPDBErr_MessageList(RTE_CONTEXT, RTEINFO_STARTUP_ARGUMENT, m_Name, m_Value) );
    }

private:
    void SetPrev(RTEConf_ParameterNameValuePair *prev) { m_Prev = prev; }
    void SetNext(RTEConf_ParameterNameValuePair *next) { m_Next = next; }

    SAPDB_ToStringClass m_Name;
    SAPDB_ToStringClass m_Value;
    RTEConf_ParameterNameValuePair *m_Prev;
    RTEConf_ParameterNameValuePair *m_Next;
};

enum xp_paramType
{
    NXP_INT_TYPE,
    NXP_STRING_TYPE,
    NXP_CRYPT_TYPE
};

struct  RTEConf_ParameterValueRecord_
{
    xp_paramType xp_value_t ;
    union           of_xp_value_t
    {
        RTEConf_Parameter::Integer      xp_integer ;
        RTEConf_Parameter::String       xp_string; 
        RTEConf_Parameter::CryptInfo    xp_crypt ;
    }  xp_type ;
}  ;

typedef struct RTEConf_ParameterValueRecord_   RTEConf_ParameterValueRecord ;

static SAPDB_Char* szDevType[ NUM_DEVSP_TYPES ] = 
{ 
    (SAPDB_Char*)"SYS",  
    (SAPDB_Char*)"MSYS",
    (SAPDB_Char*)"ALOG" , 
    (SAPDB_Char*)"MALOG",
    (SAPDB_Char*)"TLOG",
    (SAPDB_Char*)"DATA", 
    (SAPDB_Char*)"MDATA",
    (SAPDB_Char*)"TRACE" 
} ;

static struct szAccessModeMapping 
{
    SAPDB_Char const *accessModeName;
    RTE_VolumeAccessMode accessMode;
} accessModeList[] =
{
    { "NORMAL",     RTE_VolumeAccessModeNormal },
    { "SEQUENTIAL", RTE_VolumeAccessModeSequential },
    { 0,            RTE_VolumeAccessModeNormal }
};

struct xparam_strncmp_table
{
    RTEConf_Parameter::Name name;		/* Name found in XParam file */
    size_t                  len;       /* Maximum length to compare */

    SAPDB_Int4              type;      /* Classification of expected type */

    RTE_DevSpaceType            dt;
    RTE_DevSpaceType            mdt;
};

static  struct xparam_strncmp_table RteXparamTable1[]=
{
 { KERNELPARAM_LOG_VOLUME_NAME_ ,       PAN_ARCHIVE_LOG_N_LN,
		XP_V_SET_DEVSP_NAME,   RTE_DevSpaceLog,    RTE_DevSpaceFiller    },
 { KERNELPARAM_LOG_VOLUME_SIZE_,        PAN_ARCHIVE_LOG_N_SIZE_LN,
		XP_V_SET_DEVSP_SIZE,   RTE_DevSpaceLog,    RTE_DevSpaceFiller    },

 { KERNELPARAM_DATA_VOLUME_NAME_,       PAN_DATADEV_N_LN,
		XP_V_SET_DEVSP_NAME,   RTE_DevSpaceData,   RTE_DevSpaceFiller    },
 { KERNELPARAM_DATA_VOLUME_SIZE_,       PAN_DATADEV_N_SIZE_LN,
		XP_V_SET_DEVSP_SIZE,   RTE_DevSpaceData,   RTE_DevSpaceFiller    },
 { KERNELPARAM_DATA_VOLUME_MODE_,       PAN_DATA_VOLUME_MODE_N_LN,
		XP_V_SET_VOLUME_MODE,  RTE_DevSpaceFiller,   RTE_DevSpaceFiller },

 { KERNELPARAM_HS_NODE_,                PAN_HS_NODE_N_LN,
		XP_V_SET_HS_NODE_NAME, RTE_DevSpaceFiller,   RTE_DevSpaceFiller },

 { KERNELPARAM_M_LOG_VOLUME_NAME_,      PAN_M_ARCHIVE_LOG_N_LN,
		XP_V_SET_M_DEVSP_NAME, RTE_DevSpaceLog,    RTE_DevSpaceMirrorLog  },
 { KERNELPARAM_M_DATA_VOLUME_NAME_ ,    PAN_M_DATADEV_N_LN,
		XP_V_SET_M_DEVSP_NAME, RTE_DevSpaceData,   RTE_DevSpaceMirrorData },
 { KERNELPARAM_M_SYSDEV_ ,              PAN_M_SYS_N_LN,
		XP_V_SET_M_DEVSP_NAME, RTE_DevSpaceSystem,    RTE_DevSpaceMirrorSystem  },

 { KERNELPARAM_SYSDEV_ ,                PAN_SYS_N_LN,      
		XP_V_SET_DEVSP_NAME,   RTE_DevSpaceSystem,    RTE_DevSpaceFiller    },
 { KERNELPARAM_SYS_SIZE_ ,              PAN_SYS_N_SIZE_LN,
		XP_V_SET_DEVSP_SIZE,   RTE_DevSpaceSystem,    RTE_DevSpaceFiller    },

 { KERNELPARAM__TASKCLUSTER_ ,          PAN_TASKCLUSTER_N_LN,
		XP_V_SET_TASKCLUSTER,  RTE_DevSpaceFiller, RTE_DevSpaceFiller    },

    // even if dafs is not supported in this release, the volume type is now       
    // checked, because raw devices must not be checked against configured ulimits 
    // http://pts:1080/webpts?wptsdetail=yes&ErrorType=0&ErrorID=1127157
 { KERNELPARAM_LOG_VOLUME_TYPE_ ,       PAN_ARCHIVE_LOG_N_LN,
		XP_V_SET_FILE_SYSTEM_ACCESS_TYPE,    RTE_DevSpaceLog         },
 { KERNELPARAM_M_LOG_VOLUME_TYPE_ ,     PAN_M_ARCHIVE_LOG_N_LN,
		XP_V_SET_FILE_SYSTEM_ACCESS_TYPE,    RTE_DevSpaceMirrorLog   },
 { KERNELPARAM_DATA_VOLUME_TYPE_,       PAN_DATADEV_N_LN,
		XP_V_SET_FILE_SYSTEM_ACCESS_TYPE,    RTE_DevSpaceData        },
};

struct xparam_strcmp_table
{
    RTEConf_Parameter::Name name;		/* Name found in XParam file */

    SAPDB_Int4              type;       /* Claasification of expected type */

    size_t                  size;       /* Size in RTE struct */
    SAPDB_ULong             offset;     /* Offset in RTE struct */
};

static struct xparam_strcmp_table RteXparamTable2[] =
{
 { KERNELPARAM__AK_DUMP_ALLOWED,    XP_V_BOOL_Y,    XP_SZ_OFF(fAKDumpAllowed)     },
 { KERNELPARAM_SYMBOL_DEMANGLING,   XP_V_BOOL_Y,    XP_SZ_OFF(allowDemangle)       },
 { KERNELPARAM__BACKUP_HISTFILE,    XP_V_STRING,    XP_SZ_OFF(szBackupHistFile)    },
 { KERNELPARAM__BACKUP_MED_DEF,     XP_V_STRING,    XP_SZ_OFF(szBackupMedDefFile)  },
 { KERNELPARAM_CACHE_SIZE ,         XP_V_LONG,      XP_SZ_OFF(cacheSize)           },
 { KERNELPARAM__COMMENT,            XP_V_IGNORED,     0, 0                         },
 { KERNELPARAM_DIAG_HISTORY_NUM,    XP_V_ULONG,     XP_SZ_OFF(uCrashHistoryNum)    },
 { KERNELPARAM_DIAG_HISTORY_PATH,   XP_V_STRING,    XP_SZ_OFF(szCrashHistoryPath)  },
 { KERNELPARAM__DELAY_COMMIT,       XP_V_BOOL_Y,    XP_SZ_OFF(fDelayCommit)        },
 { KERNELPARAM__DELAY_LOGWRITER,    XP_V_LONG,      XP_SZ_OFF(lDelayLW)            },
 { KERNELPARAM__IOPROCS_SWITCH,     XP_V_LONG,      XP_SZ_OFF(lDevQueue)           },
 { KERNELPARAM_KERNELDIAGSIZE,      XP_V_ULONG,     XP_SZ_OFF(ulDiagSize)          },
 { KERNELPARAM__EVENT_ALIVE_CYCLE,  XP_V_ULONG,     XP_SZ_OFF(ulEventAliveCycle)   },
 { KERNELPARAM__EVENTSIZE,          XP_V_ULONG,     XP_SZ_OFF(ulEventSize)         },
 { KERNELPARAM__EVENTFILE,          XP_V_STRING,    XP_SZ_OFF(szEventFile)         },
 { KERNELPARAM_FORMAT_DATAVOLUME,   XP_V_BOOL_Y,    XP_SZ_OFF(fFormatDataVolume)   },
 { KERNELPARAM_FORMATTING_MODE,     XP_V_IGNORED,    0, 0 },
 { KERNELPARAM_HEAP_MEM_POOL,       XP_V_LONG,      XP_SZ_OFF(heapMemPoolSize)     },
 { KERNELPARAM__IOPROCS_FOR_PRIO,   XP_V_LONG,      XP_SZ_OFF(lPrioDeviPerDevspace) },
 { KERNELPARAM__IOPROCS_FOR_READER, XP_V_LONG,      XP_SZ_OFF(lReaderDeviPerDevspace) },
 { KERNELPARAM__KERNELDUMPFILE,     XP_V_STRING,    XP_SZ_OFF(szDumpFilename)      },
 { KERNELPARAM__KERNELTRACEFILE,    XP_V_IGNORED,   XP_SZ_OFF(szTraceDevspace)    },
 { KERNELPARAM_KERNELTRACESIZE,     XP_V_IGNORED,   XP_SZ_OFF(lTraceDevspaceSize) },
 { KERNELPARAM_LOAD_BALANCING_CHK,  XP_V_LONG,      XP_SZ_OFF(uLoadBalancingCheck) },
 { KERNELPARAM_LOAD_BALANCING_DIF,  XP_V_LONG,      XP_SZ_OFF(uLoadBalancingDiff)  },
 { KERNELPARAM_LOAD_BALANCING_EQ,   XP_V_LONG,      XP_SZ_OFF(uLoadBalancingEquality)},
 { KERNELPARAM_LOG_MIRRORED,        XP_V_BOOL_Y,    XP_SZ_OFF(fLogMirrored)        },
 { KERNELPARAM_LOG_MODE,            XP_V_IGNORED,    0, 0 },
 { KERNELPARAM_MAXUSERTASKS,        XP_V_ULONG,     XP_SZ_OFF(ulMaxUser)           },
 { KERNELPARAM_MAXBACKUPDEVS,       XP_V_LONG,      XP_SZ_OFF(lNoOfBackupDevs)     },
 { KERNELPARAM__MAX_BACKUP_TASKS,   XP_V_ULONG,     XP_SZ_OFF(ulMaxBackupTasks)    },
 { KERNELPARAM_MAXCPU,              XP_V_ULONG,     XP_SZ_OFF(ulMaxCPU)            },
 { KERNELPARAM_MAXPAGER,            XP_V_ULONG,     XP_SZ_OFF(ulMaxDataWriter)     },
 { KERNELPARAM_MAXVOLUMES,          XP_V_IGNORED,   XP_SZ_OFF(lMaxDevspaces)      },
 { KERNELPARAM__MAXEVENTS,          XP_V_ULONG,     XP_SZ_OFF(ulMaxEvents)         },
 { KERNELPARAM__MAXEVENTTASKS,      XP_V_ULONG,     XP_SZ_OFF(ulMaxEventTasks)     },
 { KERNELPARAM__MAXGARBAGE_COLL,    XP_V_ULONG,     XP_SZ_OFF(ulMaxGarbageCollector) },
 { KERNELPARAM__IOPROCS_PER_DEV,    XP_V_LONG,      XP_SZ_OFF(lDeviPerDevspace)    },
 { KERNELPARAM__MAX_MESSAGE_FILES,  XP_V_ULONG,     XP_SZ_OFF(ulMaxMessageFiles)   },
 { KERNELPARAM_MAXRGN_REQUEST,      XP_V_ULONG,     XP_SZ_OFF(ulRegLockSlice)      },
 { KERNELPARAM_MAXSERVERTASKS,      XP_V_ULONG,     XP_SZ_OFF(ulMaxServer)         },
 { KERNELPARAM__MAXTASK_STACK,      XP_V_ULONG,     XP_SZ_OFF(ulMaxUsUtStack)     },
 { KERNELPARAM_MEMORY_SLOT_SIZE,    XP_V_LONG,      XP_SZ_OFF(memorySlotSize)     },
 { KERNELPARAM__MINREPLY_SIZE,      XP_V_ULONG,     XP_SZ_OFF(ulMinReplySize)     },
 { KERNELPARAM__MIRRORED_DATA,      XP_V_BOOL_Y,    XP_SZ_OFF(fMirrData)           },
 { KERNELPARAM__MP_DISP_LOOPS,      XP_V_ULONG,     XP_SZ_OFF(ulDispLoopsBefSemop)},
 { KERNELPARAM__MP_DISP_PRIO,       XP_V_BOOL_Y,    XP_SZ_OFF(fDynDispQueSrch)     },
 { KERNELPARAM__MP_RGN_BUSY_WAIT,   XP_V_BOOL_Y,    XP_SZ_OFF(fEndExclBusyWait)    },
 { KERNELPARAM__MP_RGN_DIRTY_READ,  XP_V_BOOL_Y,    XP_SZ_OFF(fBegExclDirtyRead)   },
 { KERNELPARAM_MP_RGN_LOOP,         XP_V_ULONG,     XP_SZ_OFF(ulRegionCollisionLoop) },
 { KERNELPARAM__MP_RGN_PRIO,        XP_V_BOOL_Y,    XP_SZ_OFF(fBegExclQueWhenPrio) },
 { KERNELPARAM__MP_RGN_QUEUE,       XP_V_BOOL_Y,    XP_SZ_OFF(fExclQueue)          },
 { KERNELPARAM_MMAP_MEM_POOL,       XP_V_LONG,      XP_SZ_OFF(mmapMemPoolSize)     },
 { KERNELPARAM__MULT_IO_BLOCK_CNT,  XP_V_ULONG,     XP_SZ_OFF(ulMultIOBlockCount)  },
 { KERNELPARAM_OFFICIAL_NODE,       XP_V_STRING,    XP_SZ_OFF(szOfficialNode) },
 { KERNELPARAM_OMS_HEAP_LIMIT  ,    XP_V_ULONG,     XP_SZ_OFF(ulOMSHeapLimit) },
 { KERNELPARAM__PACKET_SIZE,        XP_V_ULONG,     XP_SZ_OFF(ulPacketSize)       },
/*
 To enable page size parameter via 'XPARAM' use this, but since the kernel still uses tsp00_Page...

 { KERNELPARAM__PAGE_SIZE,          XP_V_IGNORED,    XP_SZ_OFF(ulDBPageSize)       },
 */
 { KERNELPARAM__PAGE_SIZE,          XP_V_IGNORED,    0, 0 },
 { KERNELPARAM_KERNELVERSION,       XP_V_STRING,    XP_SZ_OFF(szKernelVersion)     },
 { KERNELPARAM__PRIO_BASE_COM,      XP_V_LONG,      XP_SZ_OFF(lPrioBaseCOM)        },
 { KERNELPARAM__PRIO_BASE_IOC,      XP_V_LONG,      XP_SZ_OFF(lPrioBaseIOC)        },
 { KERNELPARAM__PRIO_BASE_RAV,      XP_V_LONG,      XP_SZ_OFF(lPrioBaseRAV)        },
 { KERNELPARAM__PRIO_BASE_REX,      XP_V_LONG,      XP_SZ_OFF(lPrioBaseREX)        },
 { KERNELPARAM__PRIO_BASE_U2U,      XP_V_LONG,      XP_SZ_OFF(lPrioBaseU2U)        },
 { KERNELPARAM__PRIO_FACTOR,        XP_V_LONG,      XP_SZ_OFF(lPrioFactor)         },
 { KERNELPARAM__RTEDUMPFILE,        XP_V_STRING,    XP_SZ_OFF(szRTEDumpFilename)   },
 { KERNELPARAM_RUNDIRECTORY,        XP_V_STRING,    XP_SZ_OFF(szRunDirectory)      },
 { KERNELPARAM_SERVERDB,            XP_V_IGNORED,     0, 0                         },
 { KERNELPARAM_SET_VOLUME_LOCK,     XP_V_BOOL_Y,    XP_SZ_OFF(fSetVolumeLock)      },
 { KERNELPARAM_SHM_MEM_POOL,        XP_V_LONG,      XP_SZ_OFF(shmMemPoolSize)     },
 { KERNELPARAM_SHOW_MAX_STACK_USE,  XP_V_BOOL_Y,    XP_SZ_OFF(showMaxStackUse)     },
 { KERNELPARAM_TRACE_PAGES_LW,      XP_V_LONG,      XP_SZ_OFF(tracePagesAL)        },
 { KERNELPARAM_TRACE_PAGES_BUP,     XP_V_LONG,      XP_SZ_OFF(tracePagesBUP)       },
 { KERNELPARAM_TRACE_PAGES_PG,      XP_V_LONG,      XP_SZ_OFF(tracePagesDW)        },
 { KERNELPARAM_TRACE_PAGES_EV,      XP_V_LONG,      XP_SZ_OFF(tracePagesEV)        },
 { KERNELPARAM_TRACE_PAGES_GC,      XP_V_LONG,      XP_SZ_OFF(tracePagesGC)        },
 { KERNELPARAM_TRACE_PAGES_SV,      XP_V_LONG,      XP_SZ_OFF(tracePagesSV)        },
 { KERNELPARAM_TRACE_PAGES_TI,      XP_V_LONG,      XP_SZ_OFF(tracePagesTI)        },
 { KERNELPARAM_TRACE_PAGES_TW,      XP_V_LONG,      XP_SZ_OFF(tracePagesTW)        },
 { KERNELPARAM_TRACE_PAGES_US,      XP_V_LONG,      XP_SZ_OFF(tracePagesUS)        },
 { KERNELPARAM_TRACE_PAGES_UT,      XP_V_LONG,      XP_SZ_OFF(tracePagesUT)        },
 { KERNELPARAM__USE_ASYNC_IO,       XP_V_BOOL_Y,    XP_SZ_OFF(fUseAsyncIO)         },
 { KERNELPARAM__USE_BCK_SECURDESC,  XP_V_BOOL_Y,    XP_SZ_OFF(fUseWinSecurDesc)    },
 { KERNELPARAM__USE_IOPROCS_ONLY,   XP_V_BOOL_N,    XP_SZ_OFF(fAllowSingleIO)      },
 { KERNELPARAM__UTILITY_PROTFILE,   XP_V_STRING,    XP_SZ_OFF(szUtilityProtFile)   },
 { KERNELPARAM_UTILITY_PROTSIZE,    XP_V_ULONG,     XP_SZ_OFF(ulUtilityProtSize)   },
 { KERNELPARAM_VALLOC_MEM_POOL,     XP_V_LONG,      XP_SZ_OFF(vallocMemPoolSize)     },
 { KERNELPARAM___PARAM_CHANGED___,  XP_V_ULONG,     XP_SZ_OFF(ulXparamChanged)     },
 { KERNELPARAM_SYMBOL_RESOLUTION,   XP_V_BOOL_Y,    XP_SZ_OFF(allowSymbolResolution) },
 { KERNELPARAM_PREALLOCATE_IOWORKER,XP_V_BOOL_Y,    XP_SZ_OFF(preallocateIOWorker) },
/***************************************************************/
/* OS Depending Parameter                                      */
/***************************************************************/
#if defined(_WIN32)
 { KERNELPARAM_ALLOW_COMPR_DEVSP,   XP_V_BOOL_Y,    XP_SZ_OFF(fAllowCompressedDevsp) },
 { KERNELPARAM_DYNAMIC_SERVER,      XP_V_BOOL_Y,    XP_SZ_OFF(fDynamicServerTasks)   },
 { KERNELPARAM_MEM_ENHANCE_LIMIT,   XP_V_LONG,      XP_SZ_OFF(lMemEnhancementLimit)  },
 { KERNELPARAM_RESTART_SHUTDOWN,    XP_V_BOOL_A,    XP_SZ_OFF(fAutoRestartShutdown)  },
 { KERNELPARAM_USE_FIBERS,          XP_V_BOOL_Y,    XP_SZ_OFF(fUseFibers)            },
 { KERNELPARAM_USE_MEM_ENHANCE,     XP_V_BOOL_Y,    XP_SZ_OFF(fUseMemEnhancement)    },
#else
 { KERNELPARAM_GATEWAYTYPE,         XP_V_IGNORED,    0, 0 },
 { KERNELPARAM_OPMSG1,              XP_V_STRING,    XP_SZ_OFF(szOpMsg1)              },
 { KERNELPARAM_OPMSG2,              XP_V_STRING,    XP_SZ_OFF(szOpMsg2)              },
 { KERNELPARAM__SHMKERNEL,          XP_V_LONG,      XP_SZ_OFF(lShmKernel)            },
 { KERNELPARAM__TASK_STACK_AREA,    XP_V_IGNORED,   0, 0                             },
 { KERNELPARAM__USE_PROC_SCOPE,     XP_V_BOOL_Y,    XP_SZ_OFF(fUseProcessScope)      },  /* PTS 1109046 */
 { KERNELPARAM_SUPPRESS_CORE,       XP_V_BOOL_Y,    XP_SZ_OFF(suppressCore)          },
 { KERNELPARAM_USE_COROUTINES,      XP_V_BOOL_Y,    XP_SZ_OFF(fUseCoroutines)        },
 { KERNELPARAM_SIMULATE_VECTORIO,   XP_V_STRING,    XP_SZ_OFF(szVectorIoMode)        },
#endif
#if defined(_WIN32) || defined(LINUX)
 { KERNELPARAM_HIRES_TIMER_TYPE,    XP_V_STRING,    XP_SZ_OFF(szHiResTimerType)      },
#endif
 { KERNELPARAM_FORBID_LOAD_BALANCING, XP_V_BOOL_Y,  XP_SZ_OFF(fForbidLoadBalancing)  },
/***************************************************************/
/* End of OS Depending Parameter                               */
/***************************************************************/
};

/*===========================================================================*
 *  STATIC/INLINE FUNCTIONS (PROTOTYPES)                                     *
 *===========================================================================*/

static inline void *AllocateMemory(size_t size);

static SAPDB_Bool RTEConf_AnalyzeParam  ( RTE_XPARAM_REC               *XParam,
                                          RTEConf_Parameter::Name      name,
                                          RTEConf_ParameterValueRecord *xpr ,
                                          SAPDB_Bool                   inOnlineMode,
                                          SAPDBErr_MessageList         &err) ;

static SAPDB_Int4 RTEConf_FindParam ( RTEConf_Parameter::Name             name ,
                                      RTEConf_ParameterValueRecord        *xpr ,
                                      SAPDBErr_MessageList &err);

static void   RTEConf_InitParam          ( RTE_XPARAM_REC        *XParam  );

static void   RTEConf_ReadSpecialParameters(RTE_XPARAM_REC *XParam);

static void RTEConf_ModifyParameters(RTE_XPARAM_REC *XParam);

static void   RTEConf_SetTaskCluster ( RTE_XPARAM_REC            *XParam,
                                       RTEConf_Parameter::String szTaskCluster,
                                       SAPDB_ULong               ulTCNo );

static SAPDB_Bool RTEConf_SetDevspName  ( RTE_XPARAM_REC               *XParam,
                                          RTEConf_Parameter::Name      DevspName ,
                                          RTEConf_ParameterValueRecord *xpr ,
                                          SAPDB_Int                    lDevType ,
                                          SAPDB_ULong                  ulDevspNo ,
                                          SAPDBErr_MessageList         &err);

static SAPDB_Bool RTEConf_SetDevspSize  ( RTE_XPARAM_REC *XParam,
                                          SAPDB_Long     lDevType ,
                                          SAPDB_ULong    ulDevspNo ,
                                          SAPDB_Int      ulDevspSize );

static  SAPDB_Bool RTEConf_SetVolumeMode ( RTE_XPARAM_REC           *XParam,
                                           SAPDB_Char               *szAccessMode,
                                           SAPDB_ULong               ulDevspNo ,
                                           SAPDBErr_MessageList     &err);

static RTEConf_Parameter::Integer  RTEConf_XParamInt ( RTEConf_ParameterValueRecord  *xpr ,
                                                       SAPDBErr_MessageList          &err) ;

static void  RTEConf_AllocDevspDescr ( RTE_XPARAM_REC *XParam,
                                       SAPDB_Long     lDevspType,
                                       SAPDB_Int      ulNumDevsp);

externC SAPDB_Bool RTEConf_CheckDuplicateDevSpaceName( DEVSPACES_DESCR *devspacesArray,
                                                       SAPDB_Char *szDevspaceName,
                                                       SAPDBErr_MessageList &errList  );

static SAPDB_Bool RTEConf_SetFileSystemAccessType  ( RTE_XPARAM_REC *XParam,
                                             SAPDB_Long                lDevType ,
                                             SAPDB_Char               *szFileSystemAccessType,
                                             SAPDB_ULong               ulDevspNo ,
                                             SAPDBErr_MessageList     &err);
   

static SAPDB_Bool RTEConf_FullPathsOfFilenamesAreEqual( SAPDB_Char *pFileName1,
                                                        SAPDB_Char *pFileName2 );

/*===========================================================================*
 *  METHODS                                                                  *
 *===========================================================================*/

/*!--------------------------------------------------------------------
   @description    Check if the configured volumes do not exceed a given limit
   @param          limit [in] the limit in bytes to check the volume sizes against
   @return value   false if the size of one or more configured volumes exceeds the limit, true if not

 --------------------------------------------------------------------*/

externC SAPDB_Bool RTEConf_CheckVolumeSize(RTE_DevSpaceType type,RTE_XPARAM_REC *XparamParameters,SAPDB_UInt8 limit)
{
    SAPDB_UInt4 i;
    for(i=0;i<XparamParameters->DevspDescr[type].ulNumDevs;i++)
    {
        if(( DEVSPACE_UNUSED != XparamParameters->DevspDescr[type].Devspaces[i].lDevspaceType )
                             && XparamParameters->DevspDescr[type].Devspaces[i].sizeLimitedByUlimit )
        {
            SAPDB_UInt8 volumeSizeInBytes = XparamParameters->DevspDescr[type].Devspaces[i].lDevspaceSize * XparamParameters->ulDBPageSize;
            if(volumeSizeInBytes > limit)
            {
                RTE_Message(SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_CONF_FSIZE_EXCEEDS_ULIMIT1,
                    SAPDB_ToString(volumeSizeInBytes / (1024*1024)),
                    SAPDB_ToString(type),
                    SAPDB_ToString(i+1),
                    SAPDB_ToString(limit / (1024*1024))));
                RTE_Message(SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_CONF_FSIZE_EXCEEDS_ULIMIT2));
                return false;
            }
        }
    }
    return true;
}

/*!--------------------------------------------------------------------
   @description    Check if given names has duplicate in devspacesArray
   @param          devspacesArray [in] Array of devspace description arrays
   @param          szDevspaceName [in] Devspacename to check
   @return value   true is no duplicate, false if duplicate

 --------------------------------------------------------------------*/

externC SAPDB_Bool RTEConf_CheckDuplicateDevSpaceName( DEVSPACES_DESCR *devspacesArray,
                                                       SAPDB_Char      *szDevspaceName,
                                                       SAPDBErr_MessageList &errList )
{
    SAPDBTRACE_ROUTINE_DEBUG("RTEConf_CheckDuplicateDevSpaceName", Runtime_Trace, 5);

    SAPDB_Bool   Ok = true;;
    SAPDB_Int4   devSpaceIterator;
    for(devSpaceIterator = (SAPDB_Int4)RTE_DevSpaceSystem ; devSpaceIterator <= (SAPDB_Int4)RTE_DevSpaceTrace ; devSpaceIterator++)
    {
        DEVSPACES_DESCR   *pDevspDesc;
        SAPDB_UInt4        ulDevNo;
        SAPDB_Char      *pDevspaceName;

        pDevspDesc = devspacesArray + devSpaceIterator;

        for ( ulDevNo = 0; ulDevNo < pDevspDesc->ulNumDevs; ulDevNo++ )
        {
            if (pDevspDesc->Devspaces[ulDevNo].lDevspaceType == DEVSPACE_UNUSED) 
                continue;

            pDevspaceName = (SAPDB_Char *)pDevspDesc->Devspaces[ulDevNo].szDevspaceName;

            Ok = !RTEConf_FullPathsOfFilenamesAreEqual( pDevspaceName,szDevspaceName );
            if ( !Ok )
            {
                errList = SAPDBErr_MessageList(
	                RTE_CONTEXT,
                    RTEERR_CONF_DUPLICATE_VOLUME_NAME,
                    szDevspaceName,
	                SAPDB_ToString((RTE_DevSpaceType)devSpaceIterator),
	                SAPDB_ToString(ulDevNo+1)
                    );
                return Ok;
            }
        }
    }

    return Ok;
}

static void MessageAndCrash(const SAPDBErr_MessageList &err)
{
    RTE_Message(err);
    SLEEP(10000);
    SAPDBErr_MessageList emptyMessage;
    RTE_Crash(emptyMessage);
}
/* some parameters have to be read before others can be read, for example MAXARCHIVELOGS must be read before ARCHIVE_LOG_* can be read */

static void RTEConf_ReadSpecialParameters(RTE_XPARAM_REC *XParam)
{
    RTEConf_Parameter::Integer valueInt;
    RTEConf_Parameter::String valueString;
    SAPDBErr_MessageList err;

    RTEConf_AllocDevspDescr ( XParam, RTE_DevSpaceTrace, 1 ) ;
/*
    if((RTEConf_ParameterAccess::Instance())->GetInteger(KERNELPARAM__PAGE_SIZE,valueInt,err))
    {
		if ( valueInt != XParam->ulDBPageSize )
		{
        // put a trace output here...
        }
    }
 */
    if((RTEConf_ParameterAccess::Instance())->GetString(KERNELPARAM_FORMATTING_MODE,valueString,err))
    {
		switch ( valueString[0] )
		{
            case 'a' :
            case 'A' : 
                XParam->ulFormattingMode = RTE_FORMATTING_MODE_AUTO;
                break ;
            case 'p' :
            case 'P' : 
                XParam->ulFormattingMode = RTE_FORMATTING_MODE_PARALLEL;
                break ;
            case 's' :
            case 'S' : 
                XParam->ulFormattingMode = RTE_FORMATTING_MODE_SERIAL;
                break ;
            default  : 
                MessageAndCrash(SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_XP_INVALID_FORMATTING_MODE,(SAPDB_Char*)(valueString)));
            break;
		}
    }
    if((RTEConf_ParameterAccess::Instance())->GetInteger(KERNELPARAM_MAXVOLUMES,valueInt,err))
    {
        XParam->lMaxDevspaces = (SAPDB_Int)valueInt;
    }

#ifdef SYSTEMDEVSPACE_MIGRATION_QUESTION_ANSWERED
    SAPDB_Int maxSysDevspaces = 0; /* ---> default 0 would be more accurate, but TorstenS needs some  */
#else
    SAPDB_Int maxSysDevspaces = 1;
#endif
    /* Still needed, but only for inplace migration... */
    if((RTEConf_ParameterAccess::Instance())->GetInteger(KERNELPARAM__MAXSYSDEVSPACES,valueInt,err))
    {
        maxSysDevspaces = (SAPDB_Int)valueInt;
    }
    if ( maxSysDevspaces > 0 )
    {
        RTEConf_AllocDevspDescr ( XParam, RTE_DevSpaceSystem, maxSysDevspaces ) ;
        if ( XParam->fMirrData )
        {
            RTEConf_AllocDevspDescr ( XParam, RTE_DevSpaceMirrorSystem, maxSysDevspaces);
        }
    }
#ifdef SYSTEMDEVSPACE_MIGRATION_QUESTION_ANSWERED
    XParam->lMaxDevspaces += maxSysDevspaces;
#else
    ++(XParam->lMaxDevspaces); /* always add a worker for System Devspace migration... see above... */
#endif

    if((RTEConf_ParameterAccess::Instance())->GetInteger(KERNELPARAM_MAXLOGVOLUMES,valueInt,err))
    {
        SAPDB_Int maxArchiveLogs = (SAPDB_Int)valueInt;
        RTEConf_AllocDevspDescr ( XParam, 
                                  RTE_DevSpaceLog,
                                  maxArchiveLogs);
        RTEConf_AllocDevspDescr ( XParam,
                                  RTE_DevSpaceMirrorLog,
                                  maxArchiveLogs );
    }
    if((RTEConf_ParameterAccess::Instance())->GetInteger(KERNELPARAM_MAXDATAVOLUMES,valueInt,err))
    {
        SAPDB_Int maxDataDevspaces = (SAPDB_Int)valueInt;
        RTEConf_AllocDevspDescr ( XParam,
                                  RTE_DevSpaceData,
                                  maxDataDevspaces ) ;
        RTEConf_AllocDevspDescr ( XParam,
                                  RTE_DevSpaceMirrorData,
                                  maxDataDevspaces);
    }

    if((RTEConf_ParameterAccess::Instance())->GetInteger(KERNELPARAM_KERNELTRACESIZE,valueInt,err))
    {
        XParam->lTraceDevspaceSize = 
            XParam->DevspDescr [ RTE_DevSpaceTrace ].Devspaces[0].lDevspaceSize = 
                (SAPDB_Int)valueInt;
    }
    
    if((RTEConf_ParameterAccess::Instance())->GetString(KERNELPARAM__KERNELTRACEFILE,valueString,err))
    {
        strncpy(XParam->szTraceDevspace,(char *)valueString,sizeof(tsp2_devnamec));
        strncpy(XParam->DevspDescr [ sp2dt_trace ].Devspaces[0].szDevspaceName,(char *)valueString,sizeof(tsp2_devnamec));
        XParam->DevspDescr [ RTE_DevSpaceTrace ].Devspaces[0].lDevspaceType = RTE_DevSpaceTrace ;
    }
}

// Since Windows Runtime does not allow message voutput in a very early state, these parameter handlings
// are withdrawn from RTEConf_ReadSpecialParameters()... If knldiag is usable, this is no longer needed
extern "C" void RTEConf_HandleSpecialParametersWithMessageOutput()
{
    RTEConf_Parameter::Integer valueInt;
    RTEConf_Parameter::String valueString;
    SAPDBErr_MessageList err;

    if( (RTEConf_ParameterAccess::Instance())->GetInteger(KERNELPARAM_MEMORY_ALLOCATION_LIMIT,valueInt,err)
      && 0 != valueInt )
    {
        SAPDB_ULong oldLimit;
        RTE_ISystem::Instance().SetMemoryLimitInBytes(((SAPDB_Int)valueInt) * 1024, oldLimit);
        RTE_Message(SAPDBErr_MessageList( RTE_CONTEXT,
                                          RTEINFO_CONF_MEMORY_ALLOCATION_LIMIT,
                                          SAPDB_ToString((SAPDB_Int)valueInt)
                                        ));
    }
    else
    {
        RTE_Message(SAPDBErr_MessageList( RTE_CONTEXT,
                                          RTEINFO_CONF_MEMORY_ALLOCATION_UNLIMITED
                                        ));
    }

    if( !(RTEConf_ParameterAccess::Instance())->GetString(KERNELPARAM_USE_SYSTEM_PAGE_CACHE,valueString,err)
	  || ( *valueString == 'n' || *valueString == 'N' ) )
    {
        RTEMem_SystemPageCache::Instance().Disable();
        RTE_Message(SAPDBErr_MessageList( RTE_CONTEXT,
                                          RTEINFO_CONF_SYSTEM_PAGE_CACHE_DISABLED
                                        ));
    }
    else
    {
        RTE_Message(SAPDBErr_MessageList( RTE_CONTEXT,
                                          RTEINFO_CONF_SYSTEM_PAGE_CACHE_ENABLED
                                        ));
    }
}

static void RTEConf_ModifyParameters(RTE_XPARAM_REC *XParam)
{
    RTEConf_ParameterAccess * parameter;
    RTEConf_Parameter::Integer valueInt;
    RTEConf_Parameter::String valueString;
    SAPDBErr_MessageList err;

    XParam->ulMaxUsUtStack  <<= 10;
    
    XParam->ulPacketSize    &= ~7;
    XParam->ulMinReplySize  &= ~7;

	if ( XParam->ulDispLoopsBefSemop < 2 )
		XParam->ulDispLoopsBefSemop = 2;

    parameter = RTEConf_ParameterAccess::Instance();

    if(parameter->GetInteger(KERNELPARAM__DATA_CACHE_RGNS,valueInt,err))
    { XParam->ulNoOfRegions += (SAPDB_Int)valueInt;  }
    if(parameter->GetInteger(KERNELPARAM__TRANS_RGNS,valueInt,err))
    { XParam->ulNoOfRegions += (SAPDB_Int)valueInt;  }
    if(parameter->GetInteger(KERNELPARAM__TAB_RGNS,valueInt,err))
    { XParam->ulNoOfRegions += (SAPDB_Int)valueInt;  }
    if(parameter->GetInteger(KERNELPARAM__ROW_RGNS,valueInt,err))
    { XParam->ulNoOfRegions += (SAPDB_Int)valueInt;  }
    if(parameter->GetInteger(KERNELPARAM__OMS_RGNS,valueInt,err))
    { XParam->ulNoOfRegions += (SAPDB_Int)valueInt;  }
    if(parameter->GetInteger(KERNELPARAM_CONVERTER_REGIONS,valueInt,err))
    { XParam->ulNoOfRegions += (SAPDB_Int)valueInt;  }
    if(parameter->GetInteger(KERNELPARAM__TREE_RGNS,valueInt,err))
    { XParam->ulNoOfRegions += /* NumSplitt = NumTree */ 2 * (SAPDB_Int)valueInt; }

    if(parameter->GetString(KERNELPARAM_LOG_MODE,valueString,err))
    {
        if ( 'U' == toupper(valueString[1]) )   //log mode dUal ?
        {
            XParam->fLogMirrored = true;
        }
    }

    if( XParam->fLogMirrored )
    {
        SAPDB_ULong numberOfLogDevSpaces = XParam->DevspDescr[RTE_DevSpaceLog].ulNumDevs;
        for(SAPDB_ULong currentDevSpace = 0;currentDevSpace < numberOfLogDevSpaces;currentDevSpace++)
        {
            XParam->DevspDescr[RTE_DevSpaceMirrorLog].Devspaces[currentDevSpace].lDevspaceSize
                = XParam->DevspDescr[RTE_DevSpaceLog].Devspaces[currentDevSpace].lDevspaceSize;
        }
    }
    else
    {
        RTEMem_RteAllocator::Instance().Deallocate(XParam->DevspDescr[RTE_DevSpaceMirrorLog].Devspaces);
        XParam->DevspDescr[RTE_DevSpaceMirrorLog].Devspaces = 0;
        XParam->DevspDescr[RTE_DevSpaceMirrorLog].ulNumDevs = 0 ;
    }

    if (XParam->fMirrData)
    {
        SAPDB_Int maxSysDevspaces = 1;
        /* Still needed, but only for inplace migration... */
        if(parameter->GetInteger(KERNELPARAM__MAXSYSDEVSPACES,valueInt,err))
        {
            maxSysDevspaces = (SAPDB_Int)valueInt;
        }
        for(SAPDB_Int currentSysDevSpace = 0;currentSysDevSpace < maxSysDevspaces; currentSysDevSpace++)
        {
            XParam->DevspDescr[RTE_DevSpaceMirrorSystem].Devspaces[currentSysDevSpace].lDevspaceSize
                = XParam->DevspDescr[RTE_DevSpaceSystem].Devspaces[currentSysDevSpace].lDevspaceSize;
        }

        SAPDB_Int maxDataDevspaces = 0;
        if(parameter->GetInteger(KERNELPARAM_MAXDATAVOLUMES,valueInt,err))
        {
            maxDataDevspaces = (SAPDB_Int)valueInt;
        }
        for(SAPDB_Int currentDataDevSpace = 0;currentDataDevSpace < maxDataDevspaces;currentDataDevSpace++)
        {
            XParam->DevspDescr[RTE_DevSpaceMirrorData].Devspaces[currentDataDevSpace].lDevspaceSize
                = XParam->DevspDescr[RTE_DevSpaceData].Devspaces[currentDataDevSpace].lDevspaceSize;
        }
    }
    else
    {
        RTEMem_RteAllocator::Instance().Deallocate(XParam->DevspDescr[RTE_DevSpaceMirrorSystem].Devspaces);
        XParam->DevspDescr[RTE_DevSpaceMirrorSystem].Devspaces = 0;
        XParam->DevspDescr[RTE_DevSpaceMirrorSystem].ulNumDevs = 0;
        RTEMem_RteAllocator::Instance().Deallocate(XParam->DevspDescr[RTE_DevSpaceMirrorData].Devspaces);
        XParam->DevspDescr[RTE_DevSpaceMirrorData].Devspaces = 0;
        XParam->DevspDescr[RTE_DevSpaceMirrorData].ulNumDevs = 0 ;
    }

    if ( XParam->fForbidLoadBalancing )
    {
        XParam->uLoadBalancingCheck = 0;
    }
    else if (( XParam->uLoadBalancingCheck != 0) && (XParam->uLoadBalancingCheck < 2 ))
    {
        XParam->uLoadBalancingCheck = 2;
    }

#ifndef WIN32
    /* http://pts:1080/webpts?wptsdetail=yes&ErrorType=1&ErrorID=1132876 */
         if ( 0 == SAPDB_strcasecmp(XParam->szVectorIoMode.asCharp(), "NEVER") )
    {
        XParam->simulateVectorIo = RTE_SimVioNever;
    }
    else if ( 0 == SAPDB_strcasecmp(XParam->szVectorIoMode.asCharp(), "IF_OPEN_DIRECT") )
    {
        XParam->simulateVectorIo = RTE_SimVioIfOpenDirect;
    }
    else if ( 0 == SAPDB_strcasecmp(XParam->szVectorIoMode.asCharp(), "IF_RAW_DEVICE") )
    {
        XParam->simulateVectorIo = RTE_SimVioIfRawDevice;
    }
    else if ( 0 == SAPDB_strcasecmp(XParam->szVectorIoMode.asCharp(), "IF_OPEN_DIRECT_OR_RAW_DEVICE") )
    {
        XParam->simulateVectorIo = RTE_SimVioIfOpenDirectOrRawDevice;
    }
    else if ( 0 == SAPDB_strcasecmp(XParam->szVectorIoMode.asCharp(), "ALWAYS") )
    {
        XParam->simulateVectorIo = RTE_SimVioAlways;
    }
    else
    {
#if defined(LINUX)
        SAPDB_strcpy(XParam->szVectorIoMode.asCharp(), "IF_OPEN_DIRECT_OR_RAW_DEVICE");
        XParam->simulateVectorIo = RTE_SimVioIfOpenDirectOrRawDevice;
#else
        SAPDB_strcpy(XParam->szVectorIoMode.asCharp(), "NEVER");
        XParam->simulateVectorIo = RTE_SimVioNever;
#endif
    }
#endif
}

//----

void RTEConf_AddParameterToParameterList(RTEConf_ParameterNameValuePair *&pList, SAPDB_Char *name, SAPDB_Char *value)
{
    RTEConf_ParameterNameValuePair *pNewEntry = new ( RTEMem_RteAllocator::Instance() ) 
                                RTEConf_ParameterNameValuePair(name, value);
    if ( !pNewEntry )
    {
        return; /* out of memory ignored */
    }

    RTEConf_ParameterNameValuePair *pLast = pList;
    for ( RTEConf_ParameterNameValuePair *pSearch = pList; pLast && pSearch; pSearch = pSearch->GetNext() )
    {
        pLast = pSearch;

        switch ( pSearch->NameCompare(name) )
        {
        case 0:
            /* doubled entry ignored!!!! */
            destroy(pNewEntry, RTEMem_RteAllocator::Instance());
            pLast = 0;
            break;
        case 1:
            pNewEntry->Enqueue(pSearch->GetPrev(), pSearch);
            pLast = 0;
            break;
        default:
            break;
        }
    }

    if ( pNewEntry )
    {
        if ( pLast )
        {
            pNewEntry->Enqueue(pLast, 0);
        }

        if ( 0 == pNewEntry->GetPrev() )
        {
            pList = pNewEntry; /* if new header, set it as new header */
        }
    }
}

//----

void RTEConf_DumpParameterList(RTEConf_ParameterNameValuePair *pList)
{
    RTEConf_ParameterNameValuePair *pNext;
    for ( RTEConf_ParameterNameValuePair *pEntry = pList; pEntry; pEntry = pNext )
    {
        pNext = pEntry->GetNext();
        pEntry->Show();
        destroy(pEntry, RTEMem_RteAllocator::Instance());
    }
}

//----

externC SAPDB_Bool RTEConf_ReadAndAnalyzeParam ( tsp00_DbNamec VAR_ARRAY_REF    ServerDB,
                                                 RTE_XPARAM_REC                 *XParam ,
                                                 SAPDBErr_MessageList           &err)
{
    RTEConf_ParameterNameValuePair *pList = 0; 
    memset (XParam, 0, sizeof(RTE_XPARAM_REC) );

    /* --- Set XPARAM default values */
    RTEConf_InitParam ( XParam );

    RTE_Message( SAPDBErr_MessageList(RTE_CONTEXT, RTEINFO_BEGIN_OF_STARTUP_ARGUMENTS) );

    /* read the special parameters other parameters depend on (MAXARCHIVELOGS etc.) */
    RTEConf_ReadSpecialParameters(XParam);

    RTEConf_ParameterReader paramReader;
    paramReader.StartIteration();

    RTEConf_Parameter::Name name;
    RTEConf_Parameter::Type type;
    RTEConf_ParameterValueRecord valueRec;
    while(paramReader.Next(name,type,err))
    {
        switch (type)
        {
        case RTEConf_Parameter::t_Integer:
        {
            RTEConf_Parameter::Integer value;
            RTEConf_ParameterAccess::Instance()->GetInteger(name,value,err);
            RTEConf_AddParameterToParameterList(pList, (SAPDB_Char *)name, SAPDB_ToString( (SAPDB_Int4)value ));
            valueRec.xp_value_t = NXP_INT_TYPE;
            valueRec.xp_type.xp_integer = (SAPDB_Int4)value;
            break;
        }
        case RTEConf_Parameter::t_Real:
            break;
        case RTEConf_Parameter::t_String:
        {
            RTEConf_Parameter::String value;
            RTEConf_ParameterAccess::Instance()->GetString(name,value,err);
            RTEConf_AddParameterToParameterList(pList, (SAPDB_Char *)name, (SAPDB_Char *)value );
            valueRec.xp_value_t = NXP_STRING_TYPE;
            valueRec.xp_type.xp_string = value;
            break;
        }
        case RTEConf_Parameter::t_CryptInfo:
        {
            RTEConf_Parameter::CryptInfo value;
            RTEConf_ParameterAccess::Instance()->GetCryptInfo(name,value,err);
            RTEConf_AddParameterToParameterList(pList, (SAPDB_Char *)name, (SAPDB_Char *)"***" );
            valueRec.xp_value_t = NXP_CRYPT_TYPE;
            memcpy(valueRec.xp_type.xp_crypt,(SAPDB_Byte *)value,sizeof(RTEConf_Parameter::CryptInfo));
            break;
        }
        default:
            continue;
        }
        err.ClearMessageList();
        if(!RTEConf_AnalyzeParam ( XParam , name , &valueRec ,false, err))
        {
            return false;
        }
    }

    RTEConf_DumpParameterList(pList);

    RTE_Message( SAPDBErr_MessageList(RTE_CONTEXT, RTEINFO_END_OF_STARTUP_ARGUMENTS) );

    RTEConf_ModifyParameters(XParam);

    if(!(err.IsEmpty() || SAPDBErr_MessageList::Info == err.Type()) || !(paramReader.EndIteration(err)))
    {
        return false;
    }
    else
    {
        return true;
    }
}

/* This routine should only be used in ( .c ) modules that cannot handle Msg_Lists */

externC SAPDB_Bool RTEConf_ReadAndAnalyzeParamWithOutput ( tsp00_DbNamec VAR_ARRAY_REF    ServerDB,
                                                            RTE_XPARAM_REC                 *XParam )
{
    SAPDBErr_MessageList errList;
    SAPDB_Bool returnValue = RTEConf_ReadAndAnalyzeParam( ServerDB, XParam, errList );
    if(!returnValue)
    {
        RTE_Message(errList);
    }
    return returnValue;
}


externC void   RTEConf_FreeTaskClusterArrayInXParamStructure( RTE_XPARAM_REC *XParam)
{
    SAPDBTRACE_ROUTINE_DEBUG("RTEConf_FreeTaskClusterArrayInXParamStructure", Runtime_Trace, 5);

    if ( XParam->TaskClusterArray != NULL )
    {
        int i ;
        for ( i=0; XParam->TaskClusterArray[ i ] ; i++ )
        {
            RTEMem_RteAllocator::Instance().Deallocate ( XParam->TaskClusterArray[ i ] ) ;
        }
        RTEMem_RteAllocator::Instance().Deallocate ( XParam->TaskClusterArray ) ;
    }
}

externC void RTEConf_FreeDevDescrInXParamStructure( RTE_XPARAM_REC *XParam,int idx )
{
    SAPDBTRACE_ROUTINE_DEBUG("RTEConf_FreeDevDescrInXParamStructure", Runtime_Trace, 5);

    RTEMem_RteAllocator::Instance().Deallocate(XParam->DevspDescr[idx].Devspaces);
}

static void  RTEConf_CopyStringOutOfValueRecord ( unsigned char *s, RTEConf_ParameterValueRecord * xpr ,size_t sizeOfDestinationArea )

{
    size_t lengthOfSourceString = strlen((char *)xpr->xp_type.xp_string);
    if( lengthOfSourceString > sizeOfDestinationArea)
    {
        MessageAndCrash(SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_CONF_NOT_ENOUGH_SPACE_FOR_STRING_PARAM,SAPDB_ToString(sizeOfDestinationArea),SAPDB_ToString(lengthOfSourceString)));
    }
    if ( NXP_STRING_TYPE != xpr->xp_value_t  )
    {
        MessageAndCrash(SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_CONF_TYPE_MISMATCH,SAPDB_ToString(xpr->xp_value_t),SAPDB_ToString(NXP_STRING_TYPE)));
    }

    strncpy  ((char *) s , (char *)xpr->xp_type.xp_string , lengthOfSourceString + 1 );
}

static inline void *AllocateMemory(size_t size)
{
    void *adr = RTEMem_RteAllocator::Instance().Allocate(size);
    if(!adr)
    {
        SAPDB_Char sizeString[256];
        SAPDB_sprintf(sizeString,256,"%d bytes",size);
        MessageAndCrash(SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_ALLOCATION_FAILED,sizeString)); 
    }
    return adr;
}

static SAPDB_Bool RTEConf_AnalyzeParam ( RTE_XPARAM_REC                 *XParam  ,
                                         RTEConf_Parameter::Name        name ,
                                         RTEConf_ParameterValueRecord   *xpr ,
                                         SAPDB_Bool                     inOnlineMode,
                                         SAPDBErr_MessageList           &err)
{
    SAPDBTRACE_ROUTINE_DEBUG("RTEConf_AnalyzeParam", Runtime_Trace, 5);
    SAPDB_Bool fOk = true;
    SAPDB_Int4 which;
    RTEConf_Parameter::String valueString = xpr->xp_type.xp_string;
    struct xparam_strcmp_table *pE;

	which = RTEConf_FindParam(name, xpr,err);
	if ( which < 0 )
	{
        if(inOnlineMode)
        {
            return false;
        }
        else
        {
/*IST on request of Juergen Primsch 1993-01-05: suppress this warning */
            SAPDB_UInt8 lengthOfMessage = (SAPDB_UInt8)strlen((SAPDB_Char *)name) + strlen(UNKNOWN_PARAMETER_MESSAGE) + 1;
            SAPDB_Char *message = (SAPDB_Char *)alloca((int)lengthOfMessage);
            SAPDB_sprintf(message,(int)lengthOfMessage,UNKNOWN_PARAMETER_MESSAGE"%s",(SAPDB_Char *)name);
            SAPDBTRACE_WRITELN (Runtime_Trace, 1, message);
            return true;
        }
	}

	if ( which < RTE_NUMBER_OF_ELEMENTS_IN_XPARAM_TABLE1 )
	{
		struct xparam_strncmp_table *pN;
        SAPDB_UInt2 indexOfElement;

		pN = &RteXparamTable1[which];

        indexOfElement = atoi( (SAPDB_Char *)name + pN->len + 1 ) - 1;

		switch( pN->type )
		{
		case XP_V_SET_TASKCLUSTER:
            RTEConf_SetTaskCluster( XParam, xpr->xp_type.xp_string, indexOfElement ) ;
            // if anything had gone wrong, RTEConf_SetTaskCluster() would have called RTE_Crash()...
            break;

		case XP_V_SET_DEVSP_NAME:
            fOk = RTEConf_SetDevspName ( XParam, name, xpr, pN->dt, indexOfElement ,err);
			break;

        case XP_V_SET_M_DEVSP_NAME:
            fOk = RTEConf_SetDevspName ( XParam, name, xpr, pN->mdt, indexOfElement ,err);
			break;

        case XP_V_SET_DEVSP_SIZE:
			fOk = RTEConf_SetDevspSize ( XParam, pN->dt,
									indexOfElement, (SAPDB_Int)RTEConf_XParamInt ( xpr ,err) ) ;
			break;

        case XP_V_SET_VOLUME_MODE:
            fOk = RTEConf_SetVolumeMode ( XParam, (SAPDB_Char *)xpr->xp_type.xp_string, indexOfElement ,err);
			break;
        case XP_V_SET_HS_NODE_NAME:
            fOk = (RTEConf_ParameterAccess::Instance())->AddHssNode((SAPDB_Char *)valueString,indexOfElement);
            if(!fOk)
                MessageAndCrash(SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_INVALID_NODE_NAME_ENTRY,(SAPDB_Char *)name,(SAPDB_Char *)valueString ));
			break;
        case XP_V_SET_FILE_SYSTEM_ACCESS_TYPE:
             fOk = RTEConf_SetFileSystemAccessType ( XParam,
                                                     pN->dt, 
                                                     (SAPDB_Char *)xpr->xp_type.xp_string,
                                                     indexOfElement,
                                                     err);
   			break;
   
        default:
            break;
        }
	}
	else
	{

		/*
		 * Reduced to offset into RteXparamTable2
		 */
		which -= RTE_NUMBER_OF_ELEMENTS_IN_XPARAM_TABLE1;
		pE = &RteXparamTable2[which];

        switch( pE->type )
		{
		case XP_V_BOOL_Y:
			*(tsp00_Bool *)XP_PTR(XParam, pE) =
					(tsp00_Bool)( *valueString == 'y' || *valueString == 'Y' );
			break;

		case XP_V_BOOL_N:
			*(tsp00_Bool *)XP_PTR(XParam, pE) =
					(tsp00_Bool)( *valueString == 'n' || *valueString == 'N' );
			break;

		case XP_V_BOOL_A:
			*(tsp00_Bool *)XP_PTR(XParam, pE) =
					(tsp00_Bool)( *valueString == 'a' || *valueString == 'A' );
			break;

		case XP_V_BOOL_S:
			*(tsp00_Bool *)XP_PTR(XParam, pE) =
					(tsp00_Bool)( *valueString == 's' || *valueString == 'S' );
			break;

		case XP_V_LONG:
			*(tsp00_Int *)XP_PTR(XParam, pE) = (tsp00_Int)RTEConf_XParamInt( xpr , err);
			break;

		case XP_V_ULONG:
			*(tsp00_Uint *)XP_PTR(XParam, pE) = (tsp00_Uint)RTEConf_XParamInt( xpr ,err);
			break;

        case XP_V_STRING:
            RTEConf_CopyStringOutOfValueRecord (  XP_PTR(XParam, pE), xpr, pE->size);
            break;

		case XP_V_CRYPT:
			COPY ( XP_PTR(XParam,pE), xpr->xp_type.xp_crypt , pE->size ) ;
			break;

		case XP_V_IGNORED:
			break;

        case XP_V_SPECIAL_LONG:
			*(tsp00_Int *)XP_PTR(XParam, pE) = (tsp00_Int)RTEConf_XParamInt( xpr ,err);
			/* Currently, there are no special longs */
            break;

        case XP_V_SPECIAL_ULONG:
			*(tsp00_Uint *)XP_PTR(XParam, pE) = (tsp00_Uint)RTEConf_XParamInt( xpr ,err);
            break;

		case XP_V_SPECIAL_STRING:
            break;
        case XP_V_SPECIAL_SPECIAL:
			break;

		default:
			break;
		}
	}
    return fOk;
}

/*
 * ===========================================================================
 */

static  SAPDB_Bool RTEConf_SetDevspSize ( RTE_XPARAM_REC            *XParam,
                                          SAPDB_Long                lDevType ,
                                          SAPDB_ULong               ulDevspNo ,
                                          SAPDB_Int                 ulDevspSize )
{
    SAPDBTRACE_ROUTINE_DEBUG("RTEConf_SetDevspSize", Runtime_Trace, 5);

    SAPDB_Bool fOk ;

    if ( ulDevspSize == 0 )
        return ( TRUE ) ;

    if ( ( fOk = XParam->DevspDescr [ lDevType ]. ulNumDevs > ulDevspNo ) )
    { 
        DEV_DESCR *ActDevsp = XParam->DevspDescr[lDevType].Devspaces + ulDevspNo;
        ActDevsp->lDevspaceSize = ulDevspSize ;
    }
    else
    { 
        MessageAndCrash(SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_XP_TOO_MANY_DEVSPACES, szDevType[lDevType] ,SAPDB_ToString(XParam->DevspDescr [ lDevType ]. ulNumDevs )));
    }

    return (fOk) ;
}

/*
 * ===========================================================================
 */

static  SAPDB_Bool RTEConf_SetVolumeMode ( RTE_XPARAM_REC           *XParam,
                                           SAPDB_Char               *szAccessMode,
                                           SAPDB_ULong               ulDevspNo,
                                           SAPDBErr_MessageList     &err)
{
    SAPDBTRACE_ROUTINE_DEBUG("RTEConf_SetVolumeMode", Runtime_Trace, 5);

    SAPDB_Bool fOk ;
    if ( ( fOk = XParam->DevspDescr [ RTE_DevSpaceData ]. ulNumDevs > ulDevspNo ) )
    { 
        DEV_DESCR *ActDevsp = XParam->DevspDescr[RTE_DevSpaceData].Devspaces + ulDevspNo;
        int iMode;
        
        for ( iMode = 0; accessModeList[iMode].accessModeName; iMode++ )
        {
            if ( 0 == strncmp( szAccessMode,
                               accessModeList[iMode].accessModeName,
                               strlen(accessModeList[iMode].accessModeName)) )
            {
                ActDevsp->accessMode = accessModeList[iMode].accessMode;
                RTE_Message(SAPDBErr_MessageList(RTE_CONTEXT,RTEINFO_CONF_DATA_VOLUME_MODE, SAPDB_ToString(szAccessMode), SAPDB_ToString(ulDevspNo+1)));
                return fOk;
            }
        }

        RTE_Message(SAPDBErr_MessageList(RTE_CONTEXT,RTEWARN_CONF_UNKNOWN_VOLUME_ACCESS_MODE, SAPDB_ToString(szAccessMode), SAPDB_ToString(ulDevspNo+1)));
    }
    else
    { 
        MessageAndCrash(SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_XP_TOO_MANY_DEVSPACES, szDevType[RTE_DevSpaceData] ,SAPDB_ToString(XParam->DevspDescr [ RTE_DevSpaceData ]. ulNumDevs )));
    }

    return (fOk) ;
}

/*
 * ===========================================================================
 */

static  void   RTEConf_SetTaskCluster( RTE_XPARAM_REC            *XParam,
                                       RTEConf_Parameter::String szTaskCluster,
                                       SAPDB_ULong               ulTCNo )
{
    SAPDBTRACE_ROUTINE_DEBUG("RTEConf_SetTaskCluster", Runtime_Trace, 5);

    size_t TaskClusterLen = STRLEN_UTF8( szTaskCluster ) + 1;

    if ( XParam->TaskClusterArray == NULL )
    {
        XParam->TaskClusterArray = (char **)RTEMem_RteAllocator::Instance().Allocate(MAX_TASKCLUSTER_PARTS * sizeof ( char * ) );
        if ( 0 == XParam->TaskClusterArray)
        {
            MessageAndCrash(SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_MALLOC_FAILED_FOR,"set TASKCLUSTER" ));
        }
        else
        {
            memset ( XParam->TaskClusterArray, 0,
                MAX_TASKCLUSTER_PARTS * sizeof ( char * ) ) ;
        }
    }

    if (ulTCNo >= MAX_TASKCLUSTER_PARTS-1 )
    { 
        MessageAndCrash(SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_XP_TOO_MANY_TASKCLUSTER,SAPDB_ToString(ulTCNo),SAPDB_ToString(MAX_TASKCLUSTER_PARTS)));
    } 
    XParam->TaskClusterArray[ulTCNo] = (char *)RTEConf_MakeACopyOfString(szTaskCluster);
}

/*
 * ===========================================================================
 */

static SAPDB_Bool RTEConf_SetFileSystemAccessType  ( RTE_XPARAM_REC *XParam,
                                             SAPDB_Long                lDevType ,
                                             SAPDB_Char               *szFileSystemAccessType,
                                             SAPDB_ULong               ulDevspNo ,
                                             SAPDBErr_MessageList     &err)
{
    SAPDBTRACE_ROUTINE_DEBUG("RTEConf_SetVolumeMode", Runtime_Trace, 5);

    SAPDB_Bool fOk ;

    if ( ( fOk = XParam->DevspDescr [ lDevType ]. ulNumDevs > ulDevspNo ) )
    {
        DEV_DESCR *ActDevsp = XParam->DevspDescr[lDevType].Devspaces + ulDevspNo;
        if('F' == toupper(*szFileSystemAccessType) )
        {
             ActDevsp->sizeLimitedByUlimit = true;
        }
    }
    else
    {
        MessageAndCrash(SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_XP_TOO_MANY_DEVSPACES, szDevType[lDevType] ,SAPDB_ToString(XParam->DevspDescr [ lDevType ]. ulNumDevs )));
    }

    return (fOk) ;
}

/*
 * ===========================================================================
 */

static void RTEConf_InitParam ( RTE_XPARAM_REC *XParam  )
{
  SAPDBTRACE_ROUTINE_DEBUG("RTEConf_InitParam", Runtime_Trace, 5);

  /* All parameters not set here are automatically set to 0 / FALSE */

  XParam->ulRegLockSlice        = MAX_EXCLUSIVE;
  XParam->ulDispLoopsBefSemop   = MIN_DISP_LOOPS;
  XParam->fExclQueue            = TRUE;
  XParam->lPrioBaseU2U          = 100;
  XParam->lPrioBaseRAV          = 80;
  XParam->lPrioBaseIOC          = 80;
  XParam->lPrioBaseCOM          = 10;
  XParam->lPrioBaseREX          = 40;
  XParam->lPrioFactor           = 80;
  XParam->ulMultIOBlockCount    = 8;
  XParam->fFormatDataVolume     = TRUE;
  XParam->ulMaxCPU              = 1;

  XParam->ulMaxEvents           = 100;
  XParam->ulMaxMessageFiles     = 5;

/***************************************************************/
#if defined(_WIN32)
/***************************************************************/
#if defined ( DYNAMIC_SERVER )
   XParam->fDynamicServerTasks  = TRUE;
#endif

  XParam->fUseMemEnhancement    = FALSE;
  XParam->lMemEnhancementLimit  = 0;
  XParam->fUseFibers            = TRUE;
  XParam->fUseAsyncIO           = 1;
  XParam->fUseWinSecurDesc      = 1;

/***************************************************************/
#else
/***************************************************************/
#ifdef OSF1
  XParam->fUseAsyncIO           = 1 ;
#endif
/***************************************************************/
#endif
/***************************************************************/

  XParam->ulDBPageSize          = sizeof ( tsp00_Page ) ; /* XXX default value, overwritten by XParam... Will detect if tsp00_Page is really gone.. */
  XParam->ulNoOfRegions         = MAX_REGIONS ;

  XParam->memorySlotSize        = 1; /* 1 MB memory slot size */

  /* Specify fastest allocation on the system */
#if defined(_WIN32)
  XParam->vallocMemPoolSize     = -1; /* Use valloc allocated memory */
#elif defined(HPUX)
  XParam->shmMemPoolSize        = -1; /* Use 'SYSV IPC Shm' allocated memory */
#else /* all other UNIX */
  XParam->mmapMemPoolSize       = -1; /* Use mmap allocated memory */
#endif

  XParam->allowDemangle         = true;

  return;
}

static  void    RTEConf_AllocDevspDescr ( RTE_XPARAM_REC         *XParam,
                                          SAPDB_Long             lDevspType,
                                          SAPDB_Int              ulNumDevsp)
{
    SAPDBTRACE_ROUTINE_DEBUG("RTEConf_AllocDevspDescr", Runtime_Trace, 5);

    SAPDB_Int i ;
    
    XParam->DevspDescr[lDevspType].Devspaces = (struct dev_descr *)RTEMem_RteAllocator::Instance().Allocate(ulNumDevsp * sizeof ( DEV_DESCR ) );
    if(0 == XParam->DevspDescr[lDevspType].Devspaces )
    {
        MessageAndCrash(SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_MALLOC_FAILED_FOR,"DEVSPACE_DESCR" ));
    }

    for ( i=0; i < ulNumDevsp; i++ )
    {
        XParam->DevspDescr[lDevspType].Devspaces[i].lDevspaceType = DEVSPACE_UNUSED;
        XParam->DevspDescr[lDevspType].Devspaces[i].physicalDevID = RTE_UNDEF_ID;
        XParam->DevspDescr[lDevspType].Devspaces[i].accessMode    = RTE_VolumeAccessModeNormal;
        XParam->DevspDescr[lDevspType].Devspaces[i].sizeLimitedByUlimit = false;
    }

    XParam->DevspDescr[lDevspType].ulNumDevs = ulNumDevsp ;
}

/*
 * ===========================================================================
 */

static  SAPDB_Bool RTEConf_SetDevspName ( RTE_XPARAM_REC                  *XParam,
                                          RTEConf_Parameter::Name         DevspName ,
                                          RTEConf_ParameterValueRecord    *xpr ,
                                          SAPDB_Int                       lDevType ,
                                          SAPDB_ULong                     ulDevspNo ,
                                          SAPDBErr_MessageList            &err)
{
    SAPDBTRACE_ROUTINE_DEBUG("RTEConf_SetDevspName", Runtime_Trace, 5);

    SAPDB_Bool fOk ;

    RTEConf_Parameter::String szDevName = xpr->xp_type.xp_string;
    if ( szDevName[0] == '\0' )
    {
        fOk = FALSE;
    }
    else
    {
        fOk = RTEConf_CheckDuplicateDevSpaceName( XParam->DevspDescr, (SAPDB_Char *)szDevName, err );

        if ( fOk )
        {
            if (( fOk = XParam->DevspDescr [ lDevType ]. ulNumDevs > ulDevspNo ))
            {
                DEV_DESCR *ActDevsp = XParam->DevspDescr[lDevType].Devspaces + ulDevspNo;
                size_t count = strlen((const char*) szDevName);
                if (count > sizeof(tsp2_devname)) {
                    memcpy (ActDevsp->szDevspaceName, szDevName, sizeof(tsp2_devname));
                    ActDevsp->szDevspaceName[sizeof(tsp2_devname)] = 0;
                } else {
                    memcpy (ActDevsp->szDevspaceName, szDevName, count + 1);
                }
                ActDevsp->lDevspaceType = lDevType ;
            }
            else
            {
                MessageAndCrash(SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_XP_TOO_MANY_DEVSPACES, szDevType[lDevType] ,SAPDB_ToString(XParam->DevspDescr [ lDevType ]. ulNumDevs )));
            }
        }
        else
        {
            err = err + SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_CONF_ERROR_IN_VOLUME_DEFINTION,
                SAPDB_ToString((RTE_DevSpaceType)lDevType),
                SAPDB_ToString(ulDevspNo+1));
        }
    }
    return (fOk) ;
}

static RTEConf_Parameter::Integer  RTEConf_XParamInt ( RTEConf_ParameterValueRecord  *xpr ,SAPDBErr_MessageList &err)
{
    SAPDBTRACE_ROUTINE_DEBUG("RTEConf_XParamInt", Runtime_Trace, 5);

    if ( NXP_INT_TYPE  == xpr->xp_value_t )
    {
        return ( xpr->xp_type.xp_integer );
    }
    else
    {
   		err = SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_ILLEGAL_XP_TYPE, SAPDB_ToString( xpr->xp_value_t ));
        return ( -1 );
    }

}

/*
 * Search parameter in table and return index if found. -1 if not found
 * The returned index can be used as index into RteXparamTable1.
 */
static SAPDB_Int4 RTEConf_FindParam( RTEConf_Parameter::Name             name ,
                                     RTEConf_ParameterValueRecord        *xpr ,
                                     SAPDBErr_MessageList                &err)
{
    SAPDBTRACE_ROUTINE_DEBUG("RTEConf_FindParam", Runtime_Trace, 5);

    SAPDB_Int4 which;

	/*
     * First entry is special! All other are compared with strcmp()...
     */
	for ( which = 0; which < RTE_NUMBER_OF_ELEMENTS_IN_XPARAM_TABLE1; which ++ )
	{
		struct xparam_strncmp_table *pN;

		pN = &RteXparamTable1[which];
		if ( !STRNCMP_UTF8(name, pN->name, pN->len) )
		{
          if ( xpr )
			switch( pN->type )
            {
			case XP_V_SET_TASKCLUSTER:
			case XP_V_SET_DEVSP_NAME:
			case XP_V_SET_M_DEVSP_NAME:
			case XP_V_SET_VOLUME_MODE:
                if( NXP_STRING_TYPE != xpr->xp_value_t )
                {
   		            err = SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_ILLEGAL_XP_TYPE, SAPDB_ToString(  xpr->xp_value_t));
					which = -1;
				}
				break;

			case XP_V_SET_DEVSP_SIZE:
                if( NXP_INT_TYPE != xpr->xp_value_t )
                {
   		            err = SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_ILLEGAL_XP_TYPE, SAPDB_ToString( xpr->xp_value_t ));
					which = -1;
				}
				break;
			}
			return which;
		}
	}

    for ( which = 0; which < RTE_NUMBER_OF_ELEMENTS_IN_XPARAM_TABLE2; which++ )
	{
		struct xparam_strcmp_table *pE;
		pE = &RteXparamTable2[which];

        if ( !STRNCMP_UTF8( name, pE->name, STRLEN_UTF8(pE->name) ) )
		{
          if ( xpr )
			switch( pE->type )
			{
			case XP_V_LONG:
			case XP_V_ULONG:
			case XP_V_REGIONS:
			case XP_V_SPECIAL_LONG:
			case XP_V_SPECIAL_ULONG:
                if( NXP_INT_TYPE != xpr->xp_value_t )
                {
   		            err = SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_ILLEGAL_XP_TYPE ,SAPDB_ToString( xpr->xp_value_t ));
					which = -1;
				}
                break;

			case XP_V_BOOL_Y:
			case XP_V_BOOL_N:
			case XP_V_BOOL_A:
			case XP_V_BOOL_S:
			case XP_V_STRING:
			case XP_V_SPECIAL_STRING:
                if( NXP_STRING_TYPE != xpr->xp_value_t )
                {
   		            err = SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_ILLEGAL_XP_TYPE ,SAPDB_ToString( xpr->xp_value_t ));
					which = -1;
				}
				break;

			case XP_V_IGNORED:
			case XP_V_SPECIAL_SPECIAL:
				break;

			case XP_V_CRYPT:
                if( NXP_CRYPT_TYPE != xpr->xp_value_t )
                {
   		            err = SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_ILLEGAL_XP_TYPE, SAPDB_ToString( xpr->xp_value_t ));
					which = -1;
				}
				break;

			default:
				which = -1;
				break;
			}
			break;
		}
	}

	if ( which == RTE_NUMBER_OF_ELEMENTS_IN_XPARAM_TABLE2 )
	{
        err = SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_XP_UNKNOWN_PARAM,(SAPDB_Char *)(name));
		which = -1;
	}

	/*
	 * Add number of elements in first table (subtracted in analyze_param...
	 */
	if ( which >= 0 )
	{
		which += RTE_NUMBER_OF_ELEMENTS_IN_XPARAM_TABLE1;
	}

	return which;
}


/*!--------------------------------------------------------------------
   @description    Compare the fully expanded file paths of two given file names
   @param          pFileName1 [in] pointer to the first file name
   @param          pFileName2 [in] pointer to the second file name
   @return value   true if the expanded file paths are the same, false if not

 --------------------------------------------------------------------*/

static SAPDB_Bool RTEConf_FullPathsOfFilenamesAreEqual( SAPDB_Char *pFileName1,SAPDB_Char *pFileName2 )
{
    SAPDB_Char *pFilePath1;
    SAPDB_Char *pFilePath2;
#if defined (_WIN32)
    SAPDB_UInt4 bytesNeeded = GetFullPathName( pFileName1,0,NULL,NULL ); // this call returns the number of bytes needed for the full path
    if ( 0 != bytesNeeded )
    {
        pFilePath1 = (SAPDB_Char *)alloca(bytesNeeded);
        bytesNeeded = GetFullPathName( pFileName1,bytesNeeded,pFilePath1,NULL );
    }
    if ( 0 == bytesNeeded ) // bytesNeeded = 0 means that something went wrong (unlikely), so take the base name
    {
        pFilePath1 = pFileName1;
    }

    bytesNeeded = GetFullPathName( pFileName2,0,NULL,NULL ); // this call returns the number of bytes needed for the full path
    if ( 0 != bytesNeeded ) 
    {
        pFilePath2 = (SAPDB_Char *)alloca(bytesNeeded);
        bytesNeeded = GetFullPathName( pFileName2,bytesNeeded,pFilePath2,NULL );
    }
    if ( 0 == bytesNeeded )// bytesNeeded = 0 means that something went wrong (unlikely), so take the base name
    {
        pFilePath2 = pFileName2;
    }

    return ( 0 == _stricmp( pFilePath1, pFilePath2 ) );
#else
    struct stat stat1;
    struct stat stat2;

    SAPDB_Bool match = false;
    if( (0 == RTE_save_stat(pFileName1,&stat1)) && (0 == RTE_save_stat(pFileName2,&stat2)) )
    {
        if( stat1.st_mode == stat2.st_mode) // st_mode tells if the object represented by name is a device or a file or...
        {                                   // if the st_mode fields do not match, the two objects are not the same
            if( S_ISBLK( stat1.st_mode ) || S_ISCHR( stat1.st_mode ) )
            {
                if( stat1.st_rdev == stat2.st_rdev )    // for two devices that are the same, the st_rdev fields match
                {
                    match = true;                
                }
            }
            else
            {
                if( (stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino) )  // for two regular files that are the same, the st_dev and st_ino fields match
                {
                    match = true;                
                }
            }
        }
    }
    return match;
#endif
}

/*****************************************************************************/
/*                                                                           */
/*                                                                           */
/*                       class RTEConf_ParameterAccess                       */
/*                                                                           */
/*                                                                           */
/*****************************************************************************/

/*---------------------------------------------------------------------------*/

RTEConf_ParameterAccess *RTEConf_ParameterAccess::m_Instance=NULL;

/*---------------------------------------------------------------------------*/

void RTEConf_ParameterReader::StartIteration(void)
{
    m_NumberBuffer = ALLOCATE_ARRAY(SAPDB_Char,SIZE_OF_NUMBER_BUFFER_);
    m_Iterator = new RTEConf_ParameterIterator(*(RTEConf_ParameterAccess::Instance())->m_Conf_Parameter);
}

/*---------------------------------------------------------------------------*/

SAPDB_Bool RTEConf_ParameterReader::EndIteration(SAPDBErr_MessageList &err)
{
	if(NULL == m_Iterator)
	{
        err = SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_ITERATION_HAD_NOT_BEEN_STARTED);
        return false;
	}
    else
    {
		DEALLOCATE_MEMORY(m_NumberBuffer);
		delete m_Iterator;
		m_Iterator = NULL;
		return true;
	}
}

/*---------------------------------------------------------------------------*/

SAPDB_Bool RTEConf_ParameterReader::Next(RTEConf_Parameter::Name &parameterName,SAPDB_Char *&valueString,SAPDBErr_MessageList &err)
{
	if(NULL == m_Iterator)
	{
        err = SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_ITERATION_HAD_NOT_BEEN_STARTED);
        return false;
	}
    else
    {
		RTEConf_Parameter::Type parameterType;
		SAPDB_Bool endOfListReached;
        SAPDBErr_MessageList err;
		while(m_Iterator->Next(parameterName,parameterType,endOfListReached,err))	
		/* this is done in a loop, because it is possible that the Iterator::Next() gives elements that are actually not in the parameter set anymore 
           (this happens when elements are Delete()d after the construction of the iterator. If such an element is detected, the next element is searched */
		{
			switch(parameterType)
			{
			case RTEConf_Parameter::t_String:
				{
					RTEConf_Parameter::String stringValue;
					if((RTEConf_ParameterAccess::Instance())->GetString(parameterName,stringValue,err))
					{
						valueString = (SAPDB_Char *)stringValue;
						return true;
					}
				}
				break;
			case RTEConf_Parameter::t_Integer:
				{
					RTEConf_Parameter::Integer integerValue;
					if((RTEConf_ParameterAccess::Instance())->GetInteger(parameterName,integerValue,err))
					{
						SAPDB_sprintf(m_NumberBuffer,SIZE_OF_NUMBER_BUFFER_,"%qd",integerValue);
						valueString = m_NumberBuffer;
						return true;
					}
				}
				break;
			case RTEConf_Parameter::t_Real:
				{
					RTEConf_Parameter::Real realValue;
					if((RTEConf_ParameterAccess::Instance())->GetReal(parameterName,realValue,err))
					{
						SAPDB_sprintf(m_NumberBuffer,SIZE_OF_NUMBER_BUFFER_,"%f",realValue);
						valueString = m_NumberBuffer;
						return true;
					}
				}
				break;
			case RTEConf_Parameter::t_CryptInfo:
				valueString = (SAPDB_Char *)"";
				return true;
				break;
			}
		}
	}
	return false;
}

/*---------------------------------------------------------------------------*/

SAPDB_Bool RTEConf_ParameterReader::Next(RTEConf_Parameter::Name &parameterName,RTEConf_Parameter::Type &parameterType,SAPDBErr_MessageList &err)
{
	if(NULL == m_Iterator)
	{
        err = SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_ITERATION_HAD_NOT_BEEN_STARTED);
        return false;
	}
    else
	{
		SAPDB_Bool endOfListReached;
		return m_Iterator->Next(parameterName,parameterType,endOfListReached,err);
	}
}

/*---------------------------------------------------------------------------*/

RTEConf_ParameterAccess *RTEConf_ParameterAccess::Instance(void)
{
    if(NULL == m_Instance)
    {
        SAPDB_Char *dbName;
#ifdef _WIN32
        dbName = kgs.szServerDB;
#else
        dbName = en81_dbname;
#endif
        if(dbName[0])
            m_Instance = new RTEConf_ParameterAccess(dbName);
    }
    return m_Instance;
}

/*---------------------------------------------------------------------------*/
#define FORMAT_STRING_FOR_FORMAT_STRING "%%s%%0%dd"
#define NUMBER_OF_DOUBLED_PERCENTS      2

SAPDB_Char *RTEConf_ParameterAccess::BuildIndexedParamName(
    SAPDB_Char *baseParamName, 
    SAPDB_UInt indexDigits, 
    SAPDB_UInt indexToUse)
{
    SAPDB_UInt sizeOfFormatString   = (SAPDB_UInt)strlen(FORMAT_STRING_FOR_FORMAT_STRING) 
                                    - NUMBER_OF_DOUBLED_PERCENTS
                                    + (SAPDB_UInt)log10((float)indexDigits);
    SAPDB_Char *formatString = (SAPDB_Char *)alloca(sizeOfFormatString);
    SAPDB_sprintf(formatString,sizeOfFormatString,FORMAT_STRING_FOR_FORMAT_STRING,indexDigits);

    SAPDB_UInt sizeOfIndexedParamName = (SAPDB_UInt)strlen(baseParamName) + indexDigits + 1;
    SAPDB_Char *indexedParamName = (SAPDB_Char *)AllocateMemory(sizeOfIndexedParamName);
    SAPDB_sprintf(indexedParamName,sizeOfIndexedParamName,formatString,baseParamName,indexToUse);

    return indexedParamName;
}

/*---------------------------------------------------------------------------*/

SAPDB_Bool RTEConf_ParameterAccess::AddHssNode(SAPDB_Char *nodeName,SAPDB_UInt indexOfElement)
{   
    // indexOfElement is a C-array index. That means that for HS_NODE_001 indexOfElement is 0 etc..
    SAPDB_UInt numberOfElement = indexOfElement + 1;    
    RTE_HssNode newNode;
    newNode.index = numberOfElement;
    strncpy(newNode.name , nodeName,sizeof(RTE_Nodename));

    Container_List < RTE_HssNode > ::Iterator iterator = m_hssNodeList.Begin();
    while(iterator != m_hssNodeList.End())
    {
        if((0 == strcmp(iterator->name,nodeName)))
        {
            m_hssNodeListConsistent = false;
        }
        ++iterator;
    }

    if(!m_hssNodeList.InsertEnd( newNode ).IsValid())
    {
        return false;
    }

    SAPDB_Char *localNodeName = (SAPDB_Char *)RTE_ISystem::Instance().GetLocalNodeName();
    if( 0 == strcmp(nodeName,localNodeName))
    {
        m_localHSSIndex = numberOfElement;
    }

    if(1 == numberOfElement) // def.: the node #1 is the default node. It must be present.
    {
        m_defaultNodeIsPresent = true;
    }

    return true;
}

/*---------------------------------------------------------------------------*/

SAPDB_Bool RTEConf_ParameterAccess::GetHssConfiguration(
    SAPDB_Bool &hssNodesConfigured,
    RTEConf_Parameter::Integer &delayTime,
    SAPDBErr_MessageList &err)
{
    // first check: consistent HSS configuration?
    if(!m_hssNodeListConsistent)
    {
        err = SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_CONF_INCONSISTENT_HSS_CONFIG);
        return false;
    }

    // second check: are there any HSS nodes configured at all?
    hssNodesConfigured = !m_hssNodeList.IsEmpty();
    if(hssNodesConfigured)
    {
        // third check: is a default node configured?
        if(!m_defaultNodeIsPresent)
        {
            err = SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_CONF_MISSING_DEFAULT_HSS_NODE);
            return false;
        }
        // fourth check: if there are HSS nodes configured: Is my own node name among them?
        if(0 == m_localHSSIndex)
        {
            err = SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_CONF_LOCAL_NODE_NOT_FOUND_IN_HSS_CONFIG,(SAPDB_Char *)RTE_ISystem::Instance().GetLocalNodeName());
            return false;
        }

        // fifth check: is a delay time configured for my node name?
        SAPDB_Char *delayTimeName = BuildIndexedParamName((SAPDB_Char *)KERNELPARAM_HS_DELAY_TIME_ , PAN_HS_DELAY_TIME_DIGITS , m_localHSSIndex);
        SAPDBErr_MessageList errGettingParameter;
        RTEConf_Parameter::Integer myDelayTime;
        if((RTEConf_ParameterAccess::Instance())->GetInteger((RTEConf_Parameter::Name)delayTimeName,myDelayTime,errGettingParameter))
        {
            delayTime = myDelayTime;
        }
        else
        {
            // As the delay time parameters are not mandatory, a missing one is not fatal. But any other errors are.
            if(RTEINFO_CONF_NOT_FOUND_ID == errGettingParameter.ID())
            {
                delayTime = 0;
            }
            else
            {
                err = errGettingParameter;
                return false;
            }
        }
        DEALLOCATE_MEMORY(delayTimeName);
    }
    return true;
}

/*---------------------------------------------------------------------------*/

SAPDB_Bool RTEConf_ParameterAccess::SetInteger(RTEConf_Parameter::Name name, RTEConf_Parameter::Integer  value,SAPDBErr_MessageList &err)
{
    if(m_Conf_Parameter->UpdateOnlinePossible(name))
    {
        if(m_Conf_Parameter->SetValue(name,value,err))
        {
            return m_Conf_Parameter->SetUpdateOnline(name,true,err);    // If call to SetValue() ahd created a new parameter, it would be initialized with UpdateOnlinePossible=false. It could not be changed anymore...
        }
        else
        {
            return false;
        }
    }
    else
    {
        err = SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_CANT_CHANGE_PARAMETER_ONLINE, (SAPDB_Char *)name);
        return false;
    }
}

/*---------------------------------------------------------------------------*/

SAPDB_Bool RTEConf_ParameterAccess::SetReal(RTEConf_Parameter::Name name, RTEConf_Parameter::Real  value,SAPDBErr_MessageList &err)
{
    if(m_Conf_Parameter->UpdateOnlinePossible(name))
    {
        if(m_Conf_Parameter->SetValue(name,value,err))
        {
            return m_Conf_Parameter->SetUpdateOnline(name,true,err);    // If call to SetValue() ahd created a new parameter, it would be initialized with UpdateOnlinePossible=false. It could not be changed anymore...
        }
        else
        {
            return false;
        }
    }
    else
    {
        err = SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_CANT_CHANGE_PARAMETER_ONLINE, (SAPDB_Char *)name);
        return false;
    }
}

/*---------------------------------------------------------------------------*/

SAPDB_Bool RTEConf_ParameterAccess::SetString(RTEConf_Parameter::Name name, RTEConf_Parameter::String  value,SAPDBErr_MessageList &err)
{
    if(m_Conf_Parameter->UpdateOnlinePossible(name))
    {
        if(m_Conf_Parameter->SetValue(name,value,err))
        {
            return m_Conf_Parameter->SetUpdateOnline(name,true,err);
        }
        else
        {
            return false;
        }
    }
    else
    {
        err = SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_CANT_CHANGE_PARAMETER_ONLINE, (SAPDB_Char *)name);
        return false;
    }
}

/*---------------------------------------------------------------------------*/

SAPDB_Bool RTEConf_ParameterAccess::SetCryptInfo(RTEConf_Parameter::Name name, RTEConf_Parameter::CryptInfo  &value,SAPDBErr_MessageList &err)
{
    RTEConf_Parameter::CryptInfo *CryptInfoValue = &value;

    if(m_Conf_Parameter->UpdateOnlinePossible(name))
    {
        if(m_Conf_Parameter->SetValue(name,value,err))
        {
            return m_Conf_Parameter->SetUpdateOnline(name,true,err);
        }
        else
        {
            return false;
        }
    }
    else
    {
        err = SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_CANT_CHANGE_PARAMETER_ONLINE, (SAPDB_Char *)name);
        return false;
    }
}

/*---------------------------------------------------------------------------*/

RTEConf_ParameterAccess::RTEConf_ParameterAccess(SAPDB_Char *dbName)
    : m_hssNodeListConsistent(true),m_localHSSIndex(0),m_hssNodeList(RTEMem_RteAllocator::Instance()),m_defaultNodeIsPresent(false)
{
    SAPDB_Bool dataRead;
    SAPDB_Bool fileReadSuccess;

    m_Conf_Parameter = new (AllocateMemory(sizeof(RTEConf_Parameter))) RTEConf_Parameter(dbName,0,RTECONF_MAXNAMELENGTH,RTECONF_MAXSTRINGLENGTH);
    SAPDBErr_MessageList err;
    fileReadSuccess = m_Conf_Parameter->Read(dataRead,err);

    // if the file does not exist, Read() returns true and sets dataRead to false. For the kernel, this is an error case, so 
    // an error message has to be generated and m_FileReadOk must be false.
    if( !fileReadSuccess )
    {
        MessageAndCrash(err);
    }
    if( !dataRead )
    {
        MessageAndCrash(SAPDBErr_MessageList(RTE_CONTEXT,RTEERR_CONF_PARAMFILE_NOT_FOUND,dbName,SAPDB_ToString(LAST_SYSTEM_ERROR_)));
    }
}

/*---------------------------------------------------------------------------*/

void *RTEConf_ParameterAccess::operator new(size_t size)
{
    return AllocateMemory(size);
}

/*---------------------------------------------------------------------------*/

externC void vconf_param_get_int4      ( tsp11_ConfParamName        VAR_ARRAY_REF conf_param_name,
									     tsp00_Int4                 VAR_VALUE_REF conf_param_value,
									     tsp00_ErrText              VAR_ARRAY_REF errtext,
									     tsp11_ConfParamReturnValue VAR_VALUE_REF conf_param_ret )
{
    SAPDB_Int4 lengthOfName = conf_param_name.length();
    SAPDB_UTF8 *nameAsCString = (SAPDB_UTF8 *)AllocateMemory(lengthOfName+1);
    RTEConf_Parameter::Integer value;
    memcpy(nameAsCString,conf_param_name.asCharp(),lengthOfName);
    nameAsCString[lengthOfName]=0;
    SAPDBErr_MessageList err;
    if(RTEConf_ParameterAccess::Instance()->GetInteger(nameAsCString,value,err))
	{
		conf_param_ret.becomes(ok_sp11);
        conf_param_value = (tsp00_Int4)value;
	}
	else
	{
		conf_param_ret.becomes(not_ok_sp11);
		errtext.c2p(err.Message());
	}
    DEALLOCATE_MEMORY(nameAsCString);
}

/*---------------------------------------------------------------------------*/

externC void vconf_param_get_integer   ( tsp11_ConfParamName        VAR_ARRAY_REF conf_param_name,
									     tsp00_Int8                 VAR_VALUE_REF conf_param_value,
									     tsp00_ErrText              VAR_ARRAY_REF errtext,
									     tsp11_ConfParamReturnValue VAR_VALUE_REF conf_param_ret )
{
    SAPDB_Int4 lengthOfName = conf_param_name.length();
    SAPDB_UTF8 *nameAsCString = (SAPDB_UTF8 *)AllocateMemory(lengthOfName+1);
    memcpy(nameAsCString,conf_param_name.asCharp(),lengthOfName);
    nameAsCString[lengthOfName]=0;
    SAPDBErr_MessageList err;
    if(RTEConf_ParameterAccess::Instance()->GetInteger(nameAsCString,conf_param_value,err))
	{
		conf_param_ret.becomes(ok_sp11);
	}
	else
	{
		conf_param_ret.becomes(not_ok_sp11);
		errtext.c2p(err.Message());
	}
    DEALLOCATE_MEMORY(nameAsCString);
}

/*---------------------------------------------------------------------------*/

externC void vconf_param_get_real      ( tsp11_ConfParamName        VAR_ARRAY_REF conf_param_name,
									     tsp00_Longreal             VAR_VALUE_REF conf_param_value,
									     tsp00_ErrText              VAR_ARRAY_REF errtext,
									     tsp11_ConfParamReturnValue VAR_VALUE_REF conf_param_ret )
{
    SAPDB_Int4 lengthOfName = conf_param_name.length();
    SAPDB_UTF8 *nameAsCString = (SAPDB_UTF8 *)AllocateMemory(lengthOfName+1);
    memcpy(nameAsCString,conf_param_name.asCharp(),lengthOfName);
    nameAsCString[lengthOfName]=0;
    SAPDBErr_MessageList err;

    if(RTEConf_ParameterAccess::Instance()->GetReal(nameAsCString,conf_param_value,err))
	{
		conf_param_ret.becomes(ok_sp11);
	}
	else
	{
		conf_param_ret.becomes(not_ok_sp11);
		errtext.c2p(err.Message());
	}
    DEALLOCATE_MEMORY(nameAsCString);
}

/*---------------------------------------------------------------------------*/

externC void vconf_param_get_string    ( tsp11_ConfParamName        VAR_ARRAY_REF conf_param_name,
									     tsp11_ConfParamValue       VAR_ARRAY_REF conf_param_value,
									     tsp00_Int4                 VAR_VALUE_REF conf_param_length,
									     tsp00_ErrText              VAR_ARRAY_REF errtext,
									     tsp11_ConfParamReturnValue VAR_VALUE_REF conf_param_ret )
{
	RTEConf_Parameter::String StringValue;
    SAPDB_Int4 lengthOfName = conf_param_name.length();
    SAPDB_UTF8 *nameAsCString = (SAPDB_UTF8 *)RTEMem_RteAllocator::Instance().Allocate(lengthOfName+1);
    memcpy(nameAsCString,conf_param_name.asCharp(),lengthOfName);
    nameAsCString[lengthOfName]=0;
    SAPDBErr_MessageList err;

    if(RTEConf_ParameterAccess::Instance()->GetString(nameAsCString,StringValue,err))
	{
		conf_param_ret.becomes(ok_sp11);
        conf_param_length = (SAPDB_Int4)strlen((SAPDB_Char *)StringValue);
		conf_param_value.c2p((SAPDB_Char *)StringValue);
	}
	else
	{
		conf_param_ret.becomes(not_ok_sp11);
		errtext.c2p(err.Message());
	}
    DEALLOCATE_MEMORY(nameAsCString);
}

/*---------------------------------------------------------------------------*/

externC void vconf_param_get_cryptinfo ( tsp11_ConfParamName        VAR_ARRAY_REF conf_param_name,
									     tsp00_CryptName            VAR_ARRAY_REF conf_param_value,
									     tsp00_ErrText              VAR_ARRAY_REF errtext,
									     tsp11_ConfParamReturnValue VAR_VALUE_REF conf_param_ret )
{
    SAPDB_Int4 lengthOfName = conf_param_name.length();
    SAPDB_UTF8 *nameAsCString = (SAPDB_UTF8 *)RTEMem_RteAllocator::Instance().Allocate(lengthOfName+1);
    memcpy(nameAsCString,conf_param_name.asCharp(),lengthOfName);
    nameAsCString[lengthOfName]=0;
    SAPDBErr_MessageList err;

    if(RTEConf_ParameterAccess::Instance()->GetCryptInfo(nameAsCString,*((RTEConf_Parameter::CryptInfo *)(conf_param_value.asCharp())),err))
	{
		conf_param_ret.becomes(ok_sp11);
	}
	else
	{
		conf_param_ret.becomes(not_ok_sp11);
		errtext.c2p(err.Message());
	}

    DEALLOCATE_MEMORY(nameAsCString);
}


/*---------------------------------------------------------------------------*/

externC SAPDB_Bool RTEConf_ParameterAccessGetInteger   ( SAPDB_UTF8  *  conf_param_name,
									                     SAPDB_Int8  *  conf_param_value,
									                     SAPDB_Char  ** errtext)
{
    SAPDBErr_MessageList err;

    RTEConf_ParameterAccess* instance = RTEConf_ParameterAccess::Instance();
    if(!instance)
    {
        *errtext = RTEConf_MakeACopyOfString((SAPDB_Char *)"database name not yet available");
        return false;
    }
    
    if(instance->GetInteger(conf_param_name,*conf_param_value,err))
	{
		return true;
	}
	else
	{
		*errtext = RTEConf_MakeACopyOfString((SAPDB_Char *)err.Message());
        return false;
    }
}

/*---------------------------------------------------------------------------*/

externC SAPDB_Bool RTEConf_ParameterAccessGetReal      ( SAPDB_UTF8  *  conf_param_name,
									                     SAPDB_Real8 *  conf_param_value,
									                     SAPDB_Char  ** errtext)
{
    SAPDBErr_MessageList err;

    RTEConf_ParameterAccess* instance = RTEConf_ParameterAccess::Instance();
    if(!instance)
    {
        *errtext = RTEConf_MakeACopyOfString((SAPDB_Char *)"database name not yet available");
        return false;
    }
    
    if(instance->GetReal(conf_param_name,*conf_param_value,err))
	{
		return true;
	}
	else
	{
		*errtext = RTEConf_MakeACopyOfString((SAPDB_Char *)err.Message());
        return false;
    }
}

/*---------------------------------------------------------------------------*/

externC SAPDB_Bool RTEConf_ParameterAccessGetString    ( SAPDB_UTF8  *  conf_param_name,
									                     SAPDB_Char  ** conf_param_value,
									                     SAPDB_Char  ** errtext)
{
	RTEConf_Parameter::String StringValue = (RTEConf_Parameter::String)conf_param_value;
    SAPDBErr_MessageList err;

    RTEConf_ParameterAccess* instance = RTEConf_ParameterAccess::Instance();
    if(!instance)
    {
        *errtext = RTEConf_MakeACopyOfString((SAPDB_Char *)"database name not yet available");
        return false;
    }
    
    if(instance->GetString(conf_param_name,StringValue,err))
	{
        *conf_param_value = (SAPDB_Char *)StringValue;
		return true;
	}
	else
	{
		*errtext = RTEConf_MakeACopyOfString((SAPDB_Char *)err.Message());
        return false;
    }
}

/*---------------------------------------------------------------------------*/

externC SAPDB_Bool RTEConf_ParameterAccessGetCryptInfo ( SAPDB_UTF8  *  conf_param_name,
									                     SAPDB_Byte  *  conf_param_value,
									                     SAPDB_Char  ** errtext)
{
    SAPDBErr_MessageList err;

    RTEConf_ParameterAccess* instance = RTEConf_ParameterAccess::Instance();
    if(!instance)
    {
        *errtext = RTEConf_MakeACopyOfString((SAPDB_Char *)"database name not yet available");
        return false;
    }
    
    if(instance->GetCryptInfo(conf_param_name,*((RTEConf_Parameter::CryptInfo *)conf_param_value),err))
	{
		return true;
	}
	else
	{
		*errtext = RTEConf_MakeACopyOfString((SAPDB_Char *)err.Message());
        return false;
    }
}

/*---------------------------------------------------------------------------*/


externC void vconf_param_put           ( tsp11_ConfParamName        VAR_ARRAY_REF conf_param_name,
                                         tsp11_ConfParamValue       VAR_ARRAY_REF conf_param_value,
                                         boolean                                  is_numeric,
                                         tsp00_ErrText              VAR_ARRAY_REF errtext,
                                         tsp11_ConfParamReturnValue VAR_VALUE_REF conf_param_ret )
{
    SAPDB_Int4 lengthOfName = conf_param_name.length();
    SAPDB_UTF8 *nameAsCString = (SAPDB_UTF8 *)AllocateMemory(lengthOfName+1);

    memcpy(nameAsCString,conf_param_name.asCharp(),lengthOfName);
    nameAsCString[lengthOfName]=0;

    SAPDB_Int4 lengthOfValue = conf_param_value.length();
    SAPDB_UTF8 *valueAsCString = (SAPDB_UTF8 *)AllocateMemory(lengthOfValue+1);
    
    memcpy(valueAsCString,conf_param_value.asCharp(),lengthOfValue);
    valueAsCString[lengthOfValue]=0;

    RTE_XPARAM_REC *XParam = KGS->XParam ;

    RTEConf_ParameterValueRecord xpr;
    SAPDBErr_MessageList err;

    conf_param_ret.becomes(ok_sp11);

    if(is_numeric)
    {
        if(!(RTEConf_ParameterAccess::Instance())->SetInteger(nameAsCString,(RTEConf_Parameter::Integer)atoi((SAPDB_Char *)valueAsCString),err))
        {
            errtext.c2p(RTEConf_MakeACopyOfString((SAPDB_Char *)err.Message()));
            conf_param_ret.becomes(not_ok_sp11);
        }
        xpr.xp_value_t = NXP_INT_TYPE;
        xpr.xp_type.xp_integer = atoi( (SAPDB_Char *)valueAsCString );
    }
    else
    {
        if(!(RTEConf_ParameterAccess::Instance())->SetString(nameAsCString,valueAsCString,err))
        {
            errtext.c2p(RTEConf_MakeACopyOfString((SAPDB_Char *)err.Message()));
            conf_param_ret.becomes(not_ok_sp11);
        }
        xpr.xp_value_t = NXP_STRING_TYPE;
        xpr.xp_type.xp_string = valueAsCString;
    }
    if(conf_param_ret == ok_sp11)
    {
        if(!RTEConf_AnalyzeParam  ( XParam, nameAsCString, &xpr, true, err) )
        {
            if(RTEERR_ILLEGAL_XP_TYPE_ID == err.ID())
            {
                SAPDB_Char errorMessage[sizeof(tsp00_ErrText)];
                if(is_numeric)
                {
                    SAPDB_sprintf(errorMessage,sizeof(tsp00_ErrText),"param. %s must not be numeric",nameAsCString);
                }
                else
                {
                    SAPDB_sprintf(errorMessage,sizeof(tsp00_ErrText),"param. %s must be numeric",nameAsCString);
                }
                errtext.c2p(errorMessage);
            }
            else
            {
                errtext.c2p(RTEConf_MakeACopyOfString((SAPDB_Char *)err.Message()));
            }
            conf_param_ret.becomes(not_ok_sp11);
        }
    }
    DEALLOCATE_MEMORY(nameAsCString);
    DEALLOCATE_MEMORY(valueAsCString);
}

/*---------------------------------------------------------------------------*/
 
externC SAPDB_Bool RTEConf_ParameterAccessSetCrashSem( SAPDB_Int8 conf_param_value,
                                                       SAPDB_Char ** errtext)
{
    SAPDBErr_MessageList err;
    if((RTEConf_ParameterAccess::Instance())->MarkCrashed(conf_param_value ,err))
    {
        return true;
    }
    *errtext = RTEConf_MakeACopyOfString((SAPDB_Char *)err.Message());
    return false;
}

/*---------------------------------------------------------------------------*/
 
externC SAPDB_Bool RTEConf_ParameterAccessResetParamChangedFlag ( SAPDB_Char ** errtext )
{
    SAPDBErr_MessageList err;
    if((RTEConf_ParameterAccess::Instance())->MarkAsVerified(err))
    {
        return true;
    }
    else
    {   
        *errtext = RTEConf_MakeACopyOfString((SAPDB_Char *)err.Message());
        return false;
    }
}

/*---------------------------------------------------------------------------*/
 
externC SAPDB_Bool RTEConf_ParameterAccessIsVerified ( )
{
    if(!RTEConf_ParameterAccess::Instance()->FileInOldFormat())
    {
      return RTEConf_ParameterAccess::Instance()->IsVerified();
    } 
    else 
    {
      return true;
    } // end if
}

/*---------------------------------------------------------------------------*/
 
externC SAPDB_Bool RTEConf_ParameterAccessGetCrashSem ( )
{
    if(!RTEConf_ParameterAccess::Instance()->FileInOldFormat())
    {
      return RTEConf_ParameterAccess::Instance()->IsCrashed();
    } 
    else 
    {
      return true;
    } // end if
}

/*---------------------------------------------------------------------------*/
 
externC void RTEConf_ParameterAccessFreeErrorMessage(SAPDB_Char *errtext)
{
    DEALLOCATE_MEMORY(errtext);
}

/*===========================================================================*
 *  END OF CODE                                                              *
 *===========================================================================*/

