diff options
author | Guy Sagnes <guy.sagnes@continental-corporation.com> | 2014-02-25 10:32:29 +0100 |
---|---|---|
committer | Ralf Anton Beier <ralf.anton.beier@continental-corporation.com> | 2014-02-25 11:33:41 +0100 |
commit | 880e7ffe185e5b410ee6183c4ce355a8a204ab28 (patch) | |
tree | 9c18d6aecfaf69a6753b4c2f251583cfe9f3722e /src | |
parent | 94b07e2221c3333a5a54f689eca4249667892f74 (diff) | |
download | persistence-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.am | 70 | ||||
-rw-r--r-- | src/pers_data_organization.c | 101 | ||||
-rw-r--r-- | src/pers_ipc.c | 316 | ||||
-rw-r--r-- | src/pers_ipc_dbus.c | 1590 | ||||
-rw-r--r-- | src/pers_local_shared_db_access.c | 287 | ||||
-rw-r--r-- | src/pers_low_level_db_access.c | 1515 | ||||
-rw-r--r-- | src/pers_resource_config_table.c | 247 |
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 ;
+}
+
|