summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIngo Huerner <ingo_huerner@mentor.com>2017-02-21 10:21:29 +0100
committerIngo Huerner <ingo_huerner@mentor.com>2017-02-21 10:21:29 +0100
commite88cdcdee8aa92d62b6a77ed1e938afb107229f4 (patch)
tree61527f6575824231743618e440f9632476f77cc6
parent2e190294dfd19ab9612e2576ebbaeff738990f70 (diff)
downloadpersistence-client-library-e88cdcdee8aa92d62b6a77ed1e938afb107229f4.tar.gz
Handling of dbus pending calls rework (mutex handling improved, added condvar).
Improved registration to PAS: if PAS is not available when calling pclInit, PCL registers itself as soon as PAS will be available
-rw-r--r--src/persistence_client_library.c112
-rw-r--r--src/persistence_client_library_data_organization.c3
-rw-r--r--src/persistence_client_library_data_organization.h4
-rw-r--r--src/persistence_client_library_dbus_cmd.c14
-rw-r--r--src/persistence_client_library_dbus_service.c150
-rw-r--r--src/persistence_client_library_dbus_service.h3
-rw-r--r--src/persistence_client_library_pas_interface.c26
7 files changed, 227 insertions, 85 deletions
diff --git a/src/persistence_client_library.c b/src/persistence_client_library.c
index 1739e5c..1b1b551 100644
--- a/src/persistence_client_library.c
+++ b/src/persistence_client_library.c
@@ -238,82 +238,69 @@ static int private_pclInitLibrary(const char* appName, int shutdownMode)
{
int rval = 1;
char blacklistPath[PERS_ORG_MAX_LENGTH_PATH_FILENAME] = {0};
- int lock = pthread_mutex_lock(&gDbusPendingRegMtx); // block until pending received
- if(lock == 0)
- {
- gShutdownMode = shutdownMode;
+
+ gShutdownMode = shutdownMode;
#if USE_APPCHECK
- doInitAppcheck(appName); // check if we have a trusted application
+ doInitAppcheck(appName); // check if we have a trusted application
#endif
#if USE_FILECACHE
- DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("Using the filecache!!!"));
- pfcInitCache(appName);
+ DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("Using the filecache!!!"));
+ pfcInitCache(appName);
#endif
- // Assemble backup blacklist path
- snprintf(blacklistPath, PERS_ORG_MAX_LENGTH_PATH_FILENAME, "%s%s/%s", CACHEPREFIX, appName, gBackupFilename);
+ // Assemble backup blacklist path
+ snprintf(blacklistPath, PERS_ORG_MAX_LENGTH_PATH_FILENAME, "%s%s/%s", CACHEPREFIX, appName, gBackupFilename);
- if(readBlacklistConfigFile(blacklistPath) == -1)
- {
- DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("initLibrary - Err access blacklist:"), DLT_STRING(blacklistPath));
- }
+ if(readBlacklistConfigFile(blacklistPath) == -1)
+ {
+ DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("initLibrary - Err access blacklist:"), DLT_STRING(blacklistPath));
+ }
- if(setup_dbus_mainloop() == -1)
- {
- DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("initLibrary - Failed to setup main loop"));
- pthread_mutex_unlock(&gDbusPendingRegMtx);
- return EPERS_DBUS_MAINLOOP;
- }
+ if(setup_dbus_mainloop() == -1)
+ {
+ DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("initLibrary - Failed to setup main loop"));
+ return EPERS_DBUS_MAINLOOP;
+ }
- if(gShutdownMode != PCL_SHUTDOWN_TYPE_NONE)
- {
- if(register_lifecycle(shutdownMode) == -1) // register for lifecycle dbus messages
- {
- DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("initLibrary => Failed reg to LC dbus interface"));
- pthread_mutex_unlock(&gDbusPendingRegMtx);
- return EPERS_REGISTER_LIFECYCLE;
- }
- }
+
+ if(gShutdownMode != PCL_SHUTDOWN_TYPE_NONE)
+ {
+ if(register_lifecycle(shutdownMode) == -1) // register for lifecycle dbus messages
+ {
+ DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("initLibrary => Failed reg to LC dbus interface"));
+ }
+ }
#if USE_PASINTERFACE
- DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("PAS interface is enabled!!"));
- if(register_pers_admin_service() == -1)
- {
- DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("initLibrary - Failed reg to PAS dbus interface"));
- pthread_mutex_unlock(&gDbusPendingRegMtx);
- return EPERS_REGISTER_ADMIN;
- }
- else
- {
- DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("initLibrary - Successfully established IPC protocol for PCL."));
- }
+ DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("PAS interface is enabled!!"));
+ if(register_pers_admin_service() == -1)
+ {
+ DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("initLibrary - Failed reg to PAS dbus interface"));
+ }
+ else
+ {
+ DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("initLibrary - Successfully established IPC protocol for PCL."));
+ gPasRegistered = 1; // remember registration to PAS
+ }
#else
- DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("PAS interface not enabled, enable with \"./configure --enable-pasinterface\""));
+ DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("PAS interface not enabled, enable with \"./configure --enable-pasinterface\""));
#endif
- if((rval = load_custom_plugins(customAsyncInitClbk)) < 0) // load custom plugins
- {
- DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("Failed to load custom plugins"));
- pthread_mutex_unlock(&gDbusPendingRegMtx);
- return rval;
- }
-
- init_key_handle_array();
+ if((rval = load_custom_plugins(customAsyncInitClbk)) < 0) // load custom plugins
+ {
+ DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("Failed to load custom plugins"));
+ return rval;
+ }
- pers_unlock_access();
+ init_key_handle_array();
- strncpy(gAppId, appName, PERS_RCT_MAX_LENGTH_RESPONSIBLE); // assign application name
- gAppId[PERS_RCT_MAX_LENGTH_RESPONSIBLE-1] = '\0';
+ strncpy(gAppId, appName, PERS_RCT_MAX_LENGTH_RESPONSIBLE); // assign application name
+ gAppId[PERS_RCT_MAX_LENGTH_RESPONSIBLE-1] = '\0';
- pthread_mutex_unlock(&gDbusPendingRegMtx);
- }
- else
- {
- DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("private_pclInitLibrary - mutex lock failed:"), DLT_INT(lock));
- }
+ pers_unlock_access();
return rval;
}
@@ -371,12 +358,13 @@ static int private_pclDeinitLibrary(void)
#if USE_PASINTERFACE == 1
rval = unregister_pers_admin_service();
if(0 != rval)
- {
- DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pclDeinitLibrary - Err to de-initialize IPC protocol for PCL."));
- }
+ {
+ DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pclDeinitLibrary - Err to de-initialize IPC protocol for PCL."));
+ }
else
{
- DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("pclDeinitLibrary - Succ de-initialized IPC protocol for PCL."));
+ DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("pclDeinitLibrary - Succ de-initialized IPC protocol for PCL."));
+ gPasRegistered = 0;
}
#endif
@@ -400,8 +388,6 @@ static int private_pclDeinitLibrary(void)
deleteBackupTree();
deleteNotifyTree();
- pthread_mutex_unlock(&gDbusPendingRegMtx);
-
#if USE_FILECACHE
pfcDeinitCache();
#endif
diff --git a/src/persistence_client_library_data_organization.c b/src/persistence_client_library_data_organization.c
index ef77d2f..db26ef5 100644
--- a/src/persistence_client_library_data_organization.c
+++ b/src/persistence_client_library_data_organization.c
@@ -27,6 +27,9 @@ char gAppId[PERS_RCT_MAX_LENGTH_RESPONSIBLE] = { [0 ... PERS_RCT_MAX_LENGTH_RESP
/// flag to indicate if client library has been initialized
unsigned int gPclInitCounter = 0;
+/// flag to indicate if PCL has registered to PAS
+int gPasRegistered = 0;
+
int(* gChangeNotifyCallback)(pclNotification_s * notifyStruct);
/// character lookup table used for parsing configuration files
diff --git a/src/persistence_client_library_data_organization.h b/src/persistence_client_library_data_organization.h
index 211fb3a..429b77a 100644
--- a/src/persistence_client_library_data_organization.h
+++ b/src/persistence_client_library_data_organization.h
@@ -280,6 +280,10 @@ extern unsigned int gPclInitCounter __attribute__ ((visibility ("hidden")));
extern int gDbusPendingRvalue __attribute__ ((visibility ("hidden")));
+/// flag to indicate if PCL has registered to PAS
+extern int gPasRegistered;
+
+
/**
* @brief definition of change callback function
*
diff --git a/src/persistence_client_library_dbus_cmd.c b/src/persistence_client_library_dbus_cmd.c
index 0f17bd4..18b5f74 100644
--- a/src/persistence_client_library_dbus_cmd.c
+++ b/src/persistence_client_library_dbus_cmd.c
@@ -457,11 +457,15 @@ void msg_pending_func(DBusPendingCall *call, void *data)
DBusError err;
dbus_error_init(&err);
+ DBusMessage *message = NULL;
+
(void)data;
- DBusMessage *message = dbus_pending_call_steal_reply(call);
+ pthread_mutex_lock(&gDbusPendingRegMtx);
+
+ message = dbus_pending_call_steal_reply(call);
- if (dbus_set_error_from_message(&err, message))
+ if(dbus_set_error_from_message(&err, message))
{
DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("msgPendFunc - Access denied") );
}
@@ -472,8 +476,12 @@ void msg_pending_func(DBusPendingCall *call, void *data)
}
gDbusPendingRvalue = replyArg; // set the return value
- dbus_message_unref(message);
+
+ gDbusPendingCondValue = 1;
+ pthread_cond_signal(&gDbusPendingCond);
// unlock the mutex because we have received the reply to the dbus message
pthread_mutex_unlock(&gDbusPendingRegMtx);
+
+ dbus_message_unref(message);
}
diff --git a/src/persistence_client_library_dbus_service.c b/src/persistence_client_library_dbus_service.c
index b19d607..981982e 100644
--- a/src/persistence_client_library_dbus_service.c
+++ b/src/persistence_client_library_dbus_service.c
@@ -29,15 +29,16 @@
DLT_IMPORT_CONTEXT(gPclDLTContext);
pthread_mutex_t gDbusPendingRegMtx = PTHREAD_MUTEX_INITIALIZER;
-
-pthread_mutex_t gDeliverpMtx = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t gDbusPendingCond = PTHREAD_COND_INITIALIZER;
+int gDbusPendingCondValue = 0;
pthread_mutex_t gMainCondMtx = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t gMainLoopCond = PTHREAD_COND_INITIALIZER;
+int gMainLoopCondValue = 0;
-pthread_t gMainLoopThread;
+pthread_mutex_t gDeliverpMtx = PTHREAD_MUTEX_INITIALIZER;
-int gMainLoopCondValue = 0;
+pthread_t gMainLoopThread;
const char* gDbusLcConsDest = "org.genivi.NodeStateManager";
@@ -47,6 +48,7 @@ const char* gDbusLcInterface = "org.genivi.NodeStateManager.Consumer";
const char* gDbusLcCons = "/org/genivi/NodeStateManager/Consumer";
const char* gDbusLcConsMsg = "LifecycleRequest";
+
const char* gDbusPersAdminConsInterface = "org.genivi.persistence.adminconsumer";
const char* gPersAdminConsumerPath = "/org/genivi/persistence/adminconsumer";
const char* gDbusPersAdminPath = "/org/genivi/persistence/admin";
@@ -103,10 +105,54 @@ static void unregisterMessageHandler(DBusConnection *connection, void *user_data
}
+#if USE_PASINTERFACE
+
+void* doSendPasRegister(void *data)
+{
+ long rval = 0;
+
+ rval = (long)register_pers_admin_service(); // register to PAS
+
+ return (void*)rval;
+}
+
+void* registerToPas(void* data)
+{
+ pthread_t thread;
+ long* retval = NULL;
+
+ // create send thread in order to wait until registration succeeded
+ pthread_create(&thread, NULL, doSendPasRegister, NULL);
+
+ // wait untill registration has finished
+ pthread_join(thread, (void**)&retval);
+
+ if((long)retval == -1)
+ {
+ //printf("==> PAS Appeared - register failed\n");
+ DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("NameOwnerChanged - Failed reg to PAS dbus interface"));
+ }
+ else
+ {
+ //printf("==> PAS Appeared - register success\n");
+ DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("NameOwnerChanged - Successfully established IPC protocol for PCL."));
+ gPasRegistered = 1; // remember registration to PAS
+ }
+
+ return NULL;
+}
+
+#endif
+
+
+
/* catches messages not directed to any registered object path ("garbage collector") */
static DBusHandlerResult handleObjectPathMessageFallback(DBusConnection * connection, DBusMessage * message, void * user_data)
{
DBusHandlerResult result = DBUS_HANDLER_RESULT_HANDLED;
+ DBusError error;
+ DBusMessage *reply;
+ dbus_error_init (&error);
(void)user_data;
if((0==strcmp(gDbusPersAdminConsInterface, dbus_message_get_interface(message))))
@@ -134,9 +180,6 @@ static DBusHandlerResult handleObjectPathMessageFallback(DBusConnection * connec
if(validMessage == 1)
{
- DBusError error;
- DBusMessage *reply;
- dbus_error_init (&error);
char *ldbid, *user_no, *seat_no;
if (!dbus_message_get_args(message, &error, DBUS_TYPE_STRING, &notifyStruct.resource_id,
@@ -157,7 +200,7 @@ static DBusHandlerResult handleObjectPathMessageFallback(DBusConnection * connec
DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("handleObjPathMsgFback - DBus No mem"), DLT_STRING(dbus_message_get_interface(message)) );
}
- result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;;
+ result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
dbus_message_unref(reply);
}
else
@@ -178,8 +221,88 @@ static DBusHandlerResult handleObjectPathMessageFallback(DBusConnection * connec
}
dbus_connection_flush(connection);
}
+ else
+ {
+ result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+ }
+ else
+ {
+ result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
}
+#if USE_PASINTERFACE
+ else if((0==strcmp("org.freedesktop.DBus", dbus_message_get_interface(message))))
+ {
+ if(dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
+ {
+ if((0==strcmp("NameOwnerChanged", dbus_message_get_member(message))))
+ {
+ char* dbusname = NULL;
+ char* new_owner = NULL;
+ char* old_owner = NULL;
+
+ if(!dbus_message_get_args(message, &error, DBUS_TYPE_STRING, &dbusname,
+ DBUS_TYPE_STRING, &new_owner,
+ DBUS_TYPE_STRING, &old_owner,
+ DBUS_TYPE_INVALID))
+ {
+ reply = dbus_message_new_error(message, error.name, error.message);
+
+ if(reply == 0)
+ {
+ DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("handleObjPathMsgFback - DBus No mem"), DLT_STRING(dbus_message_get_interface(message)) );
+ }
+
+ if(!dbus_connection_send(connection, reply, 0))
+ {
+ DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("handleObjPathMsgFback - DBus No mem"), DLT_STRING(dbus_message_get_interface(message)) );
+ }
+
+ result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ dbus_message_unref(reply);
+ }
+ else
+ {
+ if(0==strcmp(gDbusPersAdminInterface, dbusname)) // listen when PAS becomes available/unavailable
+ {
+ if(new_owner != NULL)
+ {
+ if(new_owner[0] == '\0')
+ {
+ DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("NameOwnerChanged - PAS service appeared"));
+ if(gPasRegistered == 0)
+ {
+ pthread_t thread;
+ // create register thread to prevent blocking of mainloop until registration has finished
+ pthread_create(&thread, NULL, registerToPas, NULL);
+ }
+ }
+ }
+
+ if(old_owner != NULL)
+ {
+ if(old_owner[0] == '\0')
+ {
+ printf("PAS Disappeared\n");
+ DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("NameOwnerChanged - PAS service disappeared"));
+ gPasRegistered = 0; // just remember not PAS disappeared, no ned to unregister as service is not available anymore
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+ }
+ }
+#endif
+ else
+ {
+ result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
return result;
}
@@ -412,11 +535,11 @@ int setup_dbus_mainloop(void)
else
{
// persistence administrator message
- const struct DBusObjectPathVTable vtablePersAdmin = {unregisterMessageHandler, checkPersAdminMsg, NULL, NULL, NULL, NULL};
+ static const struct DBusObjectPathVTable vtablePersAdmin = {unregisterMessageHandler, checkPersAdminMsg, NULL, NULL, NULL, NULL};
// lifecycle message
- const struct DBusObjectPathVTable vtableLifecycle = {unregisterMessageHandler, checkLifecycleMsg, NULL, NULL, NULL, NULL};
+ static const struct DBusObjectPathVTable vtableLifecycle = {unregisterMessageHandler, checkLifecycleMsg, NULL, NULL, NULL, NULL};
// fallback
- const struct DBusObjectPathVTable vtableFallback = {unregisterObjectPathFallback, handleObjectPathMessageFallback, NULL, NULL, NULL, NULL};
+ static const struct DBusObjectPathVTable vtableFallback = {unregisterObjectPathFallback, handleObjectPathMessageFallback, NULL, NULL, NULL, NULL};
#if USE_PASINTERFACE != 1
(void)vtablePersAdmin;
@@ -428,6 +551,9 @@ int setup_dbus_mainloop(void)
gPollInfo.fds[0].events = POLLIN;
dbus_bus_add_match(conn, "type='signal',interface='org.genivi.persistence.admin',member='PersistenceModeChanged',path='/org/genivi/persistence/admin'", &err);
+#if USE_PASINTERFACE
+ dbus_bus_add_match(conn, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged',path='/org/freedesktop/DBus'", &err);
+#endif
// register for messages
if ( (TRUE==dbus_connection_register_object_path(conn, gDbusLcConsPath, &vtableLifecycle, conn))
@@ -670,13 +796,11 @@ int deliverToMainloop(MainLoopData_u* payload)
pthread_mutex_lock(&gDeliverpMtx); // make sure deliverToMainloop will be used exclusively
rval = deliverToMainloop_NM(payload);
-
pthread_mutex_lock(&gMainCondMtx); // mutex needed for pthread condition used to wait on other thread (mainloop)
while(0 == gMainLoopCondValue)
pthread_cond_wait(&gMainLoopCond, &gMainCondMtx);
pthread_mutex_unlock(&gMainCondMtx);
-
gMainLoopCondValue = 0;
pthread_mutex_unlock(&gDeliverpMtx);
diff --git a/src/persistence_client_library_dbus_service.h b/src/persistence_client_library_dbus_service.h
index 365d11b..d3f70d6 100644
--- a/src/persistence_client_library_dbus_service.h
+++ b/src/persistence_client_library_dbus_service.h
@@ -65,6 +65,9 @@ typedef struct MainLoopData_u_{
/// dbus pending mutex => visibility "hidden" to prevent the use outside the library
extern pthread_mutex_t gDbusPendingRegMtx __attribute__ ((visibility ("hidden")));
+extern pthread_cond_t gDbusPendingCond;
+extern int gDbusPendingCondValue;
+
/// dbus mainloop conditional variable => visibility "hidden" to prevent the use outside the library
extern pthread_mutex_t gMainCondMtx __attribute__ ((visibility ("hidden")));
/// dbus mainloop mutex => visibility "hidden" to prevent the use outside the library
diff --git a/src/persistence_client_library_pas_interface.c b/src/persistence_client_library_pas_interface.c
index 2e41bc7..cda4e01 100644
--- a/src/persistence_client_library_pas_interface.c
+++ b/src/persistence_client_library_pas_interface.c
@@ -191,13 +191,21 @@ int register_pers_admin_service(void)
if(-1 == deliverToMainloop(&data))
{
- DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("regPas - failed write pipe"), DLT_INT(errno));
- rval = -1;
+ DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("regPas - failed write pipe"), DLT_INT(errno));
+ rval = -1;
}
else
{
- pthread_mutex_lock(&gDbusPendingRegMtx); // block until pending received
+ pthread_mutex_lock(&gDbusPendingRegMtx);
+ while(0 == gDbusPendingCondValue)
+ {
+ pthread_cond_wait(&gDbusPendingCond, &gDbusPendingRegMtx);
+ }
+ pthread_mutex_unlock(&gDbusPendingRegMtx);
+
+ gDbusPendingCondValue = 0;
rval = gDbusPendingRvalue;
+
}
return rval;
}
@@ -218,13 +226,19 @@ int unregister_pers_admin_service(void)
if(-1 == deliverToMainloop(&data))
{
- DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("unregPas - failed write pipe"), DLT_INT(errno));
- rval = -1;
+ DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("unregPas - failed write pipe"), DLT_INT(errno));
+ rval = -1;
}
else
{
- pthread_mutex_lock(&gDbusPendingRegMtx); // block until pending received
+ pthread_mutex_lock(&gDbusPendingRegMtx);
+ while(0 == gDbusPendingCondValue)
+ pthread_cond_wait(&gDbusPendingCond, &gDbusPendingRegMtx);
+ pthread_mutex_unlock(&gDbusPendingRegMtx);
+
+ gDbusPendingCondValue = 0;
rval = gDbusPendingRvalue;
+
}
return rval;
}