1 /**********************************************************************************************************************
3 * Copyright (C) 2013 Continental Automotive Systems, Inc.
5 * Author: Jean-Pierre.Bogler@continental-corporation.com
7 * Implementation of the NodeStateManager
9 * The NodeStateManager (NSM) is a central state manager for the system node. It manages the "NodeState",
10 * the "ApplicationMode" and many other states of the complete system. In addition, the NSM offers a
11 * session handling and a shutdown management.
12 * The NSM communicates with the NodeStateMachine (NSMC) to request and inform it about state changes
13 * and the NodeStateAccess (NSMA) to connect to the D-Bus.
15 * This Source Code Form is subject to the terms of the Mozilla Public
16 * License, v. 2.0. If a copy of the MPL was not distributed with this
17 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
19 **********************************************************************************************************************/
22 /**********************************************************************************************************************
26 **********************************************************************************************************************/
27 #include "NodeStateManager.h" /* Own Header file */
28 #include "NodeStateTypes.h" /* Typedefinitions to use the NSM */
29 #include "string.h" /* Memcpy etc. */
30 #include "gio/gio.h" /* GLib lists */
31 #include "dlt/dlt.h" /* DLT Log'n'Trace */
32 #include "NodeStateMachine.h" /* Talk to NodeStateMachine */
33 #include "NodeStateAccess.h" /* Access the IPC (D-Bus) */
34 #include "syslog.h" /* Syslog messages */
35 #include <systemd/sd-daemon.h> /* Systemd wdog */
36 #include <persistence_client_library.h> /* Init/DeInit PCL */
37 #include <persistence_client_library_key.h> /* Access persistent data */
40 /**********************************************************************************************************************
42 * Local defines, macros and type definitions.
44 **********************************************************************************************************************/
46 /* Defines to access persistence keys */
47 #define NSM_PERS_APPLICATION_MODE_DB 0xFF
48 #define NSM_PERS_APPLICATION_MODE_KEY "ERG_OIP_NSM_NODE_APPMODE"
50 /* The type defines the structure for a lifecycle consumer client */
53 gchar *sBusName; /* Bus name of the lifecycle client */
54 gchar *sObjName; /* Object path of the client */
55 guint32 u32RegisteredMode; /* Bit array of shutdown modes */
56 NSMA_tLcConsumerHandle hClient; /* Handle for proxy object for lifecycle client */
57 gboolean boShutdown; /* Only "run up" clients which are shut down */
58 } NSM__tstLifecycleClient;
61 /* The type is used to store failed applications. A struct is used to allow extsions in future */
64 gchar sName[NSM_MAX_SESSION_OWNER_LENGTH];
65 } NSM__tstFailedApplication;
68 /* List of names for the available default sessions, will are automatically provided by NSM */
69 static const gchar* NSM__asDefaultSessions[] = { "DiagnosisSession",
72 "NetworkActiveSession",
73 "NetworkPassiveSession",
75 "PermanentModeSession",
80 "PlatformThermalSession",
81 "PlatformSupplySession",
85 /**********************************************************************************************************************
87 * Prototypes for file local functions (see implementation for description)
89 **********************************************************************************************************************/
91 /* Helper functions to destruct objects */
92 static void NSM__vFreeFailedApplicationObject(gpointer pFailedApplication);
93 static void NSM__vFreeSessionObject (gpointer pSession );
94 static void NSM__vFreeLifecycleClientObject (gpointer pLifecycleClient );
97 /* Helper functions to compare objects in lists */
98 static gboolean NSM__boIsPlatformSession (NsmSession_s *pstSession);
99 static gint NSM__i32LifecycleClientCompare (gconstpointer pL1, gconstpointer pL2);
100 static gint NSM__i32SessionOwnerNameSeatCompare(gconstpointer pS1, gconstpointer pS2);
101 static gint NSM__i32SessionNameSeatCompare (gconstpointer pS1, gconstpointer pS2);
102 static gint NSM__i32SessionOwnerCompare (gconstpointer pS1, gconstpointer pS2);
103 static gint NSM__i32ApplicationCompare (gconstpointer pA1, gconstpointer pA2);
106 /* Helper functions to recognize failed applications and disable their sessions */
107 static void NSM__vDisableSessionsForApp(NSM__tstFailedApplication* pstFailedApp);
108 static NsmErrorStatus_e NSM__enSetAppStateFailed (NSM__tstFailedApplication* pstFailedApp);
109 static NsmErrorStatus_e NSM__enSetAppStateValid (NSM__tstFailedApplication* pstFailedApp);
112 /* Helper functions to control and start the "lifecycle request" sequence */
113 static void NSM__vCallNextLifecycleClient(void);
114 static void NSM__vOnLifecycleRequestFinish(const NsmErrorStatus_e enErrorStatus);
117 /* Internal functions, to set and get values. Indirectly used by D-Bus and StateMachine */
118 static NsmErrorStatus_e NSM__enRegisterSession (NsmSession_s *session,
119 gboolean boInformBus,
120 gboolean boInformMachine);
121 static NsmErrorStatus_e NSM__enUnRegisterSession (NsmSession_s *session,
122 gboolean boInformBus,
123 gboolean boInformMachine);
124 static NsmErrorStatus_e NSM__enSetNodeState (NsmNodeState_e enNodeState,
125 gboolean boInformBus,
126 gboolean boInformMachine);
127 static NsmErrorStatus_e NSM__enSetBootMode (const gint i32BootMode,
128 gboolean boInformMachine);
129 static NsmErrorStatus_e NSM__enSetApplicationMode (NsmApplicationMode_e enApplicationMode,
130 gboolean boInformBus,
131 gboolean boInformMachine);
132 static NsmErrorStatus_e NSM__enSetShutdownReason (NsmShutdownReason_e enNewShutdownReason,
133 gboolean boInformMachine);
135 static void NSM__vPublishSessionChange (NsmSession_s *pstChangedSession,
136 gboolean boInformBus,
137 gboolean boInformMachine);
138 static NsmErrorStatus_e NSM__enSetDefaultSessionState(NsmSession_s *pstSession,
139 gboolean boInformBus,
140 gboolean boInformMachine);
141 static NsmErrorStatus_e NSM__enSetProductSessionState(NsmSession_s *pstSession,
142 gboolean boInformBus,
143 gboolean boInformMachine);
144 static NsmErrorStatus_e NSM__enSetSessionState (NsmSession_s *pstSession,
145 gboolean boInformBus,
146 gboolean boInformMachine);
147 static NsmErrorStatus_e NSM__enGetSessionState (NsmSession_s *pstSession);
150 /* Internal functions that are directly used from D-Bus and StateMachine */
151 static NsmErrorStatus_e NSM__enGetNodeState (NsmNodeState_e *penNodeState);
152 static NsmErrorStatus_e NSM__enGetApplicationMode(NsmApplicationMode_e *penApplicationMode);
155 /* Callbacks for D-Bus interfaces of the NodeStateManager */
156 static NsmErrorStatus_e NSM__enOnHandleSetBootMode (const gint i32BootMode);
157 static NsmErrorStatus_e NSM__enOnHandleSetNodeState (const NsmNodeState_e enNodeState);
158 static NsmErrorStatus_e NSM__enOnHandleSetApplicationMode (const NsmApplicationMode_e enApplMode);
159 static NsmErrorStatus_e NSM__enOnHandleRequestNodeRestart (const NsmRestartReason_e enRestartReason,
160 const guint u32RestartType);
161 static NsmErrorStatus_e NSM__enOnHandleSetAppHealthStatus (const gchar *sAppName,
162 const gboolean boAppState);
163 static gboolean NSM__boOnHandleCheckLucRequired (void);
164 static NsmErrorStatus_e NSM__enOnHandleRegisterSession (const gchar *sSessionName,
165 const gchar *sSessionOwner,
166 const NsmSeat_e enSeatId,
167 const NsmSessionState_e enSessionState);
168 static NsmErrorStatus_e NSM__enOnHandleUnRegisterSession (const gchar *sSessionName,
169 const gchar *sSessionOwner,
170 const NsmSeat_e enSeatId);
171 static NsmErrorStatus_e NSM__enOnHandleRegisterLifecycleClient (const gchar *sBusName,
172 const gchar *sObjName,
173 const guint u32ShutdownMode,
174 const guint u32TimeoutMs);
175 static NsmErrorStatus_e NSM__enOnHandleUnRegisterLifecycleClient(const gchar *sBusName,
176 const gchar *sObjName,
177 const guint u32ShutdownMode);
178 static NsmErrorStatus_e NSM__enOnHandleGetSessionState (const gchar *sSessionName,
179 const NsmSeat_e enSeatId,
180 NsmSessionState_e *penSessionState);
181 static NsmErrorStatus_e NSM__enOnHandleSetSessionState (const gchar *sSessionName,
182 const gchar *sSessionOwner,
183 const NsmSeat_e enSeatId,
184 const NsmSessionState_e enSessionState);
185 static guint NSM__u32OnHandleGetAppHealthCount (void);
186 static guint NSM__u32OnHandleGetInterfaceVersion (void);
188 /* Functions to simplify internal work flow */
189 static void NSM__vInitializeVariables (void);
190 static void NSM__vCreatePlatformSessions(void);
191 static void NSM__vCreateMutexes (void);
192 static void NSM__vDeleteMutexes (void);
194 /* LTPROF helper function */
195 static void NSM__vLtProf(gchar *pszBus, gchar *pszObj, guint32 dwReason, gchar *pszInOut, guint32 dwValue);
196 static void NSM__vSyslogOpen(void);
197 static void NSM__vSyslogClose(void);
199 /* Systemd watchdog functions */
200 static gboolean NSM__boOnHandleTimerWdog(gpointer pUserData);
201 static void NSM__vConfigureWdogTimer(void);
203 /**********************************************************************************************************************
205 * Local variables and constants
207 **********************************************************************************************************************/
209 /* Context for Log'n'Trace */
210 DLT_DECLARE_CONTEXT(NsmContext);
212 /* Variables for "Properties" hosted by the NSM */
213 static GMutex *NSM__pSessionMutex = NULL;
214 static GSList *NSM__pSessions = NULL;
216 static GList *NSM__pLifecycleClients = NULL;
218 static GMutex *NSM__pNodeStateMutex = NULL;
219 static NsmNodeState_e NSM__enNodeState = NsmNodeState_NotSet;
221 static GMutex *NSM__pNextApplicationModeMutex = NULL;
222 static GMutex *NSM__pThisApplicationModeMutex = NULL;
223 static NsmApplicationMode_e NSM__enNextApplicationMode = NsmApplicationMode_NotSet;
224 static NsmApplicationMode_e NSM__enThisApplicationMode = NsmApplicationMode_NotSet;
225 static gboolean NSM__boThisApplicationModeRead = FALSE;
227 static GSList *NSM__pFailedApplications = NULL;
229 /* Variables for internal state management (of lifecycle requests) */
230 static NSM__tstLifecycleClient *NSM__pCurrentLifecycleClient = NULL;
232 /* Constant array of callbacks which are registered at the NodeStateAccess library */
233 static const NSMA_tstObjectCallbacks NSM__stObjectCallBacks = { &NSM__enOnHandleSetBootMode,
234 &NSM__enOnHandleSetNodeState,
235 &NSM__enOnHandleSetApplicationMode,
236 &NSM__enOnHandleRequestNodeRestart,
237 &NSM__enOnHandleSetAppHealthStatus,
238 &NSM__boOnHandleCheckLucRequired,
239 &NSM__enOnHandleRegisterSession,
240 &NSM__enOnHandleUnRegisterSession,
241 &NSM__enOnHandleRegisterLifecycleClient,
242 &NSM__enOnHandleUnRegisterLifecycleClient,
243 &NSM__enGetApplicationMode,
244 &NSM__enOnHandleGetSessionState,
245 &NSM__enGetNodeState,
246 &NSM__enOnHandleSetSessionState,
247 &NSM__u32OnHandleGetAppHealthCount,
248 &NSM__u32OnHandleGetInterfaceVersion,
249 &NSM__vOnLifecycleRequestFinish
252 /**********************************************************************************************************************
254 * Local (static) functions
256 **********************************************************************************************************************/
259 /**********************************************************************************************************************
261 * This helper function is called from various places to check if a session is a "platform" session.
263 * @param pstSession: Pointer to the session for which a check should be done, if it is a platform session
265 * @return TRUE: The session is a "platform" session
266 * FALSE: The session is not a "platform" session
268 **********************************************************************************************************************/
269 static gboolean NSM__boIsPlatformSession(NsmSession_s *pstSession)
271 /* Function local variables */
272 gboolean boIsPlatformSession = FALSE;
273 guint16 u16SessionIdx = 0;
275 for(u16SessionIdx = 0;
276 (u16SessionIdx < sizeof(NSM__asDefaultSessions)/sizeof(gchar*))
277 && (boIsPlatformSession == FALSE);
280 boIsPlatformSession = (g_strcmp0(pstSession->sName, NSM__asDefaultSessions[u16SessionIdx]) == 0);
283 return boIsPlatformSession;
288 * NSM__enRegisterSession:
289 * @session: Ptr to NsmSession_s structure containing data to register a session
290 * @boInformBus: Flag whether the a dbus signal should be send to inform about the new session
291 * @boInformMachine: Flag whether the NSMC should be informed about the new session
293 * The internal function is used to register a session. It is either called from the dbus callback
294 * or it is called via the internal context of the NSMC.
296 static NsmErrorStatus_e NSM__enRegisterSession(NsmSession_s *session, gboolean boInformBus, gboolean boInformMachine)
298 /* Function local variables */
299 NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet; /* Return value */
300 NsmSession_s *pNewSession = NULL; /* Pointer to new created session */
301 GSList *pListEntry = NULL; /* Pointer to list entry */
303 if( (g_strcmp0(session->sOwner, NSM_DEFAULT_SESSION_OWNER) != 0)
304 && (session->enState > NsmSessionState_Unregistered))
306 if(NSM__boIsPlatformSession(session) == FALSE)
308 g_mutex_lock(NSM__pSessionMutex);
310 pListEntry = g_slist_find_custom(NSM__pSessions, session, &NSM__i32SessionNameSeatCompare);
312 if(pListEntry == NULL)
314 enRetVal = NsmErrorStatus_Ok;
316 pNewSession = g_new0(NsmSession_s, 1);
317 memcpy(pNewSession, session, sizeof(NsmSession_s));
319 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Registered session." ),
320 DLT_STRING(" Name: " ), DLT_STRING(session->sName ),
321 DLT_STRING(" Owner: " ), DLT_STRING(session->sOwner ),
322 DLT_STRING(" Seat: " ), DLT_INT((gint) session->enSeat ),
323 DLT_STRING(" Initial state: "), DLT_INT((gint) session->enState));
325 /* Return OK and append new object */
326 NSM__pSessions = g_slist_append(NSM__pSessions, pNewSession);
328 /* Inform D-Bus and StateMachine about the new session. */
329 NSM__vPublishSessionChange(pNewSession, boInformBus, boInformMachine);
333 /* Error: The session already exists. Don't store passed state. */
334 enRetVal = NsmErrorStatus_WrongSession;
335 DLT_LOG(NsmContext, DLT_LOG_WARN, DLT_STRING("NSM: Failed to register session. Session already exists."),
336 DLT_STRING(" Name: " ), DLT_STRING(session->sName ),
337 DLT_STRING(" Owner: " ), DLT_STRING(session->sOwner ),
338 DLT_STRING(" Seat: " ), DLT_INT((gint) session->enSeat ),
339 DLT_STRING(" Initial state: "), DLT_INT((gint) session->enState ));
342 g_mutex_unlock(NSM__pSessionMutex);
346 /* Error: It is not allowed to re-register a default session! */
347 enRetVal = NsmErrorStatus_Parameter;
348 DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to register session. Re-Registration of default session not allowed."),
349 DLT_STRING(" Name: " ), DLT_STRING(session->sName ),
350 DLT_STRING(" Owner: " ), DLT_STRING(session->sOwner ),
351 DLT_STRING(" Seat: " ), DLT_INT((gint) session->enSeat ),
352 DLT_STRING(" Initial state: "), DLT_INT((gint) session->enState ));
357 /* Error: A parameter with an invalid value has been passed */
358 enRetVal = NsmErrorStatus_Parameter;
359 DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to register session. Invalid owner or state."),
360 DLT_STRING(" Name: " ), DLT_STRING(session->sName ),
361 DLT_STRING(" Owner: " ), DLT_STRING(session->sOwner ),
362 DLT_STRING(" Seat: " ), DLT_INT((gint) session->enSeat ),
363 DLT_STRING(" Initial state: "), DLT_INT((gint) session->enState ));
371 * NSM__enUnRegisterSession:
372 * @session: Ptr to NsmSession_s structure containing data to unregister a session
373 * @boInformBus: Flag whether the a dbus signal should be send to inform about the lost session
374 * @boInformMachine: Flag whether the NSMC should be informed about the lost session
376 * The internal function is used to unregister a session. It is either called from the dbus callback
377 * or it is called via the internal context of the NSMC.
379 static NsmErrorStatus_e NSM__enUnRegisterSession(NsmSession_s *session, gboolean boInformBus, gboolean boInformMachine)
381 /* Function local variables */
382 NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet; /* Return value */
383 NsmSession_s *pExistingSession = NULL; /* Pointer to existing session */
384 GSList *pListEntry = NULL; /* Pointer to list entry */
386 if(NSM__boIsPlatformSession(session) == FALSE)
388 g_mutex_lock(NSM__pSessionMutex);
390 pListEntry = g_slist_find_custom(NSM__pSessions, session, &NSM__i32SessionOwnerNameSeatCompare);
392 /* Check if the session exists */
393 if(pListEntry != NULL)
395 /* Found the session in the list. Now remove it. */
396 enRetVal = NsmErrorStatus_Ok;
397 pExistingSession = (NsmSession_s*) pListEntry->data;
399 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Unregistered session." ),
400 DLT_STRING(" Name: " ), DLT_STRING(pExistingSession->sName ),
401 DLT_STRING(" Owner: " ), DLT_STRING(pExistingSession->sOwner ),
402 DLT_STRING(" Seat: " ), DLT_INT( pExistingSession->enSeat ),
403 DLT_STRING(" Last state: "), DLT_INT( pExistingSession->enState));
405 pExistingSession->enState = NsmSessionState_Unregistered;
407 /* Inform D-Bus and StateMachine about the unregistered session */
408 NSM__vPublishSessionChange(pExistingSession, boInformBus, boInformMachine);
410 NSM__vFreeSessionObject(pExistingSession);
411 NSM__pSessions = g_slist_remove(NSM__pSessions, pExistingSession);
415 /* Error: The session is unknown. */
416 enRetVal = NsmErrorStatus_WrongSession;
417 DLT_LOG(NsmContext, DLT_LOG_WARN, DLT_STRING("NSM: Failed to unregister session. Session unknown."),
418 DLT_STRING(" Name: " ), DLT_STRING(session->sName ),
419 DLT_STRING(" Owner: " ), DLT_STRING(session->sOwner ),
420 DLT_STRING(" Seat: " ), DLT_INT((gint) session->enSeat ));
423 g_mutex_unlock(NSM__pSessionMutex);
427 /* Error: Failed to unregister session. The passed session is a "platform" session. */
428 enRetVal = NsmErrorStatus_WrongSession;
429 DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to unregister session. The session is a platform session."),
430 DLT_STRING(" Name: " ), DLT_STRING(session->sName ),
431 DLT_STRING(" Owner: " ), DLT_STRING(session->sOwner ),
432 DLT_STRING(" Seat: " ), DLT_INT((gint) session->enSeat ));
439 /**********************************************************************************************************************
441 * The function is called from IPC and StateMachine to set the NodeState.
443 * @param enNodeState: New NodeState that should be stored.
444 * @param boInformBus: Defines whether a D-Bus signal should be send when the NodeState could be changed.
445 * @param boInformMachine: Defines whether the StateMachine should be informed about the new NodeState.
447 * @return see NsmErrorStatus_e
449 **********************************************************************************************************************/
450 static NsmErrorStatus_e NSM__enSetNodeState(NsmNodeState_e enNodeState, gboolean boInformBus, gboolean boInformMachine)
452 /* Function local variables */
453 NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet; /* Return value */
455 /* Check if the passed parameter is valid */
456 if((enNodeState > NsmNodeState_NotSet) && (enNodeState < NsmNodeState_Last))
458 /* Assert that the Node not already is shut down. Otherwise it will switch of immediately */
459 enRetVal = NsmErrorStatus_Ok;
461 g_mutex_lock(NSM__pNodeStateMutex);
463 /* Only store the new value and emit a signal, if the new value is different */
464 if(NSM__enNodeState != enNodeState)
466 /* Store the last NodeState, before switching to the new one */
467 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Changed NodeState." ),
468 DLT_STRING(" Old NodeState: "), DLT_INT((gint) NSM__enNodeState),
469 DLT_STRING(" New NodeState: "), DLT_INT((gint) enNodeState ));
472 /* Store the passed NodeState and emit a signal to inform system that the NodeState changed */
473 NSM__enNodeState = enNodeState;
475 /* If required, inform the D-Bus about the change (send signal) */
476 if(boInformBus == TRUE)
478 (void) NSMA_boSendNodeStateSignal(NSM__enNodeState);
481 /* If required, inform the StateMachine about the change */
482 if(boInformMachine == TRUE)
484 NsmcSetData(NsmDataType_NodeState, (unsigned char*) &NSM__enNodeState, sizeof(NsmDataType_NodeState));
487 /* Leave the lock now, because its not recursive. 'NSM__vCallNextLifecycleClient' may need it. */
488 g_mutex_unlock(NSM__pNodeStateMutex);
490 /* Check if a new life cycle request needs to be started based on the new ShutdownType */
491 if(NSM__pCurrentLifecycleClient == NULL)
493 NSM__vCallNextLifecycleClient();
498 /* NodeState stays the same. Just leave the lock. */
499 g_mutex_unlock(NSM__pNodeStateMutex);
504 /* Error: The passed boot mode is invalid. Return an error. */
505 enRetVal = NsmErrorStatus_Parameter;
506 DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to change NodeState. Invalid parameter."),
507 DLT_STRING(" Old NodeState: "), DLT_INT(NSM__enNodeState ),
508 DLT_STRING(" Desired NodeState: "), DLT_INT((gint) enNodeState) );
515 /**********************************************************************************************************************
517 * The function is called from IPC and StateMachine to get the NodeState.
519 * @return see NsmNodeState_e
521 **********************************************************************************************************************/
522 static NsmErrorStatus_e NSM__enGetNodeState(NsmNodeState_e *penNodeState)
524 NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet;
526 if(penNodeState != NULL)
528 enRetVal = NsmErrorStatus_Ok;
530 g_mutex_lock(NSM__pNodeStateMutex);
531 *penNodeState = NSM__enNodeState;
532 g_mutex_unlock(NSM__pNodeStateMutex);
536 enRetVal = NsmErrorStatus_Parameter;
543 /**********************************************************************************************************************
545 * The function is called from IPC and StateMachine to set the BootMode.
547 * @param i32BootMode: New BootMode that should be stored.
548 * @param boInformBus: Defines whether a D-Bus signal should be send when the BootMode could be changed.
549 * @param boInformMachine: Defines whether the StateMachine should be informed about the new BootMode.
551 * @return see NsmErrorStatus_e
553 **********************************************************************************************************************/
554 static NsmErrorStatus_e NSM__enSetBootMode(const gint i32BootMode, gboolean boInformMachine)
556 /* Function local variables */
557 gint i32CurrentBootMode = 0;
558 NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet;
560 /* The BootMode property should be thread safe by D-Bus. No critical section need. */
561 (void) NSMA_boGetBootMode(&i32CurrentBootMode);
562 enRetVal = NsmErrorStatus_Ok;
564 if(i32CurrentBootMode != i32BootMode)
566 (void) NSMA_boSetBootMode(i32BootMode);
568 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Changed BootMode." ),
569 DLT_STRING(" Old BootMode: "), DLT_INT(i32CurrentBootMode),
570 DLT_STRING(" New BootMode: "), DLT_INT(i32BootMode ));
572 /* Inform the machine if desired. The D-Bus will auto. update, because this is property */
573 if(boInformMachine == TRUE)
575 NsmcSetData(NsmDataType_BootMode, (unsigned char*) &i32BootMode, sizeof(gint));
579 /* Return ok. There is no limitation for this value. */
583 /**********************************************************************************************************************
585 * The function is called from IPC and StateMachine to set the ApplicationMode.
587 * @param enApplicationMode: New application mode that should be stored.
588 * @param boInformBus: Defines whether a D-Bus signal should be send when the ApplicationMode could be changed.
589 * @param boInformMachine: Defines whether the StateMachine should be informed about the new ApplicationMode.
591 * @return see NsmErrorStatus_e
593 **********************************************************************************************************************/
594 static NsmErrorStatus_e
595 NSM__enSetApplicationMode(NsmApplicationMode_e enApplicationMode,
596 gboolean boInformBus,
597 gboolean boInformMachine)
599 /* Function local variables */
600 NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet; /* Return value */
603 /* Check if the passed parameter is valid */
604 if( (enApplicationMode > NsmApplicationMode_NotSet)
605 && (enApplicationMode < NsmApplicationMode_Last ))
607 /* The passed parameter is valid. Return OK */
608 enRetVal = NsmErrorStatus_Ok;
610 g_mutex_lock(NSM__pNextApplicationModeMutex);
612 /* Only store new value and emit signal, if new value is different */
613 if(NSM__enNextApplicationMode != enApplicationMode)
615 /* Store new value and emit signal with new application mode */
618 DLT_STRING("NSM: Changed ApplicationMode.");
619 DLT_STRING("Old AppMode:"); DLT_INT((int) NSM__enNextApplicationMode);
620 DLT_STRING("New AppMode:"); DLT_INT((int) enApplicationMode));
622 NSM__enNextApplicationMode = enApplicationMode;
624 /* If original persistent value has not been read before, get it now! */
625 g_mutex_lock(NSM__pThisApplicationModeMutex);
627 if(NSM__boThisApplicationModeRead == FALSE)
629 /* Get data from persistence */
630 pcl_return = pclKeyReadData(NSM_PERS_APPLICATION_MODE_DB,
631 NSM_PERS_APPLICATION_MODE_KEY,
634 (unsigned char*) &NSM__enThisApplicationMode,
635 sizeof(NSM__enThisApplicationMode));
637 if(pcl_return != sizeof(NSM__enThisApplicationMode))
639 NSM__enThisApplicationMode = NsmApplicationMode_NotSet;
642 DLT_STRING("NSM: Failed to read ApplicationMode.");
643 DLT_STRING("Error: Unexpected PCL return.");
644 DLT_STRING("Return:"); DLT_INT(pcl_return));
647 NSM__boThisApplicationModeRead = TRUE;
650 g_mutex_unlock(NSM__pThisApplicationModeMutex);
652 /* Write the new application mode to persistence */
653 pcl_return = pclKeyWriteData(NSM_PERS_APPLICATION_MODE_DB,
654 NSM_PERS_APPLICATION_MODE_KEY,
657 (unsigned char*) &NSM__enNextApplicationMode,
658 sizeof(NSM__enNextApplicationMode));
660 if(pcl_return != sizeof(NSM__enNextApplicationMode))
664 DLT_STRING("NSM: Failed to persist ApplicationMode.");
665 DLT_STRING("Error: Unexpected PCL return.");
666 DLT_STRING("Return:"); DLT_INT(pcl_return));
669 if(boInformBus == TRUE)
671 NSMA_boSendApplicationModeSignal(NSM__enNextApplicationMode);
674 if(boInformMachine == TRUE)
676 NsmcSetData(NsmDataType_AppMode,
677 (unsigned char*) &NSM__enNextApplicationMode,
678 sizeof(NsmApplicationMode_e));
682 g_mutex_unlock(NSM__pNextApplicationModeMutex);
686 /* Error: The passed application mode is invalid. Return an error. */
687 enRetVal = NsmErrorStatus_Parameter;
690 DLT_STRING("NSM: Failed to change ApplicationMode.");
691 DLT_STRING("Error:"); DLT_STRING("Invalid parameter.");
692 DLT_STRING("Old AppMode:"); DLT_INT((int) NSM__enNextApplicationMode);
693 DLT_STRING("New AppMode:"); DLT_INT((int) enApplicationMode));
700 /**********************************************************************************************************************
702 * The function is called from IPC and StateMachine to get the ApplicationMode.
704 * @return see NsmApplicationMode_e
706 **********************************************************************************************************************/
707 static NsmErrorStatus_e
708 NSM__enGetApplicationMode(NsmApplicationMode_e *penApplicationMode)
710 NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet;
713 if(penApplicationMode != NULL)
715 g_mutex_lock(NSM__pThisApplicationModeMutex);
717 /* Check if value already was obtained from persistence */
718 if(NSM__boThisApplicationModeRead == FALSE)
720 /* There was no read attempt before. Read from persistence */
721 pcl_return = pclKeyReadData(NSM_PERS_APPLICATION_MODE_DB,
722 NSM_PERS_APPLICATION_MODE_KEY,
725 (unsigned char*) &NSM__enThisApplicationMode,
726 sizeof(NSM__enThisApplicationMode));
728 /* Check the PCL return */
729 if(pcl_return != sizeof(NSM__enThisApplicationMode))
731 /* Read failed. From now on always return 'NsmApplicationMode_NotSet' */
732 NSM__enThisApplicationMode = NsmApplicationMode_NotSet;
735 DLT_STRING("NSM: Failed to read ApplicationMode.");
736 DLT_STRING("Error: Unexpected PCL return.");
737 DLT_STRING("Return:"); DLT_INT(pcl_return));
740 /* There was a first read attempt from persistence */
741 NSM__boThisApplicationModeRead = TRUE;
744 enRetVal = NsmErrorStatus_Ok;
745 *penApplicationMode = NSM__enThisApplicationMode;
747 g_mutex_unlock(NSM__pThisApplicationModeMutex);
751 enRetVal = NsmErrorStatus_Parameter;
758 /**********************************************************************************************************************
760 * The function is called from the StateMachine. There is no D-Bus interface to set the ShutdownReason,
761 * because it is a property.
763 * @param enNewShutdownReason: New ShutdownReason that should be stored.
764 * @param boInformMachine: Determines if StateMachine needs to be called on a successful change.
765 * Most of the time this should be false, because the machine sets the
766 * value and can check the return value for errors.
768 * @return see NsmErrorStatus_e
770 **********************************************************************************************************************/
771 static NsmErrorStatus_e NSM__enSetShutdownReason(NsmShutdownReason_e enNewShutdownReason, gboolean boInformMachine)
773 /* Function local variables */
774 NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet; /* Return value */
775 NsmShutdownReason_e enCurrentShutdownReason = NsmShutdownReason_NotSet;
777 /* Check if the passed parameter is valid */
778 if((enNewShutdownReason > NsmShutdownReason_NotSet) && (enNewShutdownReason < NsmShutdownReason_Last))
780 /* The passed parameter is valid. Return OK */
781 enRetVal = NsmErrorStatus_Ok;
782 (void) NSMA_boGetShutdownReason(&enCurrentShutdownReason);
784 /* Only store the new value and emit a signal, if the new value is different */
785 if(enNewShutdownReason != enCurrentShutdownReason)
787 /* Store new value and emit signal with new application mode */
788 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Changed ShutdownReason."),
789 DLT_STRING(" Old ShutdownReason: "), DLT_INT((gint) enCurrentShutdownReason),
790 DLT_STRING(" New ShutdownReason: "), DLT_INT((gint) enNewShutdownReason ));
792 (void) NSMA_boSetShutdownReason(enNewShutdownReason);
794 if(boInformMachine == TRUE)
796 NsmcSetData(NsmDataType_ShutdownReason, (unsigned char*) &enNewShutdownReason, sizeof(NsmShutdownReason_e));
802 /* Error: The passed application mode is invalid. Return an error. */
803 enRetVal = NsmErrorStatus_Parameter;
804 DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to change ShutdownReason. Invalid parameter." ),
805 DLT_STRING(" Old ShutdownReason: "), DLT_INT((gint) enCurrentShutdownReason),
806 DLT_STRING(" Desired ShutdownReason: "), DLT_INT((gint) enNewShutdownReason ));
812 /**********************************************************************************************************************
814 * The function is called when a session state changed. It informs the system (IPC and StateMachine) about
815 * the changed session state.
817 * @param pstSession: Pointer to structure with updated session information.
818 * @param boInformBus: Defines whether a D-Bus signal should be send on session change.
819 * @param boInformMachine: Defines whether the StateMachine should be informed about session change.
821 **********************************************************************************************************************/
822 static void NSM__vPublishSessionChange(NsmSession_s *pstChangedSession, gboolean boInformBus, gboolean boInformMachine)
824 NsmErrorStatus_e enStateMachineReturn = NsmErrorStatus_NotSet;
826 if(boInformBus == TRUE)
828 NSMA_boSendSessionSignal(pstChangedSession);
831 if(boInformMachine == TRUE)
833 enStateMachineReturn = NsmcSetData(NsmDataType_SessionState, (unsigned char*) pstChangedSession, sizeof(NsmSession_s));
835 if(enStateMachineReturn != NsmErrorStatus_Ok)
837 DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to inform state machine about changed session state." ),
838 DLT_STRING(" State machine returned: "), DLT_INT( enStateMachineReturn ),
839 DLT_STRING(" Application: "), DLT_STRING(pstChangedSession->sOwner ),
840 DLT_STRING(" Session: "), DLT_STRING(pstChangedSession->sName ),
841 DLT_STRING(" Seat: "), DLT_INT( pstChangedSession->enSeat ),
842 DLT_STRING(" Desired state: "), DLT_INT( pstChangedSession->enState));
848 /**********************************************************************************************************************
850 * The function is called when the state of a product session should be changed.
852 * @param pstSession: Pointer to structure where session name, owner, seat and desired SessionState are defined.
853 * @param boInformBus: Defines whether a D-Bus signal should be send on session change.
854 * @param boInformMachine: Defines whether the StateMachine should be informed about session change.
856 * @return see NsmErrorStatus_e
858 **********************************************************************************************************************/
859 static NsmErrorStatus_e NSM__enSetProductSessionState(NsmSession_s *pstSession, gboolean boInformBus, gboolean boInformMachine)
861 /* Function local variables */
862 NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet; /* Return value */
863 GSList *pListEntry = NULL;
864 NsmSession_s *pExistingSession = NULL;
866 g_mutex_lock(NSM__pSessionMutex);
868 pListEntry = g_slist_find_custom(NSM__pSessions, pstSession, &NSM__i32SessionOwnerNameSeatCompare);
870 if(pListEntry != NULL)
872 enRetVal = NsmErrorStatus_Ok;
873 pExistingSession = (NsmSession_s*) pListEntry->data;
875 if(pExistingSession->enState != pstSession->enState)
877 pExistingSession->enState = pstSession->enState;
878 NSM__vPublishSessionChange(pExistingSession, boInformBus, boInformMachine);
883 enRetVal = NsmErrorStatus_WrongSession;
884 DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to set session state. Session unknown."),
885 DLT_STRING(" Application: "), DLT_STRING(pstSession->sOwner ),
886 DLT_STRING(" Session: "), DLT_STRING(pstSession->sName ),
887 DLT_STRING(" Seat: "), DLT_INT( pstSession->enSeat ),
888 DLT_STRING(" Desired state: "), DLT_INT( pstSession->enState));
891 g_mutex_unlock(NSM__pSessionMutex);
897 /**********************************************************************************************************************
899 * The function is called when the state of a default session should be changed.
901 * @param pstSession: Pointer to structure where session name, owner, seat and desired SessionState are defined.
902 * @param boInformBus: Defines whether a D-Bus signal should be send on session change.
903 * @param boInformMachine: Defines whether the StateMachine should be informed about session change.
905 * @return see NsmErrorStatus_e
907 **********************************************************************************************************************/
908 static NsmErrorStatus_e NSM__enSetDefaultSessionState(NsmSession_s *pstSession, gboolean boInformBus, gboolean boInformMachine)
910 /* Function local variables */
911 NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet; /* Return value */
912 GSList *pListEntry = NULL;
913 NsmSession_s *pExistingSession = NULL;
915 /* Lock the sessions to be able to change them! */
916 g_mutex_lock(NSM__pSessionMutex);
918 pListEntry = g_slist_find_custom(NSM__pSessions, pstSession, &NSM__i32SessionNameSeatCompare);
920 if(pListEntry != NULL)
922 pExistingSession = (NsmSession_s*) pListEntry->data;
924 /* Check that the caller owns the session */
925 if(g_strcmp0(pExistingSession->sOwner, pstSession->sOwner) == 0)
927 enRetVal = NsmErrorStatus_Ok;
929 if(pExistingSession->enState != pstSession->enState)
931 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Changed default session's state."),
932 DLT_STRING(" Application: "), DLT_STRING(pExistingSession->sOwner ),
933 DLT_STRING(" Session: "), DLT_STRING(pExistingSession->sName ),
934 DLT_STRING(" Seat: "), DLT_INT( pExistingSession->enSeat ),
935 DLT_STRING(" Old state: "), DLT_INT( pExistingSession->enState),
936 DLT_STRING(" New state: "), DLT_INT( pstSession->enState ));
938 pExistingSession->enState = pstSession->enState;
940 NSM__vPublishSessionChange(pExistingSession, boInformBus, boInformMachine);
942 if(pstSession->enState == NsmSessionState_Inactive)
944 g_strlcpy(pExistingSession->sOwner, NSM_DEFAULT_SESSION_OWNER, sizeof(pExistingSession->sOwner));
950 /* The caller does not own the session. Check if he can become the owner. */
951 if(g_strcmp0(pExistingSession->sOwner, NSM_DEFAULT_SESSION_OWNER) == 0)
953 /* The session has no owner. The new owner can obtain the session by setting it to an "active" state */
954 if(pstSession->enState != NsmSessionState_Inactive)
956 /* The session has been activated. Overtake the owner. Broadcast new state. */
957 enRetVal = NsmErrorStatus_Ok;
958 g_strlcpy(pExistingSession->sOwner, pstSession->sOwner, sizeof(pExistingSession->sOwner));
960 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Changed default session's state."),
961 DLT_STRING(" Application: "), DLT_STRING(pExistingSession->sOwner ),
962 DLT_STRING(" Session: "), DLT_STRING(pExistingSession->sName ),
963 DLT_STRING(" Seat: "), DLT_INT( pExistingSession->enSeat ),
964 DLT_STRING(" Old state: "), DLT_INT( pExistingSession->enState),
965 DLT_STRING(" New state: "), DLT_INT( pstSession->enState ));
967 pExistingSession->enState = pstSession->enState;
969 NSM__vPublishSessionChange(pExistingSession, boInformBus, boInformMachine);
973 /* The session has no owner, but could not be activated because the passed state is "inactive". */
974 enRetVal = NsmErrorStatus_Parameter;
976 DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to enable default session. Passed state is 'inactive'. "),
977 DLT_STRING(" Session: "), DLT_STRING(pstSession->sName ),
978 DLT_STRING(" Seat: "), DLT_INT( pstSession->enSeat ),
979 DLT_STRING(" Owning application: "), DLT_STRING(pExistingSession->sOwner ),
980 DLT_STRING(" Requesting application: "), DLT_STRING(pstSession->sOwner ));
985 /* The session owners do not match and the existing session has an owner */
986 enRetVal = NsmErrorStatus_Error;
988 DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to set default session state. Session has another owner."),
989 DLT_STRING(" Session: "), DLT_STRING(pstSession->sName ),
990 DLT_STRING(" Seat: "), DLT_INT( pstSession->enSeat ),
991 DLT_STRING(" Owning application: "), DLT_STRING(pExistingSession->sOwner ),
992 DLT_STRING(" Requesting application: "), DLT_STRING(pstSession->sOwner ));
998 /* This should never happen, because the function is only called for default sessions! */
999 enRetVal = NsmErrorStatus_Internal;
1000 DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Critical error. Default session not found in session list!"),
1001 DLT_STRING(" Application: "), DLT_STRING(pstSession->sOwner ),
1002 DLT_STRING(" Session: "), DLT_STRING(pstSession->sName ),
1003 DLT_STRING(" Seat: "), DLT_INT( pstSession->enSeat ),
1004 DLT_STRING(" Desired state: "), DLT_INT( pstSession->enState ));
1007 /* Unlock the sessions again. */
1008 g_mutex_unlock(NSM__pSessionMutex);
1014 /**********************************************************************************************************************
1016 * The function is called from IPC and StateMachine to set a session state.
1018 * @param pstSession: Pointer to structure where session name, owner, seat and desired SessionState are defined.
1019 * @param boInformBus: Defines whether a D-Bus signal should be send on session change.
1020 * @param boInformMachine: Defines whether the StateMachine should be informed about session change.
1022 * @return see NsmErrorStatus_e
1024 **********************************************************************************************************************/
1025 static NsmErrorStatus_e NSM__enSetSessionState(NsmSession_s *pstSession, gboolean boInformBus, gboolean boInformMachine)
1027 /* Function local variables */
1028 NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet; /* Return value */
1030 /* Check if the passed parameters are valid. */
1031 if( (g_strcmp0(pstSession->sOwner, NSM_DEFAULT_SESSION_OWNER) != 0)
1032 && (pstSession->enState > NsmSessionState_Unregistered )
1033 && (pstSession->enSeat > NsmSeat_NotSet )
1034 && (pstSession->enSeat < NsmSeat_Last ))
1036 /* Parameters are valid. Check if a platform session state is set */
1037 if(NSM__boIsPlatformSession(pstSession) == TRUE)
1039 enRetVal = NSM__enSetDefaultSessionState(pstSession, boInformBus, boInformMachine);
1043 enRetVal = NSM__enSetProductSessionState(pstSession, boInformBus, boInformMachine);
1048 /* Error: An invalid parameter has been passed. */
1049 enRetVal = NsmErrorStatus_Parameter;
1050 DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to change session state. Invalid paramter."),
1051 DLT_STRING(" Application: "), DLT_STRING(pstSession->sOwner ),
1052 DLT_STRING(" Session: "), DLT_STRING(pstSession->sName ),
1053 DLT_STRING(" Seat: "), DLT_INT( pstSession->enSeat ),
1054 DLT_STRING(" Desired state: "), DLT_INT( pstSession->enState ));
1061 /**********************************************************************************************************************
1063 * The function is called from IPC and StateMachine to get the session state.
1065 * @param pstSession: Pointer to structure where session name, owner and seat are defined and SessionState will be set.
1067 * @return see NsmErrorStatus_e
1069 **********************************************************************************************************************/
1070 static NsmErrorStatus_e NSM__enGetSessionState(NsmSession_s *pstSession)
1072 /* Function local variables */
1073 NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet; /* Return value */
1074 NsmSession_s *pExistingSession = NULL; /* Pointer to existing session */
1075 GSList *pListEntry = NULL;
1077 g_mutex_lock(NSM__pSessionMutex);
1079 /* Search for session with name, seat and owner. */
1080 pListEntry = g_slist_find_custom(NSM__pSessions, pstSession, &NSM__i32SessionNameSeatCompare);
1082 if(pListEntry != NULL)
1084 /* Found the session in the list. Return its state. */
1085 enRetVal = NsmErrorStatus_Ok;
1086 pExistingSession = (NsmSession_s*) pListEntry->data;
1087 pstSession->enState = pExistingSession->enState;
1091 /* Error: The session is unknown. */
1092 enRetVal = NsmErrorStatus_WrongSession;
1093 DLT_LOG(NsmContext, DLT_LOG_WARN, DLT_STRING("NSM: Failed to retrieve session state. Unknown session."),
1094 DLT_STRING(" Session: "), DLT_STRING(pstSession->sName ),
1095 DLT_STRING(" Seat: "), DLT_INT( pstSession->enSeat ));
1098 g_mutex_unlock(NSM__pSessionMutex);
1104 static void NSM__vFreeFailedApplicationObject(gpointer pFailedApplication)
1106 /* Function local variables. Cast the passed object */
1107 NSM__tstFailedApplication *pstFailedApplication = (NSM__tstFailedApplication*) pFailedApplication;
1109 g_free(pstFailedApplication);
1113 /**********************************************************************************************************************
1115 * The function is called either manually for one object or for every "session object", when the list of registered
1116 * sessions is destroyed with "g_slist_free_full". All memory occupied by the "session object" is released.
1118 * @param pSession: Pointer to the session object
1122 **********************************************************************************************************************/
1123 static void NSM__vFreeSessionObject(gpointer pSession)
1125 /* Function local variables. Cast the passed object */
1126 NsmSession_s *pstSession = (NsmSession_s*) pSession;
1128 /* Free the session object */
1133 /**********************************************************************************************************************
1135 * The function is called either manually for one object or for every "lifecycle client object", when the list of
1136 * registered lifecycle clients is destroyed with "g_slist_free_full".
1137 * All memory occupied by the "lifecycle client object" is released.
1139 * @param pLifecycleClient: Pointer to the lifecycle client object
1143 **********************************************************************************************************************/
1144 static void NSM__vFreeLifecycleClientObject(gpointer pLifecycleClient)
1146 /* Function local variables. Cast the passed object */
1147 NSM__tstLifecycleClient *pstLifecycleClient = (NSM__tstLifecycleClient*) pLifecycleClient;
1149 /* Free internal strings and objects */
1150 g_free(pstLifecycleClient->sBusName);
1151 g_free(pstLifecycleClient->sObjName);
1153 /* No need to check for NULL. Only valid clients come here */
1154 NSMA_boFreeLcConsumerProxy(pstLifecycleClient->hClient);
1156 /* Free the shutdown client object */
1157 g_free(pstLifecycleClient);
1161 /**********************************************************************************************************************
1163 * The function is used to "custom compare" and identify a lifecycle client in the list of clients.
1164 * Because the function is not used for sorting, the return value 1 is not used.
1166 * @param pS1: Lifecycle client from list
1167 * @param pS2: Lifecycle client to compare
1169 * @return -1: pL1 < pL2
1171 * 1: pL1 > pL2 (unused, because function not used for sorting)
1173 **********************************************************************************************************************/
1174 static gint NSM__i32LifecycleClientCompare(gconstpointer pL1, gconstpointer pL2)
1176 /* Function local variables. Cast the passed objects */
1177 NSM__tstLifecycleClient *pListClient = NULL;
1178 NSM__tstLifecycleClient *pCompareClient = NULL;
1181 pListClient = (NSM__tstLifecycleClient*) pL1;
1182 pCompareClient = (NSM__tstLifecycleClient*) pL2;
1184 /* Compare the bus name of the client */
1185 if(g_strcmp0(pListClient->sBusName, pCompareClient->sBusName) == 0)
1187 /* Bus names are equal. Now compare object name */
1188 if(g_strcmp0(pListClient->sObjName, pCompareClient->sObjName) == 0)
1190 i32RetVal = 0; /* Clients are identical. Return 0. */
1194 i32RetVal = -1; /* Object names are different. Return -1. */
1199 i32RetVal = -1; /* Bus names are different. Return -1. */
1202 return i32RetVal; /* Return result of comparison. */
1206 /**********************************************************************************************************************
1208 * The function is used to "custom compare" and identify a session in the list of sessions.
1209 * It compares the "session name", the "session owner" and "seat".
1210 * Because the function is not used for sorting, the return value 1 is not used.
1212 * @param pS1: Session from list
1213 * @param pS2: Session to compare
1215 * @return -1: pS1 < pS2
1217 * 1: pS1 > pS2 (unused, because function not used for sorting)
1219 **********************************************************************************************************************/
1220 static gint NSM__i32SessionOwnerNameSeatCompare(gconstpointer pS1, gconstpointer pS2)
1222 /* Function local variables. Cast the passed objects */
1223 NsmSession_s *pListSession = NULL;
1224 NsmSession_s *pSearchSession = NULL;
1227 pListSession = (NsmSession_s*) pS1;
1228 pSearchSession = (NsmSession_s*) pS2;
1230 if(g_strcmp0(pListSession->sOwner, pSearchSession->sOwner) == 0)
1232 i32RetVal = NSM__i32SessionNameSeatCompare(pS1, pS2);
1236 i32RetVal = -1; /* Session owners differ. Return -1. */
1239 return i32RetVal; /* Return result of comparison */
1243 /**********************************************************************************************************************
1245 * The function is used to "custom compare" and identify a session in the list of sessions.
1246 * It compares the "session name" and "seat".
1247 * Because the function is not used for sorting, the return value 1 is not used.
1249 * @param pS1: Session from list
1250 * @param pS2: Session to compare
1252 * @return -1: pS1 < pS2
1254 * 1: pS1 > pS2 (unused, because function not used for sorting)
1256 **********************************************************************************************************************/
1257 static gint NSM__i32SessionNameSeatCompare(gconstpointer pS1, gconstpointer pS2)
1259 /* Function local variables. Cast the passed objects */
1260 NsmSession_s *pListSession = NULL;
1261 NsmSession_s *pSearchSession = NULL;
1264 pListSession = (NsmSession_s*) pS1;
1265 pSearchSession = (NsmSession_s*) pS2;
1267 /* Compare seats of the sessions. */
1268 if(pListSession->enSeat == pSearchSession->enSeat)
1270 /* Seats are equal. Compare session names. */
1271 if(g_strcmp0(pListSession->sName, pSearchSession->sName) == 0)
1273 i32RetVal = 0; /* Session are equal. Return 0. */
1277 i32RetVal = -1; /* Session names differ. Return -1. */
1282 i32RetVal = -1; /* Session seats differ. Return -1. */
1289 /**********************************************************************************************************************
1291 * The function is used to "custom compare" and identify an application name.
1292 * Because the function is not used for sorting, the return value 1 is not used.
1294 * @param pA1: Application object from list
1295 * @param pA2: Application object to compare
1297 * @return -1: pA1 < pA2
1299 * 1: pA1 > pA2 (unused, because function not used for sorting)
1301 **********************************************************************************************************************/
1302 static gint NSM__i32ApplicationCompare(gconstpointer pA1, gconstpointer pA2)
1304 /* Function local variables. Cast the passed objects */
1305 NSM__tstFailedApplication *pListApp = NULL;
1306 NSM__tstFailedApplication *pSearchApp = NULL;
1309 pListApp = (NSM__tstFailedApplication*) pA1;
1310 pSearchApp = (NSM__tstFailedApplication*) pA2;
1312 /* Compare names of the applications */
1313 if(g_strcmp0(pListApp->sName, pSearchApp->sName) == 0)
1315 i32RetVal = 0; /* Names are equal. Return 0. */
1319 i32RetVal = -1; /* Names are different. Return -1. */
1322 return i32RetVal; /* Return result of comparison */
1326 /**********************************************************************************************************************
1328 * The function is used to "custom compare" and identify a session with a special owner.
1329 * Because the function is not used for sorting, the return value 1 is not used.
1331 * @param pS1: Session from list
1332 * @param pS2: Session to compare
1334 * @return -1: pS1 < pS2
1336 * 1: pS1 > pS2 (unused, because function not used for sorting)
1338 **********************************************************************************************************************/
1339 static gint NSM__i32SessionOwnerCompare(gconstpointer pS1, gconstpointer pS2)
1341 /* Function local variables. Cast the passed objects */
1342 NsmSession_s *pListSession = NULL;
1343 NsmSession_s *pSearchSession = NULL;
1346 pListSession = (NsmSession_s*) pS1;
1347 pSearchSession = (NsmSession_s*) pS2;
1349 /* Compare owners of the sessions */
1350 if(g_strcmp0(pListSession->sOwner, pSearchSession->sOwner) == 0)
1352 i32RetVal = 0; /* Owners are equal. Return 0. */
1356 i32RetVal = -1; /* Owners are different. Return -1. */
1359 return i32RetVal; /* Return result of comparison */
1363 /**********************************************************************************************************************
1365 * The function is called after a lifecycle client was informed about the changed life cycle.
1366 * The return value of the last informed client will be evaluated and the next lifecycle client
1367 * to inform will be determined and called.
1368 * If there is no client left, the lifecycle sequence will be finished.
1370 * @param pSrcObject: Source object (lifecycle client proxy)
1371 * @param pRes: Result of asynchronous call
1372 * @param pUserData: Pointer to the current lifecycle client object
1376 **********************************************************************************************************************/
1377 static void NSM__vOnLifecycleRequestFinish(const NsmErrorStatus_e enErrorStatus)
1379 if(enErrorStatus == NsmErrorStatus_Ok)
1381 /* The clients "LifecycleRequest" has been successfully processed. */
1382 NSM__vLtProf(NSM__pCurrentLifecycleClient->sBusName, NSM__pCurrentLifecycleClient->sObjName, 0, "leave: ", 0);
1383 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Successfully called lifecycle client."));
1387 /* Error: The method of the lifecycle client returned an error */
1388 NSM__vLtProf(NSM__pCurrentLifecycleClient->sBusName, NSM__pCurrentLifecycleClient->sObjName, 0, "leave: error: ", enErrorStatus);
1389 DLT_LOG(NsmContext, DLT_LOG_WARN, DLT_STRING("NSM: Failed to call life cycle client." ),
1390 DLT_STRING(" Return Value: "), DLT_INT((gint) enErrorStatus));
1393 NSM__vCallNextLifecycleClient();
1397 /**********************************************************************************************************************
1399 * The function is called when:
1400 * - The NodeState changes (NSM__boHandleSetNodeState), to initiate a lifecycle sequence
1401 * - A client returned and the next client has to be called (NSM__vOnLifecycleRequestFinish)
1403 * If the clients need to "run up" or shut down for the current NodeState, the function
1404 * searches the list forward or backward until a client is found, which needs to be informed.
1406 * PLEASE NOTE: If all clients have been informed about a "shut down", this function will quit the
1407 * "g_main_loop", which leads to the the termination of the NSM!
1411 **********************************************************************************************************************/
1412 static void NSM__vCallNextLifecycleClient(void)
1414 /* Function local variables */
1415 GList *pListEntry = NULL; /* Iterate through list entries */
1416 NSM__tstLifecycleClient *pClient = NULL; /* Client object from list */
1417 guint32 u32ShutdownType = NSM_SHUTDOWNTYPE_NOT; /* Return value */
1418 gboolean boShutdown = FALSE;
1420 NSM__pCurrentLifecycleClient = NULL;
1422 g_mutex_lock(NSM__pNodeStateMutex);
1424 /* Based on NodeState determine if clients have to shutdown or run up. Find a client that has not been informed */
1425 switch(NSM__enNodeState)
1427 /* For "shutdown" search backward in the list, until there is a client that has not been shut down */
1428 case NsmNodeState_ShuttingDown:
1429 u32ShutdownType = NSM_SHUTDOWNTYPE_NORMAL;
1430 for( pListEntry = g_list_last(NSM__pLifecycleClients);
1431 (pListEntry != NULL) && (NSM__pCurrentLifecycleClient == NULL);
1432 pListEntry = g_list_previous(pListEntry))
1434 /* Check if client has not been shut down and is registered for "normal shutdown" */
1435 pClient = (NSM__tstLifecycleClient*) pListEntry->data;
1436 if( ( pClient->boShutdown == FALSE)
1437 && ( (pClient->u32RegisteredMode & u32ShutdownType) != 0 ))
1439 /* Found a "running" previous client, registered for the shutdown mode */
1440 NSM__pCurrentLifecycleClient = (NSM__tstLifecycleClient*) pListEntry->data;
1445 /* For "fast shutdown" search backward in the list, until there is a client that has not been shut down */
1446 case NsmNodeState_FastShutdown:
1447 u32ShutdownType = NSM_SHUTDOWNTYPE_FAST;
1448 for( pListEntry = g_list_last(NSM__pLifecycleClients);
1449 (pListEntry != NULL) && (NSM__pCurrentLifecycleClient == NULL);
1450 pListEntry = g_list_previous(pListEntry))
1452 /* Check if client has not been shut down and is registered for "fast shutdown" */
1453 pClient = (NSM__tstLifecycleClient*) pListEntry->data;
1454 if( ( pClient->boShutdown == FALSE)
1455 && ( (pClient->u32RegisteredMode & u32ShutdownType) != 0 ))
1457 /* Found a "running" previous client, registered for the shutdown mode */
1458 NSM__pCurrentLifecycleClient = (NSM__tstLifecycleClient*) pListEntry->data;
1463 /* For a "running" mode search forward in the list (get next), until there is a client that is shut down */
1465 u32ShutdownType = NSM_SHUTDOWNTYPE_RUNUP;
1466 for(pListEntry = g_list_first(NSM__pLifecycleClients);
1467 (pListEntry != NULL) && (NSM__pCurrentLifecycleClient == NULL);
1468 pListEntry = g_list_next(pListEntry))
1470 /* Check if client is shut down */
1471 pClient = (NSM__tstLifecycleClient*) pListEntry->data;
1472 if(pClient->boShutdown == TRUE)
1474 /* The client was shutdown. It should run up, because we are in a running mode */
1475 NSM__pCurrentLifecycleClient = (NSM__tstLifecycleClient*) pListEntry->data;
1481 /* Check if a client could be found that needs to be informed */
1482 if(NSM__pCurrentLifecycleClient != NULL)
1484 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Call lifecycle client." ),
1485 DLT_STRING(" Bus name: "), DLT_STRING(NSM__pCurrentLifecycleClient->sBusName ),
1486 DLT_STRING(" Obj name: "), DLT_STRING(NSM__pCurrentLifecycleClient->sObjName ),
1487 DLT_STRING(" Registered types: "), DLT_INT(NSM__pCurrentLifecycleClient->u32RegisteredMode),
1488 DLT_STRING(" Client: "), DLT_INT( (guint) NSM__pCurrentLifecycleClient->hClient ),
1489 DLT_STRING(" ShutdownType: "), DLT_UINT(u32ShutdownType ));
1491 /* Remember that client received a run-up or shutdown call */
1492 pClient->boShutdown = (u32ShutdownType != NSM_SHUTDOWNTYPE_RUNUP);
1494 NSM__vLtProf(NSM__pCurrentLifecycleClient->sBusName, NSM__pCurrentLifecycleClient->sObjName, u32ShutdownType, "enter: ", 0);
1496 NSMA_boCallLcClientRequest(NSM__pCurrentLifecycleClient->hClient, u32ShutdownType);
1501 /* The last client was called. Depending on the NodeState check if we can end. */
1502 switch(NSM__enNodeState)
1504 /* All registered clients have been 'fast shutdown'. Set NodeState to "shutdown" */
1505 case NsmNodeState_FastShutdown:
1506 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Informed all registered clients about 'fast shutdown'. Set NodeState to 'shutdown'"));
1508 NSM__enNodeState = NsmNodeState_Shutdown;
1509 NsmcSetData(NsmDataType_NodeState, (unsigned char*) &NSM__enNodeState, sizeof(NsmNodeState_e));
1510 NSMA_boSendNodeStateSignal(NSM__enNodeState);
1514 /* All registered clients have been 'shutdown'. Set NodeState to "shutdown" */
1515 case NsmNodeState_ShuttingDown:
1516 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Informed all registered clients about 'shutdown'. Set NodeState to 'shutdown'."));
1518 NSM__enNodeState = NsmNodeState_Shutdown;
1519 NsmcSetData(NsmDataType_NodeState, (unsigned char*) &NSM__enNodeState, sizeof(NsmNodeState_e));
1520 NSMA_boSendNodeStateSignal(NSM__enNodeState);
1524 /* We are in a running state. Nothing to do */
1531 g_mutex_unlock(NSM__pNodeStateMutex);
1533 if(boShutdown == TRUE)
1535 NSMA_boQuitEventLoop();
1540 /**********************************************************************************************************************
1542 * The callback is called when a check for LUC is required.
1543 * It uses the NodeStateMachine to determine whether LUC is required.
1545 * @param pboRetVal: Pointer, where to store the StateMAchine's return value
1547 **********************************************************************************************************************/
1548 static gboolean NSM__boOnHandleCheckLucRequired(void)
1550 /* Determine if LUC is required by asking the NodeStateMachine */
1551 return (NsmcLucRequired() == 0x01) ? TRUE : FALSE;
1555 /**********************************************************************************************************************
1557 * The callback is called when the "boot mode" should be set.
1558 * It sets the BootMode using an internal function.
1560 * @param i32BootMode: New boot mode
1561 * @param penRetVal: Pointer, where to store the return value
1563 **********************************************************************************************************************/
1564 static NsmErrorStatus_e NSM__enOnHandleSetBootMode(const gint i32BootMode)
1566 /* Use internal setter to set the BootMode and inform the StateMachine */
1567 return NSM__enSetBootMode(i32BootMode, TRUE);
1571 /**********************************************************************************************************************
1573 * The callback is called when the "node state" should be set.
1574 * It sets the NodeState using an internal function.
1576 * @param enNodeStateId: New node state
1577 * @param penRetVal: Pointer, where to store the return value
1579 **********************************************************************************************************************/
1580 static NsmErrorStatus_e NSM__enOnHandleSetNodeState(const NsmNodeState_e enNodeState)
1582 return NSM__enSetNodeState(enNodeState, TRUE, TRUE);
1586 /**********************************************************************************************************************
1588 * The callback is called when the "application mode" should be set.
1589 * It sets the ApplicationMode using an internal function.
1591 * @param enApplicationModeId: New application mode
1592 * @param penRetVal: Pointer, where to store the return value
1594 **********************************************************************************************************************/
1595 static NsmErrorStatus_e NSM__enOnHandleSetApplicationMode(const NsmApplicationMode_e enApplMode)
1597 return NSM__enSetApplicationMode(enApplMode, TRUE, TRUE);
1601 /**********************************************************************************************************************
1603 * The callback is called when the node reset is requested.
1604 * It passes the request to the NodestateMachine.
1606 * @param i32RestartReason: Restart reason
1607 * @param i32RestartType: Restart type
1608 * @param penRetVal: Pointer, where to store the return value
1610 **********************************************************************************************************************/
1611 static NsmErrorStatus_e NSM__enOnHandleRequestNodeRestart(const NsmRestartReason_e enRestartReason,
1612 const guint u32RestartType)
1614 NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet;
1616 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Node restart has been requested."));
1618 if(NsmcRequestNodeRestart(enRestartReason, u32RestartType) == 0x01)
1620 enRetVal = NsmErrorStatus_Ok;
1621 (void) NSMA_boSetRestartReason(enRestartReason);
1625 enRetVal = NsmErrorStatus_Error;
1632 /**********************************************************************************************************************
1634 * The called is called when a new session should be registered.
1635 * It checks the passed parameters and creates a NsmSession_s structure of them.
1636 * If everything is ok, the new session will be created and the system and StateMachine will be informed.
1638 * @param sSessionName: Name of the new session
1639 * @param sSessionOwner: Owner of the new session
1640 * @param enSeatId: Seat which belongs to the new session
1641 * @param enSessionState: Initial state of the new session
1642 * @param penRetVal: Pointer, where to store the return value
1644 **********************************************************************************************************************/
1645 static NsmErrorStatus_e NSM__enOnHandleRegisterSession(const gchar *sSessionName,
1646 const gchar *sSessionOwner,
1647 const NsmSeat_e enSeatId,
1648 const NsmSessionState_e enSessionState)
1650 /* Function local variables */
1651 glong u32SessionNameLen = 0; /* Length of passed session owner */
1652 glong u32SessionOwnerLen = 0; /* Length of passed session name */
1653 NsmSession_s stSession; /* To search for existing session */
1654 NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet;
1656 /* Check if the passed parameters are valid */
1657 u32SessionNameLen = g_utf8_strlen(sSessionName, -1);
1658 u32SessionOwnerLen = g_utf8_strlen(sSessionOwner, -1);
1660 if( (u32SessionNameLen < NSM_MAX_SESSION_NAME_LENGTH )
1661 && (u32SessionOwnerLen < NSM_MAX_SESSION_OWNER_LENGTH)
1662 && (enSeatId > NsmSeat_NotSet )
1663 && (enSeatId < NsmSeat_Last ))
1665 /* Initialize temporary session object to check if session already exists */
1666 g_strlcpy((gchar*) stSession.sName, sSessionName, sizeof(stSession.sName) );
1667 g_strlcpy((gchar*) stSession.sOwner, sSessionOwner, sizeof(stSession.sOwner));
1668 stSession.enSeat = enSeatId;
1669 stSession.enState = enSessionState;
1671 enRetVal = NSM__enRegisterSession(&stSession, TRUE, TRUE);
1675 /* Error: A parameter with an invalid value has been passed */
1676 enRetVal = NsmErrorStatus_Parameter;
1677 DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to register session. Invalid parameter."),
1678 DLT_STRING("Name:" ), DLT_STRING(sSessionName ),
1679 DLT_STRING("Owner:" ), DLT_STRING(sSessionOwner ),
1680 DLT_STRING("Seat:" ), DLT_INT((gint) enSeatId ),
1681 DLT_STRING("Initial state:"), DLT_INT((gint) enSessionState ));
1688 /**********************************************************************************************************************
1690 * The callback is called when a session should be unregistered.
1691 * It checks the passed parameters and creates a NsmSession_s structure of them.
1692 * If everything is ok, the new session will be removed and the system and StateMachine will be informed.
1694 * @param sSessionName: Name of the new session that should be unregistered.
1695 * @param sSessionOwner: Current owner of the session that should be unregistered.
1696 * @param enSeat: Seat for which the session should be unregistered.
1697 * @param penRetVal: Pointer, where to store the return value
1699 **********************************************************************************************************************/
1700 static NsmErrorStatus_e NSM__enOnHandleUnRegisterSession(const gchar *sSessionName,
1701 const gchar *sSessionOwner,
1702 const NsmSeat_e enSeatId)
1704 /* Function local variables */
1705 glong u32SessionNameLen = 0; /* Length of passed session owner */
1706 glong u32SessionOwnerLen = 0; /* Length of passed session name */
1707 NsmSession_s stSearchSession = {0}; /* To search for existing session */
1708 NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet;
1710 /* Check if the passed parameters are valid */
1711 u32SessionNameLen = g_utf8_strlen(sSessionName, -1);
1712 u32SessionOwnerLen = g_utf8_strlen(sSessionOwner, -1);
1714 if( (u32SessionNameLen < NSM_MAX_SESSION_NAME_LENGTH )
1715 && (u32SessionOwnerLen < NSM_MAX_SESSION_OWNER_LENGTH))
1717 /* Assign seat, session name and owner to search for session */
1718 stSearchSession.enSeat = enSeatId;
1719 g_strlcpy((gchar*) stSearchSession.sName, sSessionName, sizeof(stSearchSession.sName) );
1720 g_strlcpy((gchar*) stSearchSession.sOwner, sSessionOwner, sizeof(stSearchSession.sOwner));
1722 enRetVal = NSM__enUnRegisterSession(&stSearchSession, TRUE, TRUE);
1726 /* Error: Invalid parameter. The session or owner name is to long. */
1727 enRetVal = NsmErrorStatus_Parameter;
1728 DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to unregister session. The session or owner name is to long."),
1729 DLT_STRING(" Name: " ), DLT_STRING(sSessionName ),
1730 DLT_STRING(" Owner: " ), DLT_STRING(sSessionOwner ),
1731 DLT_STRING(" Seat: " ), DLT_INT((gint) enSeatId ));
1738 /**********************************************************************************************************************
1740 * The callback is called when a lifecycle client should be registered.
1741 * In the list of lifecycle clients it will be checked if the client already exists.
1742 * If it exists, it's settings will be updated. Otherwise a new client will be created.
1744 * @param sBusName: Bus name of the remote application that hosts the lifecycle client interface
1745 * @param sObjName: Object name of the lifecycle client
1746 * @param u32ShutdownMode: Shutdown mode for which the client wants to be informed
1747 * @param u32TimeoutMs: Timeout in ms. If the client does not return after the specified time, the NSM
1748 * aborts its shutdown and calls the next client.
1749 * @param penRetVal: Pointer, where to store the return value
1751 **********************************************************************************************************************/
1752 static NsmErrorStatus_e NSM__enOnHandleRegisterLifecycleClient(const gchar *sBusName,
1753 const gchar *sObjName,
1754 const guint u32ShutdownMode,
1755 const guint u32TimeoutMs)
1757 NSM__tstLifecycleClient stTestLifecycleClient = {0};
1758 NSM__tstLifecycleClient *pstNewClient = NULL;
1759 NSM__tstLifecycleClient *pstExistingClient = NULL;
1760 GList *pListEntry = NULL;
1761 NSMA_tLcConsumerHandle *hConsumer = NULL;
1762 GError *pError = NULL;
1763 NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet;
1765 /* The parameters are valid. Create a temporary client to search the list */
1766 stTestLifecycleClient.sBusName = (gchar*) sBusName;
1767 stTestLifecycleClient.sObjName = (gchar*) sObjName;
1769 /* Check if the lifecycle client already is registered */
1770 pListEntry = g_list_find_custom(NSM__pLifecycleClients, &stTestLifecycleClient, &NSM__i32LifecycleClientCompare);
1772 if(pListEntry == NULL)
1774 /* The client does not exist. Try to create a new proxy */
1775 hConsumer = NSMA_hCreateLcConsumer(sBusName, sObjName, u32TimeoutMs);
1777 /* The new proxy could be created. Create and store new client */
1778 if(hConsumer != NULL)
1780 enRetVal = NsmErrorStatus_Ok;
1782 /* Create client object and copies of the strings. */
1783 pstNewClient = g_new0(NSM__tstLifecycleClient, 1);
1784 pstNewClient->u32RegisteredMode = u32ShutdownMode;
1785 pstNewClient->sBusName = g_strdup(sBusName);
1786 pstNewClient->sObjName = g_strdup(sObjName);
1787 pstNewClient->boShutdown = FALSE;
1788 pstNewClient->hClient = hConsumer;
1791 /* Append the new client to the list */
1792 NSM__pLifecycleClients = g_list_append(NSM__pLifecycleClients, pstNewClient);
1794 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Registered new lifecycle consumer." ),
1795 DLT_STRING(" Bus name: "), DLT_STRING(pstNewClient->sBusName ),
1796 DLT_STRING(" Obj name: "), DLT_STRING(pstNewClient->sObjName ),
1797 DLT_STRING(" Timeout: " ), DLT_UINT( u32TimeoutMs ),
1798 DLT_STRING(" Mode(s): "), DLT_INT( pstNewClient->u32RegisteredMode),
1799 DLT_STRING(" Client: "), DLT_UINT((guint) pstNewClient->hClient ));
1803 enRetVal = NsmErrorStatus_Dbus;
1804 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Failed to register new lifecycle consumer. D-Bus error."),
1805 DLT_STRING(" Bus name: "), DLT_STRING(sBusName ),
1806 DLT_STRING(" Obj name: "), DLT_STRING(sObjName ),
1807 DLT_STRING(" Timeout: " ), DLT_UINT( u32TimeoutMs ),
1808 DLT_STRING(" Registered mode(s): "), DLT_INT( u32ShutdownMode ),
1809 DLT_STRING(" Error: "), DLT_STRING(pError->message ));
1811 g_error_free(pError);
1816 /* The client already exists. Assert to update the values for timeout and mode */
1817 enRetVal = NsmErrorStatus_Ok;
1818 pstExistingClient = (NSM__tstLifecycleClient*) pListEntry->data;
1819 pstExistingClient->u32RegisteredMode |= u32ShutdownMode;
1820 NSMA_boSetLcClientTimeout(pstExistingClient->hClient, u32TimeoutMs);
1822 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Changed lifecycle consumer registration." ),
1823 DLT_STRING(" Bus name: "), DLT_STRING(pstExistingClient->sBusName ),
1824 DLT_STRING(" Obj name: "), DLT_STRING(pstExistingClient->sObjName ),
1825 DLT_STRING(" Timeout: " ), DLT_UINT( u32TimeoutMs ),
1826 DLT_STRING(" Registered mode(s): "), DLT_INT( pstExistingClient->u32RegisteredMode));
1833 /**********************************************************************************************************************
1835 * The callback is called when a lifecycle client should be unregistered or a shutdown
1836 * mode should be removed. In the list of lifecycle clients will be checked if the client exists. If the
1837 * client is found, the registration for the passed shutdown modes will be removed. If the client finally
1838 * is not registered for any shutdown mode, its entry will be removed from the list.
1840 * @param sBusName: Bus name of the remote application that hosts the lifecycle client interface
1841 * @param sObjName: Object name of the lifecycle client
1842 * @param u32ShutdownMode: Shutdown mode for which the client wants to unregister
1843 * @param penRetVal: Pointer, where to store the return value
1845 **********************************************************************************************************************/
1846 static NsmErrorStatus_e NSM__enOnHandleUnRegisterLifecycleClient(const gchar *sBusName,
1847 const gchar *sObjName,
1848 const guint u32ShutdownMode)
1850 NSM__tstLifecycleClient *pstExistingClient = NULL;
1851 NSM__tstLifecycleClient stSearchClient = {0};
1852 GList *pListEntry = NULL;
1853 NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet;
1855 stSearchClient.sBusName = (gchar*) sBusName;
1856 stSearchClient.sObjName = (gchar*) sObjName;
1858 /* Check if the lifecycle client already is registered */
1859 pListEntry = g_list_find_custom(NSM__pLifecycleClients, &stSearchClient, &NSM__i32LifecycleClientCompare);
1861 /* Check if an existing client could be found */
1862 if(pListEntry != NULL)
1864 /* The client could be found in the list. Change the registered shutdown mode */
1865 enRetVal = NsmErrorStatus_Ok;
1866 pstExistingClient = (NSM__tstLifecycleClient*) pListEntry->data;
1867 pstExistingClient->u32RegisteredMode &= ~(u32ShutdownMode);
1869 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Unregistered lifecycle consumer for mode(s)." ),
1870 DLT_STRING(" Bus name: "), DLT_STRING(pstExistingClient->sBusName ),
1871 DLT_STRING(" Obj name: "), DLT_STRING(pstExistingClient->sObjName ),
1872 DLT_STRING(" New mode: "), DLT_INT( pstExistingClient->u32RegisteredMode),
1873 DLT_STRING(" Client: " ), DLT_UINT((guint) pstExistingClient->hClient) );
1875 if(pstExistingClient->u32RegisteredMode == NSM_SHUTDOWNTYPE_NOT)
1877 /* The client is not registered for at least one mode. Remove it from the list */
1878 NSM__vFreeLifecycleClientObject(pstExistingClient);
1879 NSM__pLifecycleClients = g_list_remove(NSM__pLifecycleClients, pstExistingClient);
1884 /* Warning: The client could not be found in the list of clients. */
1885 enRetVal = NsmErrorStatus_Parameter;
1886 DLT_LOG(NsmContext, DLT_LOG_WARN, DLT_STRING("NSM: Failed to unregister lifecycle consumer."),
1887 DLT_STRING(" Bus name: "), DLT_STRING(sBusName),
1888 DLT_STRING(" Obj name: "), DLT_STRING(sObjName),
1889 DLT_STRING(" Unregistered mode(s): "), DLT_INT( u32ShutdownMode));
1896 /**********************************************************************************************************************
1898 * The function is used to get the state of the passed session.
1899 * It checks the passed parameters and creates a NsmSession_s structure of them.
1900 * If everything is ok, the state of the session will be determined and written to penSessionState.
1902 * @param sSessionName: Name of the session whose state just be returned
1903 * @param sSessionName: Owner of the session whose state just be returned
1904 * @param enSeatId: Seat of the session
1905 * @param penSessionState: Pointer where to store the session state
1906 * @param penRetVal: Pointer where to store the return value
1908 **********************************************************************************************************************/
1909 static NsmErrorStatus_e NSM__enOnHandleGetSessionState(const gchar *sSessionName,
1910 const NsmSeat_e enSeatId,
1911 NsmSessionState_e *penSessionState)
1913 /* Function local variables */
1914 NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet;
1915 glong u32SessionNameLen = 0; /* Length of passed session owner */
1916 NsmSession_s stSearchSession = {0}; /* To search for existing session */
1918 /* Check if the passed parameters are valid */
1919 u32SessionNameLen = g_utf8_strlen(sSessionName, -1);
1921 if(u32SessionNameLen < NSM_MAX_SESSION_OWNER_LENGTH)
1923 /* Search for session with name, seat and owner. */
1924 stSearchSession.enSeat = enSeatId;
1925 g_strlcpy((gchar*) stSearchSession.sName, sSessionName, sizeof(stSearchSession.sName) );
1927 enRetVal = NSM__enGetSessionState(&stSearchSession);
1928 *penSessionState = stSearchSession.enState;
1932 /* Error: Invalid parameter. The session or owner name is to long. */
1933 enRetVal = NsmErrorStatus_Parameter;
1934 DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to get session state. The session name is to long."),
1935 DLT_STRING(" Name: " ), DLT_STRING(sSessionName ),
1936 DLT_STRING(" Seat: " ), DLT_INT((gint) enSeatId ));
1943 /**********************************************************************************************************************
1945 * The function sets the state of a session to a passed value.
1946 * It checks the passed parameters and creates a NsmSession_s structure of them.
1947 * If everything is ok, the state of the session will be set accordingly.
1949 * @param sSessionName: Name of the session whose state just be set
1950 * @param sSessionOwner: Owner of the session
1951 * @param enSeatId: Seat of the session
1952 * @param enSessionState: New state of the session
1953 * @param penRetVal: Pointer where to store the return value
1955 **********************************************************************************************************************/
1956 static NsmErrorStatus_e NSM__enOnHandleSetSessionState(const gchar *sSessionName,
1957 const gchar *sSessionOwner,
1958 const NsmSeat_e enSeatId,
1959 const NsmSessionState_e enSessionState)
1961 /* Function local variables */
1962 NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet;
1963 glong u32SessionNameLen = 0; /* Length of passed session owner */
1964 glong u32SessionOwnerLen = 0; /* Length of passed session name */
1965 NsmSession_s stSession = {0}; /* Session object passed to internal function */
1967 /* Check if the passed parameters are valid */
1968 u32SessionNameLen = g_utf8_strlen(sSessionName, -1);
1969 u32SessionOwnerLen = g_utf8_strlen(sSessionOwner, -1);
1971 if( (u32SessionNameLen < NSM_MAX_SESSION_NAME_LENGTH )
1972 && (u32SessionOwnerLen < NSM_MAX_SESSION_OWNER_LENGTH))
1974 /* Build session object to pass it internally */
1975 g_strlcpy((gchar*) stSession.sName, sSessionName, sizeof(stSession.sName) );
1976 g_strlcpy((gchar*) stSession.sOwner, sSessionOwner, sizeof(stSession.sOwner));
1978 stSession.enSeat = enSeatId;
1979 stSession.enState = enSessionState;
1981 enRetVal = NSM__enSetSessionState(&stSession, TRUE, TRUE);
1985 /* Error: Invalid parameter. The session or owner name is to long. */
1986 enRetVal = NsmErrorStatus_Parameter;
1987 DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to set session state. Invalid parameter."),
1988 DLT_STRING(" Name: " ), DLT_STRING(sSessionName ),
1989 DLT_STRING(" Owner: " ), DLT_STRING(sSessionOwner ),
1990 DLT_STRING(" Seat: " ), DLT_INT((gint) enSeatId ));
1997 /**********************************************************************************************************************
1999 * The helper function is called by 'NSM__boOnHandleSetAppHealthStatus', when an application became valid again.
2000 * It removes the application from the list of invalid apps.
2002 * @param pstFailedApp: Pointer to structure with information about the failed application.
2004 * @return NsmErrorStatus_Ok: The application has been removed from the list of failed apps.
2005 * NsmErrorStatus_WrongSession: The application has never been on the list of failed apps.
2007 **********************************************************************************************************************/
2008 static NsmErrorStatus_e NSM__enSetAppStateValid(NSM__tstFailedApplication* pstFailedApp)
2010 /* Function local variables */
2011 GSList *pAppListEntry = NULL; /* List entry of application */
2012 NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet; /* Return value */
2013 NSM__tstFailedApplication *pstExistingApplication = NULL;
2015 /* An application has become valid again. Check if it really was invalid before. */
2016 pAppListEntry = g_slist_find_custom(NSM__pFailedApplications, pstFailedApp, &NSM__i32ApplicationCompare);
2018 if(pAppListEntry != NULL)
2020 /* We found at least one entry for the application. Remove it from the list */
2021 enRetVal = NsmErrorStatus_Ok;
2022 pstExistingApplication = (NSM__tstFailedApplication*) pAppListEntry->data;
2023 NSM__pFailedApplications = g_slist_remove(NSM__pFailedApplications, pstExistingApplication);
2024 NSM__vFreeFailedApplicationObject(pstExistingApplication);
2026 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: An application has become valid again." ),
2027 DLT_STRING(" Application: "), DLT_STRING(pstFailedApp->sName));
2031 /* Error: There was no session registered for the application that failed. */
2032 enRetVal = NsmErrorStatus_Error;
2033 DLT_LOG(NsmContext, DLT_LOG_WARN, DLT_STRING("NSM: Failed to set application valid. Application was never invalid."),
2034 DLT_STRING(" Application: "), DLT_STRING(pstFailedApp->sName ));
2041 /**********************************************************************************************************************
2043 * The helper function is called by 'NSM__enSetAppStateFailed', when an application failed.
2044 * It looks for sessions that have been registered by the app.
2046 * @param pstFailedApp: Pointer to structure with information about the failed application.
2048 **********************************************************************************************************************/
2049 static void NSM__vDisableSessionsForApp(NSM__tstFailedApplication* pstFailedApp)
2051 /* Function local variables */
2052 GSList *pSessionListEntry = NULL;
2053 NsmSession_s *pstExistingSession = NULL;
2054 NsmSession_s stSearchSession = {0};
2056 /* Only set the "owner" of the session (to the AppName) to search for all sessions of the app. */
2057 g_strlcpy(stSearchSession.sOwner, pstFailedApp->sName, sizeof(stSearchSession.sOwner));
2059 g_mutex_lock(NSM__pSessionMutex);
2060 pSessionListEntry = g_slist_find_custom(NSM__pSessions, &stSearchSession, &NSM__i32SessionOwnerCompare);
2062 if(pSessionListEntry != NULL)
2064 /* Found at least one session. */
2067 /* Get the session object for the list entry */
2068 pstExistingSession = (NsmSession_s*) pSessionListEntry->data;
2069 pstExistingSession->enState = NsmSessionState_Unregistered;
2071 /* Inform D-Bus and StateMachine that a session became invalid */
2072 NSM__vPublishSessionChange(pstExistingSession, TRUE, TRUE);
2074 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: A session has become invalid, because an application failed."),
2075 DLT_STRING(" Application: "), DLT_STRING(pstExistingSession->sOwner ),
2076 DLT_STRING(" Session: "), DLT_STRING(pstExistingSession->sName ),
2077 DLT_STRING(" Seat: "), DLT_INT( pstExistingSession->enSeat ),
2078 DLT_STRING(" State: "), DLT_INT( pstExistingSession->enState ));
2080 /* Remove or "reset" session */
2081 if(NSM__boIsPlatformSession(pstExistingSession) == TRUE)
2083 /* It is a default session. Don't remove it. Set owner to NSM again. */
2084 g_strlcpy(pstExistingSession->sOwner, NSM_DEFAULT_SESSION_OWNER, sizeof(pstExistingSession->sOwner));
2088 /* The session has been registered by a failed app. Remove it. */
2089 NSM__pSessions = g_slist_remove(NSM__pSessions, pstExistingSession);
2090 NSM__vFreeSessionObject(pstExistingSession);
2093 /* Try to find the next session that had been registered for the app. */
2094 pSessionListEntry = g_slist_find_custom(NSM__pSessions, &stSearchSession, &NSM__i32SessionOwnerCompare);
2096 } while(pSessionListEntry != NULL);
2100 /* There have been no session registered for this application. */
2101 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: There had been no registered sessions." ),
2102 DLT_STRING(" Application: "), DLT_STRING(pstFailedApp->sName));
2105 g_mutex_unlock(NSM__pSessionMutex);
2109 /**********************************************************************************************************************
2111 * The helper function is called by 'NSM__boOnHandleSetAppHealthStatus', when an application failed.
2113 * @param pstFailedApp: Pointer to structure with information about the failed application.
2115 * @return always "NsmErrorStatus_Ok"
2117 **********************************************************************************************************************/
2118 static NsmErrorStatus_e NSM__enSetAppStateFailed(NSM__tstFailedApplication* pstFailedApp)
2120 /* Function local variables */
2121 GSList *pFailedAppListEntry = NULL; /* List entry of application */
2122 NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet; /* Return value */
2123 NSM__tstFailedApplication *pstFailedApplication = NULL;
2125 /* An application failed. Check if the application already is known as 'failed'. */
2126 pFailedAppListEntry = g_slist_find_custom(NSM__pFailedApplications, pstFailedApp, &NSM__i32ApplicationCompare);
2128 if(pFailedAppListEntry == NULL)
2130 /* The application is not on the list yet. Create it. */
2131 enRetVal = NsmErrorStatus_Ok;
2133 pstFailedApplication = g_new(NSM__tstFailedApplication, 1);
2134 g_strlcpy(pstFailedApplication->sName, pstFailedApp->sName, sizeof(pstFailedApplication->sName));
2135 NSM__pFailedApplications = g_slist_append(NSM__pFailedApplications, pstFailedApplication);
2137 /* Disable all session that have been registered by the application */
2138 NSM__vDisableSessionsForApp(pstFailedApplication);
2142 /* Warning: The application is already in the list of failed session. */
2143 enRetVal = NsmErrorStatus_Ok;
2144 DLT_LOG(NsmContext, DLT_LOG_WARN, DLT_STRING("NSM: The application has already been marked as 'failed'."),
2145 DLT_STRING(" Application: "), DLT_STRING(pstFailedApp->sName ));
2152 /**********************************************************************************************************************
2154 * The function is called when an application has become invalid or valid again.
2155 * If an application became inactive, it will be added to the list of failed applications
2156 * and signals for the session registered by the application will be emitted.
2157 * If an application became valid again, it will only be removed from the list of failed sessions.
2159 * @param sAppName: Application which changed its state.
2160 * @param boAppState: Indicates if the application became invalid or valid again.
2161 * @param penRetVal: Pointer where to store the return value
2163 **********************************************************************************************************************/
2164 static NsmErrorStatus_e NSM__enOnHandleSetAppHealthStatus(const gchar *sAppName,
2165 const gboolean boAppState)
2167 /* Function local variables */
2168 NSM__tstFailedApplication stSearchApplication = {0}; /* Temporary application object for search */
2169 NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet;
2171 /* Check if passed parameters are valid */
2172 if(strlen(sAppName) < NSM_MAX_SESSION_OWNER_LENGTH)
2174 /* The application name is valid. Copy it for further checks. */
2175 g_strlcpy((gchar*) stSearchApplication.sName, sAppName, sizeof(stSearchApplication.sName));
2177 if(boAppState == TRUE)
2179 enRetVal = NSM__enSetAppStateValid(&stSearchApplication);
2183 enRetVal = NSM__enSetAppStateFailed(&stSearchApplication);
2188 /* Error: The passed application name is too long. */
2189 enRetVal = NsmErrorStatus_Parameter;
2190 DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Failed to set application health status. The application name is too long."),
2191 DLT_STRING(" Owner: " ), DLT_STRING(sAppName ),
2192 DLT_STRING(" State: " ), DLT_INT(boAppState ));
2200 /**********************************************************************************************************************
2202 * The function returns the current AppHealthCount, which is stored in local variable.
2204 * @param pu32AppHealthCount: Pointer where to store the AppHealthCount (number of failed applications).
2206 **********************************************************************************************************************/
2207 static guint NSM__u32OnHandleGetAppHealthCount(void)
2209 return g_slist_length(NSM__pFailedApplications);
2213 /**********************************************************************************************************************
2215 * The function returns the current interface version of the NodeStateManager.
2217 * @param pu32InterfaceVersion: Pointer where to store the interface version.
2219 **********************************************************************************************************************/
2220 static guint NSM__u32OnHandleGetInterfaceVersion(void)
2222 /* Return interface version to caller. */
2223 return NSM_INTERFACE_VERSION;
2227 /**********************************************************************************************************************
2229 * The function is called cyclically and triggers the systemd wdog.
2231 * @param pUserData: Pointer to optional user data
2233 * @return Always TRUE to keep timer callback alive.
2235 **********************************************************************************************************************/
2236 static gboolean NSM__boOnHandleTimerWdog(gpointer pUserData)
2238 (void) sd_notify(0, "WATCHDOG=1");
2239 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Triggered systemd WDOG."));
2245 /**********************************************************************************************************************
2247 * The function checks if the NSM is observed by a systemd wdog and installs a timer if necessary.
2249 **********************************************************************************************************************/
2250 static void NSM__vConfigureWdogTimer(void)
2252 const gchar *sWdogSec = NULL;
2253 guint u32WdogSec = 0;
2255 sWdogSec = g_getenv("WATCHDOG_USEC");
2257 if(sWdogSec != NULL)
2259 u32WdogSec = strtoul(sWdogSec, NULL, 10);
2261 /* The min. valid value for systemd is 1 s => WATCHDOG_USEC at least needs to contain 1.000.000 us */
2262 if(u32WdogSec >= 1000000)
2264 /* Convert us timeout in ms and divide by two to trigger wdog every half timeout interval */
2266 (void) g_timeout_add_full(G_PRIORITY_DEFAULT,
2268 &NSM__boOnHandleTimerWdog,
2271 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Started wdog timer." ),
2272 DLT_STRING("Interval [ms]:"), DLT_UINT(u32WdogSec));
2276 DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Error. Invalid wdog config." ),
2277 DLT_STRING("WATCHDOG_USEC:"), DLT_STRING(sWdogSec));
2282 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Daemon not observed by wdog"));
2287 /**********************************************************************************************************************
2289 * The function initializes all file local variables
2291 **********************************************************************************************************************/
2292 static void NSM__vInitializeVariables(void)
2294 /* Initialize file local variables */
2295 NSM__pSessionMutex = NULL;
2296 NSM__pSessions = NULL;
2297 NSM__pLifecycleClients = NULL;
2298 NSM__pNodeStateMutex = NULL;
2299 NSM__enNodeState = NsmNodeState_NotSet;
2300 NSM__pNextApplicationModeMutex = NULL;
2301 NSM__pThisApplicationModeMutex = NULL;
2302 NSM__pFailedApplications = NULL;
2303 NSM__pCurrentLifecycleClient = NULL;
2304 NSM__enNextApplicationMode = NsmApplicationMode_NotSet;
2305 NSM__enThisApplicationMode = NsmApplicationMode_NotSet;
2306 NSM__boThisApplicationModeRead = FALSE;
2310 /**********************************************************************************************************************
2312 * The function creates the platform sessions, configured in "NSM__asDefaultSessions".
2314 **********************************************************************************************************************/
2315 static void NSM__vCreatePlatformSessions(void)
2317 NsmSession_s *pNewDefaultSession = NULL;
2318 guint u32DefaultSessionIdx = 0;
2319 NsmSeat_e enSeatIdx = NsmSeat_NotSet;
2321 /* Configure the default sessions, which are always available */
2322 for(u32DefaultSessionIdx = 0;
2323 u32DefaultSessionIdx < sizeof(NSM__asDefaultSessions)/sizeof(gchar*);
2324 u32DefaultSessionIdx++)
2326 /* Create a session for every session name and seat */
2327 for(enSeatIdx = NsmSeat_NotSet + 1; enSeatIdx < NsmSeat_Last; enSeatIdx++)
2329 pNewDefaultSession = g_new0(NsmSession_s, 1);
2330 g_strlcpy((gchar*) pNewDefaultSession->sName, NSM__asDefaultSessions[u32DefaultSessionIdx], sizeof(pNewDefaultSession->sName));
2331 g_strlcpy((gchar*) pNewDefaultSession->sOwner, NSM_DEFAULT_SESSION_OWNER, sizeof(pNewDefaultSession->sOwner));
2332 pNewDefaultSession->enSeat = enSeatIdx;
2333 pNewDefaultSession->enState = NsmSessionState_Inactive;
2335 NSM__pSessions = g_slist_append(NSM__pSessions, pNewDefaultSession);
2341 /**********************************************************************************************************************
2343 * The function creates the mutexes used in the NSM.
2345 **********************************************************************************************************************/
2346 static void NSM__vCreateMutexes(void)
2348 /* Initialize the local mutexes */
2349 NSM__pNodeStateMutex = g_mutex_new();
2350 NSM__pThisApplicationModeMutex = g_mutex_new();
2351 NSM__pNextApplicationModeMutex = g_mutex_new();
2352 NSM__pSessionMutex = g_mutex_new();
2356 /**********************************************************************************************************************
2358 * The function deletes the mutexes used in the NSM.
2360 **********************************************************************************************************************/
2361 static void NSM__vDeleteMutexes(void)
2363 /* Delete the local mutexes */
2364 g_mutex_free(NSM__pNodeStateMutex);
2365 g_mutex_free(NSM__pNextApplicationModeMutex);
2366 g_mutex_free(NSM__pThisApplicationModeMutex);
2367 g_mutex_free(NSM__pSessionMutex);
2371 /**********************************************************************************************************************
2373 * The function is called to trace a syslog message for a shutdown client.
2375 * @param sBus: Bus name of the shutdown client.
2376 * @param sObj: Object name of the lifecycle client.
2377 * @param u32Reason: Shutdown reason send to the client.
2378 * @param sInOut: "enter" or "leave" (including failure reason)
2379 * @param enErrorStatus: Error value
2381 **********************************************************************************************************************/
2382 static void NSM__vLtProf(gchar *sBus, gchar *sObj, guint32 u32Reason, gchar *sInOut, NsmErrorStatus_e enErrorStatus)
2384 gchar pszLtprof[128] = "LTPROF: bus:%s obj:%s (0x%08X:%d) ";
2385 guint32 dwLength = 128;
2387 g_strlcat(pszLtprof, sInOut, dwLength);
2391 if(u32Reason == NSM_SHUTDOWNTYPE_RUNUP)
2393 g_strlcat(pszLtprof, "runup", dwLength);
2397 g_strlcat(pszLtprof, "shutdown", dwLength);
2401 syslog(LOG_NOTICE, (char *)pszLtprof, sBus, sObj, u32Reason, enErrorStatus);
2405 /**********************************************************************************************************************
2407 * The function is used to initialize syslog
2409 **********************************************************************************************************************/
2410 static void NSM__vSyslogOpen(void)
2412 openlog("NSM", LOG_PID, LOG_USER);
2416 /**********************************************************************************************************************
2418 * The function is used to deinitialize syslog
2420 **********************************************************************************************************************/
2421 static void NSM__vSyslogClose(void)
2427 /**********************************************************************************************************************
2429 * Interfaces. Exported functions. See Header for detailed description.
2431 **********************************************************************************************************************/
2434 /* The function is called by the NodeStateMachine to set a "property" of the NSM. */
2435 NsmErrorStatus_e NsmSetData(NsmDataType_e enData, unsigned char *pData, unsigned int u32DataLen)
2437 /* Function local variables */
2438 NsmErrorStatus_e enRetVal = NsmErrorStatus_NotSet; /* Return value */
2440 /* Check which data the NSMC wants to set */
2443 /* NSMC wants to set the NodeState */
2444 case NsmDataType_NodeState:
2445 enRetVal = (u32DataLen == sizeof(NsmNodeState_e))
2446 ? NSM__enSetNodeState((NsmNodeState_e) *pData, TRUE, FALSE)
2447 : NsmErrorStatus_Parameter;
2450 /* NSMC wants to set the AppMode */
2451 case NsmDataType_AppMode:
2452 enRetVal = (u32DataLen == sizeof(NsmApplicationMode_e))
2453 ? NSM__enSetApplicationMode((NsmApplicationMode_e) *pData, TRUE, FALSE)
2454 : NsmErrorStatus_Parameter;
2457 /* NSMC wants to set the BootMode */
2458 case NsmDataType_BootMode:
2459 enRetVal = (u32DataLen == sizeof(gint))
2460 ? NSM__enSetBootMode((gint) *pData, FALSE)
2461 : NsmErrorStatus_Parameter;
2464 /* NSMC wants to set the ShutdownReason */
2465 case NsmDataType_ShutdownReason:
2466 enRetVal = (u32DataLen == sizeof(NsmShutdownReason_e))
2467 ? NSM__enSetShutdownReason((NsmShutdownReason_e) *pData, FALSE)
2468 : NsmErrorStatus_Parameter;
2471 /* NSMC wants to set a SessionState */
2472 case NsmDataType_SessionState:
2473 enRetVal = (u32DataLen == sizeof(NsmSession_s))
2474 ? NSM__enSetSessionState((NsmSession_s*) pData, TRUE, FALSE)
2475 : NsmErrorStatus_Parameter;
2478 /* NSMC wants to register a session */
2479 case NsmDataType_RegisterSession:
2480 enRetVal = (u32DataLen == sizeof(NsmSession_s))
2481 ? NSM__enRegisterSession((NsmSession_s*) pData, TRUE, FALSE)
2482 : NsmErrorStatus_Parameter;
2485 /* NSMC wants to unregister a session */
2486 case NsmDataType_UnRegisterSession:
2487 enRetVal = (u32DataLen == sizeof(NsmSession_s))
2488 ? NSM__enUnRegisterSession((NsmSession_s*) pData, TRUE, FALSE)
2489 : NsmErrorStatus_Parameter;
2492 /* Error: The type of the data NSMC is trying to set is unknown or the data is read only! */
2493 case NsmDataType_RestartReason:
2494 case NsmDataType_RunningReason:
2496 enRetVal = NsmErrorStatus_Parameter;
2504 /* The function is called by the NodeStateMachine to get a "property" of the NSM. */
2505 int NsmGetData(NsmDataType_e enData, unsigned char *pData, unsigned int u32DataLen)
2507 /* Function local variables */
2508 int i32RetVal = -1; /* Return value. Positive: Amount of written bytes.
2509 Negative: An error occurred. */
2511 /* Check which data the NSMC wants to get */
2514 /* NSMC wants to get the NodeState */
2515 case NsmDataType_NodeState:
2516 if(u32DataLen == sizeof(NsmNodeState_e))
2518 if(NSM__enGetNodeState((NsmNodeState_e*) pData) == NsmErrorStatus_Ok)
2520 i32RetVal = sizeof(NsmNodeState_e);
2525 /* NSMC wants to get the ApplicationMode */
2526 case NsmDataType_AppMode:
2527 if(u32DataLen == sizeof(NsmApplicationMode_e))
2529 if(NSM__enGetApplicationMode((NsmApplicationMode_e*) pData) == NsmErrorStatus_Ok)
2531 i32RetVal = sizeof(NsmApplicationMode_e);
2536 /* NSMC wants to get the BootMode */
2537 case NsmDataType_BootMode:
2538 if(u32DataLen == sizeof(gint))
2540 if(NSMA_boGetBootMode((gint*) pData) == TRUE)
2542 i32RetVal = sizeof(gint);
2547 /* NSMC wants to get the RunningReason */
2548 case NsmDataType_RunningReason:
2549 if(u32DataLen == sizeof(NsmRunningReason_e))
2551 if(NSMA_boGetRunningReason((NsmRunningReason_e*) pData) == TRUE)
2553 i32RetVal = sizeof(NsmRunningReason_e);
2558 /* NSMC wants to get the ShutdownReason */
2559 case NsmDataType_ShutdownReason:
2560 if(u32DataLen == sizeof(NsmShutdownReason_e))
2562 if(NSMA_boGetShutdownReason((NsmShutdownReason_e*) pData) == TRUE)
2564 i32RetVal = sizeof(NsmShutdownReason_e);
2569 /* NSMC wants to get the RestartReason */
2570 case NsmDataType_RestartReason:
2571 if(u32DataLen == sizeof(NsmRestartReason_e))
2573 if(NSMA_boGetRestartReason((NsmRestartReason_e*) pData) == TRUE)
2575 i32RetVal = sizeof(NsmRestartReason_e);
2580 /* NSMC wants to get the SessionState */
2581 case NsmDataType_SessionState:
2582 if(u32DataLen == sizeof(NsmSession_s))
2584 if(NSM__enGetSessionState((NsmSession_s*) pData) == NsmErrorStatus_Ok)
2586 i32RetVal = sizeof(NsmSession_s);
2591 /* Error: The type of the data NSMC is trying to set is unknown. */
2601 unsigned int NsmGetInterfaceVersion(void)
2603 return NSM_INTERFACE_VERSION;
2607 /* The main function of the NodeStateManager */
2610 gboolean boEndByUser = FALSE;
2613 /* Initialize glib for using "g" types */
2616 /* Register NSM for DLT */
2617 DLT_REGISTER_APP("NSM", "Node State Manager");
2618 DLT_REGISTER_CONTEXT(NsmContext, "005", "Context for the NSM");
2619 DLT_ENABLE_LOCAL_PRINT();
2621 /* Initialize syslog */
2624 /* Print first msg. to show that NSM is going to start */
2625 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: NodeStateManager started."), DLT_STRING("Version:"), DLT_STRING(VERSION));
2627 /* Initialize PCL before initializing variables */
2628 pcl_return = pclInitLibrary("NodeStateManager", PCL_SHUTDOWN_TYPE_NORMAL
2629 | PCL_SHUTDOWN_TYPE_FAST);
2634 DLT_STRING("NSM: Failed to initialize PCL.");
2635 DLT_STRING("Error: Unexpected PCL return.");
2636 DLT_STRING("Return:"); DLT_INT(pcl_return));
2639 /* Currently no other resources accessing the NSM. Prepare it now! */
2640 NSM__vInitializeVariables(); /* Initialize file local variables*/
2641 NSM__vCreatePlatformSessions(); /* Create platform sessions */
2642 NSM__vCreateMutexes(); /* Create mutexes */
2644 /* Initialize the NSMA before the NSMC, because the NSMC can access properties */
2645 if(NSMA_boInit(&NSM__stObjectCallBacks) == TRUE)
2647 /* Set the properties to initial values */
2648 (void) NSMA_boSetBootMode(0);
2649 (void) NSMA_boSetRestartReason(NsmRestartReason_NotSet);
2650 (void) NSMA_boSetShutdownReason(NsmShutdownReason_NotSet);
2651 (void) NSMA_boSetRunningReason(NsmRunningReason_WakeupCan);
2653 /* Initialize/start the NSMC */
2654 if(NsmcInit() == 0x01)
2656 /* Start timer to satisfy wdog */
2657 NSM__vConfigureWdogTimer();
2659 /* The event loop is only canceled if the Node is completely shut down or there is an internal error. */
2660 boEndByUser = NSMA_boWaitForEvents();
2662 if(boEndByUser == TRUE)
2664 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Successfully canceled event loop. "),
2665 DLT_STRING("Shutting down NodeStateManager." ));
2669 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: Error in event loop. " ),
2670 DLT_STRING("Shutting down NodeStateManager."));
2673 /* The event loop returned. Clean up the NSMA. */
2674 (void) NSMA_boDeInit();
2678 /* Error: Failed to initialize the NSMC. Clean up NSMA, because it is not needed anymore. */
2679 (void) NSMA_boDeInit();
2680 DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Error. Failed to initialize the NSMC."));
2685 /* Error: Failed to initialize the NSMA. */
2686 DLT_LOG(NsmContext, DLT_LOG_ERROR, DLT_STRING("NSM: Error. Failed to initialize the NSMA."));
2689 /* Free the mutexes */
2690 NSM__vDeleteMutexes();
2692 /* Remove data from all lists */
2693 g_slist_free_full(NSM__pSessions, &NSM__vFreeSessionObject);
2694 g_slist_free_full(NSM__pFailedApplications, &NSM__vFreeFailedApplicationObject);
2695 g_list_free_full (NSM__pLifecycleClients, &NSM__vFreeLifecycleClientObject);
2697 /* Deinitialize the PCL */
2698 pcl_return = pclDeinitLibrary();
2704 DLT_STRING("NSM: Failed to deinitialize PCL.");
2705 DLT_STRING("Error: Unexpected PCL return.");
2706 DLT_STRING("Return:"); DLT_INT(pcl_return));
2709 DLT_LOG(NsmContext, DLT_LOG_INFO, DLT_STRING("NSM: NodeStateManager stopped."));
2712 NSM__vSyslogClose();
2714 /* Unregister NSM from DLT */
2715 DLT_UNREGISTER_CONTEXT(NsmContext);
2716 DLT_UNREGISTER_APP();