summaryrefslogtreecommitdiff
path: root/NodeStateManager
diff options
context:
space:
mode:
authorMonika Forstner <Monika_Forstner@mentor.com>2020-09-16 10:20:03 +0200
committerMonika Forstner <Monika_Forstner@mentor.com>2020-09-16 10:50:27 +0200
commit2fb502b4bc23aa13fee1db3395b3cae5e34cc871 (patch)
treed9cd2c64522f190500dc53291b4fbcf5100b9720 /NodeStateManager
parent253d10aada6bf5cdfe307aaff55363f08194c85e (diff)
downloadnode-state-manager-release_NSM_CommonAPI.tar.gz
NSM Release 3.0release_NSM_CommonAPI
Diffstat (limited to 'NodeStateManager')
-rw-r--r--NodeStateManager/CMakeLists.txt62
-rw-r--r--NodeStateManager/Makefile.am63
-rw-r--r--NodeStateManager/NodeStateManager.c1752
-rw-r--r--NodeStateManager/NodeStateManager.h13
-rw-r--r--NodeStateManager/NodeStateTypes.h298
-rw-r--r--NodeStateManager/Watchdog.cpp111
-rw-r--r--NodeStateManager/Watchdog.hpp45
-rw-r--r--NodeStateManager/config/node-state-manager.pc.in13
-rw-r--r--NodeStateManager/config/nodestatemanager-daemon.service (renamed from NodeStateManager/config/nodestatemanager-daemon.service.in)12
-rw-r--r--NodeStateManager/config/org.genivi.NodeStateManager.LifeCycleControl.service.in4
-rw-r--r--NodeStateManager/config/org.genivi.NodeStateManager.conf21
11 files changed, 1441 insertions, 953 deletions
diff --git a/NodeStateManager/CMakeLists.txt b/NodeStateManager/CMakeLists.txt
new file mode 100644
index 0000000..0c2d1ce
--- /dev/null
+++ b/NodeStateManager/CMakeLists.txt
@@ -0,0 +1,62 @@
+#######################################################################################################################
+#
+# Copyright (C) 2020 Mentor Graphics (Deutschland) GmbH
+#
+# Author: Vignesh_Rajendran@mentor.com
+#
+# CMake file of NodeStateManager
+#
+# 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/.
+#
+#######################################################################################################################
+
+
+cmake_minimum_required(VERSION 3.7.2 FATAL_ERROR)
+
+project(NodeStateManager LANGUAGES C CXX)
+
+set(SOURCE_FILES NodeStateManager.c Watchdog.cpp)
+set(SYSTEMD_SERVICE config/nodestatemanager-daemon.service)
+set(SYSTEMD_SERVICES_INSTALL_DIR "/etc/systemd/system/")
+
+add_definitions(-DWATERMARK="${PROJECT_VERSION}")
+
+set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -export-dynamic")
+
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-variable -Wno-unused-parameter")
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+
+include_directories(
+ ${CMAKE_SOURCE_DIR}/NodeStateAccess
+ ${CMAKE_SOURCE_DIR}/NodeStateMachineStub
+)
+
+add_executable(NodeStateManager ${SOURCE_FILES})
+
+target_link_libraries(NodeStateManager PRIVATE
+ NodeStateAccess
+ NodeStateMachineStub
+ ${DLT_LIBRARIES}
+ pthread
+ ${GLIB_LIBRARIES}
+ ${SYSTEMD_LIBRARIES})
+
+install(TARGETS NodeStateManager DESTINATION bin)
+
+install(
+ DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
+ FILES_MATCHING
+ PATTERN "*.h"
+ PATTERN "*.hpp")
+
+if(WITH_SYSTEMD_SERVICE)
+ install(
+ FILES ${CMAKE_CURRENT_SOURCE_DIR}/${SYSTEMD_SERVICE}
+ DESTINATION ${SYSTEMD_SERVICES_INSTALL_DIR}
+ PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ
+ )
+endif(WITH_SYSTEMD_SERVICE)
diff --git a/NodeStateManager/Makefile.am b/NodeStateManager/Makefile.am
deleted file mode 100644
index 1161faf..0000000
--- a/NodeStateManager/Makefile.am
+++ /dev/null
@@ -1,63 +0,0 @@
-#######################################################################################################################
-#
-# Copyright (C) 2012 Continental Automotive Systems, Inc.
-#
-# Author: Jean-Pierre.Bogler@continental-corporation.com
-#
-# Makefile template for the NodeStateManager
-#
-# 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/.
-#
-#######################################################################################################################
-
-bin_PROGRAMS = NodeStateManager
-
-NodeStateManager_SOURCES = NodeStateManager.c
-
-NodeStateManager_CFLAGS = -I$(top_srcdir)/@NSMC@ \
- -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)/@NSMC@ -l@NSMC@ \
- $(DLT_LIBS) \
- $(GIO_LIBS) \
- $(GIO_UNIX_LIBS) \
- $(GLIB_LIBS) \
- $(GOBJECT_LIBS) \
- $(SYSTEMD_LIBS) \
- $(PCL_LIBS)
-
-include_HEADERS = NodeStateManager.h NodeStateTypes.h
-
-systemdsystemunit_DATA = config/nodestatemanager-daemon.service
-
-dbussystemunit_DATA = config/org.genivi.NodeStateManager.LifeCycleControl.service
-dbuspolicy_DATA = config/org.genivi.NodeStateManager.conf
-
-# Write the package config file of the NHM to it destination
-pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = config/node-state-manager.pc
-
-# Export the dbus interface descrition of the NHM
-dbusinterfaces_DATA = $(top_srcdir)/NodeStateAccess/model/org.genivi.NodeStateManager.Consumer.xml \
- $(top_srcdir)/NodeStateAccess/model/org.genivi.NodeStateManager.LifecycleConsumer.xml \
- $(top_srcdir)/NodeStateAccess/model/org.genivi.NodeStateManager.LifecycleControl.xml \
- $(top_srcdir)/NodeStateMachineTest/org.genivi.NodeStateMachineTest.xml
-
-EXTRA_DIST = $(systemdsystemunit_DATA) \
- $(dbussystemunit_DATA) \
- $(dbuspolicy_DATA) \
- $(dbusinterfaces_DATA)
diff --git a/NodeStateManager/NodeStateManager.c b/NodeStateManager/NodeStateManager.c
index 6051183..80de639 100644
--- a/NodeStateManager/NodeStateManager.c
+++ b/NodeStateManager/NodeStateManager.c
@@ -1,6 +1,7 @@
/**********************************************************************************************************************
*
* Copyright (C) 2013 Continental Automotive Systems, Inc.
+* 2017 BMW AG
*
* Author: Jean-Pierre.Bogler@continental-corporation.com
*
@@ -10,7 +11,7 @@
* the "ApplicationMode" and many other states of the complete system. In addition, the NSM offers a
* session handling and a shutdown management.
* The NSM communicates with the NodeStateMachine (NSMC) to request and inform it about state changes
-* and the NodeStateAccess (NSMA) to connect to the D-Bus.
+* and the NodeStateAccess (NSMA) to connect to CommonAPI.
*
* 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
@@ -26,16 +27,21 @@
**********************************************************************************************************************/
#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 "Watchdog.hpp"
+#include <string.h> /* Memcpy etc. */
+#include <stdlib.h>
+#include <getopt.h>
+#include <gio/gio.h> /* GLib lists */
+#include <dlt.h> /* DLT Log'n'Trace */
+#include <syslog.h> /* Syslog messages */
+#include <pthread.h>
#include <systemd/sd-daemon.h> /* Systemd wdog */
-#include <persistence_client_library.h> /* Init/DeInit PCL */
-#include <persistence_client_library_key.h> /* Access persistent data */
-
+#include <unistd.h>
+#include <signal.h>
+#include <execinfo.h>
+#include <stdio.h>
+#include "NodeStateMachine.hpp" /* Talk to NodeStateMachine */
/**********************************************************************************************************************
*
@@ -43,21 +49,16 @@
*
**********************************************************************************************************************/
+#ifdef COVERAGE_ENABLED
+extern void __gcov_flush();
+#endif
+
+static const char *mark __attribute__((used))= "**WATERMARK**" WATERMARK "**WATERMARK**";
+
/* 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
-{
- gchar *sBusName; /* Bus name of the lifecycle client */
- gchar *sObjName; /* Object path of the client */
- guint32 u32RegisteredMode; /* Bit array of shutdown modes */
- NSMA_tLcConsumerHandle hClient; /* Handle for proxy object for lifecycle client */
- gboolean boShutdown; /* Only "run up" clients which are shut down */
-} NSM__tstLifecycleClient;
-
-
/* The type is used to store failed applications. A struct is used to allow extsions in future */
typedef struct
{
@@ -111,7 +112,8 @@ static NsmErrorStatus_e NSM__enSetAppStateValid (NSM__tstFailedApplication* p
/* Helper functions to control and start the "lifecycle request" sequence */
static void NSM__vCallNextLifecycleClient(void);
-static void NSM__vOnLifecycleRequestFinish(const NsmErrorStatus_e enErrorStatus);
+static void NSM__vCallParallelLifecycleClient(gboolean verbose);
+static void NSM__vOnLifecycleRequestFinish(size_t clientID, gboolean timeout, gboolean late);
/* Internal functions, to set and get values. Indirectly used by D-Bus and StateMachine */
@@ -123,12 +125,10 @@ static NsmErrorStatus_e NSM__enUnRegisterSession (NsmSession_s *session,
gboolean boInformMachine);
static NsmErrorStatus_e NSM__enSetNodeState (NsmNodeState_e enNodeState,
gboolean boInformBus,
- gboolean boInformMachine);
+ gboolean boInformMachine,
+ gboolean boExternalOrigin);
static NsmErrorStatus_e NSM__enSetBootMode (const gint i32BootMode,
gboolean boInformMachine);
-static NsmErrorStatus_e NSM__enSetApplicationMode (NsmApplicationMode_e enApplicationMode,
- gboolean boInformBus,
- gboolean boInformMachine);
static NsmErrorStatus_e NSM__enSetShutdownReason (NsmShutdownReason_e enNewShutdownReason,
gboolean boInformMachine);
@@ -149,13 +149,11 @@ static NsmErrorStatus_e NSM__enGetSessionState (NsmSession_s *p
/* Internal functions that are directly used from D-Bus and StateMachine */
static NsmErrorStatus_e NSM__enGetNodeState (NsmNodeState_e *penNodeState);
-static NsmErrorStatus_e NSM__enGetApplicationMode(NsmApplicationMode_e *penApplicationMode);
/* Callbacks for D-Bus interfaces of the NodeStateManager */
static NsmErrorStatus_e NSM__enOnHandleSetBootMode (const gint i32BootMode);
static NsmErrorStatus_e NSM__enOnHandleSetNodeState (const NsmNodeState_e enNodeState);
-static NsmErrorStatus_e NSM__enOnHandleSetApplicationMode (const NsmApplicationMode_e enApplMode);
static NsmErrorStatus_e NSM__enOnHandleRequestNodeRestart (const NsmRestartReason_e enRestartReason,
const guint u32RestartType);
static NsmErrorStatus_e NSM__enOnHandleSetAppHealthStatus (const gchar *sAppName,
@@ -168,12 +166,10 @@ static NsmErrorStatus_e NSM__enOnHandleRegisterSession (const gchar
static NsmErrorStatus_e NSM__enOnHandleUnRegisterSession (const gchar *sSessionName,
const gchar *sSessionOwner,
const NsmSeat_e enSeatId);
-static NsmErrorStatus_e NSM__enOnHandleRegisterLifecycleClient (const gchar *sBusName,
- const gchar *sObjName,
+static NsmErrorStatus_e NSM__enOnHandleRegisterLifecycleClient (const size_t clientHash,
const guint u32ShutdownMode,
const guint u32TimeoutMs);
-static NsmErrorStatus_e NSM__enOnHandleUnRegisterLifecycleClient(const gchar *sBusName,
- const gchar *sObjName,
+static NsmErrorStatus_e NSM__enOnHandleUnRegisterLifecycleClient(const size_t clientHash,
const guint u32ShutdownMode);
static NsmErrorStatus_e NSM__enOnHandleGetSessionState (const gchar *sSessionName,
const NsmSeat_e enSeatId,
@@ -182,23 +178,35 @@ static NsmErrorStatus_e NSM__enOnHandleSetSessionState (const gchar
const gchar *sSessionOwner,
const NsmSeat_e enSeatId,
const NsmSessionState_e enSessionState);
+static NsmErrorStatus_e NSM__enSetBlockExternalNodeState (const bool boBlock);
+
static guint NSM__u32OnHandleGetAppHealthCount (void);
static guint NSM__u32OnHandleGetInterfaceVersion (void);
/* Functions to simplify internal work flow */
static void NSM__vInitializeVariables (void);
static void NSM__vCreatePlatformSessions(void);
-static void NSM__vCreateMutexes (void);
-static void NSM__vDeleteMutexes (void);
/* LTPROF helper function */
-static void NSM__vLtProf(gchar *pszBus, gchar *pszObj, guint32 dwReason, gchar *pszInOut, guint32 dwValue);
+static void NSM__vLtProf(size_t client, guint32 dwReason, gchar *pszInOut, guint32 dwValue);
static void NSM__vSyslogOpen(void);
static void NSM__vSyslogClose(void);
+gboolean NSM__boEndByUser = FALSE;
+
/* Systemd watchdog functions */
-static gboolean NSM__boOnHandleTimerWdog(gpointer pUserData);
-static void NSM__vConfigureWdogTimer(void);
+static void *NSM__boOnHandleTimerWdog(void *pUserData);
+static void NSM__vConfigureWdogTimer(void);
+static pthread_t NSM__watchdog_thread;
+static unsigned long int NSM__WdogSec = 0;
+
+int NSM__bootloader_flag;
+static struct option NSM__options[] =
+{
+ /* These options set a flag. */
+ {"bootloader", no_argument, &NSM__bootloader_flag, 1},
+ {0, 0, 0, 0}
+};
/**********************************************************************************************************************
*
@@ -208,31 +216,36 @@ static void NSM__vConfigureWdogTimer(void);
/* Context for Log'n'Trace */
DLT_DECLARE_CONTEXT(NsmContext);
+DLT_DECLARE_CONTEXT(NsmaContext);
/* Variables for "Properties" hosted by the NSM */
-static GMutex *NSM__pSessionMutex = NULL;
+static GMutex NSM__pSessionMutex;
static GSList *NSM__pSessions = NULL;
static GList *NSM__pLifecycleClients = NULL;
-static GMutex *NSM__pNodeStateMutex = NULL;
+static GMutex NSM__pNodeStateMutex;
static NsmNodeState_e NSM__enNodeState = NsmNodeState_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 guint32 NSM__uiShutdownType = 0;
+static pthread_t NSM__callLCThread;
static GSList *NSM__pFailedApplications = NULL;
-/* Variables for internal state management (of lifecycle requests) */
-static NSM__tstLifecycleClient *NSM__pCurrentLifecycleClient = NULL;
+static guint NSM__collective_sequential_timeout = 0;
+static guint NSM__max_parallel_timeout = 0;
+static GMutex NSM__collective_timeout_mutex;
+static GCond NSM__collective_timeout_condVar;
+static gboolean NSM__collective_timeout_canceled = false;
+static GCond NSM__collective_timeout_init_condVar;
+static gboolean NSM__collective_timeout_initialized = false;
+static pthread_t NSM__collective_timeout_thread = 0;
+
+static volatile gboolean NSM__boResetActive = FALSE;
+static gboolean NSM__boBlockExternalNodeState = FALSE;
/* Constant array of callbacks which are registered at the NodeStateAccess library */
static const NSMA_tstObjectCallbacks NSM__stObjectCallBacks = { &NSM__enOnHandleSetBootMode,
&NSM__enOnHandleSetNodeState,
- &NSM__enOnHandleSetApplicationMode,
&NSM__enOnHandleRequestNodeRestart,
&NSM__enOnHandleSetAppHealthStatus,
&NSM__boOnHandleCheckLucRequired,
@@ -240,7 +253,6 @@ static const NSMA_tstObjectCallbacks NSM__stObjectCallBacks = { &NSM__enOnHandle
&NSM__enOnHandleUnRegisterSession,
&NSM__enOnHandleRegisterLifecycleClient,
&NSM__enOnHandleUnRegisterLifecycleClient,
- &NSM__enGetApplicationMode,
&NSM__enOnHandleGetSessionState,
&NSM__enGetNodeState,
&NSM__enOnHandleSetSessionState,
@@ -254,9 +266,163 @@ static const NSMA_tstObjectCallbacks NSM__stObjectCallBacks = { &NSM__enOnHandle
* Local (static) functions
*
**********************************************************************************************************************/
+static void NSM__startCollectiveTimeoutThread(size_t shutdownType);
+
+/**
+*
+* This function will be called by the NSM__collective_timeout_thread.
+* If the thread is not canceled before timeout occurred it will set the target NodeState
+* NsmNodeState_Shutdown or NsmNodeState_FullyOperational
+* @param param: Shutdown type
+*
+* @return NULL
+*
+*/
+static void *NSM__collectiveTimeoutHandler(void *param)
+{
+ NSMTriggerWatchdog(NsmWatchdogState_Active);
+ pthread_detach(pthread_self());
+
+ guint32 timeoutSec = 0;
+ guint32 shutdownType = (uint)(uintptr_t)param;
+ gboolean timeout = false;
+
+ switch (shutdownType) {
+ case NSM_SHUTDOWNTYPE_FAST | NSM_SHUTDOWNTYPE_PARALLEL:
+ timeoutSec = 2;
+ break;
+ case NSM_SHUTDOWNTYPE_FAST:
+ timeoutSec = 3;
+ break;
+ default:
+ timeoutSec = 60;
+ break;
+ }
+
+ gint64 end_time = g_get_monotonic_time () + timeoutSec * G_TIME_SPAN_SECOND;;
+
+ g_mutex_lock(&NSM__collective_timeout_mutex);
+ NSM__collective_timeout_initialized = true;
+ g_cond_broadcast(&NSM__collective_timeout_init_condVar);
+
+ NSM__collective_timeout_canceled = false;
+ NSMTriggerWatchdog(NsmWatchdogState_Sleep);
+ while(!NSM__collective_timeout_canceled)
+ {
+ if(!g_cond_wait_until (&NSM__collective_timeout_condVar,
+ &NSM__collective_timeout_mutex, end_time))
+ {
+ NSMTriggerWatchdog(NsmWatchdogState_Active);
+ timeout = true;
+ break;
+ }
+ }
+ NSMTriggerWatchdog(NsmWatchdogState_Active);
+
+ g_mutex_unlock(&NSM__collective_timeout_mutex);
+
+ if(timeout)
+ {
+ g_mutex_lock(&NSM__pNodeStateMutex);
+ if(shutdownType != NSM__uiShutdownType)
+ {
+ // Probably a different thread has already continued with shutdown/runup
+ g_mutex_unlock(&NSM__pNodeStateMutex);
+ }
+ else
+ {
+ NsmNodeState_e oldNodeState = NSM__enNodeState;
+
+ switch (shutdownType) {
+ case NSM_SHUTDOWNTYPE_FAST | NSM_SHUTDOWNTYPE_PARALLEL:
+ case NSM_SHUTDOWNTYPE_NORMAL | NSM_SHUTDOWNTYPE_PARALLEL:
+ DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Parallel shutdown took too long. Will continue with sequential now!"));
+
+ size_t shutdownType = (NSM__enNodeState == NsmNodeState_FastShutdown) ? NSM_SHUTDOWNTYPE_FAST : NSM_SHUTDOWNTYPE_NORMAL;
+ NSMA_setLcCollectiveTimeout();
+ NSM__startCollectiveTimeoutThread(shutdownType);
+ g_mutex_unlock(&NSM__pNodeStateMutex);
+ NSM__vCallNextLifecycleClient();
+ break;
+
+ case NSM_SHUTDOWNTYPE_RUNUP:
+ DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Sequential runup took too long. Will continue with parallel now!"));
+ NSMA_setLcCollectiveTimeout();
+ NSM__startCollectiveTimeoutThread(NSM_SHUTDOWNTYPE_RUNUP | NSM_SHUTDOWNTYPE_PARALLEL);
+ g_mutex_unlock(&NSM__pNodeStateMutex);
+ NSM__vCallParallelLifecycleClient(TRUE);
+ break;
+
+ case NSM_SHUTDOWNTYPE_FAST:
+ case NSM_SHUTDOWNTYPE_NORMAL:
+ DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Shutdown took too long. Will force shutdown now!"));
+
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Changed NodeState -"),
+ DLT_STRING(NODESTATE_STRING[oldNodeState]), DLT_INT((gint) oldNodeState), DLT_STRING("=>"),
+ DLT_STRING(NODESTATE_STRING[NsmNodeState_Shutdown]), DLT_INT((gint) NsmNodeState_Shutdown));
+
+ NSMA_setLcCollectiveTimeout();
+ NSM__enNodeState = NsmNodeState_Shutdown;
+ NsmcSetData(NsmDataType_NodeState, (unsigned char*) &NSM__enNodeState, sizeof(NsmNodeState_e));
+ NSMA_boSendNodeStateSignal(NSM__enNodeState);
+ g_mutex_unlock(&NSM__pNodeStateMutex);
+ break;
+
+ case NSM_SHUTDOWNTYPE_RUNUP | NSM_SHUTDOWNTYPE_PARALLEL:
+ DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Runup took too long. Will force fully operational now!"));
+
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Changed NodeState -"),
+ DLT_STRING(NODESTATE_STRING[oldNodeState]), DLT_INT((gint) oldNodeState), DLT_STRING("=>"),
+ DLT_STRING(NODESTATE_STRING[NsmNodeState_FullyOperational]), DLT_INT((gint) NsmNodeState_FullyOperational));
+
+ NSMA_setLcCollectiveTimeout();
+ NSM__enNodeState = NsmNodeState_FullyOperational;
+ NsmcSetData(NsmDataType_NodeState, (unsigned char*) &NSM__enNodeState, sizeof(NsmNodeState_e));
+ NSMA_boSendNodeStateSignal(NSM__enNodeState);
+ g_mutex_unlock(&NSM__pNodeStateMutex);
+ break;
+
+ default:
+ // This should never happen
+ g_mutex_unlock(&NSM__pNodeStateMutex);
+ DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Shutdown/Runup took to long. Error unknown state!"));
+ break;
+ }
+ }
+ }
+
+ NSMUnregisterWatchdog();
+ return NULL;
+}
+/**
+* This functions cancels the collectiveTimeout.
+* Will be called when all clients successfully returned or timed out in time
+*
+*/
+static void NSM__cancelCollectiveTimeoutThread()
+{
+ DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: NSM__cancelCollectiveTimeoutThread"));
-/**********************************************************************************************************************
+ g_mutex_lock (&NSM__collective_timeout_mutex);
+ NSM__collective_timeout_canceled = true;
+ g_cond_broadcast (&NSM__collective_timeout_condVar);
+ g_mutex_unlock(&NSM__collective_timeout_mutex);
+}
+
+static void NSM__startCollectiveTimeoutThread(size_t shutdownType)
+{
+ pthread_create(&NSM__collective_timeout_thread, NULL, &NSM__collectiveTimeoutHandler, (void*)shutdownType);
+ g_mutex_lock(&NSM__collective_timeout_mutex);
+ while (!NSM__collective_timeout_initialized)
+ {
+ // Wait until thread has been initialized
+ g_cond_wait(&NSM__collective_timeout_init_condVar, &NSM__collective_timeout_mutex);
+ }
+ NSM__collective_timeout_initialized = false;
+ g_mutex_unlock(&NSM__collective_timeout_mutex);
+}
+/**
*
* This helper function is called from various places to check if a session is a "platform" session.
*
@@ -265,7 +431,7 @@ static const NSMA_tstObjectCallbacks NSM__stObjectCallBacks = { &NSM__enOnHandle
* @return TRUE: The session is a "platform" session
* FALSE: The session is not a "platform" session
*
-**********************************************************************************************************************/
+*/
static gboolean NSM__boIsPlatformSession(NsmSession_s *pstSession)
{
/* Function local variables */
@@ -286,9 +452,9 @@ 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
+* @param session: Ptr to NsmSession_s structure containing data to register a session
+* @param boInformBus: Flag whether the a dbus signal should be send to inform about the new session
+* @param 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.
@@ -305,7 +471,7 @@ static NsmErrorStatus_e NSM__enRegisterSession(NsmSession_s *session, gboolean b
{
if(NSM__boIsPlatformSession(session) == FALSE)
{
- g_mutex_lock(NSM__pSessionMutex);
+ g_mutex_lock(&NSM__pSessionMutex);
pListEntry = g_slist_find_custom(NSM__pSessions, session, &NSM__i32SessionNameSeatCompare);
@@ -317,10 +483,10 @@ static NsmErrorStatus_e NSM__enRegisterSession(NsmSession_s *session, gboolean b
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));
+ DLT_STRING("Name:" ), DLT_STRING(session->sName ),
+ DLT_STRING("Owner:" ), DLT_STRING(session->sOwner ),
+ DLT_STRING("Seat:" ), DLT_STRING(SEAT_STRING[session->enSeat]),
+ DLT_STRING("Initial state:"), DLT_STRING(SESSIONSTATE_STRING[session->enState]));
/* Return OK and append new object */
NSM__pSessions = g_slist_append(NSM__pSessions, pNewSession);
@@ -333,23 +499,23 @@ static NsmErrorStatus_e NSM__enRegisterSession(NsmSession_s *session, gboolean b
/* 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 ));
+ DLT_STRING("Name:" ), DLT_STRING(session->sName ),
+ DLT_STRING("Owner:" ), DLT_STRING(session->sOwner ),
+ DLT_STRING("Seat:" ), DLT_STRING(SEAT_STRING[session->enSeat]),
+ DLT_STRING("Initial state:"), DLT_STRING(SESSIONSTATE_STRING[session->enState]));
}
- g_mutex_unlock(NSM__pSessionMutex);
+ 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 ));
+ DLT_STRING("Name:" ), DLT_STRING(session->sName ),
+ DLT_STRING("Owner:" ), DLT_STRING(session->sOwner ),
+ DLT_STRING("Seat:" ), DLT_STRING(SEAT_STRING[session->enSeat] ),
+ DLT_STRING("Initial state:"), DLT_STRING(SESSIONSTATE_STRING[session->enState] ));
}
}
else
@@ -357,10 +523,10 @@ static NsmErrorStatus_e NSM__enRegisterSession(NsmSession_s *session, gboolean b
/* 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 ));
+ DLT_STRING("Name:" ), DLT_STRING(session->sName ),
+ DLT_STRING("Owner:" ), DLT_STRING(session->sOwner ),
+ DLT_STRING("Seat:" ), DLT_STRING(SEAT_STRING[session->enSeat]),
+ DLT_STRING("Initial state:"), DLT_STRING(SESSIONSTATE_STRING[session->enState]));
}
return enRetVal;
@@ -369,9 +535,9 @@ static NsmErrorStatus_e NSM__enRegisterSession(NsmSession_s *session, gboolean b
/**
* 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
+* @param session: Ptr to NsmSession_s structure containing data to unregister a session
+* @param boInformBus: Flag whether the a dbus signal should be send to inform about the lost session
+* @param 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.
@@ -385,7 +551,7 @@ static NsmErrorStatus_e NSM__enUnRegisterSession(NsmSession_s *session, gboolean
if(NSM__boIsPlatformSession(session) == FALSE)
{
- g_mutex_lock(NSM__pSessionMutex);
+ g_mutex_lock(&NSM__pSessionMutex);
pListEntry = g_slist_find_custom(NSM__pSessions, session, &NSM__i32SessionOwnerNameSeatCompare);
@@ -397,10 +563,10 @@ static NsmErrorStatus_e NSM__enUnRegisterSession(NsmSession_s *session, gboolean
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));
+ DLT_STRING("Name:" ), DLT_STRING(pExistingSession->sName ),
+ DLT_STRING("Owner:" ), DLT_STRING(pExistingSession->sOwner ),
+ DLT_STRING("Seat:" ), DLT_STRING(SEAT_STRING[session->enSeat] ),
+ DLT_STRING(" Last state: "), DLT_STRING(SESSIONSTATE_STRING[session->enState]));
pExistingSession->enState = NsmSessionState_Unregistered;
@@ -415,27 +581,32 @@ static NsmErrorStatus_e NSM__enUnRegisterSession(NsmSession_s *session, gboolean
/* 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 ));
+ DLT_STRING("Name:" ), DLT_STRING(session->sName ),
+ DLT_STRING("Owner:" ), DLT_STRING(session->sOwner ),
+ DLT_STRING("Seat:" ), DLT_STRING(SEAT_STRING[session->enSeat]));
}
- g_mutex_unlock(NSM__pSessionMutex);
+ 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 ));
+ DLT_STRING("Name:" ), DLT_STRING(session->sName ),
+ DLT_STRING("Owner:" ), DLT_STRING(session->sOwner ),
+ DLT_STRING("Seat:" ), DLT_STRING(SEAT_STRING[session->enSeat] ));
}
return enRetVal;
}
+static NsmErrorStatus_e NSM__enSetBlockExternalNodeState(bool boBlock)
+{
+ NSM__boBlockExternalNodeState = boBlock;
+ return NsmErrorStatus_Ok;
+}
/**********************************************************************************************************************
*
* The function is called from IPC and StateMachine to set the NodeState.
@@ -447,7 +618,7 @@ static NsmErrorStatus_e NSM__enUnRegisterSession(NsmSession_s *session, gboolean
* @return see NsmErrorStatus_e
*
**********************************************************************************************************************/
-static NsmErrorStatus_e NSM__enSetNodeState(NsmNodeState_e enNodeState, gboolean boInformBus, gboolean boInformMachine)
+static NsmErrorStatus_e NSM__enSetNodeState(NsmNodeState_e enNodeState, gboolean boInformBus, gboolean boInformMachine, gboolean boExternalOrigin)
{
/* Function local variables */
NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet; /* Return value */
@@ -458,46 +629,84 @@ static NsmErrorStatus_e NSM__enSetNodeState(NsmNodeState_e enNodeState, gboolean
/* Assert that the Node not already is shut down. Otherwise it will switch of immediately */
enRetVal = NsmErrorStatus_Ok;
- g_mutex_lock(NSM__pNodeStateMutex);
+ g_mutex_lock(&NSM__pNodeStateMutex);
- /* Only store the new value and emit a signal, if the new value is different */
- if(NSM__enNodeState != enNodeState)
+ if(!boExternalOrigin || !NSM__boBlockExternalNodeState)
{
- /* Store the last NodeState, before switching to the new one */
- DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Changed NodeState." ),
- DLT_STRING(" Old NodeState: "), DLT_INT((gint) NSM__enNodeState),
- DLT_STRING(" New NodeState: "), DLT_INT((gint) enNodeState ));
-
-
- /* Store the passed NodeState and emit a signal to inform system that the NodeState changed */
- NSM__enNodeState = enNodeState;
-
- /* If required, inform the D-Bus about the change (send signal) */
- if(boInformBus == TRUE)
- {
- (void) NSMA_boSendNodeStateSignal(NSM__enNodeState);
- }
-
- /* If required, inform the StateMachine about the change */
- if(boInformMachine == TRUE)
- {
- NsmcSetData(NsmDataType_NodeState, (unsigned char*) &NSM__enNodeState, sizeof(NsmDataType_NodeState));
- }
-
- /* Leave the lock now, because its not recursive. 'NSM__vCallNextLifecycleClient' may need it. */
- g_mutex_unlock(NSM__pNodeStateMutex);
-
- /* Check if a new life cycle request needs to be started based on the new ShutdownType */
- if(NSM__pCurrentLifecycleClient == NULL)
- {
- NSM__vCallNextLifecycleClient();
- }
+ /* Only store the new value and emit a signal, if the new value is different */
+ if(NSM__enNodeState != enNodeState)
+ {
+ if(!(NSM__enNodeState == NsmNodeState_Shutdown && (enNodeState == NsmNodeState_ShuttingDown || enNodeState == NsmNodeState_FastShutdown)))
+ {
+ if(!NSM__boResetActive ||
+ enNodeState == NsmNodeState_Shutdown ||
+ enNodeState == NsmNodeState_ShuttingDown ||
+ enNodeState == NsmNodeState_FastShutdown)
+ {
+ /* Store the last NodeState, before switching to the new one */
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Changed NodeState -"),
+ DLT_STRING(NODESTATE_STRING[NSM__enNodeState]), DLT_INT((gint) NSM__enNodeState), DLT_STRING("=>"),
+ DLT_STRING(NODESTATE_STRING[enNodeState]), DLT_INT((gint) enNodeState));
+
+ /* Store the passed NodeState and emit a signal to inform system that the NodeState changed */
+ NSM__enNodeState = enNodeState;
+
+ /* If required, inform the D-Bus about the change (send signal) */
+ if(boInformBus == TRUE)
+ {
+ (void) NSMA_boSendNodeStateSignal(NSM__enNodeState);
+ }
+ /* If required, inform the StateMachine about the change */
+ if(boInformMachine == TRUE)
+ {
+ NsmcSetData(NsmDataType_NodeState, (unsigned char*) &NSM__enNodeState, sizeof(NsmDataType_NodeState));
+ }
+
+ /* Leave the lock now, because its not recursive. 'NSM__vCallNextLifecycleClient' may need it. */
+ if (enNodeState == NsmNodeState_FastShutdown || enNodeState == NsmNodeState_ShuttingDown)
+ {
+ size_t shutdownType = (enNodeState == NsmNodeState_FastShutdown) ? NSM_SHUTDOWNTYPE_PARALLEL | NSM_SHUTDOWNTYPE_FAST : NSM_SHUTDOWNTYPE_PARALLEL | NSM_SHUTDOWNTYPE_NORMAL;
+ NSM__cancelCollectiveTimeoutThread();
+ NSM__startCollectiveTimeoutThread(shutdownType);
+ g_mutex_unlock(&NSM__pNodeStateMutex);
+ NSM__vCallParallelLifecycleClient(TRUE);
+ }
+ else
+ {
+ NSM__cancelCollectiveTimeoutThread();
+ NSM__startCollectiveTimeoutThread(NSM_SHUTDOWNTYPE_RUNUP);
+ g_mutex_unlock(&NSM__pNodeStateMutex);
+ NSM__vCallNextLifecycleClient();
+ }
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Finished setting NodeState:"), DLT_STRING(NODESTATE_STRING[NSM__enNodeState]), DLT_INT((gint) NSM__enNodeState));
+ }
+ else
+ {
+ DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: A reset is being processed! Will not run up again!"));
+ enRetVal = NsmErrorStatus_Error;
+ g_mutex_unlock(&NSM__pNodeStateMutex);
+ }
+ }
+ else
+ {
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Already in Shutdown Mode! Will not shutdown again."));
+ g_mutex_unlock(&NSM__pNodeStateMutex);
+ }
+ }
+ else
+ {
+ /* NodeState stays the same. Just leave the lock. */
+ g_mutex_unlock(&NSM__pNodeStateMutex);
+ }
}
else
{
- /* NodeState stays the same. Just leave the lock. */
- g_mutex_unlock(NSM__pNodeStateMutex);
+ enRetVal = NsmErrorStatus_Error;
+ DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Set NodeState not allowed from external anymore!"));
+ g_mutex_unlock(&NSM__pNodeStateMutex);
}
+
+
}
else
{
@@ -525,11 +734,8 @@ static NsmErrorStatus_e NSM__enGetNodeState(NsmNodeState_e *penNodeState)
if(penNodeState != NULL)
{
- enRetVal = NsmErrorStatus_Ok;
-
- g_mutex_lock(NSM__pNodeStateMutex);
*penNodeState = NSM__enNodeState;
- g_mutex_unlock(NSM__pNodeStateMutex);
+ enRetVal = NsmErrorStatus_Ok;
}
else
{
@@ -580,180 +786,6 @@ static NsmErrorStatus_e NSM__enSetBootMode(const gint i32BootMode, gboolean boIn
return enRetVal;
}
-/**********************************************************************************************************************
-*
-* The function is called from IPC and StateMachine to set the ApplicationMode.
-*
-* @param enApplicationMode: New application mode that should be stored.
-* @param boInformBus: Defines whether a D-Bus signal should be send when the ApplicationMode could be changed.
-* @param boInformMachine: Defines whether the StateMachine should be informed about the new ApplicationMode.
-*
-* @return see NsmErrorStatus_e
-*
-**********************************************************************************************************************/
-static NsmErrorStatus_e
-NSM__enSetApplicationMode(NsmApplicationMode_e enApplicationMode,
- gboolean boInformBus,
- gboolean boInformMachine)
-{
- /* 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 ))
- {
- /* The passed parameter is valid. Return OK */
- enRetVal = NsmErrorStatus_Ok;
-
- g_mutex_lock(NSM__pNextApplicationModeMutex);
-
- /* 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 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);
-
- 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__enNextApplicationMode);
- }
-
- if(boInformMachine == TRUE)
- {
- NsmcSetData(NsmDataType_AppMode,
- (unsigned char*) &NSM__enNextApplicationMode,
- sizeof(NsmApplicationMode_e));
- }
- }
-
- 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.");
- 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;
-}
-
-
-/**********************************************************************************************************************
-*
-* The function is called from IPC and StateMachine to get the ApplicationMode.
-*
-* @return see NsmApplicationMode_e
-*
-**********************************************************************************************************************/
-static NsmErrorStatus_e
-NSM__enGetApplicationMode(NsmApplicationMode_e *penApplicationMode)
-{
- 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;
- *penApplicationMode = NSM__enThisApplicationMode;
-
- g_mutex_unlock(NSM__pThisApplicationModeMutex);
- }
- else
- {
- enRetVal = NsmErrorStatus_Parameter;
- }
-
- return enRetVal;
-}
-
/**********************************************************************************************************************
*
@@ -786,8 +818,8 @@ static NsmErrorStatus_e NSM__enSetShutdownReason(NsmShutdownReason_e enNewShutdo
{
/* Store new value and emit signal with new application mode */
DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Changed ShutdownReason."),
- DLT_STRING(" Old ShutdownReason: "), DLT_INT((gint) enCurrentShutdownReason),
- DLT_STRING(" New ShutdownReason: "), DLT_INT((gint) enNewShutdownReason ));
+ DLT_STRING(SHUTDOWNREASON_STRING[enCurrentShutdownReason]), DLT_INT((gint) enCurrentShutdownReason), DLT_STRING("=>"),
+ DLT_STRING(SHUTDOWNREASON_STRING[enNewShutdownReason]), DLT_INT((gint) enNewShutdownReason ));
(void) NSMA_boSetShutdownReason(enNewShutdownReason);
@@ -802,8 +834,8 @@ static NsmErrorStatus_e NSM__enSetShutdownReason(NsmShutdownReason_e enNewShutdo
/* 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 ShutdownReason. Invalid parameter." ),
- DLT_STRING(" Old ShutdownReason: "), DLT_INT((gint) enCurrentShutdownReason),
- DLT_STRING(" Desired ShutdownReason: "), DLT_INT((gint) enNewShutdownReason ));
+ DLT_STRING("Old ShutdownReason:"), DLT_STRING(SHUTDOWNREASON_STRING[enCurrentShutdownReason]), DLT_INT((gint) enCurrentShutdownReason),
+ DLT_STRING("Desired ShutdownReason:"), DLT_INT((gint) enNewShutdownReason ));
}
return enRetVal;
@@ -835,11 +867,11 @@ static void NSM__vPublishSessionChange(NsmSession_s *pstChangedSession, gboolean
if(enStateMachineReturn != NsmErrorStatus_Ok)
{
DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to inform state machine about changed session state." ),
- DLT_STRING(" State machine returned: "), DLT_INT( enStateMachineReturn ),
- DLT_STRING(" Application: "), DLT_STRING(pstChangedSession->sOwner ),
- DLT_STRING(" Session: "), DLT_STRING(pstChangedSession->sName ),
- DLT_STRING(" Seat: "), DLT_INT( pstChangedSession->enSeat ),
- DLT_STRING(" Desired state: "), DLT_INT( pstChangedSession->enState));
+ DLT_STRING("State machine returned:"), DLT_STRING(ERRORSTATUS_STRING[enStateMachineReturn]),
+ DLT_STRING("Application:"), DLT_STRING(pstChangedSession->sOwner ),
+ DLT_STRING("Session:"), DLT_STRING(pstChangedSession->sName ),
+ DLT_STRING("Seat:"), DLT_STRING(SEAT_STRING[pstChangedSession->enSeat] ),
+ DLT_STRING("Desired state:"), DLT_STRING(SESSIONSTATE_STRING[pstChangedSession->enState]));
}
}
}
@@ -863,7 +895,7 @@ static NsmErrorStatus_e NSM__enSetProductSessionState(NsmSession_s *pstSession,
GSList *pListEntry = NULL;
NsmSession_s *pExistingSession = NULL;
- g_mutex_lock(NSM__pSessionMutex);
+ g_mutex_lock(&NSM__pSessionMutex);
pListEntry = g_slist_find_custom(NSM__pSessions, pstSession, &NSM__i32SessionOwnerNameSeatCompare);
@@ -874,6 +906,12 @@ static NsmErrorStatus_e NSM__enSetProductSessionState(NsmSession_s *pstSession,
if(pExistingSession->enState != pstSession->enState)
{
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Changed product session's state."),
+ DLT_STRING("Application:"), DLT_STRING(pExistingSession->sOwner ),
+ DLT_STRING("Session:"), DLT_STRING(pExistingSession->sName ),
+ DLT_STRING("Seat:"), DLT_STRING(SEAT_STRING[pExistingSession->enSeat]),
+ DLT_STRING("Old state:"), DLT_STRING(SESSIONSTATE_STRING[pExistingSession->enState]),
+ DLT_STRING("New state:"), DLT_STRING(SESSIONSTATE_STRING[pstSession->enState] ));
pExistingSession->enState = pstSession->enState;
NSM__vPublishSessionChange(pExistingSession, boInformBus, boInformMachine);
}
@@ -882,13 +920,13 @@ static NsmErrorStatus_e NSM__enSetProductSessionState(NsmSession_s *pstSession,
{
enRetVal = NsmErrorStatus_WrongSession;
DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to set session state. Session unknown."),
- DLT_STRING(" Application: "), DLT_STRING(pstSession->sOwner ),
- DLT_STRING(" Session: "), DLT_STRING(pstSession->sName ),
- DLT_STRING(" Seat: "), DLT_INT( pstSession->enSeat ),
- DLT_STRING(" Desired state: "), DLT_INT( pstSession->enState));
+ DLT_STRING("Application:"), DLT_STRING(pstSession->sOwner ),
+ DLT_STRING("Session:"), DLT_STRING(pstSession->sName ),
+ DLT_STRING("Seat:"), DLT_STRING(SEAT_STRING[pstSession->enSeat]),
+ DLT_STRING("Desired state:"), DLT_INT( pstSession->enState));
}
- g_mutex_unlock(NSM__pSessionMutex);
+ g_mutex_unlock(&NSM__pSessionMutex);
return enRetVal;
}
@@ -913,7 +951,7 @@ static NsmErrorStatus_e NSM__enSetDefaultSessionState(NsmSession_s *pstSession,
NsmSession_s *pExistingSession = NULL;
/* Lock the sessions to be able to change them! */
- g_mutex_lock(NSM__pSessionMutex);
+ g_mutex_lock(&NSM__pSessionMutex);
pListEntry = g_slist_find_custom(NSM__pSessions, pstSession, &NSM__i32SessionNameSeatCompare);
@@ -929,11 +967,11 @@ static NsmErrorStatus_e NSM__enSetDefaultSessionState(NsmSession_s *pstSession,
if(pExistingSession->enState != pstSession->enState)
{
DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Changed default session's state."),
- DLT_STRING(" Application: "), DLT_STRING(pExistingSession->sOwner ),
- DLT_STRING(" Session: "), DLT_STRING(pExistingSession->sName ),
- DLT_STRING(" Seat: "), DLT_INT( pExistingSession->enSeat ),
- DLT_STRING(" Old state: "), DLT_INT( pExistingSession->enState),
- DLT_STRING(" New state: "), DLT_INT( pstSession->enState ));
+ DLT_STRING("Application:"), DLT_STRING(pExistingSession->sOwner ),
+ DLT_STRING("Session:"), DLT_STRING(pExistingSession->sName ),
+ DLT_STRING("Seat:"), DLT_STRING(SEAT_STRING[pExistingSession->enSeat]),
+ DLT_STRING("Old state:"), DLT_STRING(SESSIONSTATE_STRING[pExistingSession->enState]),
+ DLT_STRING("New state:"), DLT_STRING(SESSIONSTATE_STRING[pstSession->enState] ));
pExistingSession->enState = pstSession->enState;
@@ -958,11 +996,11 @@ static NsmErrorStatus_e NSM__enSetDefaultSessionState(NsmSession_s *pstSession,
g_strlcpy(pExistingSession->sOwner, pstSession->sOwner, sizeof(pExistingSession->sOwner));
DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Changed default session's state."),
- DLT_STRING(" Application: "), DLT_STRING(pExistingSession->sOwner ),
- DLT_STRING(" Session: "), DLT_STRING(pExistingSession->sName ),
- DLT_STRING(" Seat: "), DLT_INT( pExistingSession->enSeat ),
- DLT_STRING(" Old state: "), DLT_INT( pExistingSession->enState),
- DLT_STRING(" New state: "), DLT_INT( pstSession->enState ));
+ DLT_STRING("Application:"), DLT_STRING(pExistingSession->sOwner ),
+ DLT_STRING("Session:"), DLT_STRING(pExistingSession->sName ),
+ DLT_STRING("Seat:"), DLT_STRING(SEAT_STRING[pExistingSession->enSeat]),
+ DLT_STRING("Old state:"), DLT_STRING(SESSIONSTATE_STRING[pExistingSession->enState]),
+ DLT_STRING("New state:"), DLT_STRING(SESSIONSTATE_STRING[pstSession->enState] ));
pExistingSession->enState = pstSession->enState;
@@ -974,10 +1012,10 @@ static NsmErrorStatus_e NSM__enSetDefaultSessionState(NsmSession_s *pstSession,
enRetVal = NsmErrorStatus_Parameter;
DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to enable default session. Passed state is 'inactive'. "),
- DLT_STRING(" Session: "), DLT_STRING(pstSession->sName ),
- DLT_STRING(" Seat: "), DLT_INT( pstSession->enSeat ),
- DLT_STRING(" Owning application: "), DLT_STRING(pExistingSession->sOwner ),
- DLT_STRING(" Requesting application: "), DLT_STRING(pstSession->sOwner ));
+ DLT_STRING("Session:"), DLT_STRING(pstSession->sName ),
+ DLT_STRING("Seat:"), DLT_STRING(SEAT_STRING[pstSession->enSeat]),
+ DLT_STRING("Owning application:"), DLT_STRING(pExistingSession->sOwner ),
+ DLT_STRING("Requesting application:"), DLT_STRING(pstSession->sOwner ));
}
}
else
@@ -986,10 +1024,10 @@ static NsmErrorStatus_e NSM__enSetDefaultSessionState(NsmSession_s *pstSession,
enRetVal = NsmErrorStatus_Error;
DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to set default session state. Session has another owner."),
- DLT_STRING(" Session: "), DLT_STRING(pstSession->sName ),
- DLT_STRING(" Seat: "), DLT_INT( pstSession->enSeat ),
- DLT_STRING(" Owning application: "), DLT_STRING(pExistingSession->sOwner ),
- DLT_STRING(" Requesting application: "), DLT_STRING(pstSession->sOwner ));
+ DLT_STRING("Session:"), DLT_STRING(pstSession->sName ),
+ DLT_STRING("Seat:"), DLT_STRING(SEAT_STRING[pstSession->enSeat]),
+ DLT_STRING("Owning application:"), DLT_STRING(pExistingSession->sOwner ),
+ DLT_STRING("Requesting application:"), DLT_STRING(pstSession->sOwner ));
}
}
}
@@ -998,14 +1036,14 @@ static NsmErrorStatus_e NSM__enSetDefaultSessionState(NsmSession_s *pstSession,
/* This should never happen, because the function is only called for default sessions! */
enRetVal = NsmErrorStatus_Internal;
DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Critical error. Default session not found in session list!"),
- DLT_STRING(" Application: "), DLT_STRING(pstSession->sOwner ),
- DLT_STRING(" Session: "), DLT_STRING(pstSession->sName ),
- DLT_STRING(" Seat: "), DLT_INT( pstSession->enSeat ),
- DLT_STRING(" Desired state: "), DLT_INT( pstSession->enState ));
+ DLT_STRING("Application:"), DLT_STRING(pstSession->sOwner ),
+ DLT_STRING("Session:"), DLT_STRING(pstSession->sName ),
+ DLT_STRING("Seat:"), DLT_STRING(SEAT_STRING[pstSession->enSeat] ),
+ DLT_STRING("Desired state:"), DLT_STRING(SESSIONSTATE_STRING[pstSession->enState]));
}
/* Unlock the sessions again. */
- g_mutex_unlock(NSM__pSessionMutex);
+ g_mutex_unlock(&NSM__pSessionMutex);
return enRetVal;
}
@@ -1048,10 +1086,10 @@ static NsmErrorStatus_e NSM__enSetSessionState(NsmSession_s *pstSession, gboolea
/* Error: An invalid parameter has been passed. */
enRetVal = NsmErrorStatus_Parameter;
DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to change session state. Invalid paramter."),
- DLT_STRING(" Application: "), DLT_STRING(pstSession->sOwner ),
- DLT_STRING(" Session: "), DLT_STRING(pstSession->sName ),
- DLT_STRING(" Seat: "), DLT_INT( pstSession->enSeat ),
- DLT_STRING(" Desired state: "), DLT_INT( pstSession->enState ));
+ DLT_STRING("Application:"), DLT_STRING(pstSession->sOwner ),
+ DLT_STRING("Session:"), DLT_STRING(pstSession->sName ),
+ DLT_STRING("Seat:"), DLT_STRING(SEAT_STRING[pstSession->enSeat] ),
+ DLT_STRING("Desired state:"), DLT_STRING(SESSIONSTATE_STRING[pstSession->enState]));
}
return enRetVal;
@@ -1074,7 +1112,7 @@ static NsmErrorStatus_e NSM__enGetSessionState(NsmSession_s *pstSession)
NsmSession_s *pExistingSession = NULL; /* Pointer to existing session */
GSList *pListEntry = NULL;
- g_mutex_lock(NSM__pSessionMutex);
+ g_mutex_lock(&NSM__pSessionMutex);
/* Search for session with name, seat and owner. */
pListEntry = g_slist_find_custom(NSM__pSessions, pstSession, &NSM__i32SessionNameSeatCompare);
@@ -1091,11 +1129,11 @@ static NsmErrorStatus_e NSM__enGetSessionState(NsmSession_s *pstSession)
/* Error: The session is unknown. */
enRetVal = NsmErrorStatus_WrongSession;
DLT_LOG(NsmContext, DLT_LOG_WARN, DLT_STRING("NSM: Failed to retrieve session state. Unknown session."),
- DLT_STRING(" Session: "), DLT_STRING(pstSession->sName ),
- DLT_STRING(" Seat: "), DLT_INT( pstSession->enSeat ));
+ DLT_STRING("Session:"), DLT_STRING(pstSession->sName ),
+ DLT_STRING("Seat:"), DLT_STRING(SEAT_STRING[pstSession->enSeat]));
}
- g_mutex_unlock(NSM__pSessionMutex);
+ g_mutex_unlock(&NSM__pSessionMutex);
return enRetVal;
}
@@ -1146,13 +1184,6 @@ static void NSM__vFreeLifecycleClientObject(gpointer pLifecycleClient)
/* Function local variables. Cast the passed object */
NSM__tstLifecycleClient *pstLifecycleClient = (NSM__tstLifecycleClient*) pLifecycleClient;
- /* Free internal strings and objects */
- g_free(pstLifecycleClient->sBusName);
- g_free(pstLifecycleClient->sObjName);
-
- /* No need to check for NULL. Only valid clients come here */
- NSMA_boFreeLcConsumerProxy(pstLifecycleClient->hClient);
-
/* Free the shutdown client object */
g_free(pstLifecycleClient);
}
@@ -1182,17 +1213,9 @@ static gint NSM__i32LifecycleClientCompare(gconstpointer pL1, gconstpointer pL2)
pCompareClient = (NSM__tstLifecycleClient*) pL2;
/* Compare the bus name of the client */
- if(g_strcmp0(pListClient->sBusName, pCompareClient->sBusName) == 0)
+ if(pListClient->clientHash == pCompareClient->clientHash)
{
- /* Bus names are equal. Now compare object name */
- if(g_strcmp0(pListClient->sObjName, pCompareClient->sObjName) == 0)
- {
i32RetVal = 0; /* Clients are identical. Return 0. */
- }
- else
- {
- i32RetVal = -1; /* Object names are different. Return -1. */
- }
}
else
{
@@ -1359,6 +1382,26 @@ static gint NSM__i32SessionOwnerCompare(gconstpointer pS1, gconstpointer pS2)
return i32RetVal; /* Return result of comparison */
}
+/*
+ * Helper function to call NSM__vCallParallelLifecycleClient in a thread
+ */
+static void* callParallelLifecycleClient(void* ignore)
+{
+ NSMTriggerWatchdog(NsmWatchdogState_Active);
+ NSM__vCallParallelLifecycleClient(FALSE);
+ NSMUnregisterWatchdog();
+ return NULL;
+}
+/*
+ * Helper function to call NSM__vCallNextLifecycleClient in a thread
+ */
+static void* callLifecycleClient(void* ignore)
+{
+ NSMTriggerWatchdog(NsmWatchdogState_Active);
+ NSM__vCallNextLifecycleClient();
+ NSMUnregisterWatchdog();
+ return NULL;
+}
/**********************************************************************************************************************
*
@@ -1367,32 +1410,92 @@ static gint NSM__i32SessionOwnerCompare(gconstpointer pS1, gconstpointer pS2)
* to inform will be determined and called.
* If there is no client left, the lifecycle sequence will be finished.
*
-* @param pSrcObject: Source object (lifecycle client proxy)
-* @param pRes: Result of asynchronous call
-* @param pUserData: Pointer to the current lifecycle client object
+* @param enErrorStatus: Status of the client
+* @param clientID: array of clients that have returned
+* @param numClients: Number of clients that have finished
+* Only is greater than one when multiple parallel clients have timed out.
*
* @return void
*
**********************************************************************************************************************/
-static void NSM__vOnLifecycleRequestFinish(const NsmErrorStatus_e enErrorStatus)
+static void NSM__vOnLifecycleRequestFinish(size_t clientID, gboolean timeout, gboolean late)
{
- if(enErrorStatus == NsmErrorStatus_Ok)
- {
- /* The clients "LifecycleRequest" has been successfully processed. */
- NSM__vLtProf(NSM__pCurrentLifecycleClient->sBusName, NSM__pCurrentLifecycleClient->sObjName, 0, "leave: ", 0);
- DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Successfully called lifecycle client."));
- }
- else
+ g_mutex_lock(&NSM__pNodeStateMutex);
+
+ GList *pListEntry = NULL; /* Iterate through list entries */
+ NSM__tstLifecycleClient currentClient = {0}; /* Client object from list */
+ NSM__tstLifecycleClient *pCurrentClient = NULL; /* Client object from list */
+
+ for (pListEntry = g_list_last(NSM__pLifecycleClients);
+ (pListEntry != NULL) && (pCurrentClient == NULL);
+ pListEntry = g_list_previous(pListEntry))
{
- /* Error: The method of the lifecycle client returned an error */
- NSM__vLtProf(NSM__pCurrentLifecycleClient->sBusName, NSM__pCurrentLifecycleClient->sObjName, 0, "leave: error: ", enErrorStatus);
- DLT_LOG(NsmContext, DLT_LOG_WARN, DLT_STRING("NSM: Failed to call life cycle client." ),
- DLT_STRING(" Return Value: "), DLT_INT((gint) enErrorStatus));
- }
+ /* Check if client is the one that returned */
+ if ((((NSM__tstLifecycleClient*) pListEntry->data)->clientHash == clientID))
+ {
+ /* Found the current client */
+ pCurrentClient = (NSM__tstLifecycleClient*) pListEntry->data;
+ memcpy(&currentClient, pCurrentClient, sizeof(NSM__tstLifecycleClient));
+ /* A timed out client has still a pending call */
+ if(!timeout)
+ {
+ pCurrentClient->boPendingCall = FALSE;
+ }
- NSM__vCallNextLifecycleClient();
-}
+ if (!late)
+ {
+ /* If client is in time (or has timed out) continue as normal */
+ if (NSM_SHUTDOWNTYPE_PARALLEL & NSM__uiShutdownType)
+ {
+ pthread_create(&NSM__callLCThread, NULL, callParallelLifecycleClient, NULL);
+ pthread_detach(NSM__callLCThread);
+ }
+ else
+ {
+ pthread_create(&NSM__callLCThread, NULL, callLifecycleClient, NULL);
+ pthread_detach(NSM__callLCThread);
+ }
+ }
+ else
+ {
+ /* Add parallel flag to lifecycle request when client has registered for parallel */
+ uint32_t uiShutdownType = pCurrentClient->u32RegisteredMode & NSM_SHUTDOWNTYPE_PARALLEL ? NSM_SHUTDOWNTYPE_PARALLEL : NSM_SHUTDOWNTYPE_NOT;
+ /* If client has returned to late inform him about current possible changes */
+ if((NSM__uiShutdownType & NSM_SHUTDOWNTYPE_RUNUP) && pCurrentClient->boShutdown)
+ {
+ pCurrentClient->boShutdown = FALSE;
+ g_mutex_unlock(&NSM__pNodeStateMutex);
+ NSMA_boCallLcClientRequestWithoutTimeout(pCurrentClient, uiShutdownType | NSM_SHUTDOWNTYPE_RUNUP);
+ g_mutex_lock(&NSM__pNodeStateMutex);
+ }
+ else if((NSM__uiShutdownType & NSM_SHUTDOWNTYPE_FAST) != 0 && (pCurrentClient->u32RegisteredMode & NSM_SHUTDOWNTYPE_FAST) != 0 && !pCurrentClient->boShutdown)
+ {
+ pCurrentClient->boShutdown = TRUE;
+ g_mutex_unlock(&NSM__pNodeStateMutex);
+ NSMA_boCallLcClientRequestWithoutTimeout(pCurrentClient, uiShutdownType | NSM_SHUTDOWNTYPE_FAST);
+ g_mutex_lock(&NSM__pNodeStateMutex);
+ }
+ else if((NSM__uiShutdownType & NSM_SHUTDOWNTYPE_NORMAL) != 0 && (pCurrentClient->u32RegisteredMode & NSM_SHUTDOWNTYPE_NORMAL) != 0 && !pCurrentClient->boShutdown)
+ {
+ pCurrentClient->boShutdown = TRUE;
+ g_mutex_unlock(&NSM__pNodeStateMutex);
+ NSMA_boCallLcClientRequestWithoutTimeout(pCurrentClient, uiShutdownType | NSM_SHUTDOWNTYPE_NORMAL);
+ g_mutex_lock(&NSM__pNodeStateMutex);
+ }
+ else
+ {
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: No need to inform late shutdown client as it is in a valid state."),
+ DLT_STRING("ClientID:"), DLT_UINT64(pCurrentClient->clientHash),
+ DLT_STRING("Client is shutdown:"), DLT_BOOL((uint8_t)pCurrentClient->boShutdown),
+ DLT_STRING("Current shutdown type:"), DLT_INT(NSM__uiShutdownType));
+
+ }
+ }
+ }
+ }
+ g_mutex_unlock(&NSM__pNodeStateMutex);
+}
/**********************************************************************************************************************
*
@@ -1404,7 +1507,7 @@ static void NSM__vOnLifecycleRequestFinish(const NsmErrorStatus_e enErrorStatus)
* searches the list forward or backward until a client is found, which needs to be informed.
*
* PLEASE NOTE: If all clients have been informed about a "shut down", this function will quit the
-* "g_main_loop", which leads to the the termination of the NSM!
+* "main_loop", which leads to the the termination of the NSM!
*
* @return void
*
@@ -1414,125 +1517,322 @@ static void NSM__vCallNextLifecycleClient(void)
/* Function local variables */
GList *pListEntry = NULL; /* Iterate through list entries */
NSM__tstLifecycleClient *pClient = NULL; /* Client object from list */
- guint32 u32ShutdownType = NSM_SHUTDOWNTYPE_NOT; /* Return value */
- gboolean boShutdown = FALSE;
+ NSM__tstLifecycleClient currentLifecycleClient = {0};
+
+ g_mutex_lock(&NSM__pNodeStateMutex);
+
+ /* When a sequential client is still being informed do nothing for now */
+ if(!NSMA__SequentialClientHasPendingActiveCall())
+ {
+ if(!NSMA__ParallelClientHasPendingActiveCall(0))
+ {
+ /* Based on NodeState determine if clients have to shutdown or run up. Find a client that has not been informed */
+ switch(NSM__enNodeState)
+ {
+ case NsmNodeState_Shutdown: break;
+ /* For "shutdown" search backward in the list, until there is a client that has not been shut down */
+ case NsmNodeState_ShuttingDown:
+ NSM__uiShutdownType = NSM_SHUTDOWNTYPE_NORMAL;
+ for( pListEntry = g_list_last(NSM__pLifecycleClients);
+ (pListEntry != NULL) && (currentLifecycleClient.clientHash == 0);
+ pListEntry = g_list_previous(pListEntry))
+ {
+ /* Check if client has not been shut down and is registered for "normal shutdown" */
+ pClient = (NSM__tstLifecycleClient*) pListEntry->data;
+ if( ( pClient->boShutdown == FALSE)
+ && ( (pClient->u32RegisteredMode & NSM__uiShutdownType) != 0 )
+ && ( (pClient->u32RegisteredMode & NSM_SHUTDOWNTYPE_PARALLEL) == 0 )) // NSM_SHUTDOWNTYPE_PARALLEL have been notified earlier
+ {
+ /* Found a "running" previous client, registered for the shutdown mode */
+ memcpy(&currentLifecycleClient, pClient, sizeof(NSM__tstLifecycleClient));
+ }
+ }
+ break;
+
+ /* For "fast shutdown" search backward in the list, until there is a client that has not been shut down */
+ case NsmNodeState_FastShutdown:
+ NSM__uiShutdownType = NSM_SHUTDOWNTYPE_FAST;
+ for( pListEntry = g_list_last(NSM__pLifecycleClients);
+ (pListEntry != NULL) && (currentLifecycleClient.clientHash == 0);
+ pListEntry = g_list_previous(pListEntry))
+ {
+ /* Check if client has not been shut down and is registered for "fast shutdown" */
+ pClient = (NSM__tstLifecycleClient*) pListEntry->data;
+ if( ( pClient->boShutdown == FALSE )
+ && ( (pClient->u32RegisteredMode & NSM__uiShutdownType) != 0 )
+ && ( (pClient->u32RegisteredMode & NSM_SHUTDOWNTYPE_PARALLEL) == 0 )) // NSM_SHUTDOWNTYPE_PARALLEL have been notified earlier
+ {
+ /* Found a "running" previous client, registered for the shutdown mode */
+ memcpy(&currentLifecycleClient, pClient, sizeof(NSM__tstLifecycleClient));
+ }
+ }
+ break;
+
+ /* For a "running" mode search forward in the list (get next), until there is a client that is shut down */
+ default:
+ NSM__uiShutdownType = NSM_SHUTDOWNTYPE_RUNUP;
+ for(pListEntry = g_list_first(NSM__pLifecycleClients);
+ (pListEntry != NULL) && (currentLifecycleClient.clientHash == 0);
+ pListEntry = g_list_next(pListEntry))
+ {
+ /* Check if client is shut down */
+ pClient = (NSM__tstLifecycleClient*) pListEntry->data;
+ if(pClient->boShutdown == TRUE && ((pClient->u32RegisteredMode & NSM_SHUTDOWNTYPE_PARALLEL) == 0 ))
+ {
+ /* The client was shutdown. It should run up, because we are in a running mode */
+ memcpy(&currentLifecycleClient, pClient, sizeof(NSM__tstLifecycleClient));
+ }
+ }
+ break;
+ }
+ }
+
+ /* Check if a client could be found that needs to be informed */
+ if(currentLifecycleClient.clientHash != 0)
+ {
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Call lifecycle client." ),
+ DLT_STRING("ClientID:"), DLT_UINT64(currentLifecycleClient.clientHash ),
+ DLT_STRING("Registered types:"), DLT_INT(currentLifecycleClient.u32RegisteredMode),
+ DLT_STRING("ShutdownType:"), DLT_UINT(NSM__uiShutdownType ));
- NSM__pCurrentLifecycleClient = NULL;
+ /* Remember that client received a run-up or shutdown call */
+ pClient->boShutdown = (NSM__uiShutdownType != NSM_SHUTDOWNTYPE_RUNUP);
- g_mutex_lock(NSM__pNodeStateMutex);
+ NSM__vLtProf(currentLifecycleClient.clientHash, NSM__uiShutdownType, "enter: ", 0);
- /* Based on NodeState determine if clients have to shutdown or run up. Find a client that has not been informed */
- switch(NSM__enNodeState)
+ NSMA_boCallLcClientRequest(&currentLifecycleClient, NSM__uiShutdownType);
+ g_mutex_unlock(&NSM__pNodeStateMutex);
+ }
+ else
+ {
+ /* The last client was called. Depending on the NodeState check if we can end. */
+ switch(NSM__enNodeState)
+ {
+ case NsmNodeState_Shutdown:
+ g_mutex_unlock(&NSM__pNodeStateMutex);
+ break;
+ /* All registered clients have been 'fast shutdown'. Set NodeState to "shutdown" */
+ case NsmNodeState_FastShutdown:
+ if (!NSMA__ParallelClientHasPendingActiveCall(0))
+ {
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Informed all registered clients about 'fast shutdown'. Set NodeState to 'shutdown'"));
+ /* Store the last NodeState, before switching to the new one */
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Changed NodeState -"),
+ DLT_STRING(NODESTATE_STRING[NSM__enNodeState]), DLT_INT((gint) NSM__enNodeState), DLT_STRING("=>"),
+ DLT_STRING(NODESTATE_STRING[NsmNodeState_Shutdown]), DLT_INT((gint) NsmNodeState_Shutdown));
+
+ NSM__cancelCollectiveTimeoutThread();
+
+ NSM__enNodeState = NsmNodeState_Shutdown;
+ NsmcSetData(NsmDataType_NodeState, (unsigned char*) &NSM__enNodeState, sizeof(NsmNodeState_e));
+ NSMA_boSendNodeStateSignal(NSM__enNodeState);
+ }
+ g_mutex_unlock(&NSM__pNodeStateMutex);
+ break;
+
+ /* All registered clients have been 'shutdown'. Set NodeState to "shutdown" */
+ case NsmNodeState_ShuttingDown:
+ if (!NSMA__ParallelClientHasPendingActiveCall(0))
+ {
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Informed all registered clients about 'shutdown'. Set NodeState to 'shutdown'."));
+ /* Store the last NodeState, before switching to the new one */
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Changed NodeState -"),
+ DLT_STRING(NODESTATE_STRING[NSM__enNodeState]), DLT_INT((gint) NSM__enNodeState), DLT_STRING("=>"),
+ DLT_STRING(NODESTATE_STRING[NsmNodeState_Shutdown]), DLT_INT((gint) NsmNodeState_Shutdown));
+
+ NSM__cancelCollectiveTimeoutThread();
+
+ NSM__enNodeState = NsmNodeState_Shutdown;
+ NsmcSetData(NsmDataType_NodeState, (unsigned char*) &NSM__enNodeState, sizeof(NsmNodeState_e));
+ NSMA_boSendNodeStateSignal(NSM__enNodeState);
+ }
+ g_mutex_unlock(&NSM__pNodeStateMutex);
+ break;
+
+ default:
+ NSM__cancelCollectiveTimeoutThread();
+ NSM__startCollectiveTimeoutThread(NSM_SHUTDOWNTYPE_PARALLEL | NSM_SHUTDOWNTYPE_RUNUP);
+ g_mutex_unlock(&NSM__pNodeStateMutex);
+ NSM__vCallParallelLifecycleClient(TRUE);
+ break;
+ }
+ }
+ }
+ else
{
+ g_mutex_unlock(&NSM__pNodeStateMutex);
+ }
+}
+
+static void reportPendingCall(size_t clientID, char* reason)
+{
+ if(NSMA__ParallelClientHasPendingActiveCall(clientID))
+ DLT_LOG(NsmaContext, DLT_LOG_INFO, DLT_STRING("NSM: Will NOT inform client"), DLT_INT64(clientID),
+ DLT_STRING("about"), DLT_STRING(reason), DLT_STRING("yet, as there is still a (valid) pending lifecycle call!"));
+ else
+ DLT_LOG(NsmaContext, DLT_LOG_INFO, DLT_STRING("NSM: Will NOT inform client"), DLT_INT64(clientID),
+ DLT_STRING("about"), DLT_STRING(reason), DLT_STRING("yet, as there is still a (timed out) pending lifecycle call!"));
+}
+
+/**********************************************************************************************************************
+*
+* The function is called when:
+* - A shutdown is active before the "normal/sequential" clients
+* - A runup is active after all "normal/sequential" clients have been notified and finished
+*
+* If the clients need to "run up" or shut down for the current NodeState, the function
+* searches the list until a client is found, which needs to be informed and supports parallel shutdown.
+*
+* @return void
+*
+**********************************************************************************************************************/
+static void NSM__vCallParallelLifecycleClient(gboolean verbose)
+{
+ int arrayIndex = 0;
+ NSM__tstLifecycleClient *pClient = NULL; /* Client object from list */
+ GList *pListEntry = NULL; /* Iterate through list entries */
+ g_mutex_lock(&NSM__pNodeStateMutex);
+
+ /*
+ * Allocate a array which can hold all clients.
+ * Note: An array is needed to have a generic C(glib-2.0)/C++11 independent container.
+ * This way it is possible to pass it to NSMA_boCallParallelLcClientsRequest which internally converts it to
+ * a CommonAPI::ClientIdList
+ * */
+ NSM__tstLifecycleClient *pParallelLifecycleClients = alloca(sizeof(NSM__tstLifecycleClient) * g_list_length(NSM__pLifecycleClients));
+ memset(pParallelLifecycleClients, 0, sizeof(NSM__tstLifecycleClient) * g_list_length(NSM__pLifecycleClients));
+ if (!NSMA__SequentialClientHasPendingActiveCall())
+ {
+ switch (NSM__enNodeState)
+ {
+ case NsmNodeState_Shutdown: break;
/* For "shutdown" search backward in the list, until there is a client that has not been shut down */
case NsmNodeState_ShuttingDown:
- u32ShutdownType = NSM_SHUTDOWNTYPE_NORMAL;
- for( pListEntry = g_list_last(NSM__pLifecycleClients);
- (pListEntry != NULL) && (NSM__pCurrentLifecycleClient == NULL);
- pListEntry = g_list_previous(pListEntry))
+ NSM__uiShutdownType = NSM_SHUTDOWNTYPE_NORMAL | NSM_SHUTDOWNTYPE_PARALLEL;
+ for (pListEntry = g_list_first(NSM__pLifecycleClients); pListEntry != NULL; pListEntry = g_list_next(pListEntry))
{
- /* Check if client has not been shut down and is registered for "normal shutdown" */
+ /* Check if client has not shut down and is registered for "normal/parallel shutdown" then add him to the array */
pClient = (NSM__tstLifecycleClient*) pListEntry->data;
- if( ( pClient->boShutdown == FALSE)
- && ( (pClient->u32RegisteredMode & u32ShutdownType) != 0 ))
+ if ((pClient->boShutdown == FALSE)
+ && ((pClient->u32RegisteredMode & NSM_SHUTDOWNTYPE_PARALLEL) != 0)
+ && ((pClient->u32RegisteredMode & NSM_SHUTDOWNTYPE_NORMAL) != 0))
{
- /* Found a "running" previous client, registered for the shutdown mode */
- NSM__pCurrentLifecycleClient = (NSM__tstLifecycleClient*) pListEntry->data;
+ if (!pClient->boPendingCall)
+ {
+ /* Remember that client received a run-up or shutdown call */
+ pClient->boShutdown = TRUE;
+ pClient->boPendingCall = TRUE;
+ memcpy(&pParallelLifecycleClients[arrayIndex], pClient, sizeof(NSM__tstLifecycleClient));
+ arrayIndex++;
+ }
+ else if(verbose)
+ {
+ reportPendingCall(pClient->clientHash, "parallel shutdown");
+ }
}
}
- break;
-
- /* For "fast shutdown" search backward in the list, until there is a client that has not been shut down */
+ break;
+ /* For "fast shutdown" search backward in the list, until there is a client that has not been shut down */
case NsmNodeState_FastShutdown:
- u32ShutdownType = NSM_SHUTDOWNTYPE_FAST;
- for( pListEntry = g_list_last(NSM__pLifecycleClients);
- (pListEntry != NULL) && (NSM__pCurrentLifecycleClient == NULL);
- pListEntry = g_list_previous(pListEntry))
+ NSM__uiShutdownType = NSM_SHUTDOWNTYPE_FAST | NSM_SHUTDOWNTYPE_PARALLEL;
+ for (pListEntry = g_list_first(NSM__pLifecycleClients); pListEntry != NULL; pListEntry = g_list_next(pListEntry))
{
- /* Check if client has not been shut down and is registered for "fast shutdown" */
+ /* Check if client has not shut down and is registered for "fast/parallel shutdown" then add him to the array */
pClient = (NSM__tstLifecycleClient*) pListEntry->data;
- if( ( pClient->boShutdown == FALSE)
- && ( (pClient->u32RegisteredMode & u32ShutdownType) != 0 ))
+ if ((pClient->boShutdown == FALSE)
+ && ((pClient->u32RegisteredMode & NSM_SHUTDOWNTYPE_PARALLEL) != 0)
+ && ((pClient->u32RegisteredMode & NSM_SHUTDOWNTYPE_FAST) != 0))
{
- /* Found a "running" previous client, registered for the shutdown mode */
- NSM__pCurrentLifecycleClient = (NSM__tstLifecycleClient*) pListEntry->data;
+ if (!pClient->boPendingCall)
+ {
+ /* Remember that client received a run-up or shutdown call */
+ pClient->boShutdown = TRUE;
+ pClient->boPendingCall = TRUE;
+ memcpy(&pParallelLifecycleClients[arrayIndex], pClient, sizeof(NSM__tstLifecycleClient));
+ arrayIndex++;
+ }
+ else if(verbose)
+ {
+ reportPendingCall(pClient->clientHash, "parallel fast shutdown");
+ }
}
}
- break;
-
- /* For a "running" mode search forward in the list (get next), until there is a client that is shut down */
+ break;
default:
- u32ShutdownType = NSM_SHUTDOWNTYPE_RUNUP;
- for(pListEntry = g_list_first(NSM__pLifecycleClients);
- (pListEntry != NULL) && (NSM__pCurrentLifecycleClient == NULL);
- pListEntry = g_list_next(pListEntry))
+ NSM__uiShutdownType = NSM_SHUTDOWNTYPE_RUNUP | NSM_SHUTDOWNTYPE_PARALLEL;
+ for (pListEntry = g_list_first(NSM__pLifecycleClients); pListEntry != NULL; pListEntry = g_list_next(pListEntry))
{
- /* Check if client is shut down */
+ /* Check if client has shut down and is registered for "parallel shutdown" then add him to the array */
pClient = (NSM__tstLifecycleClient*) pListEntry->data;
- if(pClient->boShutdown == TRUE)
+ if ((pClient->boShutdown == TRUE)
+ && ((pClient->u32RegisteredMode & NSM_SHUTDOWNTYPE_PARALLEL) != 0))
{
- /* The client was shutdown. It should run up, because we are in a running mode */
- NSM__pCurrentLifecycleClient = (NSM__tstLifecycleClient*) pListEntry->data;
+ if (!pClient->boPendingCall)
+ {
+ /* Remember that client received a run-up or shutdown call */
+ pClient->boShutdown = FALSE;
+ pClient->boPendingCall = TRUE;
+ memcpy(&pParallelLifecycleClients[arrayIndex], pClient, sizeof(NSM__tstLifecycleClient));
+ arrayIndex++;
+ }
+ else if(verbose)
+ {
+ reportPendingCall(pClient->clientHash, "parallel runup");
+ }
}
}
- break;
+ }
}
/* Check if a client could be found that needs to be informed */
- if(NSM__pCurrentLifecycleClient != NULL)
+ if (arrayIndex > 0)
{
- DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Call lifecycle client." ),
- DLT_STRING(" Bus name: "), DLT_STRING(NSM__pCurrentLifecycleClient->sBusName ),
- DLT_STRING(" Obj name: "), DLT_STRING(NSM__pCurrentLifecycleClient->sObjName ),
- DLT_STRING(" Registered types: "), DLT_INT(NSM__pCurrentLifecycleClient->u32RegisteredMode),
- DLT_STRING(" Client: "), DLT_INT( (guint) NSM__pCurrentLifecycleClient->hClient ),
- DLT_STRING(" ShutdownType: "), DLT_UINT(u32ShutdownType ));
-
- /* Remember that client received a run-up or shutdown call */
- pClient->boShutdown = (u32ShutdownType != NSM_SHUTDOWNTYPE_RUNUP);
-
- NSM__vLtProf(NSM__pCurrentLifecycleClient->sBusName, NSM__pCurrentLifecycleClient->sObjName, u32ShutdownType, "enter: ", 0);
-
- NSMA_boCallLcClientRequest(NSM__pCurrentLifecycleClient->hClient, u32ShutdownType);
- boShutdown = FALSE;
+ g_mutex_unlock(&NSM__pNodeStateMutex);
+ NSMA_boCallParallelLcClientsRequest(pParallelLifecycleClients, arrayIndex, NSM__uiShutdownType);
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Informed"), DLT_INT(arrayIndex), DLT_STRING("clients!"),
+ DLT_STRING("ShutdownType:"), DLT_UINT(NSM__uiShutdownType));
}
- else
+ else if (!NSMA__SequentialClientHasPendingActiveCall() && !NSMA__ParallelClientHasPendingActiveCall(0))
{
/* The last client was called. Depending on the NodeState check if we can end. */
- switch(NSM__enNodeState)
+ switch (NSM__enNodeState)
{
- /* All registered clients have been 'fast shutdown'. Set NodeState to "shutdown" */
- case NsmNodeState_FastShutdown:
- DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Informed all registered clients about 'fast shutdown'. Set NodeState to 'shutdown'"));
-
- NSM__enNodeState = NsmNodeState_Shutdown;
- NsmcSetData(NsmDataType_NodeState, (unsigned char*) &NSM__enNodeState, sizeof(NsmNodeState_e));
- NSMA_boSendNodeStateSignal(NSM__enNodeState);
- boShutdown = TRUE;
+ case NsmNodeState_Shutdown:
+ g_mutex_unlock(&NSM__pNodeStateMutex);
break;
+ case NsmNodeState_FastShutdown:
+ case NsmNodeState_ShuttingDown:
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: No more parallel clients pending (for this lifecycle)"));
- /* All registered clients have been 'shutdown'. Set NodeState to "shutdown" */
- case NsmNodeState_ShuttingDown:
- DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Informed all registered clients about 'shutdown'. Set NodeState to 'shutdown'."));
+ size_t shutdownType = (NSM__enNodeState == NsmNodeState_FastShutdown) ? NSM_SHUTDOWNTYPE_FAST : NSM_SHUTDOWNTYPE_NORMAL;
- NSM__enNodeState = NsmNodeState_Shutdown;
- NsmcSetData(NsmDataType_NodeState, (unsigned char*) &NSM__enNodeState, sizeof(NsmNodeState_e));
- NSMA_boSendNodeStateSignal(NSM__enNodeState);
- boShutdown = TRUE;
+ NSM__cancelCollectiveTimeoutThread();
+ NSM__startCollectiveTimeoutThread(shutdownType);
+ g_mutex_unlock(&NSM__pNodeStateMutex);
+
+ NSM__vCallNextLifecycleClient();
break;
+ /* We are in a running state. */
+ default:
+ NSM__cancelCollectiveTimeoutThread();
- /* We are in a running state. Nothing to do */
- default:
- boShutdown = FALSE;
+ if (NSM__enNodeState == NsmNodeState_Resume)
+ {
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Informed all registered clients about 'resume'. Set NodeState to 'NsmNodeState_FullyOperational'."));
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Changed NodeState -"),
+ DLT_STRING(NODESTATE_STRING[NSM__enNodeState]), DLT_INT((gint) NSM__enNodeState), DLT_STRING("=>"),
+ DLT_STRING(NODESTATE_STRING[NsmNodeState_FullyOperational]), DLT_INT((gint) NsmNodeState_FullyOperational));
+ NSM__enNodeState = NsmNodeState_FullyOperational;
+ NsmcSetData(NsmDataType_NodeState, (unsigned char*) &NSM__enNodeState, sizeof(NsmNodeState_e));
+ NSMA_boSendNodeStateSignal(NsmNodeState_FullyOperational);
+ }
+ g_mutex_unlock(&NSM__pNodeStateMutex);
break;
}
}
-
- g_mutex_unlock(NSM__pNodeStateMutex);
-
- if(boShutdown == TRUE)
+ else
{
- NSMA_boQuitEventLoop();
+ g_mutex_unlock(&NSM__pNodeStateMutex);
}
}
@@ -1542,7 +1842,7 @@ static void NSM__vCallNextLifecycleClient(void)
* The callback is called when a check for LUC is required.
* It uses the NodeStateMachine to determine whether LUC is required.
*
-* @param pboRetVal: Pointer, where to store the StateMAchine's return value
+* @return Boolean if luc is required according to StateMAchine
*
**********************************************************************************************************************/
static gboolean NSM__boOnHandleCheckLucRequired(void)
@@ -1558,7 +1858,7 @@ static gboolean NSM__boOnHandleCheckLucRequired(void)
* It sets the BootMode using an internal function.
*
* @param i32BootMode: New boot mode
-* @param penRetVal: Pointer, where to store the return value
+* @return: Status of method call. (NsmErrorStatus_e)
*
**********************************************************************************************************************/
static NsmErrorStatus_e NSM__enOnHandleSetBootMode(const gint i32BootMode)
@@ -1574,30 +1874,14 @@ static NsmErrorStatus_e NSM__enOnHandleSetBootMode(const gint i32BootMode)
* It sets the NodeState using an internal function.
*
* @param enNodeStateId: New node state
-* @param penRetVal: Pointer, where to store the return value
+* @return: Status of method call. (NsmErrorStatus_e)
*
**********************************************************************************************************************/
static NsmErrorStatus_e NSM__enOnHandleSetNodeState(const NsmNodeState_e enNodeState)
{
- return NSM__enSetNodeState(enNodeState, TRUE, TRUE);
+ return NSM__enSetNodeState(enNodeState, TRUE, TRUE, TRUE);
}
-
-/**********************************************************************************************************************
-*
-* The callback is called when the "application mode" should be set.
-* It sets the ApplicationMode using an internal function.
-*
-* @param enApplicationModeId: New application mode
-* @param penRetVal: Pointer, where to store the return value
-*
-**********************************************************************************************************************/
-static NsmErrorStatus_e NSM__enOnHandleSetApplicationMode(const NsmApplicationMode_e enApplMode)
-{
- return NSM__enSetApplicationMode(enApplMode, TRUE, TRUE);
-}
-
-
/**********************************************************************************************************************
*
* The callback is called when the node reset is requested.
@@ -1605,7 +1889,7 @@ static NsmErrorStatus_e NSM__enOnHandleSetApplicationMode(const NsmApplicationMo
*
* @param i32RestartReason: Restart reason
* @param i32RestartType: Restart type
-* @param penRetVal: Pointer, where to store the return value
+* @return: Status of method call. (NsmErrorStatus_e)
*
**********************************************************************************************************************/
static NsmErrorStatus_e NSM__enOnHandleRequestNodeRestart(const NsmRestartReason_e enRestartReason,
@@ -1614,6 +1898,9 @@ static NsmErrorStatus_e NSM__enOnHandleRequestNodeRestart(const NsmRestartReason
NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet;
DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Node restart has been requested."));
+ g_mutex_lock(&NSM__pNodeStateMutex);
+ NSM__boResetActive = TRUE;
+ g_mutex_unlock(&NSM__pNodeStateMutex);
if(NsmcRequestNodeRestart(enRestartReason, u32RestartType) == 0x01)
{
@@ -1639,7 +1926,7 @@ static NsmErrorStatus_e NSM__enOnHandleRequestNodeRestart(const NsmRestartReason
* @param sSessionOwner: Owner of the new session
* @param enSeatId: Seat which belongs to the new session
* @param enSessionState: Initial state of the new session
-* @param penRetVal: Pointer, where to store the return value
+* @return: Status of method call. (NsmErrorStatus_e)
*
**********************************************************************************************************************/
static NsmErrorStatus_e NSM__enOnHandleRegisterSession(const gchar *sSessionName,
@@ -1677,8 +1964,8 @@ static NsmErrorStatus_e NSM__enOnHandleRegisterSession(const gchar *
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 ));
+ DLT_STRING("Seat:" ), DLT_STRING(SEAT_STRING[enSeatId] ),
+ DLT_STRING("Initial state:"), DLT_STRING(SESSIONSTATE_STRING[enSessionState]));
}
return enRetVal;
@@ -1694,7 +1981,7 @@ static NsmErrorStatus_e NSM__enOnHandleRegisterSession(const gchar *
* @param sSessionName: Name of the new session that should be unregistered.
* @param sSessionOwner: Current owner of the session that should be unregistered.
* @param enSeat: Seat for which the session should be unregistered.
-* @param penRetVal: Pointer, where to store the return value
+* @return: Status of method call. (NsmErrorStatus_e)
*
**********************************************************************************************************************/
static NsmErrorStatus_e NSM__enOnHandleUnRegisterSession(const gchar *sSessionName,
@@ -1704,7 +1991,7 @@ static NsmErrorStatus_e NSM__enOnHandleUnRegisterSession(const gchar *sSessi
/* Function local variables */
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 */
+ NsmSession_s stSearchSession = {{0}, {0}, 0, 0}; /* To search for existing session */
NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet;
/* Check if the passed parameters are valid */
@@ -1723,17 +2010,31 @@ static NsmErrorStatus_e NSM__enOnHandleUnRegisterSession(const gchar *sSessi
}
else
{
- /* Error: Invalid parameter. The session or owner name is to long. */
+ /* Error: Invalid parameter. The session or owner name is too long. */
enRetVal = NsmErrorStatus_Parameter;
- DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to unregister session. The session or owner name is to long."),
- DLT_STRING(" Name: " ), DLT_STRING(sSessionName ),
- DLT_STRING(" Owner: " ), DLT_STRING(sSessionOwner ),
- DLT_STRING(" Seat: " ), DLT_INT((gint) enSeatId ));
+ DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to unregister session. The session or owner name is too long."),
+ DLT_STRING("Name:" ), DLT_STRING(sSessionName ),
+ DLT_STRING("Owner:" ), DLT_STRING(sSessionOwner ),
+ DLT_STRING("Seat:" ), DLT_STRING(SEAT_STRING[enSeatId] ));
}
return enRetVal;
}
+static void NSM__adjustMaxParallelTimeout()
+{
+ GList *clientIter;
+ /* Reset max parallel timeout ... */
+ NSM__max_parallel_timeout = 0;
+ for (clientIter = NSM__pLifecycleClients; clientIter != NULL; clientIter = clientIter->next)
+ {
+ NSM__tstLifecycleClient *client = (NSM__tstLifecycleClient*) clientIter->data;
+ if ((client->u32RegisteredMode & NSM_SHUTDOWNTYPE_PARALLEL) && client->timeout > NSM__max_parallel_timeout)
+ {
+ NSM__max_parallel_timeout = ((NSM__tstLifecycleClient*) clientIter->data)->timeout;
+ }
+ }
+}
/**********************************************************************************************************************
*
@@ -1741,16 +2042,15 @@ static NsmErrorStatus_e NSM__enOnHandleUnRegisterSession(const gchar *sSessi
* In the list of lifecycle clients it will be checked if the client already exists.
* If it exists, it's settings will be updated. Otherwise a new client will be created.
*
-* @param sBusName: Bus name of the remote application that hosts the lifecycle client interface
-* @param sObjName: Object name of the lifecycle client
+* @param clientHash: Hash of the lifecycle client. Used for identification.
+* @param client: Object of the lifecycle client
* @param u32ShutdownMode: Shutdown mode for which the client wants to be informed
* @param u32TimeoutMs: Timeout in ms. If the client does not return after the specified time, the NSM
* aborts its shutdown and calls the next client.
-* @param penRetVal: Pointer, where to store the return value
+* @return: Status of method call. (NsmErrorStatus_e)
*
**********************************************************************************************************************/
-static NsmErrorStatus_e NSM__enOnHandleRegisterLifecycleClient(const gchar *sBusName,
- const gchar *sObjName,
+static NsmErrorStatus_e NSM__enOnHandleRegisterLifecycleClient(const size_t clientHash,
const guint u32ShutdownMode,
const guint u32TimeoutMs)
{
@@ -1758,72 +2058,102 @@ static NsmErrorStatus_e NSM__enOnHandleRegisterLifecycleClient(const gchar *sBus
NSM__tstLifecycleClient *pstNewClient = NULL;
NSM__tstLifecycleClient *pstExistingClient = NULL;
GList *pListEntry = NULL;
- NSMA_tLcConsumerHandle *hConsumer = NULL;
- GError *pError = NULL;
+ guint timeout = u32TimeoutMs;
NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet;
/* The parameters are valid. Create a temporary client to search the list */
- stTestLifecycleClient.sBusName = (gchar*) sBusName;
- stTestLifecycleClient.sObjName = (gchar*) sObjName;
+ stTestLifecycleClient.clientHash = clientHash;
/* Check if the lifecycle client already is registered */
pListEntry = g_list_find_custom(NSM__pLifecycleClients, &stTestLifecycleClient, &NSM__i32LifecycleClientCompare);
- if(pListEntry == NULL)
+ /* Allow a maximal timeout of 60 seconds */
+ if (60000 < timeout)
{
- /* The client does not exist. Try to create a new proxy */
- hConsumer = NSMA_hCreateLcConsumer(sBusName, sObjName, u32TimeoutMs);
-
- /* The new proxy could be created. Create and store new client */
- if(hConsumer != NULL)
- {
- enRetVal = NsmErrorStatus_Ok;
+ DLT_LOG(NsmContext, DLT_LOG_WARN, DLT_STRING("NSM: Client specified timeout greater 60 seconds. ClientID:"), DLT_UINT64(clientHash));
+ timeout = 60000;
+ }
- /* Create client object and copies of the strings. */
- pstNewClient = g_new0(NSM__tstLifecycleClient, 1);
- pstNewClient->u32RegisteredMode = u32ShutdownMode;
- pstNewClient->sBusName = g_strdup(sBusName);
- pstNewClient->sObjName = g_strdup(sObjName);
- pstNewClient->boShutdown = FALSE;
- pstNewClient->hClient = hConsumer;
+ if (pListEntry == NULL)
+ {
+ enRetVal = NsmErrorStatus_Ok;
+ /* Create client object and copies of the strings. */
+ pstNewClient = g_new0(NSM__tstLifecycleClient, 1);
+ pstNewClient->u32RegisteredMode = u32ShutdownMode;
+ pstNewClient->clientHash = clientHash;
+ pstNewClient->boShutdown = FALSE;
+ pstNewClient->timeout = timeout;
+ pstNewClient->boPendingCall = FALSE;
- /* Append the new client to the list */
- NSM__pLifecycleClients = g_list_append(NSM__pLifecycleClients, pstNewClient);
+ if(!(pstNewClient->u32RegisteredMode & NSM_SHUTDOWNTYPE_PARALLEL))
+ {
+ NSM__collective_sequential_timeout += timeout;
+ }
+ else if(timeout > NSM__max_parallel_timeout)
+ {
+ NSM__max_parallel_timeout = timeout;
+ }
- DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Registered new lifecycle consumer." ),
- DLT_STRING(" Bus name: "), DLT_STRING(pstNewClient->sBusName ),
- DLT_STRING(" Obj name: "), DLT_STRING(pstNewClient->sObjName ),
- DLT_STRING(" Timeout: " ), DLT_UINT( u32TimeoutMs ),
- DLT_STRING(" Mode(s): "), DLT_INT( pstNewClient->u32RegisteredMode),
- DLT_STRING(" Client: "), DLT_UINT((guint) pstNewClient->hClient ));
- }
- else
- {
- enRetVal = NsmErrorStatus_Dbus;
- DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Failed to register new lifecycle consumer. D-Bus error."),
- DLT_STRING(" Bus name: "), DLT_STRING(sBusName ),
- DLT_STRING(" Obj name: "), DLT_STRING(sObjName ),
- DLT_STRING(" Timeout: " ), DLT_UINT( u32TimeoutMs ),
- DLT_STRING(" Registered mode(s): "), DLT_INT( u32ShutdownMode ),
- DLT_STRING(" Error: "), DLT_STRING(pError->message ));
-
- g_error_free(pError);
- }
+ /* Append the new client to the list */
+ NSM__pLifecycleClients = g_list_append(NSM__pLifecycleClients, pstNewClient);
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Registered new lifecycle consumer." ),
+ DLT_STRING("ClientID:"), DLT_UINT64(pstNewClient->clientHash ),
+ DLT_STRING("Timeout:"), DLT_UINT( timeout ),
+ DLT_STRING("Mode(s):"), DLT_INT( pstNewClient->u32RegisteredMode));
}
else
{
/* The client already exists. Assert to update the values for timeout and mode */
- enRetVal = NsmErrorStatus_Ok;
+ enRetVal = NsmErrorStatus_Last;
+
pstExistingClient = (NSM__tstLifecycleClient*) pListEntry->data;
+
+ guint oldShutdownMode = pstExistingClient->u32RegisteredMode;
+ guint oldTimeout = pstExistingClient->timeout;
+
pstExistingClient->u32RegisteredMode |= u32ShutdownMode;
- NSMA_boSetLcClientTimeout(pstExistingClient->hClient, u32TimeoutMs);
- DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Changed lifecycle consumer registration." ),
- DLT_STRING(" Bus name: "), DLT_STRING(pstExistingClient->sBusName ),
- DLT_STRING(" Obj name: "), DLT_STRING(pstExistingClient->sObjName ),
- DLT_STRING(" Timeout: " ), DLT_UINT( u32TimeoutMs ),
- DLT_STRING(" Registered mode(s): "), DLT_INT( pstExistingClient->u32RegisteredMode));
+ if(timeout != 0)
+ {
+ pstExistingClient->timeout = timeout;
+
+ if(pstExistingClient->u32RegisteredMode != 0)
+ {
+ /* If client has been registered for sequential events and is now registered for parallel events */
+ if(!(oldShutdownMode & NSM_SHUTDOWNTYPE_PARALLEL) && (pstExistingClient->u32RegisteredMode & NSM_SHUTDOWNTYPE_PARALLEL))
+ {
+ NSM__collective_sequential_timeout -= oldTimeout;
+ }
+
+ if(!(pstExistingClient->u32RegisteredMode & NSM_SHUTDOWNTYPE_PARALLEL))
+ {
+ NSM__collective_sequential_timeout -= oldShutdownMode;
+ NSM__collective_sequential_timeout += timeout;
+ }
+ /* else if client is parallel one and timeout is the biggest */
+ else if(timeout > NSM__max_parallel_timeout)
+ {
+ NSM__max_parallel_timeout = timeout;
+ }
+ /* else if client is parallel one and his previous timeout has been biggest and now it is smaller */
+ else if(oldTimeout == NSM__max_parallel_timeout && timeout < NSM__max_parallel_timeout)
+ {
+ /* ... and search which parallel client now has the biggest timeout */
+ NSM__adjustMaxParallelTimeout();
+ }
+ }
+ }
+
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Changed lifecycle consumer registration." ),
+ DLT_STRING("ClientID:"), DLT_UINT64(pstExistingClient->clientHash ),
+ DLT_STRING("Timeout:"), DLT_UINT(pstExistingClient->timeout ),
+ DLT_STRING("Registered mode(s):"), DLT_INT(pstExistingClient->u32RegisteredMode ));
+ }
+
+ if(120000 < (NSM__collective_sequential_timeout + NSM__max_parallel_timeout) && 0 < timeout)
+ {
+ DLT_LOG(NsmContext, DLT_LOG_WARN, DLT_STRING("NSM: Collective timeout greater 120 seconds"));
}
return enRetVal;
@@ -1837,23 +2167,20 @@ static NsmErrorStatus_e NSM__enOnHandleRegisterLifecycleClient(const gchar *sBus
* client is found, the registration for the passed shutdown modes will be removed. If the client finally
* is not registered for any shutdown mode, its entry will be removed from the list.
*
-* @param sBusName: Bus name of the remote application that hosts the lifecycle client interface
-* @param sObjName: Object name of the lifecycle client
+* @param clientHash: Hash of the lifecycle client. Used for identification.
* @param u32ShutdownMode: Shutdown mode for which the client wants to unregister
-* @param penRetVal: Pointer, where to store the return value
+* @return: Status of method call. (NsmErrorStatus_e)
*
**********************************************************************************************************************/
-static NsmErrorStatus_e NSM__enOnHandleUnRegisterLifecycleClient(const gchar *sBusName,
- const gchar *sObjName,
- const guint u32ShutdownMode)
+static NsmErrorStatus_e NSM__enOnHandleUnRegisterLifecycleClient(const size_t clientHash,
+ const guint u32ShutdownMode)
{
NSM__tstLifecycleClient *pstExistingClient = NULL;
NSM__tstLifecycleClient stSearchClient = {0};
GList *pListEntry = NULL;
NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet;
- stSearchClient.sBusName = (gchar*) sBusName;
- stSearchClient.sObjName = (gchar*) sObjName;
+ stSearchClient.clientHash = clientHash;
/* Check if the lifecycle client already is registered */
pListEntry = g_list_find_custom(NSM__pLifecycleClients, &stSearchClient, &NSM__i32LifecycleClientCompare);
@@ -1864,30 +2191,44 @@ static NsmErrorStatus_e NSM__enOnHandleUnRegisterLifecycleClient(const gchar *sB
/* The client could be found in the list. Change the registered shutdown mode */
enRetVal = NsmErrorStatus_Ok;
pstExistingClient = (NSM__tstLifecycleClient*) pListEntry->data;
+ guint oldShutdownMode = pstExistingClient->u32RegisteredMode;
pstExistingClient->u32RegisteredMode &= ~(u32ShutdownMode);
- DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Unregistered lifecycle consumer for mode(s)." ),
- DLT_STRING(" Bus name: "), DLT_STRING(pstExistingClient->sBusName ),
- DLT_STRING(" Obj name: "), DLT_STRING(pstExistingClient->sObjName ),
- DLT_STRING(" New mode: "), DLT_INT( pstExistingClient->u32RegisteredMode),
- DLT_STRING(" Client: " ), DLT_UINT((guint) pstExistingClient->hClient) );
+ /* If client has been registered for parallel events and is now registered for sequential events */
+ if((oldShutdownMode & NSM_SHUTDOWNTYPE_PARALLEL) && !(pstExistingClient->u32RegisteredMode & NSM_SHUTDOWNTYPE_PARALLEL) )
+ {
+ if(pstExistingClient->timeout == NSM__max_parallel_timeout)
+ {
+ NSM__adjustMaxParallelTimeout();
+ }
+ /* If client is still registered for anything */
+ if(pstExistingClient->u32RegisteredMode)
+ {
+ NSM__collective_sequential_timeout += pstExistingClient->timeout;
+ }
+ }
+ /* If client is sequential and still registered for anything */
+ else if(!(pstExistingClient->u32RegisteredMode & NSM_SHUTDOWNTYPE_PARALLEL) && !pstExistingClient->u32RegisteredMode)
+ {
+ NSM__collective_sequential_timeout -= pstExistingClient->timeout;
+ }
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Unregistered lifecycle consumer for mode(s)." ),
+ DLT_STRING("Client hash:"), DLT_UINT64(pstExistingClient->clientHash),
+ DLT_STRING("New mode:"), DLT_INT(pstExistingClient->u32RegisteredMode));
if(pstExistingClient->u32RegisteredMode == NSM_SHUTDOWNTYPE_NOT)
{
+ NSMA_boDeleteLifecycleClient(pstExistingClient);
/* The client is not registered for at least one mode. Remove it from the list */
- NSM__vFreeLifecycleClientObject(pstExistingClient);
NSM__pLifecycleClients = g_list_remove(NSM__pLifecycleClients, pstExistingClient);
+ NSM__vFreeLifecycleClientObject(pstExistingClient);
}
}
else
{
/* Warning: The client could not be found in the list of clients. */
enRetVal = NsmErrorStatus_Parameter;
- DLT_LOG(NsmContext, DLT_LOG_WARN, DLT_STRING("NSM: Failed to unregister lifecycle consumer."),
- DLT_STRING(" Bus name: "), DLT_STRING(sBusName),
- DLT_STRING(" Obj name: "), DLT_STRING(sObjName),
- DLT_STRING(" Unregistered mode(s): "), DLT_INT( u32ShutdownMode));
- }
+ }
return enRetVal;
}
@@ -1903,7 +2244,7 @@ static NsmErrorStatus_e NSM__enOnHandleUnRegisterLifecycleClient(const gchar *sB
* @param sSessionName: Owner of the session whose state just be returned
* @param enSeatId: Seat of the session
* @param penSessionState: Pointer where to store the session state
-* @param penRetVal: Pointer where to store the return value
+* @return: Status of method call. (NsmErrorStatus_e)
*
**********************************************************************************************************************/
static NsmErrorStatus_e NSM__enOnHandleGetSessionState(const gchar *sSessionName,
@@ -1913,7 +2254,7 @@ static NsmErrorStatus_e NSM__enOnHandleGetSessionState(const gchar *sSessi
/* Function local variables */
NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet;
glong u32SessionNameLen = 0; /* Length of passed session owner */
- NsmSession_s stSearchSession = {0}; /* To search for existing session */
+ NsmSession_s stSearchSession = {{0}, {0}, 0, 0}; /* To search for existing session */
/* Check if the passed parameters are valid */
u32SessionNameLen = g_utf8_strlen(sSessionName, -1);
@@ -1929,11 +2270,11 @@ static NsmErrorStatus_e NSM__enOnHandleGetSessionState(const gchar *sSessi
}
else
{
- /* Error: Invalid parameter. The session or owner name is to long. */
+ /* Error: Invalid parameter. The session or owner name is too long. */
enRetVal = NsmErrorStatus_Parameter;
- DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to get session state. The session name is to long."),
- DLT_STRING(" Name: " ), DLT_STRING(sSessionName ),
- DLT_STRING(" Seat: " ), DLT_INT((gint) enSeatId ));
+ DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to get session state. The session name is too long."),
+ DLT_STRING("Name:" ), DLT_STRING(sSessionName ),
+ DLT_STRING("Seat:" ), DLT_STRING(SEAT_STRING[enSeatId ] ));
}
return enRetVal;
@@ -1950,7 +2291,7 @@ static NsmErrorStatus_e NSM__enOnHandleGetSessionState(const gchar *sSessi
* @param sSessionOwner: Owner of the session
* @param enSeatId: Seat of the session
* @param enSessionState: New state of the session
-* @param penRetVal: Pointer where to store the return value
+* @return: Status of method call. (NsmErrorStatus_e)
*
**********************************************************************************************************************/
static NsmErrorStatus_e NSM__enOnHandleSetSessionState(const gchar *sSessionName,
@@ -1960,9 +2301,9 @@ static NsmErrorStatus_e NSM__enOnHandleSetSessionState(const gchar *
{
/* Function local variables */
NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet;
- glong u32SessionNameLen = 0; /* Length of passed session owner */
- glong u32SessionOwnerLen = 0; /* Length of passed session name */
- NsmSession_s stSession = {0}; /* Session object passed to internal function */
+ glong u32SessionNameLen = 0; /* Length of passed session owner */
+ glong u32SessionOwnerLen = 0; /* Length of passed session name */
+ NsmSession_s stSession = {{0}, {0}, 0, 0}; /* Session object passed to internal function */
/* Check if the passed parameters are valid */
u32SessionNameLen = g_utf8_strlen(sSessionName, -1);
@@ -1982,12 +2323,12 @@ static NsmErrorStatus_e NSM__enOnHandleSetSessionState(const gchar *
}
else
{
- /* Error: Invalid parameter. The session or owner name is to long. */
+ /* Error: Invalid parameter. The session or owner name is too long. */
enRetVal = NsmErrorStatus_Parameter;
DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to set session state. Invalid parameter."),
- DLT_STRING(" Name: " ), DLT_STRING(sSessionName ),
- DLT_STRING(" Owner: " ), DLT_STRING(sSessionOwner ),
- DLT_STRING(" Seat: " ), DLT_INT((gint) enSeatId ));
+ DLT_STRING("Name:" ), DLT_STRING(sSessionName ),
+ DLT_STRING("Owner:" ), DLT_STRING(sSessionOwner ),
+ DLT_STRING("Seat:" ), DLT_STRING(SEAT_STRING[enSeatId] ));
}
return enRetVal;
@@ -2024,14 +2365,14 @@ static NsmErrorStatus_e NSM__enSetAppStateValid(NSM__tstFailedApplication* pstFa
NSM__vFreeFailedApplicationObject(pstExistingApplication);
DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: An application has become valid again." ),
- DLT_STRING(" Application: "), DLT_STRING(pstFailedApp->sName));
+ DLT_STRING("Application:"), DLT_STRING(pstFailedApp->sName));
}
else
{
/* Error: There was no session registered for the application that failed. */
enRetVal = NsmErrorStatus_Error;
DLT_LOG(NsmContext, DLT_LOG_WARN, DLT_STRING("NSM: Failed to set application valid. Application was never invalid."),
- DLT_STRING(" Application: "), DLT_STRING(pstFailedApp->sName ));
+ DLT_STRING("Application:"), DLT_STRING(pstFailedApp->sName ));
}
return enRetVal;
@@ -2051,12 +2392,12 @@ static void NSM__vDisableSessionsForApp(NSM__tstFailedApplication* pstFailedApp)
/* Function local variables */
GSList *pSessionListEntry = NULL;
NsmSession_s *pstExistingSession = NULL;
- NsmSession_s stSearchSession = {0};
+ NsmSession_s stSearchSession = {{0}, {0}, 0, 0};
/* Only set the "owner" of the session (to the AppName) to search for all sessions of the app. */
g_strlcpy(stSearchSession.sOwner, pstFailedApp->sName, sizeof(stSearchSession.sOwner));
- g_mutex_lock(NSM__pSessionMutex);
+ g_mutex_lock(&NSM__pSessionMutex);
pSessionListEntry = g_slist_find_custom(NSM__pSessions, &stSearchSession, &NSM__i32SessionOwnerCompare);
if(pSessionListEntry != NULL)
@@ -2072,10 +2413,10 @@ static void NSM__vDisableSessionsForApp(NSM__tstFailedApplication* pstFailedApp)
NSM__vPublishSessionChange(pstExistingSession, TRUE, TRUE);
DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: A session has become invalid, because an application failed."),
- DLT_STRING(" Application: "), DLT_STRING(pstExistingSession->sOwner ),
- DLT_STRING(" Session: "), DLT_STRING(pstExistingSession->sName ),
- DLT_STRING(" Seat: "), DLT_INT( pstExistingSession->enSeat ),
- DLT_STRING(" State: "), DLT_INT( pstExistingSession->enState ));
+ DLT_STRING("Application:"), DLT_STRING(pstExistingSession->sOwner ),
+ DLT_STRING("Session:"), DLT_STRING(pstExistingSession->sName ),
+ DLT_STRING("Seat:"), DLT_STRING(SEAT_STRING[pstExistingSession->enSeat]),
+ DLT_STRING("State:"), DLT_STRING(SESSIONSTATE_STRING[pstExistingSession->enState]));
/* Remove or "reset" session */
if(NSM__boIsPlatformSession(pstExistingSession) == TRUE)
@@ -2099,10 +2440,10 @@ static void NSM__vDisableSessionsForApp(NSM__tstFailedApplication* pstFailedApp)
{
/* There have been no session registered for this application. */
DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: There had been no registered sessions." ),
- DLT_STRING(" Application: "), DLT_STRING(pstFailedApp->sName));
+ DLT_STRING("Application:"), DLT_STRING(pstFailedApp->sName));
}
- g_mutex_unlock(NSM__pSessionMutex);
+ g_mutex_unlock(&NSM__pSessionMutex);
}
@@ -2142,7 +2483,7 @@ static NsmErrorStatus_e NSM__enSetAppStateFailed(NSM__tstFailedApplication* pstF
/* Warning: The application is already in the list of failed session. */
enRetVal = NsmErrorStatus_Ok;
DLT_LOG(NsmContext, DLT_LOG_WARN, DLT_STRING("NSM: The application has already been marked as 'failed'."),
- DLT_STRING(" Application: "), DLT_STRING(pstFailedApp->sName ));
+ DLT_STRING("Application:"), DLT_STRING(pstFailedApp->sName ));
}
return enRetVal;
@@ -2165,7 +2506,7 @@ static NsmErrorStatus_e NSM__enOnHandleSetAppHealthStatus(const gchar *sAppNa
const gboolean boAppState)
{
/* Function local variables */
- NSM__tstFailedApplication stSearchApplication = {0}; /* Temporary application object for search */
+ NSM__tstFailedApplication stSearchApplication = {{0}}; /* Temporary application object for search */
NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet;
/* Check if passed parameters are valid */
@@ -2188,8 +2529,8 @@ static NsmErrorStatus_e NSM__enOnHandleSetAppHealthStatus(const gchar *sAppNa
/* Error: The passed application name is too long. */
enRetVal = NsmErrorStatus_Parameter;
DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to set application health status. The application name is too long."),
- DLT_STRING(" Owner: " ), DLT_STRING(sAppName ),
- DLT_STRING(" State: " ), DLT_INT(boAppState ));
+ DLT_STRING("Owner:" ), DLT_STRING(sAppName ),
+ DLT_STRING("State:" ), DLT_STRING(SESSIONSTATE_STRING[boAppState] ));
}
@@ -2233,12 +2574,22 @@ static guint NSM__u32OnHandleGetInterfaceVersion(void)
* @return Always TRUE to keep timer callback alive.
*
**********************************************************************************************************************/
-static gboolean NSM__boOnHandleTimerWdog(gpointer pUserData)
+static void *NSM__boOnHandleTimerWdog(void *pUserData)
{
- (void) sd_notify(0, "WATCHDOG=1");
- DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Triggered systemd WDOG."));
-
- return TRUE;
+ while(!NSM__boEndByUser && NSMWatchdogIsHappy())
+ {
+ (void) sd_notify(0, "WATCHDOG=1");
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Sent heartbeat to systemd watchdog"));
+ usleep((unsigned int)NSM__WdogSec * 1000);
+ }
+
+ if(!NSM__boEndByUser)
+ {
+ DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Calling abort because of watchdog"));
+ abort(); // Don't trust on systemd timeout. Abort immediately
+ }
+
+ return NULL;
}
@@ -2250,26 +2601,29 @@ static gboolean NSM__boOnHandleTimerWdog(gpointer pUserData)
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);
+ NSM__WdogSec = 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)
+ if(NSM__WdogSec >= 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));
+ NSM__WdogSec /= 2000;
+#ifdef ENABLE_TESTS
+ NSM__WdogSec = 1000;
+#endif
+ if(!pthread_create(&NSM__watchdog_thread, NULL, NSM__boOnHandleTimerWdog, NULL)) {
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Started wdog timer." ),
+ DLT_STRING("Interval [ms]:"), DLT_UINT64(NSM__WdogSec));
+ }
+ else
+ {
+ DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to create watchdog thread"));
+ }
+
}
else
{
@@ -2292,18 +2646,10 @@ static void NSM__vConfigureWdogTimer(void)
static void NSM__vInitializeVariables(void)
{
/* Initialize file local variables */
- NSM__pSessionMutex = NULL;
NSM__pSessions = NULL;
NSM__pLifecycleClients = NULL;
- NSM__pNodeStateMutex = NULL;
NSM__enNodeState = NsmNodeState_NotSet;
- NSM__pNextApplicationModeMutex = NULL;
- NSM__pThisApplicationModeMutex = NULL;
NSM__pFailedApplications = NULL;
- NSM__pCurrentLifecycleClient = NULL;
- NSM__enNextApplicationMode = NsmApplicationMode_NotSet;
- NSM__enThisApplicationMode = NsmApplicationMode_NotSet;
- NSM__boThisApplicationModeRead = FALSE;
}
@@ -2337,51 +2683,19 @@ static void NSM__vCreatePlatformSessions(void)
}
}
-
-/**********************************************************************************************************************
-*
-* The function creates the mutexes used in the NSM.
-*
-**********************************************************************************************************************/
-static void NSM__vCreateMutexes(void)
-{
- /* Initialize the local mutexes */
- NSM__pNodeStateMutex = g_mutex_new();
- NSM__pThisApplicationModeMutex = g_mutex_new();
- NSM__pNextApplicationModeMutex = g_mutex_new();
- NSM__pSessionMutex = g_mutex_new();
-}
-
-
-/**********************************************************************************************************************
-*
-* The function deletes the mutexes used in the NSM.
-*
-**********************************************************************************************************************/
-static void NSM__vDeleteMutexes(void)
-{
- /* Delete the local mutexes */
- g_mutex_free(NSM__pNodeStateMutex);
- g_mutex_free(NSM__pNextApplicationModeMutex);
- g_mutex_free(NSM__pThisApplicationModeMutex);
- g_mutex_free(NSM__pSessionMutex);
-}
-
-
/**********************************************************************************************************************
*
* The function is called to trace a syslog message for a shutdown client.
*
-* @param sBus: Bus name of the shutdown client.
-* @param sObj: Object name of the lifecycle client.
+* @param client: Hash of the lifecycle client. Used for identification.
* @param u32Reason: Shutdown reason send to the client.
* @param sInOut: "enter" or "leave" (including failure reason)
* @param enErrorStatus: Error value
*
**********************************************************************************************************************/
-static void NSM__vLtProf(gchar *sBus, gchar *sObj, guint32 u32Reason, gchar *sInOut, NsmErrorStatus_e enErrorStatus)
+static void NSM__vLtProf(size_t client, guint32 u32Reason, gchar *sInOut, NsmErrorStatus_e enErrorStatus)
{
- gchar pszLtprof[128] = "LTPROF: bus:%s obj:%s (0x%08X:%d) ";
+ gchar pszLtprof[128] = "LTPROF: client:%Iu (0x%08X:%d) ";
guint32 dwLength = 128;
g_strlcat(pszLtprof, sInOut, dwLength);
@@ -2398,7 +2712,7 @@ static void NSM__vLtProf(gchar *sBus, gchar *sObj, guint32 u32Reason, gchar *sIn
}
}
- syslog(LOG_NOTICE, (char *)pszLtprof, sBus, sObj, u32Reason, enErrorStatus);
+ syslog(LOG_NOTICE, (char *)pszLtprof, client, u32Reason, enErrorStatus);
}
@@ -2443,14 +2757,7 @@ NsmErrorStatus_e NsmSetData(NsmDataType_e enData, unsigned char *pData, unsigned
/* NSMC wants to set the NodeState */
case NsmDataType_NodeState:
enRetVal = (u32DataLen == sizeof(NsmNodeState_e))
- ? NSM__enSetNodeState((NsmNodeState_e) *pData, TRUE, FALSE)
- : NsmErrorStatus_Parameter;
- break;
-
- /* NSMC wants to set the AppMode */
- case NsmDataType_AppMode:
- enRetVal = (u32DataLen == sizeof(NsmApplicationMode_e))
- ? NSM__enSetApplicationMode((NsmApplicationMode_e) *pData, TRUE, FALSE)
+ ? NSM__enSetNodeState((NsmNodeState_e) *pData, TRUE, FALSE, FALSE)
: NsmErrorStatus_Parameter;
break;
@@ -2488,10 +2795,24 @@ NsmErrorStatus_e NsmSetData(NsmDataType_e enData, unsigned char *pData, unsigned
? NSM__enUnRegisterSession((NsmSession_s*) pData, TRUE, FALSE)
: NsmErrorStatus_Parameter;
break;
+ case NsmDataType_RunningReason:
+ enRetVal = (u32DataLen == sizeof(NsmRunningReason_e))
+ ? NSMA_boSetRunningReason((NsmRunningReason_e) *pData)
+ : NsmErrorStatus_Parameter;
+ break;
+ case NsmDataType_RequestNodeRestart:
+ enRetVal = (u32DataLen == sizeof(NsmRestartReason_e))
+ ? NSM__enOnHandleRequestNodeRestart((NsmRestartReason_e) *pData, NSM_SHUTDOWNTYPE_FAST)
+ : NsmErrorStatus_Parameter;
+ break;
+ case NsmDataType_BlockExternalNodeState:
+ enRetVal = (u32DataLen == sizeof(bool))
+ ? NSM__enSetBlockExternalNodeState((bool) *pData)
+ : 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:
default:
enRetVal = NsmErrorStatus_Parameter;
break;
@@ -2522,17 +2843,6 @@ int NsmGetData(NsmDataType_e enData, unsigned char *pData, unsigned int u32DataL
}
break;
- /* NSMC wants to get the ApplicationMode */
- case NsmDataType_AppMode:
- if(u32DataLen == sizeof(NsmApplicationMode_e))
- {
- if(NSM__enGetApplicationMode((NsmApplicationMode_e*) pData) == NsmErrorStatus_Ok)
- {
- i32RetVal = sizeof(NsmApplicationMode_e);
- }
- }
- break;
-
/* NSMC wants to get the BootMode */
case NsmDataType_BootMode:
if(u32DataLen == sizeof(gint))
@@ -2597,55 +2907,56 @@ int NsmGetData(NsmDataType_e enData, unsigned char *pData, unsigned int u32DataL
return i32RetVal;
}
-
unsigned int NsmGetInterfaceVersion(void)
{
return NSM_INTERFACE_VERSION;
}
-
/* The main function of the NodeStateManager */
-int main(void)
+int main(int argc, char **argv)
{
- gboolean boEndByUser = FALSE;
- int pcl_return = 0;
+ NSMTriggerWatchdog(NsmWatchdogState_Active);
- /* Initialize glib for using "g" types */
- g_type_init();
+ GList *pListEntry = NULL;
+ NSM__tstLifecycleClient *pstExistingClient = NULL;
/* Register NSM for DLT */
- DLT_REGISTER_APP("NSM", "Node State Manager");
- DLT_REGISTER_CONTEXT(NsmContext, "005", "Context for the NSM");
+ DLT_REGISTER_APP("NSM", "Node State Manager|SysInfra|Lifecycle");
+
+ DLT_REGISTER_CONTEXT(NsmContext, "NSM", "Context for NSM");
+ DLT_REGISTER_CONTEXT(NsmaContext, "NSMA", "Context for NSMA");
+
+#ifdef ENABLE_TESTS
DLT_ENABLE_LOCAL_PRINT();
+#endif
+
+ int option_index = 0;
+ getopt_long (argc, argv, "", NSM__options, &option_index);
/* Initialize syslog */
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_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));
- }
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: NodeStateManager started."), DLT_STRING("Version:"), DLT_STRING(WATERMARK));
/* Currently no other resources accessing the NSM. Prepare it now! */
NSM__vInitializeVariables(); /* Initialize file local variables*/
NSM__vCreatePlatformSessions(); /* Create platform sessions */
- NSM__vCreateMutexes(); /* Create mutexes */
/* Initialize the NSMA before the NSMC, because the NSMC can access properties */
if(NSMA_boInit(&NSM__stObjectCallBacks) == TRUE)
{
/* Set the properties to initial values */
- (void) NSMA_boSetBootMode(0);
+ if(0 == NSM__bootloader_flag)
+ {
+ (void) NSMA_boSetBootMode(1);
+ }
+ else
+ {
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Starting in bootloader mode"));
+ (void) NSMA_boSetBootMode(2);
+ }
+
(void) NSMA_boSetRestartReason(NsmRestartReason_NotSet);
(void) NSMA_boSetShutdownReason(NsmShutdownReason_NotSet);
(void) NSMA_boSetRunningReason(NsmRunningReason_WakeupCan);
@@ -2655,23 +2966,43 @@ int main(void)
{
/* Start timer to satisfy wdog */
NSM__vConfigureWdogTimer();
-
+
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM has been initialized successfully"));
+ /* Inform systemd that nsm has been successfully initialized */
+ sd_notify(0, "READY=1");
/* The event loop is only canceled if the Node is completely shut down or there is an internal error. */
- boEndByUser = NSMA_boWaitForEvents();
+ NSM__boEndByUser = NSMA_boWaitForEvents();
- if(boEndByUser == TRUE)
+ /* If there are still clients registered -> delete them */
+ for (pListEntry = NSM__pLifecycleClients; pListEntry; pListEntry = pListEntry->next)
{
- DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Successfully canceled event loop. "),
+ pstExistingClient = pListEntry->data;
+ pstExistingClient = (NSM__tstLifecycleClient*) pListEntry->data;
+
+ NSM__vFreeLifecycleClientObject(pstExistingClient);
+ NSM__pLifecycleClients = g_list_remove(NSM__pLifecycleClients, pstExistingClient);
+ }
+
+ NSM__collective_sequential_timeout = 0;
+ NSM__max_parallel_timeout = 0;
+
+ if(NSM__boEndByUser == TRUE)
+ {
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Successfully canceled event loop."),
DLT_STRING("Shutting down NodeStateManager." ));
}
else
{
- DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Error in event loop. " ),
+ DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Error in event loop." ),
DLT_STRING("Shutting down NodeStateManager."));
+ NSM__boEndByUser = TRUE;
}
/* The event loop returned. Clean up the NSMA. */
(void) NSMA_boDeInit();
+
+ /* The event loop returned. Clean up the NSMC. */
+ (void) NsmcDeInit();
}
else
{
@@ -2685,27 +3016,11 @@ int main(void)
/* Error: Failed to initialize the NSMA. */
DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Error. Failed to initialize the NSMA."));
}
-
- /* Free the mutexes */
- NSM__vDeleteMutexes();
-
/* Remove data from all lists */
g_slist_free_full(NSM__pSessions, &NSM__vFreeSessionObject);
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 */
@@ -2713,7 +3028,12 @@ int main(void)
/* Unregister NSM from DLT */
DLT_UNREGISTER_CONTEXT(NsmContext);
+ DLT_UNREGISTER_CONTEXT(NsmaContext);
+
DLT_UNREGISTER_APP();
+#ifdef COVERAGE_ENABLED
+ __gcov_flush();
+#endif
return 0;
}
diff --git a/NodeStateManager/NodeStateManager.h b/NodeStateManager/NodeStateManager.h
index 522fe3e..8da6832 100644
--- a/NodeStateManager/NodeStateManager.h
+++ b/NodeStateManager/NodeStateManager.h
@@ -4,6 +4,7 @@
/**********************************************************************************************************************
*
* Copyright (C) 2012 Continental Automotive Systems, Inc.
+* 2017 BMW AG
*
* Author: Jean-Pierre.Bogler@continental-corporation.com
*
@@ -20,7 +21,7 @@
* 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
+* as open source package. Introduced 'NodeStateManagerTypes.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.
@@ -60,7 +61,7 @@ extern "C"
* The lower significant byte is equal 0 for released version only
*/
-#define NSM_INTERFACE_VERSION 0x01020100U
+#define NSM_INTERFACE_VERSION 0x01020000U
/**********************************************************************************************************************
*
@@ -86,17 +87,17 @@ extern "C"
**********************************************************************************************************************/
/** \brief Set data (property) of the NodeStateManager.
-\param[in] enData Type of the data to set (see ::NsmDataType_e).
+\param[in] enData Type of the data to set (see NsmDataType_e).
\param[in] pData Pointer to the memory location containing the data.
\param[in] u32DataLen Length of the data that should be set (in byte).
-\retval see ::NsmErrorStatus_e
+\retval see NsmErrorStatus_e
This is a generic interface that can be used by the NSMc to write a specific data item that from the NSM. */
NsmErrorStatus_e NsmSetData(NsmDataType_e enData, unsigned char *pData, unsigned int u32DataLen);
/** \brief Get data (property) of the NodeStateManager.
-\param[in] enData Type of the data to get (see ::NsmDataType_e).
+\param[in] enData Type of the data to get (see NsmDataType_e).
\param[out] pData Pointer to the memory location where the data should be stored.
\param[in] u32DataLen Length of the data that should be stored (in byte).
\retval A positive value indicates the number of bytes that have been written to the out buffer pData.
@@ -107,7 +108,7 @@ int NsmGetData(NsmDataType_e enData, unsigned char *pData, unsigned int u32DataL
/** \brief Get version of the interface
-\retval Version of the interface as defined in ::SswVersion_t
+\retval Version of the interface as defined in SswVersion_t
This function asks the lifecycle to perform a restart of the main controller. */
unsigned int NsmGetInterfaceVersion(void);
diff --git a/NodeStateManager/NodeStateTypes.h b/NodeStateManager/NodeStateTypes.h
index 7451a19..8521487 100644
--- a/NodeStateManager/NodeStateTypes.h
+++ b/NodeStateManager/NodeStateTypes.h
@@ -4,6 +4,7 @@
/**********************************************************************************************************************
*
* Copyright (C) 2012 Continental Automotive Systems, Inc.
+* 2017 BMW AG
*
* Author: Jean-Pierre.Bogler@continental-corporation.com
*
@@ -16,7 +17,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Date Author Reason
-* 2012.09.27 uidu5846 1.0.0.0 CSP_WZ#1194: Introduced 'NodeStateTypes.h' to avoid circle includes
+* 2012.09.27 uidu5846 1.0.0.0 CSP_WZ#1194: Introduced 'NodeStateManagerTypes.h' to avoid circle includes
* 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.
@@ -43,12 +44,6 @@ extern "C"
*
**********************************************************************************************************************/
-/* Definitions of D-Bus names and addresses */
-#define NSM_BUS_TYPE 1 /**< Defines bus type according to GBusType */
-#define NSM_BUS_NAME "org.genivi.NodeStateManager" /**< The bus name of the NSM */
-#define NSM_LIFECYCLE_OBJECT "/org/genivi/NodeStateManager/LifecycleControl" /**< Address of the lifecycle object */
-#define NSM_CONSUMER_OBJECT "/org/genivi/NodeStateManager/Consumer" /**< Address of the consumer object */
-
/* Defines for session handling */
#define NSM_DEFAULT_SESSION_OWNER "NodeStateManager" /**< "Owner" of the default sessions */
@@ -63,12 +58,16 @@ extern "C"
#define NSM_SHUTDOWNTYPE_NOT 0x00000000U /**< Client not registered for any shutdown */
#define NSM_SHUTDOWNTYPE_NORMAL 0x00000001U /**< Client registered for normal shutdown */
#define NSM_SHUTDOWNTYPE_FAST 0x00000002U /**< Client registered for fast shutdown */
-#define NSM_SHUTDOWNTYPE_RUNUP 0x80000000U /**< The shutdown type "run up" can not be used for
+#define NSM_SHUTDOWNTYPE_PARALLEL 0x00000004U /**< Client registered for parallel shutdown */
+#define NSM_SHUTDOWNTYPE_RUNUP 0x00000008U /**< The shutdown type "run up" can not be used for
registration. Clients which are registered and
have been shut down, will automatically be
informed about the "run up", when the shut down
is canceled. */
+#define GENERATE_ENUM(ENUM) ENUM,
+#define GENERATE_STRING(STRING) #STRING,
+
/**********************************************************************************************************************
*
* TYPE
@@ -80,162 +79,214 @@ extern "C"
* and the NodeStateMachine (NSMC). Based on this value, the setter and getter functions of the NSM and NSMC will
* interpret data behind the passed byte pointer.
*/
-typedef enum _NsmDataType_e
-{
- NsmDataType_AppMode, /**< An ApplicationMode should be set or get */
- NsmDataType_NodeState, /**< A NodeState should be set or get */
- NsmDataType_RestartReason, /**< A RestartReason should be set or get */
- 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_RegisterSession, /**< A Session should be registered */
- NsmDataType_UnRegisterSession /**< A Session should be unregistered */
-} NsmDataType_e;
+#define FOREACH_DATATYPE(DATATYPE) \
+ DATATYPE(NsmDataType_AppMode) /**< An ApplicationMode should be set or get */ \
+ DATATYPE(NsmDataType_NodeState) /**< A NodeState should be set or get */ \
+ DATATYPE(NsmDataType_RestartReason) /**< A RestartReason should be set or get */ \
+ DATATYPE(NsmDataType_SessionState) /**< A SessionState should be set or get */ \
+ DATATYPE(NsmDataType_ShutdownReason) /**< A ShutdownReason should be set or get */ \
+ DATATYPE(NsmDataType_BootMode) /**< A BootMode should be set or get */ \
+ DATATYPE(NsmDataType_RunningReason) /**< A RunningReason should be set or get */ \
+ DATATYPE(NsmDataType_RegisterSession) /**< A Session should be registered */ \
+ DATATYPE(NsmDataType_UnRegisterSession) /**< A Session should be unregistered */ \
+ DATATYPE(NsmDataType_RequestNodeRestart) /**< A NodeRestart should be triggered */ \
+ DATATYPE(NsmDataType_BlockExternalNodeState)
+typedef enum _NsmDataType_e {
+ FOREACH_DATATYPE(GENERATE_ENUM)
+}NsmDataType_e;
+static const char *DATATYPE_STRING[] __attribute__((unused)) = {
+ FOREACH_DATATYPE(GENERATE_STRING)
+};
/**
* The enumeration defines the different wake up reasons.
*/
-typedef enum _NsmErrorStatus_e
-{
- NsmErrorStatus_NotSet, /**< Initial value when error type is not set */
- NsmErrorStatus_Ok, /**< Value when no error occurred */
- NsmErrorStatus_Error, /**< A general, non-specific error occurred */
- NsmErrorStatus_Dbus, /**< Error in D-Bus communication */
- NsmErrorStatus_Internal, /**< Internal error (memory alloc. failed, etc.) */
- NsmErrorStatus_Parameter, /**< A passed parameter was incorrect */
- NsmErrorStatus_WrongSession, /**< The requested session is unknown. */
- NsmErrorStatus_ResponsePending, /**< Command accepted, return value delivered asynch. */
- NsmErrorStatus_Last /**< Last error value to identify valid errors */
-} NsmErrorStatus_e;
+#define FOREACH_ERRORSTATUS(ERRORSTATUS) \
+ ERRORSTATUS(NsmErrorStatus_NotSet) /**< Initial value when error type is not set */ \
+ ERRORSTATUS(NsmErrorStatus_Ok) /**< Value when no error occurred */ \
+ ERRORSTATUS(NsmErrorStatus_Error) /**< A general, non-specific error occurred */ \
+ ERRORSTATUS(NsmErrorStatus_Dbus) /**< Error in D-Bus communication */ \
+ ERRORSTATUS(NsmErrorStatus_Internal) /**< Internal error (memory alloc. failed, etc.) */ \
+ ERRORSTATUS(NsmErrorStatus_Parameter) /**< A passed parameter was incorrect */ \
+ ERRORSTATUS(NsmErrorStatus_WrongSession) /**< The requested session is unknown. */ \
+ ERRORSTATUS(NsmErrorStatus_ResponsePending) /**< Command accepted, return value delivered asynch. */ \
+ ERRORSTATUS(NsmErrorStatus_WrongClient) /**< A client has returned with wrong id */ \
+ ERRORSTATUS(NsmErrorStatus_Last) /**< Last error value to identify valid errors */ \
+typedef enum _NsmErrorStatus_e {
+ FOREACH_ERRORSTATUS(GENERATE_ENUM)
+}NsmErrorStatus_e;
+
+static const char *ERRORSTATUS_STRING[] __attribute__((unused)) = {
+ FOREACH_ERRORSTATUS(GENERATE_STRING)
+};
/**
* Possible application modes of the node.
*/
-typedef enum _NsmApplicationMode_e
-{
- NsmApplicationMode_NotSet, /**< Initial state */
- NsmApplicationMode_Parking, /**< Parking mode */
- NsmApplicationMode_Factory, /**< Factory mode */
- NsmApplicationMode_Transport, /**< Transport mode */
- NsmApplicationMode_Normal, /**< Normal mode */
- NsmApplicationMode_Swl, /**< Software loading mode */
- NsmApplicationMode_Last /**< Last value to identify valid values */
+#define FOREACH_APPLICATIONMODE(APPLICATIONMODE) \
+ APPLICATIONMODE(NsmApplicationMode_NotSet) /**< Initial state */\
+ APPLICATIONMODE(NsmApplicationMode_Parking) /**< Parking mode */\
+ APPLICATIONMODE(NsmApplicationMode_Factory) /**< Factory mode */\
+ APPLICATIONMODE(NsmApplicationMode_Transport) /**< Transport mode */\
+ APPLICATIONMODE(NsmApplicationMode_Normal) /**< Normal mode */\
+ APPLICATIONMODE(NsmApplicationMode_Swl) /**< Software loading mode */\
+ APPLICATIONMODE(NsmApplicationMode_Last) /**< Last value to identify valid values */\
+
+typedef enum _NsmApplicationMode_e {
+ FOREACH_APPLICATIONMODE(GENERATE_ENUM)
}NsmApplicationMode_e;
+static const char *APPLICATIONMODE_STRING[] __attribute__((unused)) = {
+ FOREACH_APPLICATIONMODE(GENERATE_STRING)
+};
+
/**
* The enumeration defines the different restart reasons.
*/
-typedef enum _NsmRestartReason_e
-{
- NsmRestartReason_NotSet, /**< Initial value when reset reason is not set */
- NsmRestartReason_ApplicationFailure, /**< Reset was requested by System Health Mon. */
- NsmRestartReason_Diagnosis, /**< Reset was requested by diagnosis */
- NsmRestartReason_Swl, /**< Reset was requested by the SWL application */
- NsmRestartReason_User, /**< Reset was requested by an user application */
- NsmRestartReason_Last /**< Last value to identify valid reset reasons */
-} NsmRestartReason_e;
+#define FOREACH_RESTARTREASON(RESTARTREASON) \
+ RESTARTREASON(NsmRestartReason_NotSet) /**< Initial value when reset reason is not set */\
+ RESTARTREASON(NsmRestartReason_ApplicationFailure) /**< Reset was requested by System Health Mon. */\
+ RESTARTREASON(NsmRestartReason_Diagnosis) /**< Reset was requested by diagnosis */\
+ RESTARTREASON(NsmRestartReason_Swl) /**< Reset was requested by the SWL application */\
+ RESTARTREASON(NsmRestartReason_User) /**< Reset was requested by an user application */\
+ RESTARTREASON(NsmRestartReason_Last) /**< Last value to identify valid reset reasons */\
+
+typedef enum _NsmRestartReason_e {
+ FOREACH_RESTARTREASON(GENERATE_ENUM)
+}NsmRestartReason_e;
+static const char *RESTARTREASON_STRING[] __attribute__((unused)) = {
+ FOREACH_RESTARTREASON(GENERATE_STRING)
+};
/**
* Session can be enabled seat depended.
*/
-typedef enum _NsmSeat_e
-{
- NsmSeat_NotSet, /**< Initial state */
- NsmSeat_Driver, /**< Driver seat */
- NsmSeat_CoDriver, /**< CoDriver seat */
- NsmSeat_Rear1, /**< Rear 1 */
- NsmSeat_Rear2, /**< Rear 2 */
- NsmSeat_Rear3, /**< Rear 3 */
- NsmSeat_Last /**< Last valid state */
+#define FOREACH_SEAT(SEAT) \
+ SEAT(NsmSeat_NotSet) /**< Initial state */ \
+ SEAT(NsmSeat_Driver) /**< Driver seat */ \
+ SEAT(NsmSeat_CoDriver) /**< CoDriver seat */ \
+ SEAT(NsmSeat_Rear1) /**< Rear 1 */ \
+ SEAT(NsmSeat_Rear2) /**< Rear 2 */ \
+ SEAT(NsmSeat_Rear3) /**< Rear 3 */ \
+ SEAT(NsmSeat_Last) /**< Last valid state */ \
+
+typedef enum _NsmSeat_e {
+ FOREACH_SEAT(GENERATE_ENUM)
}NsmSeat_e;
+static const char *SEAT_STRING[] __attribute__((unused)) = {
+ FOREACH_SEAT(GENERATE_STRING)
+};
/**
* The enumeration defines the different wake up reasons.
*/
-typedef enum _NsmSessionState_e
-{
- NsmSessionState_Unregistered, /**< Initial state, equals "not set" */
- NsmSessionState_Inactive, /**< Session is inactive */
- NsmSessionState_Active /**< Session is active */
-} NsmSessionState_e;
+#define FOREACH_SESSIONSTATE(SESSIONSTATE) \
+ SESSIONSTATE(NsmSessionState_Unregistered) /**< Initial state, equals "not set" */ \
+ SESSIONSTATE(NsmSessionState_Inactive) /**< Session is inactive */ \
+ SESSIONSTATE(NsmSessionState_Active) /**< Session is active */\
+
+typedef enum _NsmSessionState_e {
+ FOREACH_SESSIONSTATE(GENERATE_ENUM)
+}NsmSessionState_e;
+
+static const char *SESSIONSTATE_STRING[] __attribute__((unused)) = {
+ FOREACH_SESSIONSTATE(GENERATE_STRING)
+};
/**
* The enumeration defines the different shutdown reasons.
*/
-typedef enum _NsmShutdownReason_e
-{
- NsmShutdownReason_NotSet, /**< Initial value when ShutdownReason not set */
- NsmShutdownReason_Normal, /**< A normal shutdown has been performed */
- NsmShutdownReason_SupplyBad, /**< Shutdown because of bad supply */
- NsmShutdownReason_SupplyPoor, /**< Shutdown because of poor supply */
- NsmShutdownReason_ThermalBad, /**< Shutdown because of bad thermal state */
- NsmShutdownReason_ThermalPoor, /**< Shutdown because of poor thermal state */
- NsmShutdownReason_SwlNotActive, /**< Shutdown after software loading */
- NsmShutdownReason_Last /**< Last value. Identify valid ShutdownReasons */
-} NsmShutdownReason_e;
+#define FOREACH_SHUTDOWNREASON(SHUTDOWNREASON) \
+ SHUTDOWNREASON(NsmShutdownReason_NotSet) /**< Initial value when ShutdownReason not set */ \
+ SHUTDOWNREASON(NsmShutdownReason_Normal) /**< A normal shutdown has been performed */ \
+ SHUTDOWNREASON(NsmShutdownReason_SupplyBad) /**< Shutdown because of bad supply */ \
+ SHUTDOWNREASON(NsmShutdownReason_SupplyPoor) /**< Shutdown because of poor supply */ \
+ SHUTDOWNREASON(NsmShutdownReason_ThermalBad) /**< Shutdown because of bad thermal state */ \
+ SHUTDOWNREASON(NsmShutdownReason_ThermalPoor) /**< Shutdown because of poor thermal state */ \
+ SHUTDOWNREASON(NsmShutdownReason_SwlNotActive) /**< Shutdown after software loading */ \
+ SHUTDOWNREASON(NsmShutdownReason_Last) /**< Last value. Identify valid ShutdownReasons */ \
+
+typedef enum _NsmShutdownReason_e {
+ FOREACH_SHUTDOWNREASON(GENERATE_ENUM)
+}NsmShutdownReason_e;
+
+static const char *SHUTDOWNREASON_STRING[] __attribute__((unused)) = {
+ FOREACH_SHUTDOWNREASON(GENERATE_STRING)
+};
/**
* The enumeration defines the different start or wake up reasons.
*/
-typedef enum _NsmRunningReason_e
-{
- NsmRunningReason_NotSet, /**< Initial value when reason is not set. */
- NsmRunningReason_WakeupCan, /**< Wake up because of CAN activity */
- NsmRunningReason_WakeupMediaEject, /**< Wake up because of 'Eject' button */
- NsmRunningReason_WakeupMediaInsertion, /**< Wake up because of media insertion */
- NsmRunningReason_WakeupHevac, /**< Wake up because of user uses the HEVAC unit in the car.
- Even if the HEVAC actually causes activity on the CAN bus a
- different wakeup reason is required as it could result in a
- different level of functionality being started */
- NsmRunningReason_WakeupPhone, /**< Wake up because of a phone call being received.
- Even if this is passed as a CAN event a different wakeup reason
- is required as it could result in a different level of
- functionality being started */
- NsmRunningReason_WakeupPowerOnButton, /**< Startup because user presses the "Power ON" button in the car.
- Even if this is passed as a CAN event a different wakeup reason
- is required as it could result in a different level of
- functionality being started */
- NsmRunningReason_StartupFstp, /**< System was started due to a first switch to power */
- NsmRunningReason_StartupSwitchToPower, /**< System was switched to power */
- NsmRunningReason_RestartSwRequest, /**< System was restarted due to an internal SW Request
- (i.e. SWL or Diagnosis) */
- NsmRunningReason_RestartInternalHealth, /**< System was restarted due to an internal health problem */
- NsmRunningReason_RestartExternalHealth, /**< System was restarted due to an external health problem
- (i.e. external wdog believed node was in failure) */
- NsmRunningReason_RestartUnexpected, /**< System was restarted due to an unexpected kernel restart.
- This will be the default catch when no other reason is known */
- NsmRunningReason_RestartUser, /**< Target was reset due to user action (i.e user 3 finger press) */
- NsmRunningReason_PlatformEnd = 0x7F, /**< Last value (127) to identify where the platform defines end
- (product will start from here on) */
- NsmRunningReason_ProductOffset = NsmRunningReason_PlatformEnd + 1 /**< product will start from here with index 0 */
-} NsmRunningReason_e;
+
+#define FOREACH_RUNNINGREASON(RUNNINGREASON) \
+ RUNNINGREASON(NsmRunningReason_NotSet) /**< Initial value when reason is not set. */\
+ RUNNINGREASON(NsmRunningReason_WakeupCan) /**< Wake up because of CAN activity */\
+ RUNNINGREASON(NsmRunningReason_WakeupMediaEject) /**< Wake up because of 'Eject' button */\
+ RUNNINGREASON(NsmRunningReason_WakeupMediaInsertion) /**< Wake up because of media insertion */\
+ RUNNINGREASON(NsmRunningReason_WakeupHevac) /**< Wake up because of user uses the HEVAC unit in the car.
+ Even if the HEVAC actually causes activity on the CAN bus a
+ different wakeup reason is required as it could result in a
+ different level of functionality being started */\
+ RUNNINGREASON(NsmRunningReason_WakeupPhone) /**< Wake up because of a phone call being received.
+ Even if this is passed as a CAN event a different wakeup reason
+ is required as it could result in a different level of
+ functionality being started */\
+ RUNNINGREASON(NsmRunningReason_WakeupPowerOnButton) /**< Startup because user presses the "Power ON" button in the car.
+ Even if this is passed as a CAN event a different wakeup reason
+ is required as it could result in a different level of
+ functionality being started */\
+ RUNNINGREASON(NsmRunningReason_StartupFstp) /**< System was started due to a first switch to power */\
+ RUNNINGREASON(NsmRunningReason_StartupSwitchToPower) /**< System was switched to power */\
+ RUNNINGREASON(NsmRunningReason_RestartSwRequest) /**< System was restarted due to an internal SW Request
+ (i.e. SWL or Diagnosis) */\
+ RUNNINGREASON(NsmRunningReason_RestartInternalHealth) /**< System was restarted due to an internal health problem */\
+ RUNNINGREASON(NsmRunningReason_RestartExternalHealth) /**< System was restarted due to an external health problem
+ (i.e. external wdog believed node was in failure) */\
+ RUNNINGREASON(NsmRunningReason_RestartUnexpected) /**< System was restarted due to an unexpected kernel restart.
+ This will be the default catch when no other reason is known */\
+ RUNNINGREASON(NsmRunningReason_RestartUser) /**< Target was reset due to user action (i.e user 3 finger press) */\
+ RUNNINGREASON(NsmRunningReason_PlatformEnd)\
+
+typedef enum _NsmRunningReason_e {
+ FOREACH_RUNNINGREASON(GENERATE_ENUM)
+}NsmRunningReason_e;
+
+static const char *RUNNINGREASON_STRING[] __attribute__((unused)) = {
+ FOREACH_RUNNINGREASON(GENERATE_STRING)
+};
/**
* The enumeration defines the different node states
*/
-typedef enum _NsmNodeState_e
-{
- NsmNodeState_NotSet, /**< Initial state when node state is not set */
- NsmNodeState_StartUp, /**< Basic system is starting up */
- NsmNodeState_BaseRunning, /**< Basic system components have been started */
- NsmNodeState_LucRunning, /**< All 'Last user context' components have been started */
- NsmNodeState_FullyRunning, /**< All 'foreground' components have been started */
- NsmNodeState_FullyOperational, /**< All components have been started */
- NsmNodeState_ShuttingDown, /**< The system is shutting down */
- NsmNodeState_ShutdownDelay, /**< Shutdown request active. System will shutdown soon */
- NsmNodeState_FastShutdown, /**< Fast shutdown active */
- NsmNodeState_DegradedPower, /**< Node is in degraded power state */
- NsmNodeState_Shutdown, /**< Node is completely shut down */
- NsmNodeState_Last /**< Last valid entry to identify valid node states */
-} NsmNodeState_e;
+#define FOREACH_NODESTATE(NODESTATE) \
+ NODESTATE(NsmNodeState_NotSet) \
+ NODESTATE(NsmNodeState_StartUp) \
+ NODESTATE(NsmNodeState_BaseRunning) \
+ NODESTATE(NsmNodeState_LucRunning) \
+ NODESTATE(NsmNodeState_FullyRunning) \
+ NODESTATE(NsmNodeState_FullyOperational) \
+ NODESTATE(NsmNodeState_ShuttingDown) \
+ NODESTATE(NsmNodeState_ShutdownDelay) \
+ NODESTATE(NsmNodeState_FastShutdown) \
+ NODESTATE(NsmNodeState_DegradedPower) \
+ NODESTATE(NsmNodeState_Shutdown) \
+ NODESTATE(NsmNodeState_Resume) \
+ NODESTATE(NsmNodeState_Last) \
+
+typedef enum _NsmNodeState_e {
+ FOREACH_NODESTATE(GENERATE_ENUM)
+}NsmNodeState_e;
+
+static const char *NODESTATE_STRING[] __attribute__((unused)) = {
+ FOREACH_NODESTATE(GENERATE_STRING)
+};
/** The type defines the structure for a session. */
typedef struct _NsmSession_s
@@ -246,7 +297,6 @@ typedef struct _NsmSession_s
NsmSessionState_e enState; /**< State of the session */
} NsmSession_s, *pNsmSession_s;
-
#ifdef __cplusplus
}
#endif
diff --git a/NodeStateManager/Watchdog.cpp b/NodeStateManager/Watchdog.cpp
new file mode 100644
index 0000000..e308b8d
--- /dev/null
+++ b/NodeStateManager/Watchdog.cpp
@@ -0,0 +1,111 @@
+/**********************************************************************************************************************
+*
+* Copyright (C) 2017 BMW AG
+*
+* Implementation of the watchdog helper function
+*
+* 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/.
+*
+**********************************************************************************************************************/
+
+#include "Watchdog.hpp"
+#include <thread>
+#include <chrono>
+#include <mutex>
+#include <unordered_map>
+#include <dlt.h>
+#include <sys/types.h>
+#include <sys/syscall.h>
+
+static std::mutex mutex;
+static std::unordered_map<long int, NsmWatchdogState_e> threads;
+static std::unordered_map<long int, long int> specificThreads;
+
+
+DLT_IMPORT_CONTEXT(NsmContext);
+
+void NSMTriggerSpecificWatchdog(NsmWatchdogState_e state, const long int thread)
+{
+ std::lock_guard<std::mutex> lock(mutex);
+ long int threadID = thread * (-1);
+
+ if(threadID == 0)
+ {
+ threadID = (long int)syscall(SYS_gettid);
+ }
+ else
+ {
+ auto search = specificThreads.find(threadID);
+ if (search != specificThreads.end())
+ {
+ search->second = (long int) syscall(SYS_gettid); // Update last thread id of specific thread
+ }
+ else
+ {
+ specificThreads.insert(std::make_pair(threadID, (long int) syscall(SYS_gettid)));
+ }
+ }
+
+ auto search = threads.find(threadID);
+ if(search != threads.end()) {
+ search->second = state;
+ }
+ else {
+ threads.insert(std::make_pair(threadID, state));
+ }
+}
+
+void NSMTriggerWatchdog(NsmWatchdogState_e state)
+{
+ NSMTriggerSpecificWatchdog(state, 0);
+}
+
+void NSMUnregisterSpecificWatchdog(const long int thread)
+{
+ std::lock_guard<std::mutex> lock(mutex);
+ long int threadID = thread * (-1);
+
+ if(threadID == 0)
+ threadID = (long int)syscall(SYS_gettid);
+
+ threads.erase(threadID);
+}
+
+void NSMUnregisterWatchdog()
+{
+ NSMUnregisterSpecificWatchdog(0);
+}
+
+bool NSMWatchdogIsHappy()
+{
+ bool retVal = true;
+
+ std::lock_guard<std::mutex> lock(mutex);
+ for(auto &iter: threads)
+ {
+ if(iter.second == NsmWatchdogState_Unknown)
+ {
+ DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("Watchdog timeout, thread"), DLT_INT64(iter.first), DLT_STRING("is in an unknown state!"));
+ if(iter.first < 0)
+ {
+ auto search = specificThreads.find(iter.first);
+ if (search != specificThreads.end())
+ {
+ DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("Thread id of specific thread"), DLT_INT64(iter.first), DLT_STRING("is"), DLT_INT64(search->second));
+ search->second = (long int) syscall(SYS_gettid);
+ }
+ }
+ retVal = false;
+ usleep(100000); //Sleep 100ms to make sure the DLT is send
+ break;
+ }
+ else if(iter.second == NsmWatchdogState_Active)
+ {
+ iter.second = NsmWatchdogState_Unknown;
+ }
+ }
+
+ return retVal;
+}
diff --git a/NodeStateManager/Watchdog.hpp b/NodeStateManager/Watchdog.hpp
new file mode 100644
index 0000000..b109dcc
--- /dev/null
+++ b/NodeStateManager/Watchdog.hpp
@@ -0,0 +1,45 @@
+/**********************************************************************************************************************
+*
+* Copyright (C) 2017 BMW AG
+*
+* Implementation of the watchdog helper function
+*
+* 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/.
+*
+**********************************************************************************************************************/
+#ifndef NODESTATEMANAGER_WATCHDOG_HPP_
+#define NODESTATEMANAGER_WATCHDOG_HPP_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "stdbool.h"
+
+typedef enum _NsmWatchdogState_e {
+ NsmWatchdogState_Unknown,
+ NsmWatchdogState_Active,
+ NsmWatchdogState_Sleep
+}NsmWatchdogState_e;
+
+typedef enum _NsmWatchdogThread_e
+{
+ NsmThreadAuto,
+ NsmThreadSDMG
+}NsmWatchdogThread_e;
+
+void NSMTriggerWatchdog(NsmWatchdogState_e state);
+
+void NSMTriggerSpecificWatchdog(NsmWatchdogState_e state, const long int thread);
+
+void NSMUnregisterWatchdog();
+
+bool NSMWatchdogIsHappy();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NODESTATEMANAGER_WATCHDOG_HPP_ */
diff --git a/NodeStateManager/config/node-state-manager.pc.in b/NodeStateManager/config/node-state-manager.pc.in
deleted file mode 100644
index 11fb8df..0000000
--- a/NodeStateManager/config/node-state-manager.pc.in
+++ /dev/null
@@ -1,13 +0,0 @@
-# Package config file for NodeStateManager
-
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-dbusinterfacesdir=${pc_sysrootdir}@dbusinterfacesdir@
-
-Name: NodeStateManager (NSM)
-Description: Package information for the NHM.
-URL: http://www.genivi.org
-Version: @VERSION@
-Cflags: -I${includedir}
diff --git a/NodeStateManager/config/nodestatemanager-daemon.service.in b/NodeStateManager/config/nodestatemanager-daemon.service
index 71fcc3c..0afe609 100644
--- a/NodeStateManager/config/nodestatemanager-daemon.service.in
+++ b/NodeStateManager/config/nodestatemanager-daemon.service
@@ -11,18 +11,18 @@
[Unit]
Description=NodeStateManager to provide system states, session and shutdown handling
-Wants=dbus.service dlt-daemon.service pas-daemon.service
-After=dbus.service dlt-daemon.service pas-daemon.service
+Wants=dbus.service dlt-daemon.service
+After=dbus.service dlt-daemon.service
# Start up very early, because it doesn't need anything to run prior to it:
DefaultDependencies=no
[Service]
-Type=dbus
+Type=simple
WatchdogSec=20
-NotifyAccess=main
-BusName=org.genivi.NodeStateManager
-ExecStart=/usr/bin/NodeStateManager
+# NotifyAccess=main
+# BusName=org.genivi.NodeStateManager
+ExecStart=/usr/local/bin/NodeStateManager
[Install]
WantedBy=basic.target
diff --git a/NodeStateManager/config/org.genivi.NodeStateManager.LifeCycleControl.service.in b/NodeStateManager/config/org.genivi.NodeStateManager.LifeCycleControl.service.in
deleted file mode 100644
index f6e3d8a..0000000
--- a/NodeStateManager/config/org.genivi.NodeStateManager.LifeCycleControl.service.in
+++ /dev/null
@@ -1,4 +0,0 @@
-[D-BUS Service]
-Name=org.genivi.NodeStateManager
-SystemdService = nodestatemanager-daemon.service
-Exec=/bin/false
diff --git a/NodeStateManager/config/org.genivi.NodeStateManager.conf b/NodeStateManager/config/org.genivi.NodeStateManager.conf
deleted file mode 100644
index 74b188e..0000000
--- a/NodeStateManager/config/org.genivi.NodeStateManager.conf
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
-<!DOCTYPE busconfig PUBLIC
- "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
-<busconfig>
-
- <!-- Only root can own the service -->
- <policy user="root">
- <allow own="org.genivi.NodeStateManager"/>
- </policy>
-
- <policy at_console="true">
- <allow send_destination="org.genivi.NodeStateManager"/>
- <allow send_interface="org.genivi.NodeStateManager.LifeCycleConsumer"/>
- </policy>
-
- <policy context="default">
- <allow send_destination="org.genivi.NodeStateManager"/>
- <allow send_interface="org.genivi.NodeStateManager.LifeCycleConsumer"/>
- </policy>
-</busconfig>