From 53083f280394a734310fd53c2d3fd5a578de3398 Mon Sep 17 00:00:00 2001 From: Jean-Pierre Bogler Date: Tue, 29 Oct 2013 10:49:31 +0100 Subject: Update to NSM version 1.3.5 for next OSS release --- ChangeLog | 26 + NEWS | 35 ++ NodeStateAccess/Makefile.am | 12 +- NodeStateAccess/NodeStateAccess.c | 33 +- NodeStateMachineStub/NodeStateMachine.c | 4 +- NodeStateMachineStub/NodeStateMachine.h | 8 +- NodeStateManager/Makefile.am | 43 +- NodeStateManager/NodeStateManager.c | 602 ++++++++++++++------- NodeStateManager/NodeStateManager.h | 15 +- NodeStateManager/NodeStateTypes.h | 5 +- NodeStateManager/config/node-state-manager.pc.in | 2 +- .../config/nodestatemanager-daemon.service.in | 8 +- NodeStateTest/NodeStateTest.c | 148 ++++- configure.ac | 20 +- 14 files changed, 715 insertions(+), 246 deletions(-) diff --git a/ChangeLog b/ChangeLog index 29568d9..badaa2c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +16th Oct. 2013, Jean-Pierre Bogler: + - Introduced parameters for restart reason and + type in NSMC call. + +19th Sep. 2013, Jean-Pierre Bogler: + - Temporary fix to return the ApplicationMode + in which we initially were in and not the + ApplicationMode that recently was set. + - Added dependency to pas-daemon.service to + assert stable PCL handling. + +09th Sep. 2013, Jean-Pierre Bogler: + - Moved reading of "ApplicationMode" via PCL in + the "Getter function", since we can't use PCL + until the dbus interface is exported (because + the PCL needs the dbus interface to register) + +02nd Aug. 2013, Jean-Pierre Bogler: + - Introduced PCL in NSM to store ApplicationMode + +01st Aug. 2013, Jean-Pierre Bogler: + - Minor fixes and changes + +18th Apr. 2013, Jean-Pierre Bogler: + - Allow NSMC to register sessions + 15th Mar. 2013, Jean-Pierre Bogler: - Introduced NodeStateAccess - Introduced NodeStateTest diff --git a/NEWS b/NEWS index 24338f9..d31252f 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,38 @@ +1.3.5 +===== +* Extended interface of NodeStateMachine (NSMC) + +1.3.4 +===== +* Temporary workaround for ApplicationMode handling +* New startup dependency to "pas-daemon.service" + +1.3.3 +===== +* Bugfix for PCL handling + +1.3.2 +===== +* NSM stores ApplicationMode in persistence. + +1.2.2 +===== +* NSM does not terminate automatically on dbus lost. +* NSM prints version number at start up. + +1.2.1 +===== +* Added enumeration values and functions to allow the +* NodeStateMachine (NSMC) the registration of sessions. + +1.2.0 +===== +* Set up 1.2.0 as version number for the first really +* usable version, after some changes due to licensing +* issues had to be done. +* Included productive NodeStateAccess (NSMA) library +* sources in NSM to avoid delivering a stub. + 0.1.0 ===== * Initial release of the NodeStateManager diff --git a/NodeStateAccess/Makefile.am b/NodeStateAccess/Makefile.am index d7d846d..ea33d77 100644 --- a/NodeStateAccess/Makefile.am +++ b/NodeStateAccess/Makefile.am @@ -21,12 +21,12 @@ libNodeStateAccess_la_SOURCES = NodeStateAccess.c \ generated/NodeStateLifecycleControl.c \ generated/NodeStateLifecycleConsumer.c -libNodeStateAccess_la_CFLAGS = -I generated \ - $(GIO_CFLAGS) \ - $(GIO_UNIX_CFLAGS) \ - $(GLIB_CFLAGS) \ - $(GOBJECT_CFLAGS) \ - $(NSM_CFLAGS) +libNodeStateAccess_la_CFLAGS = -I$(top_srcdir)/NodeStateManager \ + -I generated \ + $(GIO_CFLAGS) \ + $(GIO_UNIX_CFLAGS) \ + $(GLIB_CFLAGS) \ + $(GOBJECT_CFLAGS) libNodeStateAccess_la_LIBDADD = $(GIO_LIBS) \ $(GIO_UNIX_LIBS) \ diff --git a/NodeStateAccess/NodeStateAccess.c b/NodeStateAccess/NodeStateAccess.c index 85a5284..c167247 100644 --- a/NodeStateAccess/NodeStateAccess.c +++ b/NodeStateAccess/NodeStateAccess.c @@ -15,10 +15,6 @@ * 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 -* 24.10.2012 Jean-Pierre Bogler CSP_WZ#1322: Initial creation -* 24.01.2013 Jean-Pierre Bogler CSP_WZ#1194: Fixed bug. LifecycleRequestComnplete did not send dbus response. -* **********************************************************************************************************************/ @@ -32,6 +28,7 @@ #include "gio/gio.h" /* glib types */ #include "NodeStateAccess.h" /* own header */ #include "NodeStateTypes.h" /* Type defintions of the NSM */ +#include /* Catch SIGTERM */ /* additional includes to use D-Bus */ #include "string.h" /* memcpy, memset, etc. */ @@ -158,6 +155,9 @@ static void NSMA__vOnBusAcquired (GDBusConnection *pConnection, const gchar* sNa static void NSMA__vOnNameAcquired(GDBusConnection *pConnection, const gchar* sName, gpointer pUserData); static void NSMA__vOnNameLost (GDBusConnection *pConnection, const gchar* sName, gpointer pUserData); +/* Linux signal callback */ +static gboolean NSMA__boOnHandleSigterm(gpointer pUserData); + /* Internal callback for async. life cycle client returns */ static void NSMA__vOnLifecycleRequestFinish(GObject *pSrcObject, GAsyncResult *pRes, gpointer pUserData); @@ -666,6 +666,11 @@ static void NSMA__vOnBusAcquired(GDBusConnection *pConnection, const gchar* sNam /* Store the connection. Needed later, to create life cycle clients. */ NSMA__pBusConnection = pConnection; + /* Do not automatically exit the main loop when connection is lost. + * The program terminates nevertheless, but will give useful traces. + */ + g_dbus_connection_set_exit_on_close(NSMA__pBusConnection, FALSE); + /* Register the callbacks */ (void) g_signal_connect(NSMA__pLifecycleControlObj, "handle-set-boot-mode", G_CALLBACK(NSMA__boOnHandleSetBootMode), NULL); (void) g_signal_connect(NSMA__pLifecycleControlObj, "handle-set-node-state", G_CALLBACK(NSMA__boOnHandleSetNodeState), NULL); @@ -859,6 +864,23 @@ static gboolean NSMA__boOnHandleLifecycleRequestComplete(NodeStateConsumer * } +/********************************************************************************************************************** +* +* The function is called when the SIGTERM signal is received +* +* @param pUserData: Optional user data (not used) +* @return TRUE: Keep callback installed +* +**********************************************************************************************************************/ +static gboolean NSMA__boOnHandleSigterm(gpointer pUserData) +{ + NSMA__boLoopEndByUser = TRUE; + g_main_loop_quit(NSMA__pMainLoop); + + return TRUE; +} + + /********************************************************************************************************************** * * Interfaces. Exported functions. See Header for detailed description. @@ -942,6 +964,9 @@ gboolean NSMA_boWaitForEvents(void) NULL, NULL); + /* Add source to catch SIGTERM signal (#15) */ + g_unix_signal_add(15, &NSMA__boOnHandleSigterm, NULL); + /* Run main loop to get D-Bus connection and export objects. The function will only return, * if there was an internal error or it has been cancelled by the user. */ diff --git a/NodeStateMachineStub/NodeStateMachine.c b/NodeStateMachineStub/NodeStateMachine.c index 07f22c1..c890658 100644 --- a/NodeStateMachineStub/NodeStateMachine.c +++ b/NodeStateMachineStub/NodeStateMachine.c @@ -94,9 +94,9 @@ NsmErrorStatus_e NsmcSetData(NsmDataType_e enData, unsigned char *pData, unsigne } -unsigned char NsmcRequestNodeRestart(void) +unsigned char NsmcRequestNodeRestart(NsmRestartReason_e enRestartReason, unsigned int u32RestartType) { - printf("NSMC: NsmcRequestNodeRestart called.\n"); + printf("NSMC: NsmcRequestNodeRestart called. Restart reason: %d. RestartType: 0x%02X\n", enRestartReason, u32RestartType); return 1; } diff --git a/NodeStateMachineStub/NodeStateMachine.h b/NodeStateMachineStub/NodeStateMachine.h index c486d20..d745602 100644 --- a/NodeStateMachineStub/NodeStateMachine.h +++ b/NodeStateMachineStub/NodeStateMachine.h @@ -16,12 +16,6 @@ * 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 -* 27.09.2012 Jean-Pierre Bogler CSP_WZ#1194: Initial creation. -* 24.10.2012 Jean-Pierre Bogler CSP_WZ#1322: Changed parameter types of interface functions. -* No change of major interface version, because -* the same native types are used. -* **********************************************************************************************************************/ #ifdef __cplusplus @@ -108,7 +102,7 @@ NsmErrorStatus_e NsmcSetData(NsmDataType_e enData, unsigned char *pData, unsigne \retval true: The request for the restart could be processed. false: Error processing the restart request. This will be used by the NSM to request a node restart when requested by one of its clients.*/ -unsigned char NsmcRequestNodeRestart(void); +unsigned char NsmcRequestNodeRestart(NsmRestartReason_e enRestartReason, unsigned int u32RestartType); /** \brief Get version of the interface diff --git a/NodeStateManager/Makefile.am b/NodeStateManager/Makefile.am index 260ca74..d3e9f50 100644 --- a/NodeStateManager/Makefile.am +++ b/NodeStateManager/Makefile.am @@ -18,28 +18,27 @@ bin_PROGRAMS = NodeStateManager NodeStateManager_SOURCES = NodeStateManager.c -NodeStateManager_CFLAGS = \ - -I$(top_srcdir)/NodeStateMachineStub \ - -I$(top_srcdir)/NodeStateAccess \ - $(DLT_CFLAGS) \ - $(GIO_CFLAGS) \ - $(GIO_UNIX_CFLAGS) \ - $(GLIB_CFLAGS) \ - $(GOBJECT_CFLAGS) \ - $(PLATFORM_CFLAGS) - -NodeStateManager_LDFLAGS = \ - $(PLATFORM_LDFLAGS) \ - -export-dynamic - -NodeStateManager_LDADD = \ - -L$(top_srcdir)/NodeStateAccess -lNodeStateAccess \ - -L$(top_srcdir)/NodeStateMachineStub -lNodeStateMachine \ - $(DLT_LIBS) \ - $(GIO_LIBS) \ - $(GIO_UNIX_LIBS) \ - $(GLIB_LIBS) \ - $(GOBJECT_LIBS) +NodeStateManager_CFLAGS = -I$(top_srcdir)/NodeStateMachineStub \ + -I$(top_srcdir)/NodeStateAccess \ + $(DLT_CFLAGS) \ + $(GIO_CFLAGS) \ + $(GIO_UNIX_CFLAGS) \ + $(GLIB_CFLAGS) \ + $(GOBJECT_CFLAGS) \ + $(SYSTEMD_CFLAGS) \ + $(PCL_CFLAGS) + +NodeStateManager_LDFLAGS = -export-dynamic + +NodeStateManager_LDADD = -L$(top_srcdir)/NodeStateAccess -lNodeStateAccess \ + -L$(top_srcdir)/NodeStateMachineStub -lNodeStateMachine \ + $(DLT_LIBS) \ + $(GIO_LIBS) \ + $(GIO_UNIX_LIBS) \ + $(GLIB_LIBS) \ + $(GOBJECT_LIBS) \ + $(SYSTEMD_LIBS) \ + $(PCL_LIBS) include_HEADERS = NodeStateManager.h NodeStateTypes.h diff --git a/NodeStateManager/NodeStateManager.c b/NodeStateManager/NodeStateManager.c index 4ed5150..6051183 100644 --- a/NodeStateManager/NodeStateManager.c +++ b/NodeStateManager/NodeStateManager.c @@ -1,6 +1,6 @@ /********************************************************************************************************************** * -* Copyright (C) 2012 Continental Automotive Systems, Inc. +* Copyright (C) 2013 Continental Automotive Systems, Inc. * * Author: Jean-Pierre.Bogler@continental-corporation.com * @@ -16,31 +16,6 @@ * 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 -* 20.06.2012 Jean-Pierre Bogler CSP_WZ#388: Initial creation -* 19.09.2012 Jean-Pierre Bogler OvipRbt#135: Added new default sessions for product, thermal and power -* management. Fixed bug, when calling 'GetSessionState'. -* Undefined parameter 'SessionOwner' was used. -* 27.09.2012 Jean-Pierre Bogler CSP_WZ#1194: Changed file header structure and license to be released -* as open source package. Introduced 'NodeStateTypes.h' to -* avoid circle includes and encapsulate type definitions. -* 08.10.2012 Jean-Pierre Bogler CSP_WZ#951: Introduced improvements and changes from 4-eye review: -* - Changed handling of failed applications -* - Changed handling of platform sessions -* - Fixed some QAC warnings -* - Added deallocation of GError objects -* 24.10.2012 Jean-Pierre Bogler CSP_WZ#1322: The NSM does not use generated D-Bus objects anymore, -* due to legal restrictions. Instead, it registers -* callbacks at the NodeStateAccess library NSMA. -* Therefore, the parameters of the callbacks changed. -* In addition, the establishment of the connection and -* the handling of life cycle clients (timeout observation) -* is done by the NSMA. -* 01.11.2012 C. Domke CSP_WZ#666: Instrumented with LTPRO messages -* 10.01.2013 Jean-Pierre Bogler CSP_WZ#1322: Initialize variables at declaration instead of using -* memset and use g_utf8_strlen instead of strlen to -* simplify configure srcipt (avoid some checks). -* **********************************************************************************************************************/ @@ -49,14 +24,18 @@ * Header includes * **********************************************************************************************************************/ -#include "NodeStateManager.h" /* Own Header file */ -#include "NodeStateTypes.h" /* Typedefinitions to use the NSM */ -#include "string.h" /* Memcpy etc. */ -#include "gio/gio.h" /* GLib lists */ -#include "dlt/dlt.h" /* DLT Log'n'Trace */ -#include "NodeStateMachine.h" /* Talk to NodeStateMachine */ -#include "NodeStateAccess.h" /* Access the IPC (D-Bus) */ -#include "syslog.h" /* Syslog messages */ +#include "NodeStateManager.h" /* Own Header file */ +#include "NodeStateTypes.h" /* Typedefinitions to use the NSM */ +#include "string.h" /* Memcpy etc. */ +#include "gio/gio.h" /* GLib lists */ +#include "dlt/dlt.h" /* DLT Log'n'Trace */ +#include "NodeStateMachine.h" /* Talk to NodeStateMachine */ +#include "NodeStateAccess.h" /* Access the IPC (D-Bus) */ +#include "syslog.h" /* Syslog messages */ +#include /* Systemd wdog */ +#include /* Init/DeInit PCL */ +#include /* Access persistent data */ + /********************************************************************************************************************** * @@ -64,6 +43,10 @@ * **********************************************************************************************************************/ +/* Defines to access persistence keys */ +#define NSM_PERS_APPLICATION_MODE_DB 0xFF +#define NSM_PERS_APPLICATION_MODE_KEY "ERG_OIP_NSM_NODE_APPMODE" + /* The type defines the structure for a lifecycle consumer client */ typedef struct { @@ -132,6 +115,12 @@ static void NSM__vOnLifecycleRequestFinish(const NsmErrorStatus_e enErrorStatus) /* Internal functions, to set and get values. Indirectly used by D-Bus and StateMachine */ +static NsmErrorStatus_e NSM__enRegisterSession (NsmSession_s *session, + gboolean boInformBus, + gboolean boInformMachine); +static NsmErrorStatus_e NSM__enUnRegisterSession (NsmSession_s *session, + gboolean boInformBus, + gboolean boInformMachine); static NsmErrorStatus_e NSM__enSetNodeState (NsmNodeState_e enNodeState, gboolean boInformBus, gboolean boInformMachine); @@ -207,6 +196,9 @@ static void NSM__vLtProf(gchar *pszBus, gchar *pszObj, guint32 dwReason, gchar * static void NSM__vSyslogOpen(void); static void NSM__vSyslogClose(void); +/* Systemd watchdog functions */ +static gboolean NSM__boOnHandleTimerWdog(gpointer pUserData); +static void NSM__vConfigureWdogTimer(void); /********************************************************************************************************************** * @@ -226,8 +218,11 @@ static GList *NSM__pLifecycleClients = NULL; static GMutex *NSM__pNodeStateMutex = NULL; static NsmNodeState_e NSM__enNodeState = NsmNodeState_NotSet; -static GMutex *NSM__pApplicationModeMutex = NULL; -static NsmApplicationMode_e NSM__enApplicationMode = NsmApplicationMode_NotSet; +static GMutex *NSM__pNextApplicationModeMutex = NULL; +static GMutex *NSM__pThisApplicationModeMutex = NULL; +static NsmApplicationMode_e NSM__enNextApplicationMode = NsmApplicationMode_NotSet; +static NsmApplicationMode_e NSM__enThisApplicationMode = NsmApplicationMode_NotSet; +static gboolean NSM__boThisApplicationModeRead = FALSE; static GSList *NSM__pFailedApplications = NULL; @@ -289,6 +284,158 @@ static gboolean NSM__boIsPlatformSession(NsmSession_s *pstSession) } +/** +* NSM__enRegisterSession: +* @session: Ptr to NsmSession_s structure containing data to register a session +* @boInformBus: Flag whether the a dbus signal should be send to inform about the new session +* @boInformMachine: Flag whether the NSMC should be informed about the new session +* +* The internal function is used to register a session. It is either called from the dbus callback +* or it is called via the internal context of the NSMC. +*/ +static NsmErrorStatus_e NSM__enRegisterSession(NsmSession_s *session, gboolean boInformBus, gboolean boInformMachine) +{ + /* Function local variables */ + NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet; /* Return value */ + NsmSession_s *pNewSession = NULL; /* Pointer to new created session */ + GSList *pListEntry = NULL; /* Pointer to list entry */ + + if( (g_strcmp0(session->sOwner, NSM_DEFAULT_SESSION_OWNER) != 0) + && (session->enState > NsmSessionState_Unregistered)) + { + if(NSM__boIsPlatformSession(session) == FALSE) + { + g_mutex_lock(NSM__pSessionMutex); + + pListEntry = g_slist_find_custom(NSM__pSessions, session, &NSM__i32SessionNameSeatCompare); + + if(pListEntry == NULL) + { + enRetVal = NsmErrorStatus_Ok; + + pNewSession = g_new0(NsmSession_s, 1); + memcpy(pNewSession, session, sizeof(NsmSession_s)); + + DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Registered session." ), + DLT_STRING(" Name: " ), DLT_STRING(session->sName ), + DLT_STRING(" Owner: " ), DLT_STRING(session->sOwner ), + DLT_STRING(" Seat: " ), DLT_INT((gint) session->enSeat ), + DLT_STRING(" Initial state: "), DLT_INT((gint) session->enState)); + + /* Return OK and append new object */ + NSM__pSessions = g_slist_append(NSM__pSessions, pNewSession); + + /* Inform D-Bus and StateMachine about the new session. */ + NSM__vPublishSessionChange(pNewSession, boInformBus, boInformMachine); + } + else + { + /* Error: The session already exists. Don't store passed state. */ + enRetVal = NsmErrorStatus_WrongSession; + DLT_LOG(NsmContext, DLT_LOG_WARN, DLT_STRING("NSM: Failed to register session. Session already exists."), + DLT_STRING(" Name: " ), DLT_STRING(session->sName ), + DLT_STRING(" Owner: " ), DLT_STRING(session->sOwner ), + DLT_STRING(" Seat: " ), DLT_INT((gint) session->enSeat ), + DLT_STRING(" Initial state: "), DLT_INT((gint) session->enState )); + } + + g_mutex_unlock(NSM__pSessionMutex); + } + else + { + /* Error: It is not allowed to re-register a default session! */ + enRetVal = NsmErrorStatus_Parameter; + DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to register session. Re-Registration of default session not allowed."), + DLT_STRING(" Name: " ), DLT_STRING(session->sName ), + DLT_STRING(" Owner: " ), DLT_STRING(session->sOwner ), + DLT_STRING(" Seat: " ), DLT_INT((gint) session->enSeat ), + DLT_STRING(" Initial state: "), DLT_INT((gint) session->enState )); + } + } + else + { + /* Error: A parameter with an invalid value has been passed */ + enRetVal = NsmErrorStatus_Parameter; + DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to register session. Invalid owner or state."), + DLT_STRING(" Name: " ), DLT_STRING(session->sName ), + DLT_STRING(" Owner: " ), DLT_STRING(session->sOwner ), + DLT_STRING(" Seat: " ), DLT_INT((gint) session->enSeat ), + DLT_STRING(" Initial state: "), DLT_INT((gint) session->enState )); + } + + return enRetVal; +} + + +/** +* NSM__enUnRegisterSession: +* @session: Ptr to NsmSession_s structure containing data to unregister a session +* @boInformBus: Flag whether the a dbus signal should be send to inform about the lost session +* @boInformMachine: Flag whether the NSMC should be informed about the lost session +* +* The internal function is used to unregister a session. It is either called from the dbus callback +* or it is called via the internal context of the NSMC. +*/ +static NsmErrorStatus_e NSM__enUnRegisterSession(NsmSession_s *session, gboolean boInformBus, gboolean boInformMachine) +{ + /* Function local variables */ + NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet; /* Return value */ + NsmSession_s *pExistingSession = NULL; /* Pointer to existing session */ + GSList *pListEntry = NULL; /* Pointer to list entry */ + + if(NSM__boIsPlatformSession(session) == FALSE) + { + g_mutex_lock(NSM__pSessionMutex); + + pListEntry = g_slist_find_custom(NSM__pSessions, session, &NSM__i32SessionOwnerNameSeatCompare); + + /* Check if the session exists */ + if(pListEntry != NULL) + { + /* Found the session in the list. Now remove it. */ + enRetVal = NsmErrorStatus_Ok; + pExistingSession = (NsmSession_s*) pListEntry->data; + + DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Unregistered session." ), + DLT_STRING(" Name: " ), DLT_STRING(pExistingSession->sName ), + DLT_STRING(" Owner: " ), DLT_STRING(pExistingSession->sOwner ), + DLT_STRING(" Seat: " ), DLT_INT( pExistingSession->enSeat ), + DLT_STRING(" Last state: "), DLT_INT( pExistingSession->enState)); + + pExistingSession->enState = NsmSessionState_Unregistered; + + /* Inform D-Bus and StateMachine about the unregistered session */ + NSM__vPublishSessionChange(pExistingSession, boInformBus, boInformMachine); + + NSM__vFreeSessionObject(pExistingSession); + NSM__pSessions = g_slist_remove(NSM__pSessions, pExistingSession); + } + else + { + /* Error: The session is unknown. */ + enRetVal = NsmErrorStatus_WrongSession; + DLT_LOG(NsmContext, DLT_LOG_WARN, DLT_STRING("NSM: Failed to unregister session. Session unknown."), + DLT_STRING(" Name: " ), DLT_STRING(session->sName ), + DLT_STRING(" Owner: " ), DLT_STRING(session->sOwner ), + DLT_STRING(" Seat: " ), DLT_INT((gint) session->enSeat )); + } + + g_mutex_unlock(NSM__pSessionMutex); + } + else + { + /* Error: Failed to unregister session. The passed session is a "platform" session. */ + enRetVal = NsmErrorStatus_WrongSession; + DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to unregister session. The session is a platform session."), + DLT_STRING(" Name: " ), DLT_STRING(session->sName ), + DLT_STRING(" Owner: " ), DLT_STRING(session->sOwner ), + DLT_STRING(" Seat: " ), DLT_INT((gint) session->enSeat )); + } + + return enRetVal; +} + + /********************************************************************************************************************** * * The function is called from IPC and StateMachine to set the NodeState. @@ -444,49 +591,106 @@ static NsmErrorStatus_e NSM__enSetBootMode(const gint i32BootMode, gboolean boIn * @return see NsmErrorStatus_e * **********************************************************************************************************************/ -static NsmErrorStatus_e NSM__enSetApplicationMode(NsmApplicationMode_e enApplicationMode, gboolean boInformBus, gboolean boInformMachine) +static NsmErrorStatus_e +NSM__enSetApplicationMode(NsmApplicationMode_e enApplicationMode, + gboolean boInformBus, + gboolean boInformMachine) { - /* Function local variables */ - NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet; /* Return value */ + /* Function local variables */ + NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet; /* Return value */ + int pcl_return = 0; /* Check if the passed parameter is valid */ - if((enApplicationMode > NsmApplicationMode_NotSet) && (enApplicationMode < NsmApplicationMode_Last)) + if( (enApplicationMode > NsmApplicationMode_NotSet) + && (enApplicationMode < NsmApplicationMode_Last )) { /* The passed parameter is valid. Return OK */ enRetVal = NsmErrorStatus_Ok; - g_mutex_lock(NSM__pApplicationModeMutex); + g_mutex_lock(NSM__pNextApplicationModeMutex); - /* Only store the new value and emit a signal, if the new value is different */ - if(NSM__enApplicationMode != enApplicationMode) + /* Only store new value and emit signal, if new value is different */ + if(NSM__enNextApplicationMode != enApplicationMode) { /* Store new value and emit signal with new application mode */ - DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Changed ApplicationMode."), - DLT_STRING(" Old ApplicationMode: "), DLT_INT(NSM__enApplicationMode ), - DLT_STRING(" New ApplicationMode: "), DLT_INT((gint) enApplicationMode)); + DLT_LOG(NsmContext, + DLT_LOG_INFO, + DLT_STRING("NSM: Changed ApplicationMode."); + DLT_STRING("Old AppMode:"); DLT_INT((int) NSM__enNextApplicationMode); + DLT_STRING("New AppMode:"); DLT_INT((int) enApplicationMode)); + + NSM__enNextApplicationMode = enApplicationMode; + + /* If original persistent value has not been read before, get it now! */ + g_mutex_lock(NSM__pThisApplicationModeMutex); - NSM__enApplicationMode = enApplicationMode; + if(NSM__boThisApplicationModeRead == FALSE) + { + /* Get data from persistence */ + pcl_return = pclKeyReadData(NSM_PERS_APPLICATION_MODE_DB, + NSM_PERS_APPLICATION_MODE_KEY, + 0, + 0, + (unsigned char*) &NSM__enThisApplicationMode, + sizeof(NSM__enThisApplicationMode)); + + if(pcl_return != sizeof(NSM__enThisApplicationMode)) + { + NSM__enThisApplicationMode = NsmApplicationMode_NotSet; + DLT_LOG(NsmContext, + DLT_LOG_WARN, + DLT_STRING("NSM: Failed to read ApplicationMode."); + DLT_STRING("Error: Unexpected PCL return."); + DLT_STRING("Return:"); DLT_INT(pcl_return)); + } + + NSM__boThisApplicationModeRead = TRUE; + } + + g_mutex_unlock(NSM__pThisApplicationModeMutex); + + /* Write the new application mode to persistence */ + pcl_return = pclKeyWriteData(NSM_PERS_APPLICATION_MODE_DB, + NSM_PERS_APPLICATION_MODE_KEY, + 0, + 0, + (unsigned char*) &NSM__enNextApplicationMode, + sizeof(NSM__enNextApplicationMode)); + + if(pcl_return != sizeof(NSM__enNextApplicationMode)) + { + DLT_LOG(NsmContext, + DLT_LOG_ERROR, + DLT_STRING("NSM: Failed to persist ApplicationMode."); + DLT_STRING("Error: Unexpected PCL return."); + DLT_STRING("Return:"); DLT_INT(pcl_return)); + } if(boInformBus == TRUE) { - NSMA_boSendApplicationModeSignal(NSM__enApplicationMode); + NSMA_boSendApplicationModeSignal(NSM__enNextApplicationMode); } if(boInformMachine == TRUE) { - NsmcSetData(NsmDataType_AppMode, (unsigned char*) &NSM__enApplicationMode, sizeof(NsmApplicationMode_e)); + NsmcSetData(NsmDataType_AppMode, + (unsigned char*) &NSM__enNextApplicationMode, + sizeof(NsmApplicationMode_e)); } } - g_mutex_unlock(NSM__pApplicationModeMutex); + g_mutex_unlock(NSM__pNextApplicationModeMutex); } else { /* Error: The passed application mode is invalid. Return an error. */ enRetVal = NsmErrorStatus_Parameter; - DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to change ApplicationMode. Invalid parameter." ), - DLT_STRING(" Old ApplicationMode: "), DLT_INT(NSM__enApplicationMode ), - DLT_STRING(" Desired ApplicationMode: "), DLT_INT((gint) enApplicationMode)); + DLT_LOG(NsmContext, + DLT_LOG_ERROR, + DLT_STRING("NSM: Failed to change ApplicationMode."); + DLT_STRING("Error:"); DLT_STRING("Invalid parameter."); + DLT_STRING("Old AppMode:"); DLT_INT((int) NSM__enNextApplicationMode); + DLT_STRING("New AppMode:"); DLT_INT((int) enApplicationMode)); } return enRetVal; @@ -500,16 +704,47 @@ static NsmErrorStatus_e NSM__enSetApplicationMode(NsmApplicationMode_e enApplica * @return see NsmApplicationMode_e * **********************************************************************************************************************/ -static NsmErrorStatus_e NSM__enGetApplicationMode(NsmApplicationMode_e *penApplicationMode) +static NsmErrorStatus_e +NSM__enGetApplicationMode(NsmApplicationMode_e *penApplicationMode) { - NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet; + NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet; + int pcl_return = 0; if(penApplicationMode != NULL) { + g_mutex_lock(NSM__pThisApplicationModeMutex); + + /* Check if value already was obtained from persistence */ + if(NSM__boThisApplicationModeRead == FALSE) + { + /* There was no read attempt before. Read from persistence */ + pcl_return = pclKeyReadData(NSM_PERS_APPLICATION_MODE_DB, + NSM_PERS_APPLICATION_MODE_KEY, + 0, + 0, + (unsigned char*) &NSM__enThisApplicationMode, + sizeof(NSM__enThisApplicationMode)); + + /* Check the PCL return */ + if(pcl_return != sizeof(NSM__enThisApplicationMode)) + { + /* Read failed. From now on always return 'NsmApplicationMode_NotSet' */ + NSM__enThisApplicationMode = NsmApplicationMode_NotSet; + DLT_LOG(NsmContext, + DLT_LOG_WARN, + DLT_STRING("NSM: Failed to read ApplicationMode."); + DLT_STRING("Error: Unexpected PCL return."); + DLT_STRING("Return:"); DLT_INT(pcl_return)); + } + + /* There was a first read attempt from persistence */ + NSM__boThisApplicationModeRead = TRUE; + } + enRetVal = NsmErrorStatus_Ok; - g_mutex_lock(NSM__pApplicationModeMutex); - *penApplicationMode = NSM__enApplicationMode; - g_mutex_unlock(NSM__pApplicationModeMutex); + *penApplicationMode = NSM__enThisApplicationMode; + + g_mutex_unlock(NSM__pThisApplicationModeMutex); } else { @@ -1380,7 +1615,7 @@ static NsmErrorStatus_e NSM__enOnHandleRequestNodeRestart(const NsmRestartReason DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Node restart has been requested.")); - if(NsmcRequestNodeRestart() == 0x01) + if(NsmcRequestNodeRestart(enRestartReason, u32RestartType) == 0x01) { enRetVal = NsmErrorStatus_Ok; (void) NSMA_boSetRestartReason(enRestartReason); @@ -1413,90 +1648,37 @@ static NsmErrorStatus_e NSM__enOnHandleRegisterSession(const gchar * const NsmSessionState_e enSessionState) { /* Function local variables */ - NsmSession_s *pNewSession = NULL; /* Pointer to new created session */ - GSList *pListEntry = NULL; /* Pointer to list entry */ glong u32SessionNameLen = 0; /* Length of passed session owner */ glong u32SessionOwnerLen = 0; /* Length of passed session name */ - NsmSession_s stSearchSession = {0}; /* To search for existing session */ - gboolean boOwnerValid = FALSE; + NsmSession_s stSession; /* To search for existing session */ NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet; /* Check if the passed parameters are valid */ u32SessionNameLen = g_utf8_strlen(sSessionName, -1); u32SessionOwnerLen = g_utf8_strlen(sSessionOwner, -1); - boOwnerValid = (g_strcmp0(sSessionOwner, NSM_DEFAULT_SESSION_OWNER) != 0); - if( (boOwnerValid == TRUE ) - && (u32SessionNameLen < NSM_MAX_SESSION_NAME_LENGTH ) + if( (u32SessionNameLen < NSM_MAX_SESSION_NAME_LENGTH ) && (u32SessionOwnerLen < NSM_MAX_SESSION_OWNER_LENGTH) && (enSeatId > NsmSeat_NotSet ) - && (enSeatId < NsmSeat_Last ) - && (enSessionState > NsmSessionState_Unregistered)) + && (enSeatId < NsmSeat_Last )) { /* Initialize temporary session object to check if session already exists */ - g_strlcpy((gchar*) stSearchSession.sName, sSessionName, sizeof(stSearchSession.sName) ); - g_strlcpy((gchar*) stSearchSession.sOwner, sSessionOwner, sizeof(stSearchSession.sOwner)); - stSearchSession.enSeat = enSeatId; - stSearchSession.enState = enSessionState; - - if(NSM__boIsPlatformSession(&stSearchSession) == FALSE) - { - g_mutex_lock(NSM__pSessionMutex); - - pListEntry = g_slist_find_custom(NSM__pSessions, &stSearchSession, &NSM__i32SessionNameSeatCompare); - - if(pListEntry == NULL) - { - enRetVal = NsmErrorStatus_Ok; - - pNewSession = g_new0(NsmSession_s, 1); - memcpy(pNewSession, &stSearchSession, sizeof(NsmSession_s)); - - DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Registered session." ), - DLT_STRING(" Name: " ), DLT_STRING(sSessionName ), - DLT_STRING(" Owner: " ), DLT_STRING(sSessionOwner ), - DLT_STRING(" Seat: " ), DLT_INT((gint) enSeatId ), - DLT_STRING(" Initial state: "), DLT_INT((gint) enSessionState)); - - /* Return OK and append new object */ - NSM__pSessions = g_slist_append(NSM__pSessions, pNewSession); - - /* Inform D-Bus and StateMachine about the new session. */ - NSM__vPublishSessionChange(pNewSession, TRUE, TRUE); - } - else - { - /* Error: The session already exists. Don't store passed state. */ - enRetVal = NsmErrorStatus_WrongSession; - DLT_LOG(NsmContext, DLT_LOG_WARN, DLT_STRING("NSM: Failed to register session. Session already exists."), - DLT_STRING(" Name: " ), DLT_STRING(sSessionName ), - DLT_STRING(" Owner: " ), DLT_STRING(sSessionOwner ), - DLT_STRING(" Seat: " ), DLT_INT((gint) enSeatId ), - DLT_STRING(" Initial state: "), DLT_INT((gint) enSessionState )); - } + g_strlcpy((gchar*) stSession.sName, sSessionName, sizeof(stSession.sName) ); + g_strlcpy((gchar*) stSession.sOwner, sSessionOwner, sizeof(stSession.sOwner)); + stSession.enSeat = enSeatId; + stSession.enState = enSessionState; - g_mutex_unlock(NSM__pSessionMutex); - } - else - { - /* Error: It is not allowed to re-register a default session! */ - enRetVal = NsmErrorStatus_Parameter; - DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to register session. Re-Registration of default session not allowed."), - DLT_STRING(" Name: " ), DLT_STRING(sSessionName ), - DLT_STRING(" Owner: " ), DLT_STRING(sSessionOwner ), - DLT_STRING(" Seat: " ), DLT_INT((gint) enSeatId ), - DLT_STRING(" Initial state: "), DLT_INT((gint) enSessionState )); - } + enRetVal = NSM__enRegisterSession(&stSession, TRUE, TRUE); } else { /* Error: A parameter with an invalid value has been passed */ enRetVal = NsmErrorStatus_Parameter; - DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to register session. 'Unregistered' not allowed."), - DLT_STRING(" Name: " ), DLT_STRING(sSessionName ), - DLT_STRING(" Owner: " ), DLT_STRING(sSessionOwner ), - DLT_STRING(" Seat: " ), DLT_INT((gint) enSeatId ), - DLT_STRING(" Initial state: "), DLT_INT((gint) enSessionState )); + DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to register session. Invalid parameter."), + DLT_STRING("Name:" ), DLT_STRING(sSessionName ), + DLT_STRING("Owner:" ), DLT_STRING(sSessionOwner ), + DLT_STRING("Seat:" ), DLT_INT((gint) enSeatId ), + DLT_STRING("Initial state:"), DLT_INT((gint) enSessionState )); } return enRetVal; @@ -1520,8 +1702,6 @@ static NsmErrorStatus_e NSM__enOnHandleUnRegisterSession(const gchar *sSessi const NsmSeat_e enSeatId) { /* Function local variables */ - NsmSession_s *pExistingSession = NULL; /* Pointer to existing session */ - GSList *pListEntry = NULL; /* Pointer to list entry */ glong u32SessionNameLen = 0; /* Length of passed session owner */ glong u32SessionOwnerLen = 0; /* Length of passed session name */ NsmSession_s stSearchSession = {0}; /* To search for existing session */ @@ -1539,54 +1719,7 @@ static NsmErrorStatus_e NSM__enOnHandleUnRegisterSession(const gchar *sSessi g_strlcpy((gchar*) stSearchSession.sName, sSessionName, sizeof(stSearchSession.sName) ); g_strlcpy((gchar*) stSearchSession.sOwner, sSessionOwner, sizeof(stSearchSession.sOwner)); - if(NSM__boIsPlatformSession(&stSearchSession) == FALSE) - { - g_mutex_lock(NSM__pSessionMutex); - - pListEntry = g_slist_find_custom(NSM__pSessions, &stSearchSession, &NSM__i32SessionOwnerNameSeatCompare); - - /* Check if the session exists */ - if(pListEntry != NULL) - { - /* Found the session in the list. Now remove it. */ - enRetVal = NsmErrorStatus_Ok; - pExistingSession = (NsmSession_s*) pListEntry->data; - - DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Unregistered session." ), - DLT_STRING(" Name: " ), DLT_STRING(pExistingSession->sName ), - DLT_STRING(" Owner: " ), DLT_STRING(pExistingSession->sOwner ), - DLT_STRING(" Seat: " ), DLT_INT( pExistingSession->enSeat ), - DLT_STRING(" Last state: "), DLT_INT( pExistingSession->enState)); - - pExistingSession->enState = NsmSessionState_Unregistered; - - /* Inform D-Bus and StateMachine about the unregistered session */ - NSM__vPublishSessionChange(pExistingSession, TRUE, TRUE); - - NSM__vFreeSessionObject(pExistingSession); - NSM__pSessions = g_slist_remove(NSM__pSessions, pExistingSession); - } - else - { - /* Error: The session is unknown. */ - enRetVal = NsmErrorStatus_WrongSession; - DLT_LOG(NsmContext, DLT_LOG_WARN, DLT_STRING("NSM: Failed to unregister session. Session unknown."), - DLT_STRING(" Name: " ), DLT_STRING(sSessionName ), - DLT_STRING(" Owner: " ), DLT_STRING(sSessionOwner ), - DLT_STRING(" Seat: " ), DLT_INT((gint) enSeatId )); - } - - g_mutex_unlock(NSM__pSessionMutex); - } - else - { - /* Error: Failed to unregister session. The passed session is a "platform" session. */ - enRetVal = NsmErrorStatus_WrongSession; - DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to unregister session. The session is a platform session."), - DLT_STRING(" Name: " ), DLT_STRING(sSessionName ), - DLT_STRING(" Owner: " ), DLT_STRING(sSessionOwner ), - DLT_STRING(" Seat: " ), DLT_INT((gint) enSeatId )); - } + enRetVal = NSM__enUnRegisterSession(&stSearchSession, TRUE, TRUE); } else { @@ -2091,6 +2224,66 @@ static guint NSM__u32OnHandleGetInterfaceVersion(void) } +/********************************************************************************************************************** +* +* The function is called cyclically and triggers the systemd wdog. +* +* @param pUserData: Pointer to optional user data +* +* @return Always TRUE to keep timer callback alive. +* +**********************************************************************************************************************/ +static gboolean NSM__boOnHandleTimerWdog(gpointer pUserData) +{ + (void) sd_notify(0, "WATCHDOG=1"); + DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Triggered systemd WDOG.")); + + return TRUE; +} + + +/********************************************************************************************************************** +* +* The function checks if the NSM is observed by a systemd wdog and installs a timer if necessary. +* +**********************************************************************************************************************/ +static void NSM__vConfigureWdogTimer(void) +{ + const gchar *sWdogSec = NULL; + guint u32WdogSec = 0; + + sWdogSec = g_getenv("WATCHDOG_USEC"); + + if(sWdogSec != NULL) + { + u32WdogSec = strtoul(sWdogSec, NULL, 10); + + /* The min. valid value for systemd is 1 s => WATCHDOG_USEC at least needs to contain 1.000.000 us */ + if(u32WdogSec >= 1000000) + { + /* Convert us timeout in ms and divide by two to trigger wdog every half timeout interval */ + u32WdogSec /= 2000; + (void) g_timeout_add_full(G_PRIORITY_DEFAULT, + u32WdogSec, + &NSM__boOnHandleTimerWdog, + NULL, + NULL); + DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Started wdog timer." ), + DLT_STRING("Interval [ms]:"), DLT_UINT(u32WdogSec)); + } + else + { + DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Error. Invalid wdog config." ), + DLT_STRING("WATCHDOG_USEC:"), DLT_STRING(sWdogSec)); + } + } + else + { + DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Daemon not observed by wdog")); + } +} + + /********************************************************************************************************************** * * The function initializes all file local variables @@ -2104,10 +2297,13 @@ static void NSM__vInitializeVariables(void) NSM__pLifecycleClients = NULL; NSM__pNodeStateMutex = NULL; NSM__enNodeState = NsmNodeState_NotSet; - NSM__pApplicationModeMutex = NULL; - NSM__enApplicationMode = NsmApplicationMode_NotSet; + NSM__pNextApplicationModeMutex = NULL; + NSM__pThisApplicationModeMutex = NULL; NSM__pFailedApplications = NULL; NSM__pCurrentLifecycleClient = NULL; + NSM__enNextApplicationMode = NsmApplicationMode_NotSet; + NSM__enThisApplicationMode = NsmApplicationMode_NotSet; + NSM__boThisApplicationModeRead = FALSE; } @@ -2151,7 +2347,8 @@ static void NSM__vCreateMutexes(void) { /* Initialize the local mutexes */ NSM__pNodeStateMutex = g_mutex_new(); - NSM__pApplicationModeMutex = g_mutex_new(); + NSM__pThisApplicationModeMutex = g_mutex_new(); + NSM__pNextApplicationModeMutex = g_mutex_new(); NSM__pSessionMutex = g_mutex_new(); } @@ -2165,7 +2362,8 @@ static void NSM__vDeleteMutexes(void) { /* Delete the local mutexes */ g_mutex_free(NSM__pNodeStateMutex); - g_mutex_free(NSM__pApplicationModeMutex); + g_mutex_free(NSM__pNextApplicationModeMutex); + g_mutex_free(NSM__pThisApplicationModeMutex); g_mutex_free(NSM__pSessionMutex); } @@ -2277,6 +2475,20 @@ NsmErrorStatus_e NsmSetData(NsmDataType_e enData, unsigned char *pData, unsigned : NsmErrorStatus_Parameter; break; + /* NSMC wants to register a session */ + case NsmDataType_RegisterSession: + enRetVal = (u32DataLen == sizeof(NsmSession_s)) + ? NSM__enRegisterSession((NsmSession_s*) pData, TRUE, FALSE) + : NsmErrorStatus_Parameter; + break; + + /* NSMC wants to unregister a session */ + case NsmDataType_UnRegisterSession: + enRetVal = (u32DataLen == sizeof(NsmSession_s)) + ? NSM__enUnRegisterSession((NsmSession_s*) pData, TRUE, FALSE) + : NsmErrorStatus_Parameter; + break; + /* Error: The type of the data NSMC is trying to set is unknown or the data is read only! */ case NsmDataType_RestartReason: case NsmDataType_RunningReason: @@ -2395,7 +2607,8 @@ unsigned int NsmGetInterfaceVersion(void) /* The main function of the NodeStateManager */ int main(void) { - gboolean boEndByUser = FALSE; + gboolean boEndByUser = FALSE; + int pcl_return = 0; /* Initialize glib for using "g" types */ g_type_init(); @@ -2409,7 +2622,19 @@ int main(void) NSM__vSyslogOpen(); /* Print first msg. to show that NSM is going to start */ - DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: NodeStateManager started.")); + DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: NodeStateManager started."), DLT_STRING("Version:"), DLT_STRING(VERSION)); + + /* Initialize PCL before initializing variables */ + pcl_return = pclInitLibrary("NodeStateManager", PCL_SHUTDOWN_TYPE_NORMAL + | PCL_SHUTDOWN_TYPE_FAST); + if(pcl_return < 0) + { + DLT_LOG(NsmContext, + DLT_LOG_WARN, + DLT_STRING("NSM: Failed to initialize PCL."); + DLT_STRING("Error: Unexpected PCL return."); + DLT_STRING("Return:"); DLT_INT(pcl_return)); + } /* Currently no other resources accessing the NSM. Prepare it now! */ NSM__vInitializeVariables(); /* Initialize file local variables*/ @@ -2428,6 +2653,9 @@ int main(void) /* Initialize/start the NSMC */ if(NsmcInit() == 0x01) { + /* Start timer to satisfy wdog */ + NSM__vConfigureWdogTimer(); + /* The event loop is only canceled if the Node is completely shut down or there is an internal error. */ boEndByUser = NSMA_boWaitForEvents(); @@ -2466,6 +2694,18 @@ int main(void) g_slist_free_full(NSM__pFailedApplications, &NSM__vFreeFailedApplicationObject); g_list_free_full (NSM__pLifecycleClients, &NSM__vFreeLifecycleClientObject); + /* Deinitialize the PCL */ + pcl_return = pclDeinitLibrary(); + + if(pcl_return < 0) + { + DLT_LOG(NsmContext, + DLT_LOG_WARN, + DLT_STRING("NSM: Failed to deinitialize PCL."); + DLT_STRING("Error: Unexpected PCL return."); + DLT_STRING("Return:"); DLT_INT(pcl_return)); + } + DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: NodeStateManager stopped.")); /* Deinit syslog */ diff --git a/NodeStateManager/NodeStateManager.h b/NodeStateManager/NodeStateManager.h index 61b9995..522fe3e 100644 --- a/NodeStateManager/NodeStateManager.h +++ b/NodeStateManager/NodeStateManager.h @@ -18,12 +18,13 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Date Author Reason -* 2012.06.01 uidu5846 1.0.0.0 CSP_WZ#388: Initial version of the NodeStateManager interface -* 2012.09.27 uidu5846 1.1.0.0 CSP_WZ#1194: Changed file header structure and license to be released -* as open source package. Introduced 'NodeStateTypes.h' to -* avoid circle includes and encapsulate type definitions. -* 2012.10.24 uidu5846 1.2.0.0 CSP_WZ#1322: Changed types of interface parameters to native types. -* Since the same native types are used, no interface change. +* 2012.06.01 uidu5846 1.0.0.0 CSP_WZ#388: Initial version of the NodeStateManager interface +* 2012.09.27 uidu5846 1.1.0.0 CSP_WZ#1194: Changed file header structure and license to be released +* as open source package. Introduced 'NodeStateTypes.h' to +* avoid circle includes and encapsulate type definitions. +* 2012.10.24 uidu5846 1.2.0.0 CSP_WZ#1322: Changed types of interface parameters to native types. +* Since the same native types are used, no interface change. +* 2013.04.18 uidu5846 1.2.1 OvipRbt#1153: Increased minor version number. * **********************************************************************************************************************/ @@ -59,7 +60,7 @@ extern "C" * The lower significant byte is equal 0 for released version only */ -#define NSM_INTERFACE_VERSION 0x01020000U +#define NSM_INTERFACE_VERSION 0x01020100U /********************************************************************************************************************** * diff --git a/NodeStateManager/NodeStateTypes.h b/NodeStateManager/NodeStateTypes.h index 023dfa9..7451a19 100644 --- a/NodeStateManager/NodeStateTypes.h +++ b/NodeStateManager/NodeStateTypes.h @@ -20,6 +20,7 @@ * and encapsulate type definitions. * 2012.10.24 uidu5846 1.0.0.1 CSP_WZ#1322: Removed "ssw_types" redefinition from header. * Since the same native types are used, no interface change. +* 2013.04.18 uidu5846 1.2.1 OvipRbt#1153 Added possibility to register sessions via the NSMC. * **********************************************************************************************************************/ @@ -87,7 +88,9 @@ typedef enum _NsmDataType_e NsmDataType_SessionState, /**< A SessionState should be set or get */ NsmDataType_ShutdownReason, /**< A ShutdownReason should be set or get */ NsmDataType_BootMode, /**< A BootMode should be set or get */ - NsmDataType_RunningReason /**< A RunningReason should be set or get */ + NsmDataType_RunningReason, /**< A RunningReason should be set or get */ + NsmDataType_RegisterSession, /**< A Session should be registered */ + NsmDataType_UnRegisterSession /**< A Session should be unregistered */ } NsmDataType_e; diff --git a/NodeStateManager/config/node-state-manager.pc.in b/NodeStateManager/config/node-state-manager.pc.in index 480ff5d..11fb8df 100644 --- a/NodeStateManager/config/node-state-manager.pc.in +++ b/NodeStateManager/config/node-state-manager.pc.in @@ -4,7 +4,7 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ -dbusinterfacesdir=@dbusinterfacesdir@ +dbusinterfacesdir=${pc_sysrootdir}@dbusinterfacesdir@ Name: NodeStateManager (NSM) Description: Package information for the NHM. diff --git a/NodeStateManager/config/nodestatemanager-daemon.service.in b/NodeStateManager/config/nodestatemanager-daemon.service.in index 6842cbd..71fcc3c 100644 --- a/NodeStateManager/config/nodestatemanager-daemon.service.in +++ b/NodeStateManager/config/nodestatemanager-daemon.service.in @@ -11,13 +11,17 @@ [Unit] Description=NodeStateManager to provide system states, session and shutdown handling -Wants=dbus.service dlt-daemon.service -After=dbus.service dlt-daemon.service +Wants=dbus.service dlt-daemon.service pas-daemon.service +After=dbus.service dlt-daemon.service pas-daemon.service # Start up very early, because it doesn't need anything to run prior to it: DefaultDependencies=no [Service] +Type=dbus +WatchdogSec=20 +NotifyAccess=main +BusName=org.genivi.NodeStateManager ExecStart=/usr/bin/NodeStateManager [Install] diff --git a/NodeStateTest/NodeStateTest.c b/NodeStateTest/NodeStateTest.c index 980e8d0..75060dd 100644 --- a/NodeStateTest/NodeStateTest.c +++ b/NodeStateTest/NodeStateTest.c @@ -35,7 +35,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Date Author Reason -* 24.01.2013 Jean-Pierre Bogler CSP_WZ#1194: Initial creation. +* 24.01.2013 Jean-Pierre Bogler CSP_WZ#1194: Initial creation. +* 18.04.2013 Jean-Pierre Bogler OvipRbt#1153: Implemented test cases 164 - 170. * **********************************************************************************************************************/ @@ -140,7 +141,9 @@ typedef struct { guint u32DataLen; /* Length of the data to be set in byte */ NsmSession_s stSession; /* Defines session and state that should be set */ -} NSMTST__tstSmSetSessionStateParam; +} NSMTST__tstSmSetSessionStateParam, + NSMTST__tstSmRegisterSessionParam, + NSMTST__tstSmUnRegisterSessionParam; /* Configure the parameters for setting a ShutdownReason using the (internal) NsmSetData interface. */ typedef struct @@ -293,6 +296,8 @@ typedef union NSMTST__tstSmSetApplicationModeParam stSmSetApplicationMode; NSMTST__tstSmSetNodeStateParam stSmSetNodeState; NSMTST__tstSmSetSessionStateParam stSmSetSessionState; + NSMTST__tstSmRegisterSessionParam stSmRegisterSession; + NSMTST__tstSmUnRegisterSessionParam stSmUnRegisterSession; NSMTST__tstSmSetShutdownReasonParam stSmSetShutdownReason; NSMTST__tstSmSetBootModeParam stSmSetBootMode; @@ -455,6 +460,8 @@ typedef struct NSMTST__tstSmSetInvalidDataReturn, NSMTST__tstSmSetShutdownModeReturn, NSMTST__tstSmSetSessionStateReturn, + NSMTST__tstSmRegisterSessionReturn, + NSMTST__tstSmUnRegisterSessionReturn, NSMTST__tstTestLifecycleRequestCompleteReturn; /* Configures the expected values for the reception of the SessionState signal send by the NSM. */ @@ -525,6 +532,8 @@ typedef union NSMTST__tstSmSetApplicationModeReturn stSmSetApplicationMode; NSMTST__tstSmSetInvalidDataReturn stSmSetInvalidData; NSMTST__tstSmSetSessionStateReturn stSmSetSessionState; + NSMTST__tstSmRegisterSessionReturn stSmRegisterSession; + NSMTST__tstSmUnRegisterSessionReturn stSmUnRegisterSession; NSMTST__tstSmGetAppModeReturn stSmGetApplicationMode; NSMTST__tstSmGetNodeStateReturn stSmGetNodeState; @@ -596,6 +605,8 @@ static gboolean NSMTST__boDbLifecycleRequestComplete (void); static gboolean NSMTST__boSmSetApplicationMode (void); static gboolean NSMTST__boSmSetNodeState (void); static gboolean NSMTST__boSmSetSessionState (void); +static gboolean NSMTST__boSmRegisterSession (void); +static gboolean NSMTST__boSmUnRegisterSession (void); static gboolean NSMTST__boSmSetShutdownReason (void); static gboolean NSMTST__boSmSetBootMode (void); static gboolean NSMTST__boSmSetInvalidData (void); @@ -842,6 +853,17 @@ static NSMTST__tstTestCase NSMTST__astTestCases[] = { &NSMTST__boTestProcessLifecycleRequest, .unParameter.stTestProcessLifecycleRequest = {NsmErrorStatus_Ok}, .unReturnValues.stTestProcessLifecycleRequest = {NSM_SHUTDOWNTYPE_FAST} }, { &NSMTST__boTestProcessLifecycleRequest, .unParameter.stTestProcessLifecycleRequest = {NsmErrorStatus_Ok}, .unReturnValues.stTestProcessLifecycleRequest = {NSM_SHUTDOWNTYPE_RUNUP} }, { &NSMTST__boTestProcessLifecycleRequest, .unParameter.stTestProcessLifecycleRequest = {NsmErrorStatus_Ok}, .unReturnValues.stTestProcessLifecycleRequest = {NSM_SHUTDOWNTYPE_RUNUP} }, + { &NSMTST__boDbSetSessionState, .unParameter.stDbSetSessionState = {"PlatformSupplySession", "NodeStateTest", NsmSeat_Driver, (NsmSessionState_e) 0x02}, .unReturnValues.stDbSetSessionState = {NsmErrorStatus_Ok} }, + { &NSMTST__boDbGetSessionState, .unParameter.stDbGetSessionState = {"PlatformSupplySession", NsmSeat_Driver}, .unReturnValues.stDbGetSessionState = {NsmErrorStatus_Ok, (NsmSessionState_e) 0x02} }, + { &NSMTST__boDbSetSessionState, .unParameter.stDbSetSessionState = {"PlatformSupplySession", "NodeStateTest", NsmSeat_Driver, (NsmSessionState_e) 0x03}, .unReturnValues.stDbSetSessionState = {NsmErrorStatus_Ok} }, + { &NSMTST__boCheckSessionSignal, .unParameter.stTestDummy = {0x00}, .unReturnValues.stCheckSessionSignal = {TRUE, "PlatformSupplySession", NsmSeat_Driver, (NsmSessionState_e) 0x03 } }, + { &NSMTST__boDbGetSessionState, .unParameter.stDbGetSessionState = {"PlatformSupplySession", NsmSeat_Driver}, .unReturnValues.stDbGetSessionState = {NsmErrorStatus_Ok, (NsmSessionState_e) 0x03} }, + { &NSMTST__boSmRegisterSession, .unParameter.stSmRegisterSession = {sizeof(NsmSession_s), {"StateMachine", "NodeStateTest", NsmSeat_Driver, NsmSessionState_Active}}, .unReturnValues.stSmRegisterSession = {NsmErrorStatus_Ok} }, + { &NSMTST__boCheckSessionSignal, .unParameter.stTestDummy = {0x00}, .unReturnValues.stCheckSessionSignal = {TRUE, "StateMachine", NsmSeat_Driver, NsmSessionState_Active } }, + { &NSMTST__boSmRegisterSession, .unParameter.stSmRegisterSession = {sizeof(NsmSession_s)-1, {"StateMachine", "NodeStateTest", NsmSeat_Driver, NsmSessionState_Active}}, .unReturnValues.stSmRegisterSession = {NsmErrorStatus_Parameter} }, + { &NSMTST__boSmUnRegisterSession, .unParameter.stSmUnRegisterSession = {sizeof(NsmSession_s)-1, {"StateMachine", "NodeStateTest", NsmSeat_Driver, NsmSessionState_Active}}, .unReturnValues.stSmRegisterSession = {NsmErrorStatus_Parameter} }, + { &NSMTST__boSmUnRegisterSession, .unParameter.stSmUnRegisterSession = {sizeof(NsmSession_s), {"StateMachine", "NodeStateTest", NsmSeat_Driver, NsmSessionState_Unregistered}}, .unReturnValues.stSmRegisterSession = {NsmErrorStatus_Ok} }, + { &NSMTST__boCheckSessionSignal, .unParameter.stTestDummy = {0x00}, .unReturnValues.stCheckSessionSignal = {TRUE, "StateMachine", NsmSeat_Driver, NsmSessionState_Unregistered } } }; @@ -2141,6 +2163,128 @@ static gboolean NSMTST__boSmSetSessionState(void) return boRetVal; } + +static gboolean NSMTST__boSmRegisterSession(void) +{ + /* Function local variables */ + gboolean boRetVal = TRUE; /* Return value */ + GError *pError = NULL; + GVariant *pDataIn = NULL; + NsmErrorStatus_e enReceivedNsmReturn = NsmErrorStatus_NotSet; + + /* Values read from parameter config */ + const guint u32DataLen = NSMTST__pstTestCase->unParameter.stSmRegisterSession.u32DataLen; + const NsmSession_s stSession = NSMTST__pstTestCase->unParameter.stSmRegisterSession.stSession; + + /* Values read from return config */ + const NsmErrorStatus_e enExpectedNsmReturn = NSMTST__pstTestCase->unReturnValues.stSmRegisterSession.enErrorStatus; + + /* Variables need to adapt test case */ + const gchar *sNsmValue = "RegisterSession"; + const NsmDataType_e enDataType = NsmDataType_RegisterSession; + const guint u32RealDataLen = sizeof(NsmSession_s); + + /* Create test case description */ + NSMTST__sTestDescription = g_strdup_printf("Set %s. Interface: StateMachine. Passed DataLen: %d.", + sNsmValue, u32DataLen); + /* Perform test call */ + pDataIn = NSMTST__pPrepareStateMachineData((guchar*) &stSession, u32RealDataLen); + (void) node_state_test_call_set_nsm_data_sync(NSMTST__pNodeStateMachine, + enDataType, + pDataIn, + u32DataLen, + (gint*) &enReceivedNsmReturn, + NULL, + &pError); + g_variant_unref(pDataIn); + + /* Evaluate result. Check if a D-Bus error occurred. */ + if(pError == NULL) + { + /* D-Bus communication successful. Check if NSM returned with the expected value. */ + if(enReceivedNsmReturn == enExpectedNsmReturn) + { + boRetVal = TRUE; + } + else + { + boRetVal = FALSE; + NSMTST__sErrorDescription = g_strdup_printf("Did not receive expected NSM return value. Received: 0x%02X. Expected: 0x%02X.", + enReceivedNsmReturn, enExpectedNsmReturn); + } + } + else + { + boRetVal = FALSE; + NSMTST__sErrorDescription = g_strdup_printf("Failed to create access NSMC via D-Bus. Error msg.: %s.", + pError->message); + g_error_free(pError); + } + + return boRetVal; +} + +static gboolean NSMTST__boSmUnRegisterSession(void) +{ + /* Function local variables */ + gboolean boRetVal = TRUE; /* Return value */ + GError *pError = NULL; + GVariant *pDataIn = NULL; + NsmErrorStatus_e enReceivedNsmReturn = NsmErrorStatus_NotSet; + + /* Values read from parameter config */ + const guint u32DataLen = NSMTST__pstTestCase->unParameter.stSmUnRegisterSession.u32DataLen; + const NsmSession_s stSession = NSMTST__pstTestCase->unParameter.stSmUnRegisterSession.stSession; + + /* Values read from return config */ + const NsmErrorStatus_e enExpectedNsmReturn = NSMTST__pstTestCase->unReturnValues.stSmUnRegisterSession.enErrorStatus; + + /* Variables need to adapt test case */ + const gchar *sNsmValue = "UnRegisterSession"; + const NsmDataType_e enDataType = NsmDataType_UnRegisterSession; + const guint u32RealDataLen = sizeof(NsmSession_s); + + /* Create test case description */ + NSMTST__sTestDescription = g_strdup_printf("Set %s. Interface: StateMachine. Passed DataLen: %d.", + sNsmValue, u32DataLen); + /* Perform test call */ + pDataIn = NSMTST__pPrepareStateMachineData((guchar*) &stSession, u32RealDataLen); + (void) node_state_test_call_set_nsm_data_sync(NSMTST__pNodeStateMachine, + enDataType, + pDataIn, + u32DataLen, + (gint*) &enReceivedNsmReturn, + NULL, + &pError); + g_variant_unref(pDataIn); + + /* Evaluate result. Check if a D-Bus error occurred. */ + if(pError == NULL) + { + /* D-Bus communication successful. Check if NSM returned with the expected value. */ + if(enReceivedNsmReturn == enExpectedNsmReturn) + { + boRetVal = TRUE; + } + else + { + boRetVal = FALSE; + NSMTST__sErrorDescription = g_strdup_printf("Did not receive expected NSM return value. Received: 0x%02X. Expected: 0x%02X.", + enReceivedNsmReturn, enExpectedNsmReturn); + } + } + else + { + boRetVal = FALSE; + NSMTST__sErrorDescription = g_strdup_printf("Failed to create access NSMC via D-Bus. Error msg.: %s.", + pError->message); + g_error_free(pError); + } + + return boRetVal; +} + + static gboolean NSMTST__boSmSetShutdownReason(void) { /* Function local variables */ diff --git a/configure.ac b/configure.ac index 913c4a7..a094b4e 100644 --- a/configure.ac +++ b/configure.ac @@ -12,14 +12,10 @@ # 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 -# 24.01.2013 Jean-Pierre Bogler Added NodeStateTest/Makefile to output files -# 14.03.2013 Jean-Pierre Bogler Updated usage for real NodeStateAccess library -# ####################################################################################################################### # Initialize autoconf -AC_INIT([node-state-manager],[1.2.0.0]) +AC_INIT([node-state-manager],[1.3.5]) AC_COPYRIGHT([Copyright (c) 2012 Continental Automotive GmbH]) AC_PREREQ([2.50]) @@ -42,12 +38,14 @@ AC_CHECK_HEADERS([string.h]) AC_CHECK_FUNCS([memcpy]) # Check for required packages -PKG_CHECK_MODULES([DLT], [automotive-dlt >= 2.2.0] ) -PKG_CHECK_MODULES([GIO], [gio-2.0 >= 2.30.0] ) -PKG_CHECK_MODULES([GIO_UNIX], [gio-unix-2.0 >= 2.30.0] ) -PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.30.0] ) -PKG_CHECK_MODULES([GOBJECT], [gobject-2.0 >= 2.30.0] ) -PKG_CHECK_MODULES([DBUS], [dbus-1 >= 1.4.10] ) +PKG_CHECK_MODULES([DLT], [automotive-dlt >= 2.2.0 ]) +PKG_CHECK_MODULES([GIO], [gio-2.0 >= 2.30.0]) +PKG_CHECK_MODULES([GIO_UNIX], [gio-unix-2.0 >= 2.30.0]) +PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.30.0]) +PKG_CHECK_MODULES([GOBJECT], [gobject-2.0 >= 2.30.0]) +PKG_CHECK_MODULES([DBUS], [dbus-1 >= 1.4.10]) +PKG_CHECK_MODULES([SYSTEMD], [libsystemd-daemon >= 37 ]) +PKG_CHECK_MODULES([PCL], [persistence_client_library >= 0.6.0 ]) # Derive path for storing systemd service files (e. g. /lib/systemd/system) AC_ARG_WITH([systemdsystemunitdir], -- cgit v1.2.1