summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGuy Sagnes <guy.sagnes@continental-corporation.com>2014-02-25 10:32:29 +0100
committerRalf Anton Beier <ralf.anton.beier@continental-corporation.com>2014-02-25 11:33:41 +0100
commit880e7ffe185e5b410ee6183c4ce355a8a204ab28 (patch)
tree9c18d6aecfaf69a6753b4c2f251583cfe9f3722e /src
parent94b07e2221c3333a5a54f689eca4249667892f74 (diff)
downloadpersistence-common-object-880e7ffe185e5b410ee6183c4ce355a8a204ab28.tar.gz
persistence-common-object-880e7ffe185e5b410ee6183c4ce355a8a204ab28.tar.bz2
persistence-common-object-880e7ffe185e5b410ee6183c4ce355a8a204ab28.zip
Added version 1.0.1
12.12.2013 * add missing licenses information / update after review feedback 20131212 - J.Kowalski 03.12.2013 * Persistence Common Object - OIP BL 0.9.130 08.08.2013 * Add instrumentation for debug purposes (low level db access) 18.06.2013 * persistence-common version 1.0.1 - Add makefile to allow creation of auto-generated code - Default error handler causes the termination of the calling process - de-central build of the common part 02.05.2013 * initial version of the common persistence libraries Change-Id: I6ac6b7f1fe453537835ac32f664c04d537d732db Signed-off-by: Guy Sagnes <guy.sagnes@continental-corporation.com>
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am70
-rw-r--r--src/pers_data_organization.c101
-rw-r--r--src/pers_ipc.c316
-rw-r--r--src/pers_ipc_dbus.c1590
-rw-r--r--src/pers_local_shared_db_access.c287
-rw-r--r--src/pers_low_level_db_access.c1515
-rw-r--r--src/pers_resource_config_table.c247
7 files changed, 4126 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..c8bf708
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,70 @@
+#######################################################################################################################
+#
+# Copyright (C) 2012 Continental Automotive Systems, Inc.
+#
+# Author: Ana.Chisca@continental-corporation.com
+#
+# Makefile template for the persistence common library
+#
+# Process this file with automake to produce a Makefile.in.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#######################################################################################################################
+
+ACLOCAL_AMFLAGS=-I m4
+
+lib_LTLIBRARIES = libpers_common.la
+
+include_HEADERS= \
+ $(top_srcdir)/inc/protected/persComTypes.h \
+ $(top_srcdir)/inc/protected/persComDataOrg.h \
+ $(top_srcdir)/inc/protected/persComDbAccess.h \
+ $(top_srcdir)/inc/protected/persComErrors.h \
+ $(top_srcdir)/inc/protected/persComRct.h \
+ $(top_srcdir)/inc/protected/persComIpc.h
+
+libpers_common_la_CFLAGS = \
+ -I $(top_srcdir)/inc/private -I $(top_srcdir)/inc/protected -I $(top_srcdir)/generated\
+ $(DLT_CFLAGS) \
+ $(GIO_CFLAGS) \
+ $(GIO_UNIX_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(GOBJECT_CFLAGS) \
+ $(DBUS_CFLAGS) \
+ $(ITZAM_CFLAGS)
+
+libpers_common_la_SOURCES = \
+ $(top_srcdir)/generated/PasClientNotificationGen.c\
+ $(top_srcdir)/src/pers_data_organization.c\
+ $(top_srcdir)/src/pers_local_shared_db_access.c\
+ $(top_srcdir)/src/pers_low_level_db_access.c\
+ $(top_srcdir)/src/pers_resource_config_table.c\
+ $(top_srcdir)/src/pers_ipc.c\
+ $(top_srcdir)/src/pers_ipc_dbus.c
+
+libpers_common_la_LDFLAGS = -version-info $(GENERIC_LIBRARY_VERSION)
+
+libpers_common_la_LIBADD = \
+ $(DLT_LIBS) \
+ $(GIO_LIBS) \
+ $(GIO_UNIX_LIBS) \
+ $(GLIB_LIBS) \
+ $(DBUS_LIBS) \
+ $(GOBJECT_LIBS) \
+ $(ITZAM_LIBS)
+
+dbuspolicy_DATA = $(top_srcdir)/dbus_config/org.genivi.persistence.admin.conf
+
+# Export interface description of org.genivi.persistence.admin DBus interface
+dbusinterfaces_DATA = $(top_srcdir)/dbus_specifications/org.genivi.persistence.admin.xml
+
+EXTRA_DIST = $(dbuspolicy_DATA) \
+ $(dbusinterfaces_DATA)
+
+# pkgconfig
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = $(top_srcdir)/pkgconfig/libperscommon.pc
+
diff --git a/src/pers_data_organization.c b/src/pers_data_organization.c
new file mode 100644
index 0000000..4c798e1
--- /dev/null
+++ b/src/pers_data_organization.c
@@ -0,0 +1,101 @@
+/**********************************************************************************************************************
+*
+* Copyright (C) 2012 Continental Automotive Systems, Inc.
+*
+* Author: Ionut.Ieremie@continental-corporation.com
+*
+* Implementation of persComDataOrg.h
+*
+* This Source Code Form is subject to the terms of the Mozilla Public
+* License, v. 2.0. If a copy of the MPL was not distributed with this
+* file, You can obtain one at http://mozilla.org/MPL/2.0/.
+*
+* Date Author Reason
+* 2012.12.10 uild9757 CSP_WZ#2798: Added gLocalFactoryDefault and gLocalConfigurableDefault
+* 2012.12.10 uild9757 CSP_WZ#388: Initial creation
+*
+**********************************************************************************************************************/
+
+#include "persComDataOrg.h"
+
+
+
+/* resource configuration table name */
+const char* gResTableCfg = PERS_ORG_RCT_NAME_ ;
+
+/** local factory-default database */
+const char* gLocalFactoryDefault = PERS_ORG_LOCAL_FACTORY_DEFAULT_DB_NAME_ ;
+
+/** local configurable-default database */
+const char* gLocalConfigurableDefault = PERS_ORG_LOCAL_CONFIGURABLE_DEFAULT_DB_NAME_ ;
+
+/* shared cached default database */
+const char* gSharedCachedDefault = PERS_ORG_SHARED_CACHE_DEFAULT_DB_NAME_ ;
+
+/* shared cached database */
+const char* gSharedCached = PERS_ORG_SHARED_CACHE_DB_NAME_ ;
+
+/* shared write through default database */
+const char* gSharedWtDefault = PERS_ORG_SHARED_WT_DEFAULT_DB_NAME_ ;
+
+/* shared write through database */
+const char* gSharedWt = PERS_ORG_SHARED_WT_DB_NAME_ ;
+
+/* local cached default database */
+const char* gLocalCachedDefault = PERS_ORG_LOCAL_CACHE_DEFAULT_DB_NAME_ ;
+
+/* local cached database */
+const char* gLocalCached = PERS_ORG_LOCAL_CACHE_DB_NAME_ ;
+
+/* local write through default database */
+const char* gLocalWtDefault = PERS_ORG_LOCAL_WT_DEFAULT_DB_NAME_ ;
+
+/* local write through default database */
+const char* gLocalWt = PERS_ORG_LOCAL_WT_DB_NAME_ ;
+
+/* directory structure node name definition */
+const char* gNode = PERS_ORG_NODE_FOLDER_NAME_ ;
+
+/* directory structure user name definition */
+const char* gUser = PERS_ORG_USER_FOLDER_NAME_ ;
+
+/* directory structure seat name definition */
+const char* gSeat = PERS_ORG_SEAT_FOLDER_NAME_ ;
+
+/* directory structure shared name definition */
+const char* gSharedPathName = PERS_ORG_SHARED_FOLDER_NAME ;
+
+/* path prefix for all data */
+const char* gRootPath = PERS_ORG_ROOT_PATH ;
+
+/* path prefix for local cached database: /Data/mnt-c/<appId>/<database_name> */
+const char* gLocalCachePath = PERS_ORG_LOCAL_CACHE_PATH_FORMAT ;
+
+/* path prefix for local write through database /Data/mnt-wt/<appId>/<database_name> */
+const char* gLocalWtPath = PERS_ORG_LOCAL_WT_PATH_FORMAT ;
+
+/* path prefix for shared cached database: /Data/mnt-c/shared/group/ */
+const char* gSharedCachePathRoot = PERS_ORG_SHARED_GROUP_CACHE_PATH_ ;
+
+/* path format for shared cached database: /Data/mnt-c/shared/group/<group_no>/<database_name> */
+const char* gSharedCachePath = PERS_ORG_SHARED_CACHE_PATH_FORMAT ;
+
+/* path prefix for shared cached database: /Data/mnt-c/shared/group/<group_no>/<database_name> */
+const char* gSharedCachePathString = PERS_ORG_SHARED_CACHE_PATH_STRING_FORMAT ;
+
+/* path prefix for shared write through database: /Data/mnt-wt/shared/group/ */
+const char* gSharedWtPathRoot = PERS_ORG_SHARED_GROUP_WT_PATH_ ;
+
+/* path prefix for shared write through database: /Data/mnt_wt/shared/group/<group_no>/<database_name> */
+const char* gSharedWtPath = PERS_ORG_SHARED_WT_PATH_FORMAT ;
+
+/* path prefix for shared write through database: /Data/mnt-wt/shared/group/<group_no>/<database_name> */
+const char* gSharedWtPathString = PERS_ORG_SHARED_WT_PATH_STRING_FORMAT ;
+
+/* path prefix for shared public cached database: /Data/mnt-c/shared/public/<database_name> */
+const char* gSharedPublicCachePath = PERS_ORG_SHARED_PUBLIC_CACHE_PATH_FORMAT ;
+
+/* path prefix for shared public write through database: /Data/mnt-wt/shared/public/<database_name> */
+const char* gSharedPublicWtPath = PERS_ORG_SHARED_PUBLIC_WT_PATH_FORMAT ;
+
+
diff --git a/src/pers_ipc.c b/src/pers_ipc.c
new file mode 100644
index 0000000..9e33138
--- /dev/null
+++ b/src/pers_ipc.c
@@ -0,0 +1,316 @@
+/**********************************************************************************************************************
+*
+* Copyright (C) 2012 Continental Automotive Systems, Inc.
+*
+* Author: Petrica.Manoila@continental-corporation.com
+*
+* Implementation of persComIpc.h
+*
+* This Source Code Form is subject to the terms of the Mozilla Public
+* License, v. 2.0. If a copy of the MPL was not distributed with this
+* file, You can obtain one at http://mozilla.org/MPL/2.0/.
+*
+* Date Author Reason
+* 2013.04.03 uidu0250 CSP_WZ#2739 : Initial creation
+*
+**********************************************************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <dlt.h>
+#include "persComErrors.h"
+#include "persComTypes.h"
+#include "persComIpc.h"
+#include "pers_ipc_dbus_if.h"
+
+
+/* ---------- local defines, macros, constants and type definitions ------------ */
+
+typedef enum persIpcChannel_e_
+{
+ persIpcChannelDBus_high = 0,
+ persIpcChannelDBus_low,
+ persIpcChannelSysSyncObj,
+ persIpcChannelLastEntry
+}persIpcChannel_e;
+
+
+#ifndef PERS_COM_IPC_PROTOCOL
+#define PERS_COM_IPC_PROTOCOL persIpcChannelDBus_high
+#endif //PERS_COM_IPC_PROTOCOL
+
+
+typedef sint_t (*persIpcInitPAS_handler_f)(PersAdminPASInitInfo_s *);
+typedef sint_t (*persIpcSendRequestToPCL_handler_f)(sint_t, sint_t, uint_t);
+typedef sint_t (*persIpcRegisterToPAS_handler_f)(PersAdminPCLInitInfo_s *, uint_t, uint_t);
+typedef sint_t (*persIpcUnRegisterFromPAS_handler_f)(uint_t);
+typedef sint_t (*persIpcSendConfirmationToPAS_handler_f)(sint_t, uint_t);
+
+
+/* ----------global variables. initialization of global contexts ------------ */
+
+DLT_DECLARE_CONTEXT(persComIpcDLTCtx);
+
+#define LT_HDR "COMMON_IPC >>"
+
+static bool_t g_bDltCtxInitialized = false; /* PersCommonIPC DLT context initialized */
+
+static bool_t g_bPersCommonIPCInitPAS = false; /* PersCommonIPC module initialized for PAS */
+static bool_t g_bPersCommonIPCInitPCL = false; /* PersCommonIPC module initialized for PCL */
+
+
+static persIpcInitPAS_handler_f persIpcInitPAS_handler[persIpcChannelLastEntry] =
+{
+ &persIpcInitPAS_DBus_high,
+ NIL,
+ NIL
+};
+
+static persIpcSendRequestToPCL_handler_f persIpcSendRequestToPCL_handler[persIpcChannelLastEntry] =
+{
+ &persIpcSendRequestToPCL_DBus_high,
+ NIL,
+ NIL
+};
+
+static persIpcRegisterToPAS_handler_f persIpcRegisterToPAS_handler[persIpcChannelLastEntry] =
+{
+ &persIpcRegisterToPAS_DBus_high,
+ NIL,
+ NIL
+};
+
+static persIpcUnRegisterFromPAS_handler_f persIpcUnRegisterFromPAS_handler[persIpcChannelLastEntry] =
+{
+ &persIpcUnRegisterFromPAS_DBus_high,
+ NIL,
+ NIL
+};
+
+static persIpcSendConfirmationToPAS_handler_f persIpcSendConfirmationToPAS_handler[persIpcChannelLastEntry] =
+{
+ &persIpcSendConfirmationToPAS_DBus_high,
+ NIL,
+ NIL
+};
+
+
+
+/**
+ * \brief Initialize PAS IPC component
+ * \note An additional thread is created for communication purposes.
+ * Initialize members of the supplied PersAdminPASInitInfo_s structure before calling this function.
+ *
+ * \param pInitInfo [in] pointer to a \ref PersAdminPASInitInfo_s structure containing
+ * the supported callbacks
+ *
+ * \return 0 for success, negative value for error (see \ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+int persIpcInitPAS( PersAdminPASInitInfo_s *pInitInfo)
+{
+ int retVal = PERS_COM_SUCCESS;
+
+ if(false == g_bDltCtxInitialized)
+ {
+ /* Initialize the logging interface */
+ DLT_REGISTER_CONTEXT(persComIpcDLTCtx, "PCOM", "PersistenceCommonIPC Context");
+ g_bDltCtxInitialized = true;
+ }
+
+ if(true == g_bPersCommonIPCInitPAS)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_WARN, DLT_STRING(LT_HDR),
+ DLT_STRING("PAS IPC protocol already initialized."));
+ return PERS_COM_SUCCESS;
+ }
+
+ if(NIL == pInitInfo)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Invalid parameter in persIpcInitPAS call."));
+ return PERS_COM_ERR_INVALID_PARAM;
+ }
+
+ if(NIL == persIpcInitPAS_handler[PERS_COM_IPC_PROTOCOL])
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Internal configuration error. No handler for persIpcInitPAS."));
+ return PERS_COM_ERR_INVALID_PARAM;
+ }
+
+ retVal = persIpcInitPAS_handler[PERS_COM_IPC_PROTOCOL](pInitInfo);
+ if(PERS_COM_SUCCESS == retVal)
+ {
+ g_bPersCommonIPCInitPAS = true;
+ }
+
+ return retVal;
+}
+
+
+/**
+ * \brief Sends a request to the PCL client specified by clientID.
+ * \note Each requestID should be unique.
+ *
+ * \param clientID [in] the client ID returned by the supplied pRegCB callback
+ * \param requestID [in] a unique identifier generated for every request
+ * \param request [in] the request to be sent (bitfield using a valid
+ * combination of any of the following flags :
+ * ::PERSISTENCE_MODE_LOCK, ::PERSISTENCE_MODE_SYNC and ::PERSISTENCE_MODE_UNLOCK)
+ *
+ * \return 0 for success, negative value for error (see \ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+int persIpcSendRequestToPCL( int clientID,
+ int requestID,
+ unsigned int request)
+{
+ if(false == g_bPersCommonIPCInitPAS)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("PAS IPC protocol not initialized."));
+ return PERS_COM_FAILURE;
+ }
+
+ if(NIL == persIpcSendRequestToPCL_handler[PERS_COM_IPC_PROTOCOL])
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Internal configuration error. No handler for persIpcSendRequestToPCL."));
+ return PERS_COM_ERR_INVALID_PARAM;
+ }
+
+ return persIpcSendRequestToPCL_handler[PERS_COM_IPC_PROTOCOL]( clientID,
+ requestID,
+ request);
+}
+
+
+/**
+ * \brief Register PCL client application to PAS
+ * \note Registers the PCL (Persistence Client Library) client application to PAS (Persistence Administration Service)
+ * in order to receive persistence mode change notifications (i.e. the memory access blocked/un-blocked).
+ * The initialization is performed based on the supplied pInitInfo parameter.
+ * Call \ref persIpcUnRegisterFromPAS to unregister from PAS when closing the application.
+ * Initialize members of the supplied PersAdminPCLInitInfo_s structure before calling this function.
+ *
+ * \param pInitInfo [in] pointer to a \ref PersAdminPCLInitInfo_s structure containing
+ * the supported callbacks
+ * \param flags [in] bitfield using a valid combination of any of the following flags : ::PERSISTENCE_MODE_LOCK, ::PERSISTENCE_MODE_SYNC and ::PERSISTENCE_MODE_UNLOCK
+ * \param timeout [in] maximum time needed to process any supported request (in milliseconds)
+ *
+ * \return 0 for success, negative value for error (see \ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+int persIpcRegisterToPAS(PersAdminPCLInitInfo_s * pInitInfo,
+ unsigned int flags,
+ unsigned int timeout)
+{
+ int retVal = PERS_COM_SUCCESS;
+
+ if(false == g_bDltCtxInitialized)
+ {
+ /* Initialize the logging interface */
+ DLT_REGISTER_CONTEXT(persComIpcDLTCtx, "PCOM", "PersistenceCommonIPC Context");
+ g_bDltCtxInitialized = true;
+ }
+
+ if(true == g_bPersCommonIPCInitPCL)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_WARN, DLT_STRING(LT_HDR),
+ DLT_STRING("PCL IPC protocol already initialized."));
+ return PERS_COM_SUCCESS;
+ }
+
+ if(NIL == pInitInfo)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Invalid parameter in persIpcRegisterToPAS call."));
+ return PERS_COM_ERR_INVALID_PARAM;
+ }
+
+ if(NIL == persIpcRegisterToPAS_handler[PERS_COM_IPC_PROTOCOL])
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Internal configuration error. No handler for persIpcRegisterToPAS."));
+ return PERS_COM_ERR_INVALID_PARAM;
+ }
+
+ retVal = persIpcRegisterToPAS_handler[PERS_COM_IPC_PROTOCOL]( pInitInfo,
+ flags,
+ timeout);
+ if(PERS_COM_SUCCESS == retVal)
+ {
+ g_bPersCommonIPCInitPCL = true;
+ }
+
+ return retVal;
+}
+
+
+/**
+ * \brief Un-Register PCL client application from PAS
+ * \note Un-registers the PCL (Persistence Client Library) client application from PAS (Persistence Administration Service) for
+ * the notifications specified trough flags.
+ * The PCL client application will no longer receive from PAS the notifications specified in flags.
+ *
+ * \param flags [in] bitfield using a valid combination of any of the following flags : ::PERSISTENCE_MODE_LOCK, ::PERSISTENCE_MODE_SYNC and ::PERSISTENCE_MODE_UNLOCK
+ *
+ * \return 0 for success, negative value for error (see \ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+int persIpcUnRegisterFromPAS( unsigned int flags )
+{
+ sint_t retVal = PERS_COM_SUCCESS;
+
+ if(NIL == persIpcUnRegisterFromPAS_handler[PERS_COM_IPC_PROTOCOL])
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Internal configuration error. No handler for persIpcUnRegisterFromPAS."));
+ return PERS_COM_ERR_INVALID_PARAM;
+ }
+
+ retVal = persIpcUnRegisterFromPAS_handler[PERS_COM_IPC_PROTOCOL](flags);
+ if(PERS_COM_SUCCESS == retVal)
+ {
+ g_bPersCommonIPCInitPCL = false;
+ }
+
+ /* Initialize the logging interface */
+ if(true == g_bDltCtxInitialized)
+ {
+ DLT_UNREGISTER_CONTEXT(persComIpcDLTCtx);
+ g_bDltCtxInitialized = false;
+ }
+
+ return retVal;
+}
+
+
+/**
+ * \brief Send 'request processed' confirmation to PAS.
+ * \note Sends confirmation to PAS that the request specified by requestID has been processed.
+ * The status parameter should reflect this request and could also return an error.
+ *
+ * \param requestID [in] the ID of the processed request
+ * \param status [in] the status of the request processed by PCL
+ * - In case of success: bitfield using any of the following flags, depending on the request : ::PERSISTENCE_STATUS_LOCKED.
+ * - In case of error: the sum of ::PERSISTENCE_STATUS_ERROR and an error code \ref PERS_COM_IPC_DEFINES_ERROR is returned.
+ *
+ * \return 0 for success, negative value for error (see \ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+int persIpcSendConfirmationToPAS( int requestID,
+ unsigned int status)
+{
+ if(false == g_bPersCommonIPCInitPCL)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("PCL IPC protocol not initialized."));
+ return PERS_COM_FAILURE;
+ }
+
+ if(NIL == persIpcSendConfirmationToPAS_handler[PERS_COM_IPC_PROTOCOL])
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Internal configuration error. No handler for persIpcSendConfirmationToPAS."));
+ return PERS_COM_ERR_INVALID_PARAM;
+ }
+
+ return persIpcSendConfirmationToPAS_handler[PERS_COM_IPC_PROTOCOL](requestID, status);
+}
diff --git a/src/pers_ipc_dbus.c b/src/pers_ipc_dbus.c
new file mode 100644
index 0000000..cac136d
--- /dev/null
+++ b/src/pers_ipc_dbus.c
@@ -0,0 +1,1590 @@
+/**********************************************************************************************************************
+*
+* Copyright (C) 2012 Continental Automotive Systems, Inc.
+*
+* Author: Petrica.Manoila@continental-corporation.com
+*
+* Implementation of pers_ipc_dbus_if.h
+*
+* This Source Code Form is subject to the terms of the Mozilla Public
+* License, v. 2.0. If a copy of the MPL was not distributed with this
+* file, You can obtain one at http://mozilla.org/MPL/2.0/.
+*
+* Date Author Reason
+* 2013.10.24 uidu0250 CSP_WZ#6327 : Change error handling for missing PCL clients
+* 2013.04.03 uidu0250 CSP_WZ#2739 : Initial creation
+*
+**********************************************************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <gio/gio.h>
+#include <dlt.h>
+
+#include "persComErrors.h"
+#include "persComTypes.h"
+#include "persComIpc.h"
+#include "PasClientNotificationGen.h"
+#include "pers_ipc_dbus_if.h"
+
+/* ---------- local defines, macros, constants and type definitions ------------ */
+
+#define PERS_IPC_INIT_DBUS_INFO_ARRAY_SIZE (uint32_t)24
+#define DBUS_MAIN_LOOP_THREAD_FLAG_SET 1
+
+typedef struct persIpcDBusClientInfo_s_
+{
+ pstr_t busName;
+ pstr_t objName;
+}persIpcDBusClientInfo_s;
+
+
+/* ----------global variables. initialization of global contexts ------------ */
+
+DLT_IMPORT_CONTEXT(persComIpcDLTCtx);
+
+#define LT_HDR "COMMON_IPC >>"
+
+
+static PersAdminPASInitInfo_s g_pPersIpcPASInfo; /* PAS IPC initialization struct */
+static PersAdminPCLInitInfo_s g_pPersIpcPCLInfo; /* PCL IPC initialization struct */
+
+static persIpcDBusClientInfo_s **g_persIpcDBusClientInfoArray = NIL;
+static uint32_t g_persIpcDBusClientInfoArraySize = 0;
+static uint32_t g_persIpcDBusClientInfoMaxArraySize = 0;
+static pthread_mutex_t g_persIpcDBusClientInfoArrayMtx; /* mutex for the access to the DBus client info array */
+
+static pthread_t g_hPASDBusThread = 0; /* PAS DBus main loop thread */
+static int g_PASDBusMainLoopThreadFlag;
+static pthread_cond_t g_PASDBusMainLoopThreadFlagCV;
+static pthread_mutex_t g_PASDBusMainLoopThreadFlagMtx;
+static pthread_t g_hPCLDBusThread = 0; /* PCL DBus main loop thread */
+static int g_PCLDBusMainLoopThreadFlag;
+static pthread_cond_t g_PCLDBusMainLoopThreadFlagCV;
+static pthread_mutex_t g_PCLDBusMainLoopThreadFlagMtx;
+
+
+static GMainLoop *g_pPASMainLoop = NIL; /* PAS DBus main loop */
+static GDBusConnection *g_pPASDBusConnection = NIL; /* PAS DBus connection */
+static GMainLoop *g_pPCLMainLoop = NIL; /* PCL DBus main loop */
+static GDBusConnection *g_pPCLDBusConnection = NIL; /* PCL DBus connection */
+static OipPersistenceAdminSkeleton *g_persIpcDBusPASSkeleton = NIL;
+static OipPersistenceAdminProxy *g_persIpcDBusPASProxy = NIL;
+static OipPersistenceAdminconsumerSkeleton *g_persIpcDBusPCLSkeleton = NIL;
+static volatile bool_t g_bPASDBusConnInit = false;
+static volatile bool_t g_bPCLDBusConnInit = false;
+
+
+/* ---------------------- local functions ---------------------------------- */
+
+static void OnBusAcquired_cb( GDBusConnection *connection, const gchar *name, gpointer user_data);
+static void OnNameAcquired_cb( GDBusConnection *connection, const gchar *name, gpointer user_data);
+static void OnNameLost_cb( GDBusConnection *connection, const gchar *name, gpointer user_data);
+
+/* RegisterPersAdminNotification */
+static gboolean OnHandleRegisterPersAdminNotification ( OipPersistenceAdmin *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_BusName,
+ const gchar *arg_ObjName,
+ gint arg_NotificationFlag,
+ guint arg_TimeoutMs);
+
+/* UnregisterPersAdminNotification */
+static gboolean OnHandleUnregisterPersAdminNotification(OipPersistenceAdmin *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_BusName,
+ const gchar *arg_ObjName,
+ gint arg_NotificationFlag,
+ guint arg_TimeoutMs);
+
+/* PersistenceAdminRequestCompleted */
+static gboolean OnHandlePersAdminRequestCompleted( OipPersistenceAdmin *object,
+ GDBusMethodInvocation *invocation,
+ guint arg_RequestId,
+ gint arg_StatusFlag);
+
+/* PersAdminRequest */
+static gboolean OnHandlePersAdminRequest( OipPersistenceAdminconsumer *object,
+ GDBusMethodInvocation *invocation,
+ guint arg_RequestId,
+ gint arg_StatusFlag );
+
+/* PAS DBus loop thread */
+static void* persIpcPASLoopThread(void *lpParam);
+
+/* PCL DBus loop thread */
+static void* persIpcPCLLoopThread(void *lpParam);
+
+/* PCL DBus initialization function */
+static sint_t persIpcInitPCL_DBus_high();
+
+/* Get DBus client ID */
+static sint_t persIpcGetIdForDBusInfo(const pstr_t busName,
+ const pstr_t objName,
+ uint32_t *clientID);
+
+/* Export org.genivi.persistence.admin interface */
+static bool_t ExportPersistenceAdminIF(GDBusConnection *connection);
+
+/* Export org.genivi.persistence.adminconsumer interface */
+static bool_t ExportPersistenceAdminConsumerIF(GDBusConnection *connection);
+
+
+
+/**
+ * \brief Initialize PAS IPC DBus component
+ *
+ * \note : The function creates the DBus connection and tries to obtain the DBus name
+ * and exports the org.genivi.persistence.admin interface.
+ * It runs the DBus main loop on a second thread.
+ *
+ * \param pInitInfo [in] pointer to a \ref PersAdminPASInitInfo_s structure containing
+ * the supported callbacks
+ *
+ * \return 0 for success, negative value for error (\ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+sint_t persIpcInitPAS_DBus_high(PersAdminPASInitInfo_s *pInitInfo)
+{
+ sint_t retVal = PERS_COM_SUCCESS;
+
+ if(NIL == pInitInfo)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Invalid parameter in persIpcInitPAS_DBus_high call."));
+ return PERS_COM_ERR_INVALID_PARAM;
+ }
+
+ if((NIL == pInitInfo->pRegCB) ||
+ (NIL == pInitInfo->pUnRegCB) ||
+ (NIL == pInitInfo->pReqCompleteCB))
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Invalid parameter in persIpcInitPAS_DBus_high call."));
+ return PERS_COM_ERR_INVALID_PARAM;
+ }
+
+ g_pPersIpcPASInfo.pRegCB = pInitInfo->pRegCB;
+ g_pPersIpcPASInfo.pUnRegCB = pInitInfo->pUnRegCB;
+ g_pPersIpcPASInfo.pReqCompleteCB = pInitInfo->pReqCompleteCB;
+
+ /* Init synchronization objects */
+ if(0 != pthread_mutex_init (&g_persIpcDBusClientInfoArrayMtx, NIL))
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to create mutex."));
+ return PERS_COM_FAILURE;
+ }
+ if(0 != pthread_mutex_init (&g_PASDBusMainLoopThreadFlagMtx, NIL))
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to create mutex."));
+ (void)pthread_mutex_destroy(&g_persIpcDBusClientInfoArrayMtx);
+ return PERS_COM_FAILURE;
+ }
+ if(0 != pthread_cond_init (&g_PASDBusMainLoopThreadFlagCV, NIL))
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to create thread cond."));
+ (void)pthread_mutex_destroy(&g_PASDBusMainLoopThreadFlagMtx);
+ (void)pthread_mutex_destroy(&g_persIpcDBusClientInfoArrayMtx);
+ return PERS_COM_FAILURE;
+ }
+ g_PASDBusMainLoopThreadFlag = 0;
+
+ /* Create DBus main loop thread */
+ if(0 != pthread_create(&g_hPASDBusThread, NIL, persIpcPASLoopThread, NIL))
+ {
+
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to create thread."));
+ (void)pthread_cond_destroy(&g_PASDBusMainLoopThreadFlagCV);
+ (void)pthread_mutex_destroy(&g_PASDBusMainLoopThreadFlagMtx);
+ (void)pthread_mutex_destroy(&g_persIpcDBusClientInfoArrayMtx);
+ return PERS_COM_FAILURE;
+ }
+
+ /* Wait for DBus connection initialization */
+ if(0 != pthread_mutex_lock (&g_PASDBusMainLoopThreadFlagMtx))
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to lock mutex."));
+ return PERS_COM_FAILURE;
+ }
+ while (!g_PASDBusMainLoopThreadFlag)
+ {
+ (void)pthread_cond_wait (&g_PASDBusMainLoopThreadFlagCV, &g_PASDBusMainLoopThreadFlagMtx);
+ }
+ (void)pthread_mutex_unlock (&g_PASDBusMainLoopThreadFlagMtx);
+
+ if(false == g_bPASDBusConnInit)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("PAS DBus connection setup failed."));
+
+ (void)pthread_cond_destroy(&g_PASDBusMainLoopThreadFlagCV);
+ (void)pthread_mutex_destroy(&g_PASDBusMainLoopThreadFlagMtx);
+ (void)pthread_mutex_destroy(&g_persIpcDBusClientInfoArrayMtx);
+
+ return PERS_COM_FAILURE; /* PERS_COM_IPC_DBUS_ERROR */
+ }
+
+ return retVal;
+}
+
+
+/**
+ * \brief Sends over DBus a request to the PCL client specified by clientId.
+ * \note : Each requestId should be unique.
+ *
+ * \param clientID [in] the client ID returned by the supplied pRegCB callback
+ * \param requestID [in] a unique identifier generated for every request
+ * \param request [in] the request to be sent (bitfield using a valid
+ * combination of any of the following flags :
+ * ::PERSISTENCE_MODE_LOCK, ::PERSISTENCE_MODE_SYNC and ::PERSISTENCE_MODE_UNLOCK)
+ *
+ * \return 0 for success, negative value for error (see \ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+sint_t persIpcSendRequestToPCL_DBus_high( sint_t clientID,
+ sint_t requestID,
+ uint_t request)
+{
+ sint_t retVal = PERS_COM_SUCCESS;
+/* gboolean gbRetVal = false; */
+ gint32 outErrorCode = PERS_COM_SUCCESS;
+ persIpcDBusClientInfo_s dbusClientInfo;
+/* OipPersistenceAdminconsumerProxy *pClientNotifProxy = NIL; */
+ GError *gError = NIL;
+ GVariant *gVarReturnVal = NIL;
+ gint clientTimeout = 500; /* default timeout in ms */
+
+ if(false == g_bPASDBusConnInit)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("DBus connection not initialized."));
+ return PERS_COM_FAILURE; /* PERS_COM_IPC_ERR_NO_CONNECTION */
+ }
+
+ (void)memset(&dbusClientInfo, 0, sizeof(dbusClientInfo));
+
+
+ /* Get client DBus info */
+
+ /* Acquire mutex on array of DBus client info */
+ if(0 != pthread_mutex_lock (&g_persIpcDBusClientInfoArrayMtx))
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to lock mutex."));
+ return PERS_COM_FAILURE;
+ }
+
+ if(clientID >= g_persIpcDBusClientInfoArraySize)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR, DLT_STRING(LT_HDR),
+ DLT_STRING("Invalid client specified :"),
+ DLT_INT(clientID));
+ (void)pthread_mutex_unlock (&g_persIpcDBusClientInfoArrayMtx);
+ return PERS_COM_ERR_INVALID_PARAM;
+ }
+
+ if(NIL != g_persIpcDBusClientInfoArray[clientID])
+ {
+ dbusClientInfo.busName = (pstr_t)malloc((strlen(g_persIpcDBusClientInfoArray[clientID]->busName) + 1) * sizeof(*(dbusClientInfo.busName)));
+ if(NIL == dbusClientInfo.busName)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Error allocating memory for client info data."));
+ (void)pthread_mutex_unlock (&g_persIpcDBusClientInfoArrayMtx);
+ return PERS_COM_ERR_MALLOC;
+ }
+ else
+ {
+ (void)memset(dbusClientInfo.busName, 0, (strlen(g_persIpcDBusClientInfoArray[clientID]->busName) + 1) * sizeof(*(dbusClientInfo.busName)));
+ (void)memcpy(dbusClientInfo.busName, g_persIpcDBusClientInfoArray[clientID]->busName, strlen(g_persIpcDBusClientInfoArray[clientID]->busName) * sizeof(*(dbusClientInfo.busName)));
+ }
+
+ dbusClientInfo.objName = (pstr_t)malloc((strlen(g_persIpcDBusClientInfoArray[clientID]->objName) + 1) * sizeof(*(dbusClientInfo.objName)));
+ if(NIL == dbusClientInfo.objName)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Error allocating memory for client info data."));
+ (void)free(dbusClientInfo.busName);
+ (void)pthread_mutex_unlock (&g_persIpcDBusClientInfoArrayMtx);
+ return PERS_COM_ERR_MALLOC;
+ }
+ else
+ {
+ (void)memset(dbusClientInfo.objName, 0, (strlen(g_persIpcDBusClientInfoArray[clientID]->objName) + 1) * sizeof(*(dbusClientInfo.objName)));
+ (void)memcpy(dbusClientInfo.objName, g_persIpcDBusClientInfoArray[clientID]->objName, strlen(g_persIpcDBusClientInfoArray[clientID]->objName) * sizeof(*(dbusClientInfo.objName)));
+ }
+ }
+
+ /* Release array mutex */
+ (void)pthread_mutex_unlock (&g_persIpcDBusClientInfoArrayMtx);
+
+
+ /* Synchronous call to "PersistenceAdminRequest" */
+
+ /* Does not work using generated code because PCL does not contain an implementation of 'GetAll' : */
+ /*
+ * checkPersAdminMsg 'org.freedesktop.DBus.Properties' -> 'GetAll'
+ * handleObjectPathMessageFallback Object: ':1.11' -> Interface: 'org.freedesktop.DBus.Properties' -> Message: 'GetAll'
+ * handleObjectPathMessageFallback -> not a signal 'GetAll'
+ */
+
+ /* TO DO : un-comment when PCL implementation is adapted to PersCommonIPC */
+
+ /* Get the proxy object */
+// pClientNotifProxy = NIL;
+// pClientNotifProxy = (OipPersistenceAdminconsumerProxy *)oip_persistence_adminconsumer_proxy_new_sync( g_pPASDBusConnection,
+// G_DBUS_PROXY_FLAGS_NONE,
+// dbusClientInfo.busName,
+// dbusClientInfo.objName,
+// NIL,
+// NIL);
+// if(NIL == pClientNotifProxy)
+// {
+// DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+// DLT_STRING("DBus PersAdminConsumer proxy creation failed."));
+// (void)free(dbusClientInfo.busName);
+// (void)free(dbusClientInfo.objName);
+// return PERS_COM_FAILURE; /* PERS_COM_IPC_DBUS_ERROR */
+// }
+//
+// (void)free(dbusClientInfo.busName);
+// (void)free(dbusClientInfo.objName);
+//
+// /* Synchronous call to "PersistenceAdminRequest" */
+// gbRetVal = oip_persistence_adminconsumer_call_persistence_admin_request_sync( (OipPersistenceAdminconsumer *)pClientNotifProxy,
+// (gint)request,
+// (guint)requestID,
+// &outErrorCode,
+// NIL,
+// &gError);
+//
+// /* Release the created proxy object */
+// g_object_unref(pClientNotifProxy);
+// pClientNotifProxy = NIL;
+//
+// if(false == gbRetVal)
+// {
+// DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+// DLT_STRING("DBus PersistenceAdminRequest call failed with DBus error :"),
+// DLT_STRING(gError->message));
+// g_error_free(gError);
+// return PERS_COM_FAILURE; /* PERS_COM_IPC_DBUS_ERROR */
+// }
+
+ gVarReturnVal = g_dbus_connection_call_sync ( g_pPASDBusConnection,
+ dbusClientInfo.busName,
+ dbusClientInfo.objName,
+ PERSISTENCE_ADMIN_CONSUMER_IFACE,
+ PERSISTENCE_ADMIN_CONSUMER_METHOD_PERS_ADMIN_REQ,
+ g_variant_new ("(ii)", (sint32_t)request, (sint32_t)requestID),
+ G_VARIANT_TYPE ("(i)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ clientTimeout,
+ NIL,
+ &gError);
+ if(NIL == gVarReturnVal)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("DBus PersistenceAdminRequest call failed with DBus error :"),
+ DLT_STRING(gError->message));
+ g_error_free(gError);
+ (void)free(dbusClientInfo.busName);
+ (void)free(dbusClientInfo.objName);
+
+ /* consider that PCL client is not available on DBus */
+ return PERS_COM_IPC_ERR_PCL_NOT_AVAILABLE;
+ }
+
+ outErrorCode = g_variant_get_int32(gVarReturnVal);
+
+ g_variant_unref(gVarReturnVal);
+
+
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_DEBUG, DLT_STRING(LT_HDR),
+ DLT_STRING("Notified client identified by DBus Name : \""),
+ DLT_STRING(dbusClientInfo.busName),
+ DLT_STRING("\" and Object Path : \""),
+ DLT_STRING(dbusClientInfo.objName),
+ DLT_STRING("\" Flags="),
+ DLT_INT(request),
+ DLT_STRING(" RequestId="),
+ DLT_INT(requestID),
+ DLT_STRING("\". Client returned "),
+ DLT_INT(outErrorCode));
+
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_DEBUG,DLT_STRING(LT_HDR),
+ DLT_STRING("DBus PersistenceAdminRequest call returned output error code :"),
+ DLT_INT(outErrorCode));
+
+ (void)free(dbusClientInfo.busName);
+ (void)free(dbusClientInfo.objName);
+
+ retVal = outErrorCode;
+
+ return retVal;
+}
+
+
+/**
+ * \brief Register PCL client to PAS over DBus
+ *
+ * \note : An additional thread is created for communication purposes.
+ * Initialize members of the supplied PersAdminPCLInitInfo_s structure before calling this function.
+ *
+ * \param pInitInfo [in] pointer to a \ref PersAdminPCLInitInfo_s structure containing
+ * the supported callbacks
+ * \param flags [in] supported notification flags
+ * \param timeout [in] maximum time needed to process any supported request
+ *
+ * \return 0 for success, negative value for error (see \ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+sint_t persIpcRegisterToPAS_DBus_high( PersAdminPCLInitInfo_s * pInitInfo,
+ uint_t flags,
+ uint_t timeout)
+{
+ sint_t retVal = PERS_COM_SUCCESS;
+ gboolean gbRetVal = false;
+ const gchar *gUniqueName = NIL;
+ gint outErrorCode;
+ GError *gError = NIL;
+
+
+ if(NIL == pInitInfo)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Invalid parameter in persIpcRegisterToPAS_DBus_high call."));
+ return PERS_COM_ERR_INVALID_PARAM;
+ }
+
+ if(NIL == pInitInfo->pReqCB)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Invalid parameter in persIpcRegisterToPAS_DBus_high call."));
+ return PERS_COM_ERR_INVALID_PARAM;
+ }
+
+ g_pPersIpcPCLInfo.pReqCB = pInitInfo->pReqCB;
+
+ /* Init DBus connection */
+ if(false == g_bPCLDBusConnInit)
+ {
+ retVal = persIpcInitPCL_DBus_high();
+ if(PERS_COM_SUCCESS != retVal)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("persIpcRegisterToPAS_DBus_high call failed with error code :"),
+ DLT_INT(retVal));
+ return retVal;
+ }
+ }
+
+ if(NIL == g_persIpcDBusPASProxy)
+ {
+ /* Get the PAS proxy object */
+ g_persIpcDBusPASProxy = (OipPersistenceAdminProxy *)oip_persistence_admin_proxy_new_sync( g_pPCLDBusConnection,
+ G_DBUS_PROXY_FLAGS_NONE,
+ PERSISTENCE_ADMIN_BUS_NAME,
+ PERSISTENCE_ADMIN_OBJ_PATH,
+ NIL,
+ NIL);
+ if(NIL == g_persIpcDBusPASProxy)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("DBus PersAdmin proxy creation failed."));
+ return PERS_COM_FAILURE; /* PERS_COM_IPC_DBUS_ERROR */
+ }
+ }
+
+ gUniqueName = g_dbus_connection_get_unique_name(g_pPCLDBusConnection);
+ if(NIL == gUniqueName)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to obtain the unique DBus name."));
+ return PERS_COM_FAILURE; /* PERS_COM_IPC_ERR_NO_CONNECTION */
+ }
+ else
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_DEBUG,DLT_STRING(LT_HDR),
+ DLT_STRING("Successfully obtained unique BusName :"),
+ DLT_STRING(gUniqueName));
+ }
+
+ /* Synchronous call to "RegisterPersAdminNotification" */
+ gbRetVal = oip_persistence_admin_call_register_pers_admin_notification_sync((OipPersistenceAdmin *)g_persIpcDBusPASProxy,
+ gUniqueName,
+ PERSISTENCE_ADMIN_CONSUMER_OBJ_PATH,
+ (gint)flags,
+ (guint)timeout,
+ &outErrorCode,
+ NIL,
+ &gError);
+ if(false == gbRetVal)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("DBus RegisterPersAdminNotification call failed with DBus error :"),
+ DLT_STRING(gError->message));
+ g_error_free(gError);
+ return PERS_COM_FAILURE; /* PERS_COM_IPC_DBUS_ERROR */
+ }
+
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_DEBUG,DLT_STRING(LT_HDR),
+ DLT_STRING("DBus RegisterPersAdminNotification call returned output error code :"),
+ DLT_INT(outErrorCode));
+
+ retVal = outErrorCode;
+
+ return retVal;
+}
+
+
+/**
+ * \brief Initialize PCL IPC DBus component
+ *
+ * \note : An additional thread is created for communication purposes.
+ *
+ * \return 0 for success, negative value for error (\ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+static sint_t persIpcInitPCL_DBus_high()
+{
+
+ sint_t retVal = PERS_COM_SUCCESS;
+ bool_t bRetVal;
+
+ if(0 != pthread_mutex_init (&g_PCLDBusMainLoopThreadFlagMtx, NIL))
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to create mutex."));
+ return PERS_COM_FAILURE;
+ }
+
+ if(0 != pthread_cond_init (&g_PCLDBusMainLoopThreadFlagCV, NIL))
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to create thread cond."));
+ (void)pthread_mutex_destroy(&g_PCLDBusMainLoopThreadFlagMtx);
+ return PERS_COM_FAILURE;
+ }
+
+ g_PCLDBusMainLoopThreadFlag = 0;
+
+ if(0 != pthread_create(&g_hPCLDBusThread, NIL, persIpcPCLLoopThread, NIL))
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to create thread."));
+ (void)pthread_cond_destroy(&g_PCLDBusMainLoopThreadFlagCV);
+ (void)pthread_mutex_destroy(&g_PCLDBusMainLoopThreadFlagMtx);
+ return PERS_COM_FAILURE;
+ }
+
+ /* Wait for DBus connection */
+ if(0 != pthread_mutex_lock (&g_PCLDBusMainLoopThreadFlagMtx))
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to lock mutex."));
+ return PERS_COM_FAILURE;
+ }
+ while (!g_PCLDBusMainLoopThreadFlag)
+ {
+ pthread_cond_wait (&g_PCLDBusMainLoopThreadFlagCV, &g_PCLDBusMainLoopThreadFlagMtx);
+ }
+ (void)pthread_mutex_unlock (&g_PCLDBusMainLoopThreadFlagMtx);
+
+ /* Check DBus connection status */
+ if(false == g_bPCLDBusConnInit)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("PCL DBus connection setup failed."));
+ (void)pthread_cond_destroy(&g_PCLDBusMainLoopThreadFlagCV);
+ (void)pthread_mutex_destroy(&g_PCLDBusMainLoopThreadFlagMtx);
+ return PERS_COM_FAILURE; /* PERS_COM_IPC_DBUS_ERROR */
+ }
+
+ /* Export the org.genivi.persistence.adminconsumer interface over DBus */
+ bRetVal = ExportPersistenceAdminConsumerIF(g_pPCLDBusConnection);
+ if(false == bRetVal)
+ {
+ /* Error: the interface could not be exported. */
+ g_main_loop_quit(g_pPCLMainLoop);
+ }
+ else
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR),
+ DLT_STRING("Successfully connected to D-Bus and exported object."));
+ }
+
+ return retVal;
+}
+
+
+/**
+ * \brief Un-Register PCL client application from PAS over DBus
+ * \note : The additional thread created for communication purposes is stopped.
+ *
+ * \param flags [in] supported notification flags
+ *
+ * \return 0 for success, negative value for error (\ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+sint_t persIpcUnRegisterFromPAS_DBus_high( uint_t flags)
+{
+ sint_t retVal = PERS_COM_SUCCESS;
+ gboolean gbRetVal = false;
+ const gchar *gUniqueName = NIL;
+ gint outErrorCode;
+ GError *gError = NIL;
+
+ if(false == g_bPCLDBusConnInit)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("DBus connection not initialized."));
+ return PERS_COM_FAILURE; /* PERS_COM_IPC_ERR_NO_CONNECTION */
+ }
+
+ if(NIL == g_persIpcDBusPASProxy)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("DBus PersAdmin proxy not available."));
+ return PERS_COM_FAILURE; /* PERS_COM_IPC_DBUS_ERROR */
+ }
+
+ gUniqueName = g_dbus_connection_get_unique_name(g_pPCLDBusConnection);
+ if(NIL == gUniqueName)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to obtain the unique DBus name."));
+ return PERS_COM_FAILURE; /* PERS_COM_IPC_ERR_NO_CONNECTION */
+ }
+
+ /* Synchronous call to "UnRegisterPersAdminNotification" */
+ gbRetVal = oip_persistence_admin_call_un_register_pers_admin_notification_sync( (OipPersistenceAdmin *)g_persIpcDBusPASProxy,
+ gUniqueName,
+ PERSISTENCE_ADMIN_CONSUMER_OBJ_PATH,
+ (gint)flags,
+ (guint)0, // deprecated
+ &outErrorCode,
+ NIL,
+ &gError);
+ if(false == gbRetVal)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("DBus UnRegisterPersAdminNotification call failed with DBus error :"),
+ DLT_STRING(gError->message));
+ g_error_free(gError);
+ return PERS_COM_FAILURE; /* PERS_COM_IPC_DBUS_ERROR */
+ }
+
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_DEBUG,DLT_STRING(LT_HDR),
+ DLT_STRING("DBus UnRegisterPersAdminNotification call returned output error code :"),
+ DLT_INT(outErrorCode));
+
+ retVal = outErrorCode;
+
+ /* Quit DBus main loop */
+ g_main_loop_quit(g_pPCLMainLoop);
+
+ /* Wait for persIpcPCLLoopThread */
+ pthread_join(g_hPCLDBusThread, NIL);
+
+ /* Release any created proxy object */
+ if(NIL != g_persIpcDBusPASProxy)
+ {
+ g_object_unref(g_persIpcDBusPASProxy);
+ g_persIpcDBusPASProxy = NIL;
+ }
+
+ return retVal;
+}
+
+
+/**
+ * \brief Send 'request processed' confirmation to PAS over DBus
+ * \note : Send confirmation to PAS that the request specified by requestId has been processed.
+ * The status parameter should reflect this request and could also return an error.
+ *
+ * \param requestID [in] the ID of the processed request
+ * \param status [in] the status of the request processed by PCL
+ * - In case of success: bitfield using any of the following flags, depending on the request : ::PERSISTENCE_STATUS_LOCKED.
+ * - In case of error: the sum of ::PERSISTENCE_STATUS_ERROR and an error code \ref PERS_COM_IPC_DEFINES_ERROR is returned.
+ *
+ * \return 0 for success, negative value for error (see \ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+sint_t persIpcSendConfirmationToPAS_DBus_high( sint_t requestID,
+ uint_t status)
+{
+ gboolean gbRetVal = false;
+ gint outErrorCode;
+ GError *gError = NIL;
+
+ if(false == g_bPCLDBusConnInit)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("DBus connection not initialized."));
+ return PERS_COM_FAILURE; /* PERS_COM_IPC_ERR_NO_CONNECTION */
+ }
+
+ if(NIL == g_persIpcDBusPASProxy)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("DBus PersAdmin proxy not available."));
+ return PERS_COM_FAILURE; /* PERS_COM_IPC_DBUS_ERROR */
+ }
+
+ /* Synchronous call to "PersistenceAdminRequestCompleted" */
+ gbRetVal = oip_persistence_admin_call_persistence_admin_request_completed_sync( (OipPersistenceAdmin *)g_persIpcDBusPASProxy,
+ (guint)requestID,
+ (gint)status,
+ &outErrorCode,
+ NIL,
+ &gError);
+ if(false == gbRetVal)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("DBus PersistenceAdminRequestCompleted call failed with DBus error :"),
+ DLT_STRING(gError->message));
+ g_error_free(gError);
+ return PERS_COM_FAILURE; /* PERS_COM_IPC_DBUS_ERROR */
+ }
+
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_DEBUG,DLT_STRING(LT_HDR),
+ DLT_STRING("DBus PersistenceAdminRequestCompleted call returned output error code :"),
+ DLT_INT(outErrorCode));
+
+ return (sint_t)outErrorCode;
+}
+
+
+/**
+ * \brief Connection to DBus callback
+ *
+ * \note The function is called when a connection to the D-Bus could be established.
+ * According to the documentation the objects should be exported here.
+ *
+ * \param connection [in] Connection, which was acquired
+ * \param name [in] Bus name
+ * \param user_data [in] Optionally user data
+ *
+ * \return void
+ */
+static void OnBusAcquired_cb( GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ bool_t bRetVal;
+
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_DEBUG,DLT_STRING(LT_HDR),
+ DLT_STRING("Successfully connected to DBus"));
+
+ /* Store the connection. */
+ g_pPASDBusConnection = connection;
+
+ /* Export the org.genivi.persistence.admin interface over DBus */
+ bRetVal = ExportPersistenceAdminIF(connection);
+ if(false == bRetVal)
+ {
+ /* Error: the interface could not be exported. */
+ g_main_loop_quit(g_pPASMainLoop);
+ }
+ else
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR),
+ DLT_STRING("Successfully connected to D-Bus and exported object."));
+ }
+}
+
+
+/**
+ * \brief DBus name obtained callback
+ *
+ * \note The function is called when the "bus name" could be acquired on the D-Bus.
+ *
+ * \param connection [in] Connection over which the bus name was acquired
+ * \param name [in] Acquired bus name
+ * \param user_data [in] Optionally user data
+ *
+ * \return void
+ */
+static void OnNameAcquired_cb( GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR),
+ DLT_STRING("Successfully obtained D-Bus name:"), DLT_STRING(name));
+
+ /* DBus connection initialized */
+ g_bPASDBusConnInit = true;
+
+ /* Notify that the DBus connection is ready */
+ if(0 != pthread_mutex_lock (&g_PASDBusMainLoopThreadFlagMtx))
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to lock mutex."));
+ return;
+ }
+ g_PASDBusMainLoopThreadFlag = DBUS_MAIN_LOOP_THREAD_FLAG_SET;
+ (void)pthread_cond_signal (&g_PASDBusMainLoopThreadFlagCV);
+ (void)pthread_mutex_unlock (&g_PASDBusMainLoopThreadFlagMtx);
+}
+
+
+/**
+ * \brief DBus name lost callback
+ *
+ * \note The function is called if either no connection to D-Bus could be established or
+ * the bus name could not be acquired.
+ *
+ * \param connection [in] Connection. If it is NIL, no D-Bus connection could be established.
+ * Otherwise the bus name was lost.
+ * \param name [in] Bus name
+ * \param user_data [in] Optionally user data
+ *
+ * \return void
+ */
+static void OnNameLost_cb( GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data )
+{
+ uint32_t clientIdx;
+
+ if(NIL == connection)
+ {
+ /* Error: the connection could not be established. */
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to establish D-Bus connection."));
+ }
+ else
+ {
+ /* Error: connection established, but name not obtained. This might be a second instance of the application */
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to obtain / Lost D-Bus name :"),
+ DLT_STRING(name));
+ }
+
+ /* DBus connection lost */
+ g_bPASDBusConnInit = false;
+
+ /* In both cases leave the main loop. */
+ g_main_loop_quit(g_pPASMainLoop);
+
+ /* Notify the DBus connection is not ready */
+ if(0 != pthread_mutex_lock (&g_PASDBusMainLoopThreadFlagMtx))
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to lock mutex."));
+ return;
+ }
+ g_PASDBusMainLoopThreadFlag = DBUS_MAIN_LOOP_THREAD_FLAG_SET;
+ (void)pthread_cond_signal (&g_PASDBusMainLoopThreadFlagCV);
+ (void)pthread_mutex_unlock (&g_PASDBusMainLoopThreadFlagMtx);
+
+ /* Acquire mutex on array of DBus client info */
+ if(0 != pthread_mutex_lock(&g_persIpcDBusClientInfoArrayMtx))
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to lock mutex."));
+ }
+ else
+ {
+ for(clientIdx = 0; clientIdx < g_persIpcDBusClientInfoArraySize; clientIdx++)
+ {
+ if(NIL != g_persIpcDBusClientInfoArray[clientIdx])
+ {
+ if(NIL != g_persIpcDBusClientInfoArray[clientIdx]->busName)
+ {
+ (void)free(g_persIpcDBusClientInfoArray[clientIdx]->busName);
+ }
+ if(NIL != g_persIpcDBusClientInfoArray[clientIdx]->objName)
+ {
+ (void)free(g_persIpcDBusClientInfoArray[clientIdx]->objName);
+ }
+ }
+ }
+ (void)pthread_mutex_unlock(&g_persIpcDBusClientInfoArrayMtx);
+ }
+}
+
+/**
+ * \brief RegisterPersAdminNotification DBus method callback
+ *
+ * \note Handler for RegisterPersAdminNotification.
+ * Signature based on generated code.
+ */
+static gboolean OnHandleRegisterPersAdminNotification ( OipPersistenceAdmin *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_BusName,
+ const gchar *arg_ObjName,
+ gint arg_NotificationFlag,
+ guint arg_TimeoutMs)
+{
+ sint_t retVal = PERS_COM_SUCCESS;
+ uint32_t clientId;
+
+ persIpcDBusClientInfo_s **tmpPersIpcDBusClientInfoArray = NIL;
+ persIpcDBusClientInfo_s *pNewClientInfo = NIL;
+
+ if((NIL == arg_BusName) || (NIL == arg_ObjName))
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Invalid parameter in RegisterPersAdminNotification handler."));
+ retVal = PERS_COM_ERR_INVALID_PARAM;
+ oip_persistence_admin_complete_register_pers_admin_notification( object,
+ invocation,
+ (gint)retVal);
+ return(TRUE);
+ }
+
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_DEBUG, DLT_STRING(LT_HDR),
+ DLT_STRING("RegisterPersAdminNotification called for BusName :"),
+ DLT_STRING(arg_BusName),
+ DLT_STRING("and ObjName :"),
+ DLT_STRING(arg_ObjName),
+ DLT_STRING("with params : NotificationFlag="),
+ DLT_INT(arg_NotificationFlag),
+ DLT_STRING(" TimeoutMs="),
+ DLT_INT(arg_TimeoutMs));
+
+ /* Check if the client is already registered */
+ retVal = persIpcGetIdForDBusInfo( (pstr_t)arg_BusName,
+ (pstr_t)arg_ObjName,
+ &clientId);
+ if(PERS_COM_SUCCESS == retVal)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_WARN, DLT_STRING(LT_HDR),
+ DLT_STRING("DBus client already registered with BusName :"),
+ DLT_STRING(arg_BusName),
+ DLT_STRING("and ObjName :"),
+ DLT_STRING(arg_ObjName));
+ retVal = PERS_COM_FAILURE; /* PERS_COM_IPC_ERR_ALREADY_DONE */
+ oip_persistence_admin_complete_register_pers_admin_notification( object,
+ invocation,
+ (gint)retVal);
+ return(TRUE);
+ }
+
+ /* Acquire mutex on array of DBus client info */
+ if(0 != pthread_mutex_lock (&g_persIpcDBusClientInfoArrayMtx))
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to lock mutex."));
+ retVal = PERS_COM_FAILURE;
+ oip_persistence_admin_complete_register_pers_admin_notification( object,
+ invocation,
+ (gint)retVal);
+ return(TRUE);
+ }
+
+ /* Add DBus info for the new client */
+ if(g_persIpcDBusClientInfoArraySize >= g_persIpcDBusClientInfoMaxArraySize)
+ {
+ if(g_persIpcDBusClientInfoArraySize > 0)
+ {
+ tmpPersIpcDBusClientInfoArray = g_persIpcDBusClientInfoArray;
+
+ g_persIpcDBusClientInfoMaxArraySize *= 2;
+ }
+ else
+ {
+ g_persIpcDBusClientInfoMaxArraySize = PERS_IPC_INIT_DBUS_INFO_ARRAY_SIZE;
+ }
+
+ g_persIpcDBusClientInfoArray = (persIpcDBusClientInfo_s**)malloc(g_persIpcDBusClientInfoMaxArraySize * sizeof(*g_persIpcDBusClientInfoArray));
+ if(NIL == g_persIpcDBusClientInfoArray)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Error allocating memory for client info mapping list."));
+ g_persIpcDBusClientInfoArray = tmpPersIpcDBusClientInfoArray;
+ (void)pthread_mutex_unlock (&g_persIpcDBusClientInfoArrayMtx);
+ retVal = PERS_COM_ERR_MALLOC;
+ oip_persistence_admin_complete_register_pers_admin_notification( object,
+ invocation,
+ (gint)retVal);
+ return(TRUE);
+ }
+ else
+ {
+ (void)memset(g_persIpcDBusClientInfoArray, 0, g_persIpcDBusClientInfoMaxArraySize * sizeof(*g_persIpcDBusClientInfoArray));
+ }
+
+ if(g_persIpcDBusClientInfoArraySize > 0)
+ {
+ (void)memcpy(g_persIpcDBusClientInfoArray, tmpPersIpcDBusClientInfoArray, g_persIpcDBusClientInfoArraySize * sizeof(*g_persIpcDBusClientInfoArray));
+ }
+ }
+
+ pNewClientInfo = NIL;
+ pNewClientInfo = (persIpcDBusClientInfo_s*)malloc(sizeof(*pNewClientInfo));
+ if(NIL == pNewClientInfo)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Error allocating memory for client info."));
+ (void)pthread_mutex_unlock (&g_persIpcDBusClientInfoArrayMtx);
+ retVal = PERS_COM_ERR_MALLOC;
+ oip_persistence_admin_complete_register_pers_admin_notification( object,
+ invocation,
+ (gint)retVal);
+ return(TRUE);
+ }
+ else
+ {
+ (void)memset(pNewClientInfo, 0, sizeof(*pNewClientInfo));
+ }
+
+ /* received Bus Name should be a null terminated string */
+ pNewClientInfo->busName = (pstr_t)malloc((strlen(arg_BusName) + 1) * sizeof(*(pNewClientInfo->busName)));
+ if(NIL == pNewClientInfo->busName)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Error allocating memory for client info data (busName)."));
+ (void)free(pNewClientInfo);
+ pNewClientInfo = NIL;
+ (void)pthread_mutex_unlock (&g_persIpcDBusClientInfoArrayMtx);
+ retVal = PERS_COM_ERR_MALLOC;
+ oip_persistence_admin_complete_register_pers_admin_notification( object,
+ invocation,
+ (gint)retVal);
+ return(TRUE);
+ }
+ else
+ {
+ (void)memset(pNewClientInfo->busName, 0, (strlen(arg_BusName) + 1) * sizeof(*(pNewClientInfo->busName)));
+ (void)memcpy(pNewClientInfo->busName, arg_BusName, (strlen(arg_BusName) * sizeof(*(pNewClientInfo->busName))));
+ }
+
+ // received object name should be a null terminated string
+ pNewClientInfo->objName = (pstr_t)malloc((strlen(arg_ObjName) + 1) * sizeof(*(pNewClientInfo->objName)));/*DG C8MR2R-MISRA-C:2004 Rule 20.4-SSW_Administrator_0002*/
+ if(NIL == pNewClientInfo->objName)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Error allocating memory for client info data (objName)."));
+ (void)free(pNewClientInfo->busName);
+ (void)free(pNewClientInfo);
+ pNewClientInfo = NIL;
+ (void)pthread_mutex_unlock (&g_persIpcDBusClientInfoArrayMtx);
+ retVal = PERS_COM_ERR_MALLOC;
+ oip_persistence_admin_complete_register_pers_admin_notification( object,
+ invocation,
+ (gint)retVal);
+ return(TRUE);
+ }
+ else
+ {
+ (void)memset(pNewClientInfo->objName, 0, (strlen(arg_ObjName) + 1) * sizeof(*(pNewClientInfo->objName)));
+ (void)memcpy(pNewClientInfo->objName, arg_ObjName, (strlen(arg_ObjName) * sizeof(*(pNewClientInfo->objName))));
+ }
+
+ g_persIpcDBusClientInfoArray[g_persIpcDBusClientInfoArraySize++] = pNewClientInfo;
+
+ clientId = g_persIpcDBusClientInfoArraySize - 1;
+
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_DEBUG, DLT_STRING(LT_HDR),
+ DLT_STRING("ClientId :"),
+ DLT_UINT32(clientId),
+ DLT_STRING("for BusName :"),
+ DLT_STRING(arg_BusName),
+ DLT_STRING("and ObjName :"),
+ DLT_STRING(arg_ObjName));
+
+ /* Release array mutex */
+ (void)pthread_mutex_unlock (&g_persIpcDBusClientInfoArrayMtx);
+
+ /* Forward the call to the PAS callback */
+ retVal = g_pPersIpcPASInfo.pRegCB( clientId, /* clientId is the array index */
+ arg_NotificationFlag,
+ arg_TimeoutMs);
+ if(PERS_COM_SUCCESS != retVal)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR, DLT_STRING(LT_HDR),
+ DLT_STRING("RegisterPersAdminNotification client callback failed with error code :"),
+ DLT_INT(retVal));
+
+ /*
+ * remove the registered client if the PAS callback returned an error,
+ * and forward the error to the PCL client
+ */
+
+ if(0 != pthread_mutex_lock (&g_persIpcDBusClientInfoArrayMtx))
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to lock mutex."));
+ }else
+ {
+ (void)free(g_persIpcDBusClientInfoArray[clientId]->busName);
+ (void)free(g_persIpcDBusClientInfoArray[clientId]->objName);
+ (void)free(g_persIpcDBusClientInfoArray[clientId]);
+ g_persIpcDBusClientInfoArray[clientId] = NIL;
+ --g_persIpcDBusClientInfoArraySize;
+
+ (void)pthread_mutex_unlock (&g_persIpcDBusClientInfoArrayMtx);
+ }
+ }
+
+ oip_persistence_admin_complete_register_pers_admin_notification( object,
+ invocation,
+ (gint)retVal);
+
+ return(TRUE);
+}
+
+
+/**
+ * \brief UnregisterPersAdminNotification DBus method callback
+ *
+ * \note Handler for UnregisterPersAdminNotification.
+ * Signature based on generated code.
+ */
+static gboolean OnHandleUnregisterPersAdminNotification(OipPersistenceAdmin *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_BusName,
+ const gchar *arg_ObjName,
+ gint arg_NotificationFlag,
+ guint arg_TimeoutMs) /* currently not used */
+{
+ sint_t retVal = PERS_COM_SUCCESS;
+ uint32_t clientId;
+
+ if((NIL == arg_BusName) || (NIL == arg_ObjName))
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Invalid parameter in UnregisterPersAdminNotification handler."));
+ retVal = PERS_COM_ERR_INVALID_PARAM;
+ oip_persistence_admin_complete_un_register_pers_admin_notification( object,
+ invocation,
+ (gint)retVal);
+ return(TRUE);
+ }
+
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_DEBUG, DLT_STRING(LT_HDR),
+ DLT_STRING("UnregisterPersAdminNotification called for BusName :"),
+ DLT_STRING(arg_BusName),
+ DLT_STRING("and ObjName :"),
+ DLT_STRING(arg_ObjName),
+ DLT_STRING("with params : NotificationFlag="),
+ DLT_INT(arg_NotificationFlag),
+ DLT_STRING(" TimeoutMs="),
+ DLT_INT(arg_TimeoutMs));
+
+ /* Check if client is registered */
+ retVal = persIpcGetIdForDBusInfo( (pstr_t)arg_BusName,
+ (pstr_t)arg_ObjName,
+ &clientId);
+ if(PERS_COM_SUCCESS != retVal)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_WARN, DLT_STRING(LT_HDR),
+ DLT_STRING("DBus client not registered. BusName :"),
+ DLT_STRING(arg_BusName),
+ DLT_STRING(" and ObjName :"),
+ DLT_STRING(arg_ObjName));
+ retVal = PERS_COM_ERR_NOT_FOUND;
+ oip_persistence_admin_complete_un_register_pers_admin_notification( object,
+ invocation,
+ (gint)retVal);
+ return(TRUE);
+ }
+
+ /* Forward the call to the PAS callback */
+ retVal = g_pPersIpcPASInfo.pUnRegCB(clientId, /* clientId is the array index */
+ arg_NotificationFlag);
+ if(PERS_COM_SUCCESS != retVal)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR, DLT_STRING(LT_HDR),
+ DLT_STRING("UnregisterPersAdminNotification client callback failed with error code :"),
+ DLT_INT(retVal));
+ }
+ else
+ {
+ /* remove the registered client if the PAS callback returned success */
+ if(0 != pthread_mutex_lock (&g_persIpcDBusClientInfoArrayMtx))
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to lock mutex."));
+ }
+ else
+ {
+ (void)free(g_persIpcDBusClientInfoArray[clientId]->busName);
+ (void)free(g_persIpcDBusClientInfoArray[clientId]->objName);
+ (void)free(g_persIpcDBusClientInfoArray[clientId]);
+ g_persIpcDBusClientInfoArray[clientId] = NIL;
+ (void)pthread_mutex_unlock (&g_persIpcDBusClientInfoArrayMtx);
+ }
+ }
+
+ oip_persistence_admin_complete_un_register_pers_admin_notification( object,
+ invocation,
+ (gint)retVal);
+ return(TRUE);
+}
+
+
+/**
+ * \brief PersAdminRequestCompleted DBus method callback
+ *
+ * \note Handler for PersistenceAdminRequestCompleted.
+ * Signature based on generated code.
+ */
+static gboolean OnHandlePersAdminRequestCompleted( OipPersistenceAdmin *object,
+ GDBusMethodInvocation *invocation,
+ guint arg_RequestId,
+ gint arg_StatusFlag)
+{
+ sint_t retVal = PERS_COM_SUCCESS;
+ const gchar * senderBusName = NIL;
+ uint32_t clientId;
+
+ /* Get the sender BusName */
+ senderBusName = g_dbus_method_invocation_get_sender(invocation);
+
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_DEBUG, DLT_STRING(LT_HDR),
+ DLT_STRING("PersistenceAdminRequestCompleted called by "),
+ DLT_STRING(senderBusName),
+ DLT_STRING("with params : RequestId="),
+ DLT_UINT32(arg_RequestId),
+ DLT_STRING("and StatusFlag="),
+ DLT_INT(arg_StatusFlag));
+
+ retVal = persIpcGetIdForDBusInfo( (pstr_t)senderBusName,
+ NIL,
+ &clientId);
+ if(PERS_COM_SUCCESS != retVal)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("DBus client not registered. BusName :"),
+ DLT_STRING(senderBusName));
+ retVal = PERS_COM_ERR_NOT_FOUND;
+ oip_persistence_admin_complete_persistence_admin_request_completed( object,
+ invocation,
+ (gint)retVal);
+ return (TRUE);
+ }
+
+ /* Forward the call to the PAS callback */
+ retVal = g_pPersIpcPASInfo.pReqCompleteCB( clientId,
+ arg_RequestId,
+ arg_StatusFlag);
+ if(PERS_COM_SUCCESS != retVal)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("PersistenceAdminRequestCompleted client callback failed with error code :"),
+ DLT_INT(retVal));
+ }
+
+ oip_persistence_admin_complete_persistence_admin_request_completed( object,
+ invocation,
+ (gint)retVal);
+
+ return (TRUE);
+}
+
+
+/**
+ * \brief PersAdminRequest DBus method callback
+ *
+ * \note Handler for PersistenceAdminRequest.
+ * Signature based on generated code.
+ */
+static gboolean OnHandlePersAdminRequest( OipPersistenceAdminconsumer *object,
+ GDBusMethodInvocation *invocation,
+ guint arg_RequestId,
+ gint arg_StatusFlag )
+{
+ sint_t retVal = PERS_COM_SUCCESS;
+
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_DEBUG, DLT_STRING(LT_HDR),
+ DLT_STRING("PersistenceAdminRequest called with params : RequestId="),
+ DLT_UINT(arg_RequestId),
+ DLT_STRING("and StatusFlag="),
+ DLT_INT(arg_StatusFlag));
+
+ /* Forward the call to the PCL callback */
+ retVal = g_pPersIpcPCLInfo.pReqCB( arg_RequestId,
+ arg_StatusFlag );
+ if(PERS_COM_SUCCESS != retVal)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("PersistenceAdminRequest client callback failed with error code :"),
+ DLT_INT(retVal));
+ }
+
+ oip_persistence_adminconsumer_complete_persistence_admin_request( object,
+ invocation,
+ (gint)retVal);
+
+ return (TRUE);
+}
+
+
+/**
+ * \brief Function that exports the org.genivi.persistence.admin interface over DBus
+ *
+ * \param connection: Connection over which the interface should be exported
+ *
+ * \return true if successful, false otherwise
+ */
+static bool_t ExportPersistenceAdminIF(GDBusConnection *connection)
+{
+ GError *pError = NIL;
+
+ /* Create object to offer on the DBus */
+ g_persIpcDBusPASSkeleton = NIL;
+ g_persIpcDBusPASSkeleton = (OipPersistenceAdminSkeleton*) oip_persistence_admin_skeleton_new();
+ if(NIL == g_persIpcDBusPASSkeleton)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to create PersistenceAdmin object."));
+ return false;
+ }
+
+ (void)g_signal_connect(g_persIpcDBusPASSkeleton, "handle-register-pers-admin-notification", G_CALLBACK(&OnHandleRegisterPersAdminNotification), NIL);
+ (void)g_signal_connect(g_persIpcDBusPASSkeleton, "handle-un-register-pers-admin-notification", G_CALLBACK(&OnHandleUnregisterPersAdminNotification), NIL);
+ (void)g_signal_connect(g_persIpcDBusPASSkeleton, "handle-persistence-admin-request-completed", G_CALLBACK(&OnHandlePersAdminRequestCompleted), NIL);
+
+
+ /* Attach interfaces to the objects and export them */
+ if(FALSE == g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(g_persIpcDBusPASSkeleton),
+ connection,
+ PERSISTENCE_ADMIN_OBJ_PATH,
+ &pError))
+ {
+ /* Error: PersistenceAdmin interface could not be exported. */
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR, DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to export PersistenceAdmin interface. Error :"),
+ DLT_STRING(pError->message));
+ g_error_free(pError);
+ g_object_unref(g_persIpcDBusPASSkeleton);
+ g_persIpcDBusPASSkeleton = NIL;
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ * \brief Function that exports the org.genivi.persistence.adminconsumer interface over DBus
+ *
+ * \param connection: Connection over which the interface should be exported
+ *
+ * \return true if successful, false otherwise
+ */
+static bool_t ExportPersistenceAdminConsumerIF(GDBusConnection *connection)
+{
+ GError *pError = NIL;
+
+ /* Create object to offer on the DBus */
+ g_persIpcDBusPCLSkeleton = NIL;
+ g_persIpcDBusPCLSkeleton = (OipPersistenceAdminconsumerSkeleton*)oip_persistence_adminconsumer_skeleton_new();
+ if(NIL == g_persIpcDBusPCLSkeleton)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to create PersistenceAdminConsumer object."));
+ return false;
+ }
+
+ (void)g_signal_connect(g_persIpcDBusPCLSkeleton, "handle-persistence-admin-request", G_CALLBACK(&OnHandlePersAdminRequest), NIL);
+
+ /* Attach interfaces to the objects and export them */
+ if(FALSE == g_dbus_interface_skeleton_export( G_DBUS_INTERFACE_SKELETON(g_persIpcDBusPCLSkeleton),
+ connection,
+ PERSISTENCE_ADMIN_CONSUMER_OBJ_PATH,
+ &pError))
+ {
+ /* Error: PersistenceAdminConsumer interface could not be exported. */
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR, DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to export PersistenceAdminConsumer interface. Error :"),
+ DLT_STRING(pError->message));
+ g_error_free(pError);
+ g_object_unref(g_persIpcDBusPCLSkeleton);
+ g_persIpcDBusPCLSkeleton = NIL;
+ return false;
+ }
+ return true;
+}
+
+
+/* PAS DBus loop thread */
+static void* persIpcPASLoopThread(void *lpParam)
+{
+ uint32_t u32ConnectionId = 0;
+
+ /* Initialize glib */
+ g_type_init(); /* deprecated. Since GLib 2.36, the type system is initialized automatically and this function does nothing.*/
+
+ /* Create the main loop */
+ g_pPASMainLoop = g_main_loop_new(NIL, FALSE);
+ if(NIL == g_pPASMainLoop)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to create DBus main loop."));
+
+ /* Notify that the DBus connection is not ready */
+ if(0 != pthread_mutex_lock (&g_PASDBusMainLoopThreadFlagMtx))
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to lock mutex."));
+ }
+ else
+ {
+ g_PASDBusMainLoopThreadFlag = DBUS_MAIN_LOOP_THREAD_FLAG_SET;
+ (void)pthread_cond_signal (&g_PASDBusMainLoopThreadFlagCV);
+ (void)pthread_mutex_unlock (&g_PASDBusMainLoopThreadFlagMtx);
+ }
+ return NIL;
+ }
+
+ /* Connect to the D-Bus. Obtain a bus name to offer PAS objects */
+ u32ConnectionId = g_bus_own_name( PERSISTENCE_ADMIN_BUS_TYPE
+ , PERSISTENCE_ADMIN_BUS_NAME
+ , G_BUS_NAME_OWNER_FLAGS_NONE
+ , &OnBusAcquired_cb
+ , &OnNameAcquired_cb
+ , &OnNameLost_cb
+ , NIL
+ , NIL);
+
+ /* The main loop is only canceled if the Node is completely shut down or the D-Bus connection fails */
+ g_main_loop_run(g_pPASMainLoop);
+
+ /* If the main loop returned, clean up. Release bus name and main loop */
+ g_bus_unown_name(u32ConnectionId);
+ g_main_loop_unref(g_pPASMainLoop);
+ g_pPASMainLoop = NIL;
+
+ /* Release the skeleton object */
+ if(NIL != g_persIpcDBusPASSkeleton)
+ {
+ g_object_unref(g_persIpcDBusPASSkeleton);
+ g_persIpcDBusPASSkeleton = NIL;
+ }
+
+ return NIL;
+}
+
+
+/* PCL DBus loop thread */
+static void* persIpcPCLLoopThread(void *lpParam)
+{
+ GError *pGError = NIL;
+
+ /* Initialize glib */
+ g_type_init(); /* deprecated. Since GLib 2.36, the type system is initialized automatically and this function does nothing.*/
+
+ /* Create the main loop */
+ g_pPCLMainLoop = g_main_loop_new(NIL, FALSE);
+
+ /* Connect to D-Bus */
+ g_pPCLDBusConnection = g_bus_get_sync( PERSISTENCE_ADMIN_BUS_TYPE,
+ NULL,
+ &pGError);
+
+ if(NIL == g_pPCLDBusConnection)
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to obtain a DBus connection. Error :"),
+ DLT_STRING(pGError->message));
+ g_error_free(pGError);
+ g_main_loop_unref(g_pPCLMainLoop);
+ if(0 != pthread_mutex_lock (&g_PCLDBusMainLoopThreadFlagMtx))
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to lock mutex."));
+ }
+ else
+ {
+ g_PCLDBusMainLoopThreadFlag = DBUS_MAIN_LOOP_THREAD_FLAG_SET;
+ (void)pthread_cond_signal (&g_PCLDBusMainLoopThreadFlagCV);
+ (void)pthread_mutex_unlock (&g_PCLDBusMainLoopThreadFlagMtx);
+ }
+ return NIL;
+ }
+
+
+ /* DBus connection initialized */
+ g_bPCLDBusConnInit = true;
+
+ /* Notify the DBus connection is ready (or not available) */
+ if(0 != pthread_mutex_lock (&g_PCLDBusMainLoopThreadFlagMtx))
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to lock mutex."));
+ }
+ g_PCLDBusMainLoopThreadFlag = DBUS_MAIN_LOOP_THREAD_FLAG_SET;
+ (void)pthread_cond_signal (&g_PCLDBusMainLoopThreadFlagCV);
+ (void)pthread_mutex_unlock (&g_PCLDBusMainLoopThreadFlagMtx);
+
+ g_main_loop_run(g_pPCLMainLoop);
+
+ g_bPCLDBusConnInit = false;
+
+ /* If the main loop returned, clean up */
+ g_main_loop_unref(g_pPCLMainLoop);
+
+ /* Release the skeleton object */
+ if(NIL != g_persIpcDBusPCLSkeleton)
+ {
+ g_object_unref(g_persIpcDBusPCLSkeleton);
+ g_persIpcDBusPCLSkeleton = NIL;
+ }
+
+ /* Release any created proxy object */
+ if(NIL != g_persIpcDBusPASProxy)
+ {
+ g_object_unref(g_persIpcDBusPASProxy);
+ g_persIpcDBusPASProxy = NIL;
+ }
+
+ return NIL;
+}
+
+
+/* Get DBus client ID */
+static sint_t persIpcGetIdForDBusInfo(const pstr_t busName,
+ const pstr_t objName,
+ uint32_t *clientID)
+{
+ uint32_t clientIdx;
+
+ if((NIL == busName) || (NIL == clientID))
+ {
+ return PERS_COM_ERR_INVALID_PARAM;
+ }
+
+ /* Acquire mutex on array of DBus client info */
+ if(0 != pthread_mutex_lock (&g_persIpcDBusClientInfoArrayMtx))
+ {
+ DLT_LOG(persComIpcDLTCtx, DLT_LOG_ERROR,DLT_STRING(LT_HDR),
+ DLT_STRING("Failed to lock mutex."));
+ return PERS_COM_FAILURE;
+ }
+
+ /* Check if client already registered */
+ for(clientIdx = 0; clientIdx < g_persIpcDBusClientInfoArraySize; ++clientIdx)
+ {
+ if(NIL != g_persIpcDBusClientInfoArray[clientIdx])
+ {
+ if(0 == strcmp(busName, g_persIpcDBusClientInfoArray[clientIdx]->busName))
+ {
+ if(NIL != objName)
+ {
+ if(0 == strcmp(objName, g_persIpcDBusClientInfoArray[clientIdx]->objName))
+ {
+ (*clientID) = clientIdx;
+ (void)pthread_mutex_unlock (&g_persIpcDBusClientInfoArrayMtx);
+ return PERS_COM_SUCCESS;
+ }
+ }
+ else
+ {
+ (*clientID) = clientIdx;
+ (void)pthread_mutex_unlock (&g_persIpcDBusClientInfoArrayMtx);
+ return PERS_COM_SUCCESS;
+ }
+ }
+ }
+ }
+
+ /* Release array mutex */
+ (void)pthread_mutex_unlock (&g_persIpcDBusClientInfoArrayMtx);
+
+ return PERS_COM_ERR_NOT_FOUND;
+}
diff --git a/src/pers_local_shared_db_access.c b/src/pers_local_shared_db_access.c
new file mode 100644
index 0000000..a7a4678
--- /dev/null
+++ b/src/pers_local_shared_db_access.c
@@ -0,0 +1,287 @@
+/**********************************************************************************************************************
+*
+* Copyright (C) 2012 Continental Automotive Systems, Inc.
+*
+* Author: Ionut.Ieremie@continental-corporation.com
+*
+* Implementation of persComDbAccess.h
+*
+* This Source Code Form is subject to the terms of the Mozilla Public
+* License, v. 2.0. If a copy of the MPL was not distributed with this
+* file, You can obtain one at http://mozilla.org/MPL/2.0/.
+*
+* Date Author Reason
+* 2013.02.05 uidl9757 CSP_WZ#2220: Adaptation for open source
+* 2013.01.03 uidl9757 CSP_WZ#2060: Remove "cursor" interface
+* 2012.12.17 uidl9757 CSP_WZ#2060: Changes to allow optimized access to DB
+* 2012.12.10 uidl9757 CSP_WZ#2060: Created
+*
+**********************************************************************************************************************/
+
+#include "persComTypes.h"
+#include <stdio.h>
+#include "string.h"
+
+#include "persComDataOrg.h"
+#include "pers_low_level_db_access_if.h"
+#include "persComDbAccess.h"
+#include "persComErrors.h"
+
+/**
+ * \brief Obtain a handler to DB indicated by dbPathname
+ * \note : DB is created if it does not exist and (bForceCreationIfNotPresent != 0)
+ *
+ * \param dbPathname [in] absolute path to database (length limited to \ref PERS_ORG_MAX_LENGTH_PATH_FILENAME)
+ * \param bForceCreationIfNotPresent [in] if !=0x0, the database is created if it does not exist
+ *
+ * \return >= 0 for valid handler, negative value for error (\ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+signed int persComDbOpen(char const * dbPathname, unsigned char bForceCreationIfNotPresent)
+{
+ sint_t iErrCode = PERS_COM_SUCCESS ;
+
+ if(NIL != dbPathname)
+ {
+ if(strlen(dbPathname) >= PERS_ORG_MAX_LENGTH_PATH_FILENAME)
+ {
+ iErrCode = PERS_COM_ERR_INVALID_PARAM ;
+ }
+ }
+ else
+ {
+ iErrCode = PERS_COM_ERR_INVALID_PARAM ;
+ }
+
+ if(PERS_COM_SUCCESS == iErrCode)
+ {
+ iErrCode = pers_lldb_open(dbPathname, PersLldbPurpose_DB, bForceCreationIfNotPresent) ;
+ }
+
+ return iErrCode ;
+}
+
+/**
+ * \brief Close handler to DB
+ *
+ * \param handlerDB [in] handler obtained with persComDbOpen
+ *
+ * \return 0 for success, negative value for error (\ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+signed int persComDbClose(signed int handlerDB)
+{
+ sint_t iErrCode = PERS_COM_SUCCESS ;
+
+ if(handlerDB < 0)
+ {
+ iErrCode = PERS_COM_ERR_INVALID_PARAM ;
+ }
+
+ if(PERS_COM_SUCCESS == iErrCode)
+ {
+ iErrCode = pers_lldb_close(handlerDB) ;
+ }
+
+ return iErrCode ;
+}
+
+/**
+ * \brief write a key-value pair into local/shared database
+ *
+ * \param handlerDB [in] handler obtained with persComDbOpen
+ * \param key [in] key's name (length limited to \ref PERS_DB_MAX_LENGTH_KEY_NAME)
+ * \param data [in] buffer with key's data
+ * \param dataSize [in] size of key's data (max allowed \ref PERS_DB_MAX_SIZE_KEY_DATA)
+ *
+ * \return 0 for success, negative value otherwise (\ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+signed int persComDbWriteKey(signed int handlerDB, char const * key, char const * data, signed int dataSize)
+{
+ sint_t iErrCode = PERS_COM_SUCCESS ;
+
+ if( (handlerDB < 0)
+ || (NIL == key)
+ || (NIL == data)
+ || (dataSize <= 0)
+ || (dataSize > PERS_DB_MAX_SIZE_KEY_DATA)
+ )
+ {
+ iErrCode = PERS_COM_ERR_INVALID_PARAM ;
+ }
+ else
+ {
+ if(strlen(key) >= PERS_DB_MAX_LENGTH_KEY_NAME)
+ {
+ iErrCode = PERS_COM_ERR_INVALID_PARAM ;
+ }
+ }
+
+ if(PERS_COM_SUCCESS == iErrCode)
+ {
+ iErrCode = pers_lldb_write_key(handlerDB, PersLldbPurpose_DB, key, data, dataSize) ;
+ }
+
+ return iErrCode ;
+}
+
+
+/**
+ * \brief read a key's value from local/shared database
+ *
+ * \param handlerDB [in] handler obtained with persComDbOpen
+ * \param key [in] key's name (length limited to \ref PERS_DB_MAX_LENGTH_KEY_NAME)
+ * \param dataBuffer_out [out]buffer where to return the read data
+ * \param dataBufferSize [in] size of dataBuffer_out
+ *
+ * \return read size, or negative value in case of error (\ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+signed int persComDbReadKey(signed int handlerDB, char const * key, char* dataBuffer_out, signed int dataBufferSize)
+{
+ sint_t iErrCode = PERS_COM_SUCCESS ;
+
+ if( (handlerDB < 0)
+ || (NIL == key)
+ || (NIL == dataBuffer_out)
+ || (dataBufferSize <= 0)
+ )
+ {
+ iErrCode = PERS_COM_ERR_INVALID_PARAM ;
+ }
+ else
+ {
+ if(strlen(key) >= PERS_DB_MAX_LENGTH_KEY_NAME)
+ {
+ iErrCode = PERS_COM_ERR_INVALID_PARAM ;
+ }
+ }
+
+ if(PERS_COM_SUCCESS == iErrCode)
+ {
+ iErrCode = pers_lldb_read_key(handlerDB, PersLldbPurpose_DB, key, dataBuffer_out, dataBufferSize) ;
+ }
+
+ return iErrCode ;
+}
+
+/**
+ * \brief read a key's value from local/shared database
+ *
+ * \param handlerDB [in] handler obtained with persComDbOpen
+ * \param key [in] key's name (length limited to \ref PERS_DB_MAX_LENGTH_KEY_NAME)
+ *
+ * \return key's size, or negative value in case of error (\ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+signed int persComDbGetKeySize(signed int handlerDB, char const * key)
+{
+ sint_t iErrCode = PERS_COM_SUCCESS ;
+
+ if( (handlerDB < 0)
+ || (NIL == key)
+ )
+ {
+ iErrCode = PERS_COM_ERR_INVALID_PARAM ;
+ }
+ else
+ {
+ if(strlen(key) >= PERS_DB_MAX_LENGTH_KEY_NAME)
+ {
+ iErrCode = PERS_COM_ERR_INVALID_PARAM ;
+ }
+ }
+
+ if(PERS_COM_SUCCESS == iErrCode)
+ {
+ iErrCode = pers_lldb_get_key_size(handlerDB, PersLldbPurpose_DB, key) ;
+ }
+
+ return iErrCode ;
+}
+
+/**
+ * \brief delete key from local/shared database
+ *
+ * \param handlerDB [in] handler obtained with persComDbOpen
+ * \param key [in] key's name (length limited to \ref PERS_DB_MAX_LENGTH_KEY_NAME)
+ *
+ * \return 0 for success, negative value otherwise (\ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+signed int persComDbDeleteKey(signed int handlerDB, char const * key)
+{
+ sint_t iErrCode = PERS_COM_SUCCESS ;
+
+ if( (handlerDB < 0)
+ || (NIL == key)
+ )
+ {
+ iErrCode = PERS_COM_ERR_INVALID_PARAM ;
+ }
+ else
+ {
+ if(strlen(key) >= PERS_DB_MAX_LENGTH_KEY_NAME)
+ {
+ iErrCode = PERS_COM_ERR_INVALID_PARAM ;
+ }
+ }
+
+ if(PERS_COM_SUCCESS == iErrCode)
+ {
+ iErrCode = pers_lldb_delete_key(handlerDB, PersLldbPurpose_DB, key) ;
+ }
+
+ return iErrCode ;
+}
+
+
+/**
+ * \brief Find the buffer's size needed to accomodate the list of keys' names in local/shared database
+ *
+ * \param handlerDB [in] handler obtained with persComDbOpen
+ *
+ * \return needed size, or negative value in case of error (\ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+signed int persComDbGetSizeKeysList(signed int handlerDB)
+{
+ sint_t iErrCode = PERS_COM_SUCCESS ;
+
+ if(handlerDB < 0)
+ {
+ iErrCode = PERS_COM_ERR_INVALID_PARAM ;
+ }
+
+ if(PERS_COM_SUCCESS == iErrCode)
+ {
+ iErrCode = pers_lldb_get_size_keys_list(handlerDB, PersLldbPurpose_DB) ;
+ }
+
+ return iErrCode ;
+}
+
+
+/**
+ * \brief Obtain the list of the keys' names in local/shared database
+ * \note : keys in the list are separated by '\0'
+ *
+ * \param handlerDB [in] handler obtained with persComDbOpen
+ * \param listBuffer_out [out]buffer where to return the list of keys
+ * \param listBufferSize [in] size of listingBuffer_out
+ * \return >=0 for size of the list, or negative value in case of error (\ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+signed int persComDbGetKeysList(signed int handlerDB, char* listBuffer_out, signed int listBufferSize)
+ {
+ sint_t iErrCode = PERS_COM_SUCCESS ;
+
+ if( (handlerDB < 0)
+ || (NIL == listBuffer_out)
+ || (listBufferSize <= 0)
+ )
+ {
+ iErrCode = PERS_COM_ERR_INVALID_PARAM ;
+ }
+
+ if(PERS_COM_SUCCESS == iErrCode)
+ {
+ iErrCode = pers_lldb_get_keys_list(handlerDB, PersLldbPurpose_DB, listBuffer_out, listBufferSize) ;
+ }
+
+ return iErrCode ;
+}
+
diff --git a/src/pers_low_level_db_access.c b/src/pers_low_level_db_access.c
new file mode 100644
index 0000000..f66fa6c
--- /dev/null
+++ b/src/pers_low_level_db_access.c
@@ -0,0 +1,1515 @@
+/**********************************************************************************************************************
+*
+* Copyright (C) 2012 Continental Automotive Systems, Inc.
+*
+* Author: Ionut.Ieremie@continental-corporation.com
+*
+* Implementation of persComDbAccess.h
+*
+* This Source Code Form is subject to the terms of the Mozilla Public
+* License, v. 2.0. If a copy of the MPL was not distributed with this
+* file, You can obtain one at http://mozilla.org/MPL/2.0/.
+*
+* Date Author Reason
+* 2013.09.14 uidl9757 CSP_WZ#4872: Improvements
+* - synchronization between threads of the same process
+* - number of maximum simultan open handles by a process is no longer limited
+* 2013.08.30 uidl9757 CSP_WZ#5356: persistency common library uses too much stack size
+* 2013.07.10 uidl9757 CSP_WZ#4586: Add instrumentation for debug purposes
+* 2013.03.21 uidl9757 CSP_WZ#3774: Default error handler causes the termination of the calling process
+* 2013.03.21 uidl9757 CSP_WZ#2798: Workaround - reading from an emptied itzam db returns error
+* 2013.02.05 uidl9757 CSP_WZ#2220: Adaptation for open source
+* 2013.01.03 uidl9757 CSP_WZ#2060: Remove "cursor" interface
+* 2012.12.17 uidl9757 CSP_WZ#2060: Changes to allow optimized access to DB
+* 2012.12.10 uidl9757 CSP_WZ#2060: Created
+*
+**********************************************************************************************************************/
+
+#include <pthread.h>
+#include <stdio.h> /*DG C7MR2R-MISRA-C:2004 Rule 20.9-SSW_PersCommon_1003*/
+#include <stdlib.h>
+#include <string.h>
+#include <malloc.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "persComTypes.h"
+
+#include "itzam.h"
+
+#include "persComErrors.h"
+#include "persComDataOrg.h"
+#include "persComDbAccess.h"
+#include "persComRct.h"
+
+#include "pers_low_level_db_access_if.h"
+
+#include "dlt.h"
+/* L&T context */
+#define LT_HDR "[persComLLDB]"
+DLT_DECLARE_CONTEXT (persComLldbDLTCtx);
+
+/* ---------------------- local definition ---------------------------- */
+/* max number of open handlers per process */
+#define PERS_LLDB_NO_OF_STATIC_HANDLES 16
+#define PERS_LLDB_MAX_STATIC_HANDLES (PERS_LLDB_NO_OF_STATIC_HANDLES-1)
+
+/* ---------------------- local types --------------------------------- */
+typedef enum {
+ dbType_unknown = 0,
+ dbType_itzam
+ /* TODO: Add here IDs for supported DB engines */
+} dbType_e;
+
+typedef struct
+{
+ char m_key[PERS_DB_MAX_LENGTH_KEY_NAME];
+ char m_data[PERS_DB_MAX_SIZE_KEY_DATA];
+ int m_dataSize ;
+}
+KeyValuePair_LocalDB_s;
+
+typedef struct
+{
+ char m_key[PERS_RCT_MAX_LENGTH_RESOURCE_ID];
+ char m_data[sizeof(PersistenceConfigurationKey_s)];
+}
+KeyValuePair_RCT_s;
+
+typedef struct
+{
+ bool_t bIsAssigned ;
+ sint_t dbHandler ;
+ pers_lldb_purpose_e ePurpose ;
+ itzam_btree btree;
+ str_t dbPathname[PERS_ORG_MAX_LENGTH_PATH_FILENAME] ;
+}lldb_handler_s ;
+
+typedef struct lldb_handles_list_el_s_
+{
+ lldb_handler_s sHandle ;
+ struct lldb_handles_list_el_s_ * pNext ;
+}lldb_handles_list_el_s ;
+
+typedef struct
+{
+ lldb_handler_s asStaticHandles[PERS_LLDB_NO_OF_STATIC_HANDLES] ; /* static area should be enough for most of the processes*/
+ lldb_handles_list_el_s* pListHead ; /* for the processes with a large number of threads which use Persistency */
+}lldb_handlers_s ;
+
+/* ---------------------- local variables --------------------------------- */
+static const char ListItemsSeparator = '\0';
+
+/* shared by all the threads within a process */
+static lldb_handlers_s g_sHandlers = {{{0}}} ;
+static pthread_mutex_t g_mutexLldb = PTHREAD_MUTEX_INITIALIZER; /*DG C7MR2R-MISRA-C:2004 Rule 18.4-SSW_PersCommon_1013*/
+
+/* ---------------------- local macros --------------------------------- */
+
+
+
+/* ---------------------- local functions --------------------------------- */
+static sint_t DeleteDataFromItzamDB( sint_t dbHandler, pconststr_t key );
+static void ErrorHandler( pconststr_t function_name, itzam_error error);
+static sint_t GetAllKeysFromItzamLocalDB( sint_t dbHandler, pstr_t buffer, sint_t size );
+static sint_t GetAllKeysFromItzamRCT( sint_t dbHandler, pstr_t buffer, sint_t size );
+static sint_t GetKeySizeFromItzamLocalDB( sint_t dbHandler, pconststr_t key) ;
+static sint_t GetDataFromItzamLocalDB( sint_t dbHandler, pconststr_t key, pstr_t buffer_out, sint_t bufSize );
+static sint_t GetDataFromItzamRCT( sint_t dbHandler, pconststr_t key, PersistenceConfigurationKey_s* pConfig);
+static sint_t SetDataInItzamLocalDB( sint_t dbHandler, pconststr_t key, pconststr_t data, sint_t dataSize );
+static sint_t SetDataInItzamRCT( sint_t dbHandler, pconststr_t key, PersistenceConfigurationKey_s const * pConfig);
+/* access to resources shared by the threads within a process */
+static bool_t lldb_handles_Lock(void);
+static bool_t lldb_handles_Unlock(void);
+static lldb_handler_s* lldb_handles_FindInUseHandle(sint_t dbHandler) ;
+static lldb_handler_s* lldb_handles_FindAvailableHandle(void) ;
+static void lldb_handles_InitHandle(lldb_handler_s* psHandle_inout, pers_lldb_purpose_e ePurpose, str_t const * dbPathname);
+static bool_t lldb_handles_DeinitHandle(sint_t dbHandler);
+
+
+/**
+ * \brief write a key-value pair into database
+ * \note : DB type is identified from dbPathname (based on extension)
+ *
+ * \param dbPathname [in] absolute path to DB
+ * \param ePurpose [in] see pers_lldb_purpose_e
+ * \param bForceCreationIfNotPresent [in] if true, the DB is created if it does not exist
+ *
+ * \return >=0 for success, negative value otherway (see pers_error_codes.h)
+ */
+sint_t pers_lldb_open(str_t const * dbPathname, pers_lldb_purpose_e ePurpose, bool_t bForceCreationIfNotPresent)
+{
+ sint_t returnValue = PERS_COM_FAILURE ;
+ bool_t bCanContinue = true ;
+ lldb_handler_s* pLldbHandler = NIL ;
+ bool_t bLocked = false ;
+
+ static bool_t bFirstCall = true ;
+
+ if(bFirstCall)
+ {
+ pid_t pid = getpid() ;
+ str_t dltContextID[16] ; /* should be at most 4 characters string, but colissions occure */
+
+ /* set an error handler - the default one will cause the termination of the calling process */
+ bFirstCall = false ;
+ itzam_set_default_error_handler(&ErrorHandler) ;
+ /* init DLT */
+ (void)snprintf(dltContextID, sizeof(dltContextID), "Pers_%04d", pid) ;
+ DLT_REGISTER_CONTEXT(persComLldbDLTCtx, dltContextID, "PersCommonLLDB");
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("register context PersCommonLLDB ContextID="); DLT_STRING(dltContextID));
+ }
+
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("<<"); DLT_STRING(dbPathname); DLT_STRING(">>, ");
+ ((PersLldbPurpose_RCT == ePurpose) ? DLT_STRING("RCT, ") : DLT_STRING("DB, "));
+ ((true == bForceCreationIfNotPresent) ? DLT_STRING("forced, ") : DLT_STRING("unforced, "));
+ DLT_STRING(" ... ")) ;
+
+ if(lldb_handles_Lock())
+ {
+ bLocked = true ;
+ pLldbHandler = lldb_handles_FindAvailableHandle() ;
+ if(NIL == pLldbHandler)
+ {
+ bCanContinue = false ;
+ returnValue = PERS_COM_ERR_OUT_OF_MEMORY ;
+ }
+ }
+ else
+ {
+ bCanContinue = false ;
+ }
+
+ if(bCanContinue)
+ {
+ itzam_state state = ITZAM_NOT_FOUND;
+ size_t treeEntrySize = (PersLldbPurpose_RCT == ePurpose) ? sizeof(KeyValuePair_RCT_s) : sizeof(KeyValuePair_LocalDB_s) ;
+
+ state = itzam_btree_open( & pLldbHandler->btree, dbPathname, &itzam_comparator_string, &ErrorHandler, 0/*recover*/, 0/*read_only*/);
+ if( state != ITZAM_OKAY )
+ {
+ if(bForceCreationIfNotPresent)
+ {
+ state = itzam_btree_create( & pLldbHandler->btree, dbPathname, ITZAM_BTREE_ORDER_DEFAULT, (itzam_int)treeEntrySize, &itzam_comparator_string, &ErrorHandler );
+ if(ITZAM_OKAY != state)
+ {
+ bCanContinue = false ;
+ returnValue = PERS_COM_FAILURE ;
+ }
+ }
+ else
+ {
+ bCanContinue = false ;
+ returnValue = PERS_COM_ERR_NOT_FOUND ;
+ }
+ }
+
+ if(bCanContinue)
+ {
+ lldb_handles_InitHandle(pLldbHandler, ePurpose, dbPathname) ;
+ returnValue = pLldbHandler->dbHandler;
+ }
+ else
+ {
+ /* clean up */
+ returnValue = PERS_COM_FAILURE ;
+ (void)lldb_handles_DeinitHandle(pLldbHandler->dbHandler) ;
+ }
+ }
+
+ if(bLocked)
+ {
+ (void)lldb_handles_Unlock() ;
+ }
+
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("<<"); DLT_STRING(dbPathname); DLT_STRING(">>, ");
+ ((PersLldbPurpose_RCT == ePurpose) ? DLT_STRING("RCT, ") : DLT_STRING("DB, "));
+ ((true == bForceCreationIfNotPresent) ? DLT_STRING("forced, ") : DLT_STRING("unforced, "));
+ DLT_STRING("retval=<"); DLT_INT(returnValue); DLT_STRING(">")) ;
+
+ return returnValue ;
+}/*DG C7MR2R-ISQP Metric 10-SSW_PersCommon_0001*/ /*DG C7MR2R-ISQP Metric 6-SSW_PersCommon_1005*/
+
+
+/**
+ * \brief write a key-value pair into database
+ * \note : DB type is identified from dbPathname (based on extension)
+ *
+ * \param handlerDB [in] handler obtained with pers_lldb_open
+ *
+ * \return 0 for success, negative value otherway (see pers_error_codes.h)
+ */
+sint_t pers_lldb_close(sint_t handlerDB)
+{
+ sint_t returnValue = PERS_COM_SUCCESS ;
+ lldb_handler_s* pLldbHandler = NIL ;
+ bool_t bLocked = false ;
+ str_t dbPathnameTemp[PERS_ORG_MAX_LENGTH_PATH_FILENAME] = "invalid path" ;
+
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("handlerDB="); DLT_INT(handlerDB); DLT_STRING("...")) ;
+
+ if(handlerDB >= 0)
+ {
+ if(lldb_handles_Lock())
+ {
+ bLocked = true ;
+ pLldbHandler = lldb_handles_FindInUseHandle(handlerDB) ;
+ if(NIL == pLldbHandler)
+ {
+ returnValue = PERS_COM_FAILURE ;
+ }
+ else
+ {
+ /* to not use DLT while mutex locked */
+ (void)strncpy(dbPathnameTemp, pLldbHandler->dbPathname, sizeof(dbPathnameTemp)) ;
+ }
+ }
+ }
+ else
+ {
+ returnValue = PERS_COM_ERR_INVALID_PARAM ;
+ }
+
+ if(PERS_COM_SUCCESS == returnValue)
+ {
+ if(ITZAM_OKAY == itzam_btree_close( & pLldbHandler->btree))
+ {
+ if( ! lldb_handles_DeinitHandle(pLldbHandler->dbHandler))
+ {
+ returnValue = PERS_COM_FAILURE ;
+ }
+ }
+ else
+ {
+ returnValue = PERS_COM_FAILURE ;
+ }
+ }
+
+ if(bLocked)
+ {
+ (void)lldb_handles_Unlock() ;
+ }
+
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("handlerDB="); DLT_INT(handlerDB);
+ DLT_STRING("<<"); DLT_STRING(dbPathnameTemp); DLT_STRING(">>, ");
+ DLT_STRING("retval=<"); DLT_INT(returnValue); DLT_STRING(">")) ;
+
+ return returnValue ;
+}/*DG C7MR2R-ISQP Metric 10-SSW_PersCommon_0001*/
+
+/**
+ * \brief write a key-value pair into database
+ * \note : DB type is identified from dbPathname (based on extension)
+ * \note : DB is created if it does not exist
+ *
+ * \param handlerDB [in] handler obtained with pers_lldb_open
+ * \param ePurpose [in] see pers_lldb_purpose_e
+ * \param key [in] key's name
+ * \param data [in] buffer with key's data
+ * \param dataSize [in] size of key's data
+ *
+ * \return 0 for success, negative value otherway (see pers_error_codes.h)
+ */
+sint_t pers_lldb_write_key(sint_t handlerDB, pers_lldb_purpose_e ePurpose, str_t const * key, str_t const * data, sint_t dataSize)
+{
+ sint_t eErrorCode = PERS_COM_SUCCESS ;
+
+ switch(ePurpose)
+ {
+ case PersLldbPurpose_DB:
+ {
+ eErrorCode = SetDataInItzamLocalDB(handlerDB, key, data, dataSize) ;
+ break ;
+ }
+ case PersLldbPurpose_RCT:
+ {
+ eErrorCode = SetDataInItzamRCT(handlerDB, key, (PersistenceConfigurationKey_s const *)data) ;
+ break ;
+ }
+ default:
+ {
+ eErrorCode = PERS_COM_ERR_INVALID_PARAM ;
+ break ;
+ }
+ }
+
+ return eErrorCode ;
+}
+
+
+/**
+ * \brief read a key's value from database
+ * \note : DB type is identified from dbPathname (based on extension)
+ *
+ * \param handlerDB [in] handler obtained with pers_lldb_open
+ * \param ePurpose [in] see pers_lldb_purpose_e
+ * \param key [in] key's name
+ * \param dataBuffer_out [out]buffer where to return the read data
+ * \param bufSize [in] size of dataBuffer_out
+ *
+ * \return read size, or negative value in case of error (see pers_error_codes.h)
+ */
+sint_t pers_lldb_read_key(sint_t handlerDB, pers_lldb_purpose_e ePurpose, str_t const * key, pstr_t dataBuffer_out, sint_t bufSize)
+{
+ sint_t eErrorCode = PERS_COM_SUCCESS ;
+
+ switch(ePurpose)
+ {
+ case PersLldbPurpose_DB:
+ {
+ eErrorCode = GetDataFromItzamLocalDB(handlerDB, key, dataBuffer_out, bufSize) ;
+ break ;
+ }
+ case PersLldbPurpose_RCT:
+ {
+ eErrorCode = GetDataFromItzamRCT(handlerDB, key, (PersistenceConfigurationKey_s*)dataBuffer_out) ;
+ break ;
+ }
+ default:
+ {
+ eErrorCode = PERS_COM_ERR_INVALID_PARAM ;
+ break ;
+ }
+ }
+
+ return eErrorCode ;
+}
+
+/**
+ * \brief read a key's value from database
+ * \note : DB type is identified from dbPathname (based on extension)
+ *
+ * \param handlerDB [in] handler obtained with pers_lldb_open
+ * \param ePurpose [in] see pers_lldb_purpose_e
+ * \param key [in] key's name
+ * \return key's size, or negative value in case of error (see pers_error_codes.h)
+ */
+sint_t pers_lldb_get_key_size(sint_t handlerDB, pers_lldb_purpose_e ePurpose, str_t const * key)
+{
+ sint_t eErrorCode = PERS_COM_SUCCESS ;
+
+ switch(ePurpose)
+ {
+ case PersLldbPurpose_DB:
+ {
+ eErrorCode = GetKeySizeFromItzamLocalDB(handlerDB, key) ;
+ break ;
+ }
+ default:
+ {
+ eErrorCode = PERS_COM_ERR_INVALID_PARAM ;
+ break ;
+ }
+ }
+
+ return eErrorCode ;
+}
+
+/**
+ * \brief delete key from database
+ * \note : DB type is identified from dbPathname (based on extension)
+ *
+ * \param handlerDB [in] handler obtained with pers_lldb_open
+ * \param ePurpose [in] see pers_lldb_purpose_e
+ * \param key [in] key's name
+ *
+ * \return 0 for success, negative value otherway (see pers_error_codes.h)
+ */
+sint_t pers_lldb_delete_key(sint_t handlerDB, pers_lldb_purpose_e ePurpose, str_t const * key)
+{
+ sint_t eErrorCode = PERS_COM_SUCCESS ;
+
+ switch(ePurpose)
+ {
+ case PersLldbPurpose_DB:
+ case PersLldbPurpose_RCT:
+ {
+ eErrorCode = DeleteDataFromItzamDB(handlerDB, key) ;
+ break ;
+ }
+ default:
+ {
+ eErrorCode = PERS_COM_ERR_INVALID_PARAM ;
+ break ;
+ }
+ }
+
+ return eErrorCode ;
+}
+
+
+/**
+ * \brief Find the buffer's size needed to accomodate the listing of keys' names in database
+ * \note : DB type is identified from dbPathname (based on extension)
+ *
+ * \param handlerDB [in] handler obtained with pers_lldb_open
+ * \param ePurpose [in] see pers_lldb_purpose_e
+ *
+ * \return needed size, or negative value in case of error (see pers_error_codes.h)
+ */
+sint_t pers_lldb_get_size_keys_list(sint_t handlerDB, pers_lldb_purpose_e ePurpose)
+{
+ sint_t eErrorCode = PERS_COM_SUCCESS ;
+
+ switch(ePurpose)
+ {
+ case PersLldbPurpose_DB:
+ {
+ eErrorCode = GetAllKeysFromItzamLocalDB(handlerDB, NIL, 0) ;
+ break ;
+ }
+ case PersLldbPurpose_RCT:
+ {
+ eErrorCode = GetAllKeysFromItzamRCT(handlerDB, NIL, 0) ;
+ break ;
+ }
+ default:
+ {
+ eErrorCode = PERS_COM_ERR_INVALID_PARAM ;
+ break ;
+ }
+ }
+
+ return eErrorCode ;
+}
+
+
+/**
+ * \brief List the keys' names in database
+ * \note : DB type is identified from dbPathname (based on extension)
+ * \note : keys are separated by '\0'
+ *
+ * \param handlerDB [in] handler obtained with pers_lldb_open
+ * \param ePurpose [in] see pers_lldb_purpose_e
+ * \param listingBuffer_out [out]buffer where to return the listing
+ * \param bufSize [in] size of listingBuffer_out
+ *
+ * \return listing size, or negative value in case of error (see pers_error_codes.h)
+ */
+ sint_t pers_lldb_get_keys_list(sint_t handlerDB, pers_lldb_purpose_e ePurpose, pstr_t listingBuffer_out, sint_t bufSize)
+ {
+ sint_t eErrorCode = PERS_COM_SUCCESS ;
+
+ switch(ePurpose)
+ {
+ case PersLldbPurpose_DB:
+ {
+ eErrorCode = GetAllKeysFromItzamLocalDB(handlerDB, listingBuffer_out, bufSize) ;
+ break ;
+ }
+ case PersLldbPurpose_RCT:
+ {
+ eErrorCode = GetAllKeysFromItzamRCT(handlerDB, listingBuffer_out, bufSize) ;
+ break ;
+ }
+ default:
+ {
+ eErrorCode = PERS_COM_ERR_INVALID_PARAM ;
+ break ;
+ }
+ }
+
+ return eErrorCode ;
+}
+
+static sint_t DeleteDataFromItzamDB( sint_t dbHandler, pconststr_t key )
+{
+ bool_t bCanContinue = true ;
+ sint_t delete_size = PERS_COM_FAILURE ;
+ lldb_handler_s* pLldbHandler = NIL ;
+ bool_t bLocked = false ;
+ str_t dbPathnameTemp[PERS_ORG_MAX_LENGTH_PATH_FILENAME] = "invalid path" ;
+
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("handlerDB="); DLT_INT(dbHandler);
+ DLT_STRING("key=<<"); DLT_STRING(key); DLT_STRING(">>...")) ;
+
+ if( (dbHandler >= 0) && (NIL != key))
+ {
+ if(lldb_handles_Lock())
+ {
+ bLocked = true ;
+ pLldbHandler = lldb_handles_FindInUseHandle(dbHandler) ;
+ if(NIL == pLldbHandler)
+ {
+ bCanContinue = false ;
+ }
+ else
+ {
+ /* to not use DLT while mutex locked */
+ (void)strncpy(dbPathnameTemp, pLldbHandler->dbPathname, sizeof(dbPathnameTemp)) ;
+ }
+ }
+ }
+ else
+ {
+ bCanContinue = false ;
+ }
+
+
+ if(bCanContinue)
+ {
+ switch(pLldbHandler->ePurpose)
+ {
+ case PersLldbPurpose_DB:
+ {
+ KeyValuePair_LocalDB_s search;
+ if( itzam_true == itzam_btree_find( &pLldbHandler->btree, key, & search ) )
+ {
+ if(ITZAM_OKAY == itzam_btree_remove( &pLldbHandler->btree, key ))
+ {
+ delete_size = search.m_dataSize ;
+ }
+ else
+ {
+ delete_size = PERS_COM_FAILURE ;
+ }
+ }
+ else
+ {
+ delete_size = PERS_COM_ERR_NOT_FOUND ;
+ }
+ break ;
+ }
+ case PersLldbPurpose_RCT:
+ {
+ KeyValuePair_RCT_s search;
+ if( itzam_true == itzam_btree_find( &pLldbHandler->btree, key, & search ) )
+ {
+ if(ITZAM_OKAY == itzam_btree_remove( &pLldbHandler->btree, key ))
+ {
+ delete_size = sizeof(PersistenceConfigurationKey_s) ;
+ }
+ else
+ {
+ delete_size = PERS_COM_FAILURE ;
+ }
+ }
+ else
+ {
+ delete_size = PERS_COM_ERR_NOT_FOUND ;
+ }
+ break ;
+ }
+ default:
+ {
+ break ;
+ }
+ }
+ }
+
+ if(bLocked)
+ {
+ (void)lldb_handles_Unlock() ;
+ }
+
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("handlerDB="); DLT_INT(dbHandler);
+ DLT_STRING("key=<<"); DLT_STRING(key); DLT_STRING(">>, ");
+ DLT_STRING("<<"); DLT_STRING(dbPathnameTemp); DLT_STRING(">>, ");
+ DLT_STRING("retval=<"); DLT_INT(delete_size); DLT_STRING(">")) ;
+
+ return delete_size;
+}/*DG C7MR2R-ISQP Metric 10-SSW_PersCommon_0001*/
+
+static void ErrorHandler(pconststr_t function_name, itzam_error error )
+{
+ (void)fprintf( stderr, "pers_lldb:ErrorHandler:Itzam error in %s: %d\n", function_name, (sint_t)error );
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_ERROR, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("ErrorHandler:Itzam error in "); DLT_STRING(function_name);
+ DLT_STRING("error=<"); DLT_INT((sint_t)error); DLT_STRING(">") ) ;
+}
+
+static sint_t GetAllKeysFromItzamLocalDB( sint_t dbHandler, pstr_t buffer, sint_t size )
+{
+ bool_t bCanContinue = true ;
+ itzam_btree_cursor cursor;
+ sint_t availableSize = size;
+ sint_t result = 0 ;
+ KeyValuePair_LocalDB_s crtKey;
+ bool_t bOnlySizeNeeded = (NIL == buffer) ;
+ itzam_state itzState ;
+ lldb_handler_s* pLldbHandler = NIL ;
+ bool_t bLocked = false ;
+ str_t dbPathnameTemp[PERS_ORG_MAX_LENGTH_PATH_FILENAME] = "invalid path" ;
+
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("dbHandler="); DLT_INT(dbHandler);
+ DLT_STRING("buffer="); DLT_UINT((uint_t)buffer);
+ DLT_STRING("size="); DLT_INT(size); DLT_STRING("...")) ;
+
+ if(dbHandler >= 0)
+ {
+ if(lldb_handles_Lock())
+ {
+ bLocked = true ;
+ pLldbHandler = lldb_handles_FindInUseHandle(dbHandler) ;
+ if(NIL == pLldbHandler)
+ {
+ bCanContinue = false ;
+ result = PERS_COM_ERR_INVALID_PARAM ;
+ }
+ else
+ {
+ if(PersLldbPurpose_DB != pLldbHandler->ePurpose)
+ {/* this would be very bad */
+ bCanContinue = false ;
+ result = PERS_COM_FAILURE ;
+ }
+ /* to not use DLT while mutex locked */
+ (void)strncpy(dbPathnameTemp, pLldbHandler->dbPathname, sizeof(dbPathnameTemp)) ;
+ }
+ }
+ }
+ else
+ {
+ bCanContinue = false ;
+ result = PERS_COM_ERR_INVALID_PARAM ;
+ }
+
+ if(bCanContinue)
+ {
+ if( ( buffer != NIL ) && ( size > 0 ) )
+ {
+ (void)memset( buffer, 0, (size_t)size );
+ }
+
+ itzState = itzam_btree_cursor_create( & cursor, & pLldbHandler->btree) ;
+ if(ITZAM_OKAY == itzState)
+ {
+ (void)memset( & crtKey, 0, sizeof( crtKey ) );
+ itzState = itzam_btree_cursor_read( & cursor, & crtKey ) ;
+ if(ITZAM_OKAY == itzState)
+ {
+ /* Add the length of the key separator to the count */
+ size_t keyLen = strnlen( crtKey.m_key, sizeof( crtKey.m_key ) ) ;
+ if(keyLen > 0)
+ {
+ if( (! bOnlySizeNeeded) && ( (sint_t)keyLen < availableSize ) )
+ {
+ (void)strncpy( buffer, crtKey.m_key, keyLen);
+ *(buffer+keyLen) = ListItemsSeparator; /*DG C7MR2R-MISRA-C:2004 Rule 17.4-SSW_PersCommon_1004*/
+ buffer += (keyLen + sizeof(ListItemsSeparator)) ; /*DG C7MR2R-MISRA-C:2004 Rule 17.4-SSW_PersCommon_1004*/
+ availableSize -= (sint_t)(keyLen + sizeof(ListItemsSeparator));
+ }
+ result += (sint_t)(keyLen + sizeof(ListItemsSeparator));
+ }
+
+ while ( itzam_btree_cursor_next( & cursor ) == itzam_true )
+ {
+ (void)memset( & crtKey, 0, sizeof( crtKey ) );
+ if( ITZAM_OKAY == itzam_btree_cursor_read( & cursor, & crtKey ) )
+ {
+ /* Add the length of the key separator to the count */
+ keyLen = strnlen( crtKey.m_key, sizeof( crtKey.m_key ) ) ; /* + sizeof( ListItemsSeparator ); */
+ if(keyLen > 0)
+ {
+ if( (! bOnlySizeNeeded) && ( (sint_t)keyLen < availableSize ) )
+ {
+ (void)strncpy( buffer, crtKey.m_key, keyLen);
+ *(buffer+keyLen) = ListItemsSeparator; /*DG C7MR2R-MISRA-C:2004 Rule 17.4-SSW_PersCommon_1004*/
+ buffer += (keyLen + sizeof(ListItemsSeparator)) ; /*DG C7MR2R-MISRA-C:2004 Rule 17.4-SSW_PersCommon_1004*/
+ availableSize -= (sint_t)(keyLen + sizeof(ListItemsSeparator));
+ }
+ result += (sint_t)(keyLen + sizeof(ListItemsSeparator));
+ }
+ }
+ }
+
+ (void)itzam_btree_cursor_free( & cursor );
+ }
+ }
+ else
+ {
+ if(ITZAM_FAILED == itzState)
+ {
+ /* no data found */
+ result = 0 ;
+ }
+ else
+ {
+ result = PERS_COM_FAILURE;
+ }
+ }
+ }
+
+ if(bLocked)
+ {
+ (void)lldb_handles_Unlock() ;
+ }
+
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("dbHandler="); DLT_INT(dbHandler);
+ DLT_STRING("<<"); DLT_STRING(dbPathnameTemp); DLT_STRING(">>, ");
+ DLT_STRING("retval=<"); DLT_INT(result); DLT_STRING(">")) ;
+
+ return result;
+}/*DG C7MR2R-ISQP Metric 10-SSW_PersCommon_0001*/ /*DG C7MR2R-ISQP Metric 11-SSW_PersCommon_1001*/ /*DG C7MR2R-ISQP Metric 1-SSW_PersCommon_1006*/ /*DG C7MR2R-ISQP Metric 6-SSW_PersCommon_1007*/
+
+static sint_t GetAllKeysFromItzamRCT( sint_t dbHandler, pstr_t buffer, sint_t size )
+{
+ bool_t bCanContinue = true ;
+ itzam_btree_cursor cursor;
+ sint_t availableSize = size;
+ sint_t result = 0 ;
+ KeyValuePair_RCT_s crtKey;
+ bool_t bOnlySizeNeeded = (NIL == buffer) ;
+ itzam_state itzState ;
+ lldb_handler_s* pLldbHandler = NIL ;
+ bool_t bLocked = false ;
+ str_t dbPathnameTemp[PERS_ORG_MAX_LENGTH_PATH_FILENAME] = "invalid path" ;
+
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("dbHandler="); DLT_INT(dbHandler);
+ DLT_STRING("buffer="); DLT_UINT((uint_t)buffer);
+ DLT_STRING("size="); DLT_INT(size); DLT_STRING("...")) ;
+
+ if(dbHandler >= 0)
+ {
+ if(lldb_handles_Lock())
+ {
+ bLocked = true ;
+ pLldbHandler = lldb_handles_FindInUseHandle(dbHandler) ;
+ if(NIL == pLldbHandler)
+ {
+ bCanContinue = false ;
+ result = PERS_COM_ERR_INVALID_PARAM ;
+ }
+ else
+ {
+ if(PersLldbPurpose_RCT != pLldbHandler->ePurpose)
+ {/* this would be very bad */
+ bCanContinue = false ;
+ result = PERS_COM_FAILURE ;
+ }
+ /* to not use DLT while mutex locked */
+ (void)strncpy(dbPathnameTemp, pLldbHandler->dbPathname, sizeof(dbPathnameTemp)) ;
+ }
+ }
+ }
+ else
+ {
+ bCanContinue = false ;
+ result = PERS_COM_ERR_INVALID_PARAM ;
+ }
+
+ if(bCanContinue)
+ {
+ if( ( buffer != NIL ) && ( size > 0 ) )
+ {
+ (void)memset( buffer, 0, (size_t)size );
+ }
+
+ itzState = itzam_btree_cursor_create( & cursor, & pLldbHandler->btree) ;
+ if(ITZAM_OKAY == itzState)
+ {
+ (void)memset( & crtKey, 0, sizeof( crtKey ) );
+ itzState = itzam_btree_cursor_read( & cursor, & crtKey ) ;
+ if(ITZAM_OKAY == itzState)
+ {
+ /* Add the length of the key separator to the count */
+ size_t keyLen = strnlen( crtKey.m_key, sizeof( crtKey.m_key ) ) ;
+ if(keyLen > 0)
+ {
+ if( (! bOnlySizeNeeded) && ( (sint_t)keyLen < availableSize ) )
+ {
+ (void)strncpy( buffer, crtKey.m_key, keyLen);
+ *(buffer+keyLen) = ListItemsSeparator; /*DG C7MR2R-MISRA-C:2004 Rule 17.4-SSW_PersCommon_1004*/
+ buffer += (sint_t)(keyLen + sizeof(ListItemsSeparator)) ; /*DG C7MR2R-MISRA-C:2004 Rule 17.4-SSW_PersCommon_1004*/
+ availableSize -= (sint_t)(keyLen + sizeof(ListItemsSeparator));
+ }
+ result += (sint_t)(keyLen + sizeof(ListItemsSeparator));
+ }
+
+ while ( itzam_btree_cursor_next( & cursor ) == itzam_true )
+ {
+ (void)memset( & crtKey, 0, sizeof( crtKey ) );
+ if( ITZAM_OKAY == itzam_btree_cursor_read( & cursor, & crtKey ) )
+ {
+ /* Add the length of the key separator to the count */
+ keyLen = strnlen( crtKey.m_key, sizeof( crtKey.m_key ) ) ; /* + sizeof( ListItemsSeparator ); */
+ if(keyLen > 0)
+ {
+ if( (! bOnlySizeNeeded) && ( (sint_t)keyLen < availableSize ) )
+ {
+ (void)strncpy( buffer, crtKey.m_key, keyLen);
+ *(buffer+keyLen) = ListItemsSeparator; /*DG C7MR2R-MISRA-C:2004 Rule 17.4-SSW_PersCommon_1004*/
+ buffer += (keyLen + sizeof(ListItemsSeparator)) ; /*DG C7MR2R-MISRA-C:2004 Rule 17.4-SSW_PersCommon_1004*/
+ availableSize -= (sint_t)(keyLen + sizeof(ListItemsSeparator));
+ }
+ result += (sint_t)(keyLen + sizeof(ListItemsSeparator));
+ }
+ }
+ }
+
+ (void)itzam_btree_cursor_free( & cursor );
+ }
+ }
+ else
+ {
+ if(ITZAM_FAILED == itzState)
+ {
+ /* no data found */
+ result = 0 ;
+ }
+ else
+ {
+ result = PERS_COM_FAILURE;
+ }
+ }
+ }
+
+ if(bLocked)
+ {
+ (void)lldb_handles_Unlock() ;
+ }
+
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("dbHandler="); DLT_INT(dbHandler);
+ DLT_STRING("<<"); DLT_STRING(dbPathnameTemp); DLT_STRING(">>, ");
+ DLT_STRING("retval=<"); DLT_INT(result); DLT_STRING(">")) ;
+
+ return result;
+}/*DG C7MR2R-ISQP Metric 10-SSW_PersCommon_0001*/ /*DG C7MR2R-ISQP Metric 11-SSW_PersCommon_0002*/ /*DG C7MR2R-ISQP Metric 1-SSW_PersCommon_1008*/ /*DG C7MR2R-ISQP Metric 6-SSW_PersCommon_1009*/
+
+
+/* return no of bytes written, or negative value in case of error */
+static sint_t SetDataInItzamLocalDB(sint_t dbHandler, pconststr_t key, pconststr_t data, sint_t dataSize)
+{
+ bool_t bCanContinue = true ;
+ sint_t size_written = PERS_COM_FAILURE;
+ lldb_handler_s* pLldbHandler = NIL ;
+ bool_t bLocked = false ;
+ str_t dbPathnameTemp[PERS_ORG_MAX_LENGTH_PATH_FILENAME] = "invalid path" ;
+
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("dbHandler="); DLT_INT(dbHandler);
+ DLT_STRING("key=<<"); DLT_STRING(key); DLT_STRING(">>, ");
+ DLT_STRING("size<<"); DLT_INT(dataSize); DLT_STRING(">> ...")) ;
+
+ if(( dbHandler >= 0)
+ && (NIL != key)
+ && (NIL != data)
+ && (dataSize > 0) )
+ {
+ if(lldb_handles_Lock())
+ {
+ bLocked = true ;
+ pLldbHandler = lldb_handles_FindInUseHandle(dbHandler) ;
+ if(NIL == pLldbHandler)
+ {
+ bCanContinue = false ;
+ size_written = PERS_COM_ERR_INVALID_PARAM ;
+ }
+ else
+ {
+ if(PersLldbPurpose_DB != pLldbHandler->ePurpose)
+ {/* this would be very bad */
+ bCanContinue = false ;
+ size_written = PERS_COM_FAILURE ;
+ }
+ /* to not use DLT while mutex locked */
+ (void)strncpy(dbPathnameTemp, pLldbHandler->dbPathname, sizeof(dbPathnameTemp)) ;
+ }
+ }
+ }
+ else
+ {
+ bCanContinue = false ;
+ size_written = PERS_COM_ERR_INVALID_PARAM ;
+ }
+
+ if(bCanContinue)
+ {
+ KeyValuePair_LocalDB_s search_insert; /* use a single variable to reduce stack size */
+
+ if( itzam_true == itzam_btree_find( & pLldbHandler->btree, key, & search_insert ) )
+ {
+ if(ITZAM_OKAY != itzam_btree_remove( & pLldbHandler->btree, key ))
+ {
+ bCanContinue = false ;
+ }
+ }
+
+ if(bCanContinue)
+ {
+ (void)memset(search_insert.m_data, 0, sizeof(search_insert.m_data) );
+ (void)strncpy(search_insert.m_key, key, sizeof(search_insert.m_key)) ;
+ (void)memcpy(search_insert.m_data, data, (size_t)dataSize) ;
+ search_insert.m_dataSize = dataSize ;
+ if(ITZAM_OKAY == itzam_btree_insert( & pLldbHandler->btree, ( void * )( & search_insert ) ))
+ {
+ size_written = dataSize;
+ }
+ }
+ }
+
+ if(bLocked)
+ {
+ (void)lldb_handles_Unlock() ;
+ }
+
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("dbHandler="); DLT_INT(dbHandler);
+ DLT_STRING("<<"); DLT_STRING(dbPathnameTemp); DLT_STRING(">>, ");
+ DLT_STRING("key=<<"); DLT_STRING(key); DLT_STRING(">>, ");
+ DLT_STRING("size<<"); DLT_INT(dataSize); DLT_STRING(">>, ");
+ DLT_STRING("retval=<"); DLT_INT(size_written); DLT_STRING(">")) ;
+
+ return size_written;
+}/*DG C7MR2R-ISQP Metric 10-SSW_PersCommon_0001*/
+
+static sint_t SetDataInItzamRCT( sint_t dbHandler, pconststr_t key, PersistenceConfigurationKey_s const * pConfig)
+{
+ bool_t bCanContinue = true ;
+ sint_t size_written = PERS_COM_FAILURE;
+ lldb_handler_s* pLldbHandler = NIL ;
+ bool_t bLocked = false ;
+ str_t dbPathnameTemp[PERS_ORG_MAX_LENGTH_PATH_FILENAME] = "invalid path" ;
+
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("dbHandler="); DLT_INT(dbHandler);
+ DLT_STRING("key=<<"); DLT_STRING(key); DLT_STRING(">>...")) ;
+
+ if( (dbHandler >= 0)
+ && (NIL != key)
+ && (NIL != pConfig) )
+ {
+ if(lldb_handles_Lock())
+ {
+ bLocked = true ;
+ pLldbHandler = lldb_handles_FindInUseHandle(dbHandler) ;
+ if(NIL == pLldbHandler)
+ {
+ bCanContinue = false ;
+ size_written = PERS_COM_ERR_INVALID_PARAM ;
+ }
+ else
+ {
+ if(PersLldbPurpose_RCT != pLldbHandler->ePurpose)
+ {/* this would be very bad */
+ bCanContinue = false ;
+ size_written = PERS_COM_FAILURE ;
+ }
+ /* to not use DLT while mutex locked */
+ (void)strncpy(dbPathnameTemp, pLldbHandler->dbPathname, sizeof(dbPathnameTemp)) ;
+ }
+ }
+ }
+ else
+ {
+ bCanContinue = false ;
+ size_written = PERS_COM_ERR_INVALID_PARAM ;
+ }
+
+ if(bCanContinue)
+ {
+ KeyValuePair_RCT_s search, insert;
+
+ (void)memset(insert.m_data, 0, sizeof(insert.m_data) );
+ (void)strncpy(insert.m_key, key, sizeof(insert.m_key)) ;
+ (void)memcpy(insert.m_data, pConfig, sizeof(PersistenceConfigurationKey_s)) ;
+
+ if( itzam_true == itzam_btree_find( & pLldbHandler->btree, key, & search ) )
+ {
+ if(ITZAM_OKAY == itzam_btree_remove( & pLldbHandler->btree, key ))
+ {
+ if(ITZAM_OKAY == itzam_btree_insert( & pLldbHandler->btree, ( void * )( & insert ) ))
+ {
+ size_written = (sint_t)sizeof(PersistenceConfigurationKey_s);
+ }
+ }
+ }
+ else
+ {
+ if(ITZAM_OKAY == itzam_btree_insert( & pLldbHandler->btree, ( void * )( & insert ) ))
+ {
+ size_written = (sint_t)sizeof(PersistenceConfigurationKey_s);
+ }
+ }
+ }
+
+ if(bLocked)
+ {
+ (void)lldb_handles_Unlock() ;
+ }
+
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("dbHandler="); DLT_INT(dbHandler);
+ DLT_STRING("<<"); DLT_STRING(dbPathnameTemp); DLT_STRING(">>, ");
+ DLT_STRING("key=<<"); DLT_STRING(key); DLT_STRING(">>, ");
+ DLT_STRING("retval=<"); DLT_INT(size_written); DLT_STRING(">")) ;
+
+ return size_written;
+}/*DG C7MR2R-ISQP Metric 10-SSW_PersCommon_0001*/
+
+/* return size of key, or negative value in case of error */
+static sint_t GetKeySizeFromItzamLocalDB(sint_t dbHandler, pconststr_t key)
+{
+ bool_t bCanContinue = true ;
+ sint_t size_read = PERS_COM_FAILURE ;
+ lldb_handler_s* pLldbHandler = NIL ;
+ bool_t bLocked = false ;
+ str_t dbPathnameTemp[PERS_ORG_MAX_LENGTH_PATH_FILENAME] = "invalid path" ;
+
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("dbHandler="); DLT_INT(dbHandler);
+ DLT_STRING("key=<<"); DLT_STRING(key); DLT_STRING(">> ...")) ;
+
+ if((dbHandler >= 0) && (NIL != key))
+ {
+ if(lldb_handles_Lock())
+ {
+ bLocked = true ;
+ pLldbHandler = lldb_handles_FindInUseHandle(dbHandler) ;
+ if(NIL == pLldbHandler)
+ {
+ bCanContinue = false ;
+ size_read = PERS_COM_ERR_INVALID_PARAM ;
+ }
+ else
+ {
+ if(PersLldbPurpose_DB != pLldbHandler->ePurpose)
+ {/* this would be very bad */
+ bCanContinue = false ;
+ size_read = PERS_COM_FAILURE ;
+ }
+ /* to not use DLT while mutex locked */
+ (void)strncpy(dbPathnameTemp, pLldbHandler->dbPathname, sizeof(dbPathnameTemp)) ;
+ }
+ }
+ }
+ else
+ {
+ bCanContinue = false ;
+ size_read = PERS_COM_ERR_INVALID_PARAM ;
+ }
+
+ if(bCanContinue)
+ {
+ KeyValuePair_LocalDB_s search;
+
+ if( itzam_btree_find( & pLldbHandler->btree, key, & search ) == itzam_true )
+ {
+ size_read = search.m_dataSize ;
+ }
+ else
+ {
+ size_read = PERS_COM_ERR_NOT_FOUND ;
+ }
+ }
+
+ if(bLocked)
+ {
+ (void)lldb_handles_Unlock() ;
+ }
+
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("dbHandler="); DLT_INT(dbHandler);
+ DLT_STRING("<<"); DLT_STRING(dbPathnameTemp); DLT_STRING(">>, ");
+ DLT_STRING("key=<<"); DLT_STRING(key); DLT_STRING(">>, ");
+ DLT_STRING("retval=<"); DLT_INT(size_read); DLT_STRING(">")) ;
+
+ return size_read;
+}/*DG C7MR2R-ISQP Metric 10-SSW_PersCommon_0001*/
+
+/* return no of bytes read, or negative value in case of error */
+static sint_t GetDataFromItzamLocalDB(sint_t dbHandler, pconststr_t key, pstr_t buffer_out, sint_t bufSize)
+{
+ bool_t bCanContinue = true ;
+ sint_t size_read = PERS_COM_FAILURE ;
+ lldb_handler_s* pLldbHandler = NIL ;
+ bool_t bLocked = false ;
+ str_t dbPathnameTemp[PERS_ORG_MAX_LENGTH_PATH_FILENAME] = "invalid path" ;
+
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("dbHandler="); DLT_INT(dbHandler);;
+ DLT_STRING("key=<<"); DLT_STRING(key); DLT_STRING(">>, ");
+ DLT_STRING("bufsize=<<"); DLT_INT(bufSize); DLT_STRING(">> ... ")) ;
+
+ if( (dbHandler >= 0)
+ && (NIL != key)
+ && (NIL != buffer_out)
+ && (bufSize > 0) )
+ {
+ if(lldb_handles_Lock())
+ {
+ bLocked = true ;
+ pLldbHandler = lldb_handles_FindInUseHandle(dbHandler) ;
+ if(NIL == pLldbHandler)
+ {
+ bCanContinue = false ;
+ size_read = PERS_COM_ERR_INVALID_PARAM ;
+ }
+ else
+ {
+ if(PersLldbPurpose_DB != pLldbHandler->ePurpose)
+ {/* this would be very bad */
+ bCanContinue = false ;
+ size_read = PERS_COM_FAILURE ;
+ }
+ /* to not use DLT while mutex locked */
+ (void)strncpy(dbPathnameTemp, pLldbHandler->dbPathname, sizeof(dbPathnameTemp)) ;
+ }
+ }
+ }
+ else
+ {
+ bCanContinue = false ;
+ size_read = PERS_COM_ERR_INVALID_PARAM ;
+ }
+
+ if(bCanContinue)
+ {
+ KeyValuePair_LocalDB_s search;
+
+ if( itzam_btree_find( & pLldbHandler->btree, key, & search ) == itzam_true )
+ {
+ if( bufSize >= search.m_dataSize)
+ {
+ size_read = search.m_dataSize ;
+ (void)memcpy(buffer_out, search.m_data, (size_t)size_read) ;
+ }
+ else
+ {
+ size_read = PERS_COM_ERR_BUFFER_TOO_SMALL ;
+ }
+ }
+ else
+ {
+ size_read = PERS_COM_ERR_NOT_FOUND ;
+ }
+ }
+
+ if(bLocked)
+ {
+ (void)lldb_handles_Unlock() ;
+ }
+
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("dbHandler="); DLT_INT(dbHandler);
+ DLT_STRING("<<"); DLT_STRING(dbPathnameTemp); DLT_STRING(">>, ");
+ DLT_STRING("key=<<"); DLT_STRING(key); DLT_STRING(">>, ");
+ DLT_STRING("bufsize=<<"); DLT_INT(bufSize); DLT_STRING(">>, ");
+ DLT_STRING("retval=<"); DLT_INT(size_read); DLT_STRING(">")) ;
+
+ return size_read;
+}/*DG C7MR2R-ISQP Metric 10-SSW_PersCommon_0001*/
+
+static sint_t GetDataFromItzamRCT( sint_t dbHandler, pconststr_t key, PersistenceConfigurationKey_s* pConfig)
+{
+ bool_t bCanContinue = true ;
+ sint_t size_read = PERS_COM_FAILURE ;
+ lldb_handler_s* pLldbHandler = NIL ;
+ bool_t bLocked = false ;
+ str_t dbPathnameTemp[PERS_ORG_MAX_LENGTH_PATH_FILENAME] = "invalid path" ;
+
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("dbHandler="); DLT_INT(dbHandler);
+ DLT_STRING("key=<<"); DLT_STRING(key); DLT_STRING(">> ...")) ;
+
+ if( (dbHandler >= 0)
+ && (NIL != key)
+ && (NIL != pConfig) )
+ {
+ if(lldb_handles_Lock())
+ {
+ bLocked = true ;
+ pLldbHandler = lldb_handles_FindInUseHandle(dbHandler) ;
+ if(NIL == pLldbHandler)
+ {
+ bCanContinue = false ;
+ size_read = PERS_COM_ERR_INVALID_PARAM ;
+ }
+ else
+ {
+ if(PersLldbPurpose_RCT != pLldbHandler->ePurpose)
+ {/* this would be very bad */
+ bCanContinue = false ;
+ size_read = PERS_COM_FAILURE ;
+ }
+ /* to not use DLT while mutex locked */
+ (void)strncpy(dbPathnameTemp, pLldbHandler->dbPathname, sizeof(dbPathnameTemp)) ;
+ }
+ }
+ }
+ else
+ {
+ bCanContinue = false ;
+ size_read = PERS_COM_ERR_INVALID_PARAM ;
+ }
+
+ if(bCanContinue)
+ {
+ KeyValuePair_RCT_s search;
+
+ if(itzam_true == itzam_btree_find( & pLldbHandler->btree, key, & search ) )
+ {
+ (void)memcpy(pConfig, &(search.m_data), sizeof(PersistenceConfigurationKey_s) );
+ size_read = sizeof(PersistenceConfigurationKey_s);
+ }
+ else
+ {
+ size_read = PERS_COM_ERR_NOT_FOUND ;
+ }
+ }
+
+ if(bLocked)
+ {
+ (void)lldb_handles_Unlock() ;
+ }
+
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("dbHandler="); DLT_INT(dbHandler);
+ DLT_STRING("<<"); DLT_STRING(dbPathnameTemp); DLT_STRING(">>, ");
+ DLT_STRING("key=<<"); DLT_STRING(key); DLT_STRING(">>, ");
+ DLT_STRING("retval=<"); DLT_INT(size_read); DLT_STRING(">")) ;
+
+ return size_read;
+}/*DG C7MR2R-ISQP Metric 10-SSW_PersCommon_0001*/
+
+static bool_t lldb_handles_Lock(void)
+{
+ bool_t bEverythingOK = true ;
+ sint_t siErr = pthread_mutex_lock(&g_mutexLldb) ;
+ if(0 != siErr)
+ {
+ bEverythingOK = false ;
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_ERROR, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("pthread_mutex_lock failed with error=<"); DLT_INT(siErr); DLT_STRING(">")) ;
+ }
+
+ return bEverythingOK ;
+}
+
+static bool_t lldb_handles_Unlock(void)
+{
+ bool_t bEverythingOK = true ;
+ sint_t siErr = pthread_mutex_unlock (&g_mutexLldb) ;
+ if(0 != siErr)
+ {
+ bEverythingOK = false ;
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_ERROR, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("pthread_mutex_unlock failed with error=<"); DLT_INT(siErr); DLT_STRING(">")) ;
+ }
+
+ return bEverythingOK ;
+}
+
+/* it is assumed dbHandler is checked by the caller */
+static lldb_handler_s* lldb_handles_FindInUseHandle(sint_t dbHandler)
+{
+ lldb_handler_s* pHandler = NIL ;
+
+ if(dbHandler <= PERS_LLDB_MAX_STATIC_HANDLES)
+ {
+ if(g_sHandlers.asStaticHandles[dbHandler].bIsAssigned)
+ {
+ pHandler = &g_sHandlers.asStaticHandles[dbHandler] ;
+ }
+ }
+ else
+ {
+ lldb_handles_list_el_s* pListElemCurrent = g_sHandlers.pListHead ;
+ while(NIL != pListElemCurrent)
+ {
+ if(dbHandler == pListElemCurrent->sHandle.dbHandler)
+ {
+ pHandler = &pListElemCurrent->sHandle;
+ break ;
+ }
+ pListElemCurrent = pListElemCurrent->pNext ;
+ }
+ }
+
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING((NIL!=pHandler) ? "Found handler <" : "ERROR can't find handler <"); DLT_INT(dbHandler); DLT_STRING(">");
+ DLT_STRING((NIL!=pHandler) ? (dbHandler <= PERS_LLDB_MAX_STATIC_HANDLES ? "in static area" : "in dynamic list") : "")) ;
+
+ return pHandler ;
+}
+
+static lldb_handler_s* lldb_handles_FindAvailableHandle(void)
+{
+ bool_t bCanContinue = true ;
+ lldb_handler_s* pHandler = NIL ;
+ lldb_handles_list_el_s* psListElemNew = NIL ;
+
+ /* first try to find an available handle in the static area */
+ sint_t siIndex = 0 ;
+ for(siIndex = 0 ; siIndex <= PERS_LLDB_MAX_STATIC_HANDLES ; siIndex++)
+ {
+ if( ! g_sHandlers.asStaticHandles[siIndex].bIsAssigned)
+ {
+ /* index setting should be done only once at the initialization of the static array
+ * Anyway, doing it here is more consistent */
+ g_sHandlers.asStaticHandles[siIndex].dbHandler = siIndex ;
+ pHandler = &g_sHandlers.asStaticHandles[siIndex] ;
+ break ;
+ }
+ }
+
+ if(NIL == pHandler)
+ {
+ /* no position available in the static array => we have to use the list
+ * allocate memory for the new element and process the situation when the list is headless */
+
+ psListElemNew = (lldb_handles_list_el_s*)malloc(sizeof(lldb_handles_list_el_s)) ; /*DG C7MR2R-MISRA-C:2004 Rule 20.4-SSW_PersCommon_1010*/
+ if(NIL == psListElemNew)
+ {
+ bCanContinue = false ;
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_ERROR, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("malloc failed")) ;
+ }
+ else
+ {
+ if(NIL == g_sHandlers.pListHead)
+ {
+ /* the list not yet used/created, so use the new created element as the head */
+ g_sHandlers.pListHead = psListElemNew ;
+ g_sHandlers.pListHead->pNext = NIL ;
+ g_sHandlers.pListHead->sHandle.dbHandler = PERS_LLDB_MAX_STATIC_HANDLES + 1 ;
+ /* the rest of the members will be set by lldb_handles_InitHandle */
+ pHandler = &psListElemNew->sHandle;
+ }
+ }
+ }
+
+ if((NIL == pHandler) && bCanContinue)
+ {
+ /* no position available in the static array => we have to use the list
+ * the memory for psListElemNew has been allocated and the list has a head
+ * The new element has to get the smallest index
+ * Now lets consider the situation when the head of the list has an index higher than (PERS_LLDB_MAX_STATIC_HANDLES + 1)
+ * => the list will have a new head !!! */
+ if(g_sHandlers.pListHead->sHandle.dbHandler > (PERS_LLDB_MAX_STATIC_HANDLES + 1))
+ {
+ psListElemNew->pNext = g_sHandlers.pListHead ;
+ psListElemNew->sHandle.dbHandler = PERS_LLDB_MAX_STATIC_HANDLES + 1 ;
+ /* the rest of the members will be set by lldb_handles_InitHandle */
+ g_sHandlers.pListHead = psListElemNew ;
+ pHandler = &psListElemNew->sHandle;
+ }
+ }
+
+ if((NIL == pHandler) && bCanContinue)
+ {
+ /* no position available in the static array => we have to use the list
+ * the memory for psListElemNew has been allocated and the list has a head (with the smallest index)
+ * The new element has to get the smallest available index
+ * So will search for the first gap between two consecutive elements of the list and will introduce the new element between */
+ lldb_handles_list_el_s* pListElemCurrent1 = g_sHandlers.pListHead ;
+ lldb_handles_list_el_s* pListElemCurrent2 = pListElemCurrent1->pNext;
+ while(NIL != pListElemCurrent2)
+ {
+ if(pListElemCurrent2->sHandle.dbHandler - pListElemCurrent1->sHandle.dbHandler > 1)
+ {
+ /* found a gap => insert the element between and use the index next to pListElemCurrent1's */
+ psListElemNew->pNext = pListElemCurrent2 ;
+ psListElemNew->sHandle.dbHandler = pListElemCurrent1->sHandle.dbHandler + 1 ;
+ pListElemCurrent1->pNext = psListElemNew ;
+ pHandler = &psListElemNew->sHandle;
+ break ;
+ }
+ else
+ {
+ pListElemCurrent1 = pListElemCurrent2 ;
+ pListElemCurrent2 = pListElemCurrent2->pNext ;
+ }
+ }
+ if(NIL == pListElemCurrent2)
+ {
+ /* reached the end of the list => the list will have a new end */
+ psListElemNew->pNext = NIL ;
+ psListElemNew->sHandle.dbHandler = pListElemCurrent1->sHandle.dbHandler + 1 ;
+ pListElemCurrent1->pNext = psListElemNew ;
+ pHandler = &psListElemNew->sHandle;
+ }
+ }
+
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING((NIL!=pHandler) ? "Found availble handler <" : "ERROR can't find available handler <");
+ DLT_INT((NIL!=pHandler) ? pHandler->dbHandler : (-1)); DLT_STRING(">");
+ DLT_STRING((NIL!=pHandler) ? (pHandler->dbHandler <= PERS_LLDB_MAX_STATIC_HANDLES ? "in static area" : "in dynamic list") : "") ) ;
+
+ return pHandler ;
+}/*DG C7MR2R-ISQP Metric 6-SSW_PersCommon_1011*/
+
+static void lldb_handles_InitHandle(lldb_handler_s* psHandle_inout, pers_lldb_purpose_e ePurpose, str_t const * dbPathname)
+{
+ psHandle_inout->bIsAssigned = true ;
+ psHandle_inout->ePurpose = ePurpose ;
+ (void)strncpy(psHandle_inout->dbPathname, dbPathname, sizeof(psHandle_inout->dbPathname)) ;
+}
+
+static bool_t lldb_handles_DeinitHandle(sint_t dbHandler)
+{
+ bool_t bEverythingOK = true ;
+ bool_t bHandlerFound = false ;
+
+
+ if(dbHandler <= PERS_LLDB_MAX_STATIC_HANDLES)
+ {
+ bHandlerFound = true ;
+ g_sHandlers.asStaticHandles[dbHandler].bIsAssigned = false ;
+ }
+ else
+ {
+ /* consider the situation when the handle is the head of the list */
+ if(NIL != g_sHandlers.pListHead)
+ {
+ if(dbHandler == g_sHandlers.pListHead->sHandle.dbHandler)
+ {
+ lldb_handles_list_el_s* pListElemTemp = NIL ;
+
+ bHandlerFound = true ;
+ pListElemTemp = g_sHandlers.pListHead ;
+ g_sHandlers.pListHead = g_sHandlers.pListHead->pNext ;
+ free(pListElemTemp) ; /*DG C7MR2R-MISRA-C:2004 Rule 20.4-SSW_PersCommon_1012*/
+ }
+ }
+ else
+ {
+ bEverythingOK = false ;
+ }
+ }
+
+ if(bEverythingOK && ( ! bHandlerFound))
+ {
+ /* consider the situation when the handle is in the list (but not the head) */
+ lldb_handles_list_el_s* pListElemCurrent1 = g_sHandlers.pListHead ;
+ lldb_handles_list_el_s* pListElemCurrent2 = pListElemCurrent1->pNext;
+ while(NIL != pListElemCurrent2)
+ {
+ if(dbHandler == pListElemCurrent2->sHandle.dbHandler)
+ {
+ /* found the handle */
+ bHandlerFound = true ;
+ pListElemCurrent1->pNext = pListElemCurrent2->pNext ;
+ free(pListElemCurrent2) ; /*DG C7MR2R-MISRA-C:2004 Rule 20.4-SSW_PersCommon_1013*/
+ break ;
+ }
+ else
+ {
+ pListElemCurrent1 = pListElemCurrent2 ;
+ pListElemCurrent2 = pListElemCurrent2->pNext ;
+ }
+ }
+ if(NIL == pListElemCurrent2)
+ {
+ /* reached the end of the list without finding the handle */
+ bEverythingOK = false ;
+ }
+ }
+
+ DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":");
+ DLT_STRING("dbHandler=<"); DLT_INT(dbHandler); DLT_STRING("> ");
+ DLT_STRING(bEverythingOK ? (dbHandler <= PERS_LLDB_MAX_STATIC_HANDLES ? "deinit handler in static area" : "deinit handler in dynamic list") : "ERROR - handler not found") ) ;
+
+ return bEverythingOK ;
+}
diff --git a/src/pers_resource_config_table.c b/src/pers_resource_config_table.c
new file mode 100644
index 0000000..5f5cc65
--- /dev/null
+++ b/src/pers_resource_config_table.c
@@ -0,0 +1,247 @@
+/**********************************************************************************************************************
+*
+* Copyright (C) 2012 Continental Automotive Systems, Inc.
+*
+* Author: Ionut.Ieremie@continental-corporation.com
+*
+* Implementation of persComRct.h
+*
+* This Source Code Form is subject to the terms of the Mozilla Public
+* License, v. 2.0. If a copy of the MPL was not distributed with this
+* file, You can obtain one at http://mozilla.org/MPL/2.0/.
+*
+* Date Author Reason
+* 2013.02.05 uidl9757 CSP_WZ#2220: Adaptation for open source
+* 2012.12.10 uidl9757 CSP_WZ#2060: Created
+*
+**********************************************************************************************************************/
+
+#include "persComTypes.h"
+#include "string.h"
+
+#include "persComErrors.h"
+#include "persComDataOrg.h"
+#include "pers_low_level_db_access_if.h"
+#include "persComRct.h"
+
+/**
+ * \brief Obtain a handler to RCT indicated by rctPathname
+ * \note : RCT is created if it does not exist and (bForceCreationIfNotPresent != 0)
+ *
+ * \param rctPathname [in] absolute path to RCT (length limited to \ref PERS_ORG_MAX_LENGTH_PATH_FILENAME)
+ * \param bForceCreationIfNotPresent [in] if !=0x0, the RCT is created if it does not exist
+ *
+ * \return >= 0 for valid handler, negative value for error (\ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+signed int persComRctOpen(char const * rctPathname, unsigned char bForceCreationIfNotPresent)
+{
+ sint_t iErrCode = PERS_COM_SUCCESS ;
+
+ if(NIL != rctPathname)
+ {
+ if(strlen(rctPathname) >= PERS_ORG_MAX_LENGTH_PATH_FILENAME)
+ {
+ iErrCode = PERS_COM_ERR_INVALID_PARAM ;
+ }
+ }
+ else
+ {
+ iErrCode = PERS_COM_ERR_INVALID_PARAM ;
+ }
+
+ if(PERS_COM_SUCCESS == iErrCode)
+ {
+ iErrCode = pers_lldb_open(rctPathname, PersLldbPurpose_RCT, bForceCreationIfNotPresent);
+ }
+
+ return iErrCode ;
+}
+
+/**
+ * \brief Close handler to RCT
+ *
+ * \param handlerRCT [in] handler obtained with persComRctOpen
+ *
+ * \return 0 for success, negative value for error (\ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+signed int persComRctClose(signed int handlerRCT)
+{
+ sint_t iErrCode = PERS_COM_SUCCESS ;
+
+ if(handlerRCT < 0)
+ {
+ iErrCode = PERS_COM_ERR_INVALID_PARAM ;
+ }
+
+ if(PERS_COM_SUCCESS == iErrCode)
+ {
+ iErrCode = pers_lldb_close(handlerRCT) ;
+ }
+
+ return iErrCode ;
+}
+
+/**
+ * \brief write a resourceID-value pair into RCT
+ *
+ * \param handlerRCT [in] handler obtained with persComRctOpen
+ * \param resourceID [in] resource's identifier (length limited to \ref PERS_RCT_MAX_LENGTH_RESOURCE_ID)
+ * \param psConfig [in] configuration for resourceID
+ *
+ * \return 0 for success, negative value for error (\ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+signed int persComRctWrite(signed int handlerRCT, char const * resourceID, PersistenceConfigurationKey_s const * psConfig)
+{
+ sint_t iErrCode = PERS_COM_SUCCESS ;
+
+ if( (handlerRCT < 0)
+ || (NIL == resourceID)
+ || (NIL == psConfig)
+ )
+ {
+ iErrCode = PERS_COM_ERR_INVALID_PARAM ;
+ }
+ else
+ {
+ if(strlen(resourceID) >= PERS_RCT_MAX_LENGTH_RESOURCE_ID)
+ {
+ iErrCode = PERS_COM_ERR_INVALID_PARAM ;
+ }
+ }
+
+ if(PERS_COM_SUCCESS == iErrCode)
+ {
+ iErrCode = pers_lldb_write_key(handlerRCT, PersLldbPurpose_RCT, resourceID, (pstr_t)psConfig, sizeof(PersistenceConfigurationKey_s)) ;
+ }
+
+ return iErrCode ;
+}
+
+
+/**
+ * \brief read a resourceID's configuration from RCT
+ *
+ * \param handlerRCT [in] handler obtained with persComRctOpen
+ * \param resourceID [in] resource's identifier (length limited to \ref PERS_RCT_MAX_LENGTH_RESOURCE_ID)
+ * \param psConfig_out [out]where to return the configuration for resourceID
+ *
+ * \return read size [byte], or negative value for error (\ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+signed int persComRctRead(signed int handlerRCT, char const * resourceID, PersistenceConfigurationKey_s const * psConfig_out)
+{
+ sint_t iErrCode = PERS_COM_SUCCESS ;
+
+ if( (handlerRCT < 0)
+ || (NIL == resourceID)
+ || (NIL == psConfig_out)
+ )
+ {
+ iErrCode = PERS_COM_ERR_INVALID_PARAM ;
+ }
+ else
+ {
+ if(strlen(resourceID) >= PERS_RCT_MAX_LENGTH_RESOURCE_ID)
+ {
+ iErrCode = PERS_COM_ERR_INVALID_PARAM ;
+ }
+ }
+
+ if(PERS_COM_SUCCESS == iErrCode)
+ {
+ iErrCode = pers_lldb_read_key(handlerRCT, PersLldbPurpose_RCT, resourceID, (pstr_t)psConfig_out, sizeof(PersistenceConfigurationKey_s)) ;
+ }
+
+ return iErrCode ;
+}
+
+
+/**
+ * \brief delete a resourceID's configuration from RCT
+ *
+ * \param handlerRCT [in] handler obtained with persComRctOpen
+ * \param resourceID [in] resource's identifier (length limited to \ref PERS_RCT_MAX_LENGTH_RESOURCE_ID)
+ *
+ * \return 0 for success, or negative value for error (\ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+signed int persComRctDelete(signed int handlerRCT, char const * resourceID)
+{
+ sint_t iErrCode = PERS_COM_SUCCESS ;
+
+ if( (handlerRCT < 0)
+ || (NIL == resourceID)
+ )
+ {
+ iErrCode = PERS_COM_ERR_INVALID_PARAM ;
+ }
+ else
+ {
+ if(strlen(resourceID) >= PERS_RCT_MAX_LENGTH_RESOURCE_ID)
+ {
+ iErrCode = PERS_COM_ERR_INVALID_PARAM ;
+ }
+ }
+
+ if(PERS_COM_SUCCESS == iErrCode)
+ {
+ iErrCode = pers_lldb_delete_key(handlerRCT, PersLldbPurpose_RCT, resourceID) ;
+ }
+
+ return iErrCode ;
+}
+
+
+/**
+ * \brief Find the buffer's size needed to accomodate the listing of resourceIDs in RCT
+ *
+ * \param handlerRCT [in] handler obtained with persComRctOpen
+ *
+ * \return needed size [byte], or negative value for error (\ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+signed int persComRctGetSizeResourcesList(signed int handlerRCT)
+{
+ sint_t iErrCode = PERS_COM_SUCCESS ;
+
+ if(handlerRCT < 0)
+ {
+ iErrCode = PERS_COM_ERR_INVALID_PARAM ;
+ }
+
+ if(PERS_COM_SUCCESS == iErrCode)
+ {
+ iErrCode = pers_lldb_get_size_keys_list(handlerRCT, PersLldbPurpose_RCT) ;
+ }
+
+ return iErrCode ;
+}
+
+
+/**
+ * \brief Get the list of the resourceIDs in RCT
+ * \note : resourceIDs in the list are separated by '\0'
+ *
+ * \param handlerRCT [in] handler obtained with persComRctOpen
+ * \param listBuffer_out [out]buffer where to return the list of resourceIDs
+ * \param listBufferSize [in] size of listBuffer_out
+ *
+ * \return list size [byte], or negative value for error (\ref PERS_COM_ERROR_CODES_DEFINES)
+ */
+signed int persComRctGetResourcesList(signed int handlerRCT, char* listBuffer_out, signed int listBufferSize)
+{
+ sint_t iErrCode = PERS_COM_SUCCESS ;
+
+ if( (handlerRCT < 0)
+ || (NIL == listBuffer_out)
+ || (listBufferSize <= 0)
+ )
+ {
+ iErrCode = PERS_COM_ERR_INVALID_PARAM ;
+ }
+
+ if(PERS_COM_SUCCESS == iErrCode)
+ {
+ iErrCode = pers_lldb_get_keys_list(handlerRCT, PersLldbPurpose_RCT, (pstr_t)listBuffer_out, listBufferSize) ;
+ }
+
+ return iErrCode ;
+}
+