1 /******************************************************************************
4 * Company XS Embedded GmbH
5 *****************************************************************************/
6 /******************************************************************************
7 * This Source Code Form is subject to the terms of the
8 * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed
9 * with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 ******************************************************************************/
12 * @file persistence_client_library.c
13 * @ingroup Persistence client library
14 * @author Ingo Huerner
15 * @brief Implementation of the persistence client library.
16 * Library provides an API to access persistent data
21 #include "persistence_client_library_lc_interface.h"
22 #include "persistence_client_library_pas_interface.h"
23 #include "persistence_client_library_dbus_service.h"
24 #include "persistence_client_library_handle.h"
25 #include "persistence_client_library_custom_loader.h"
26 #include "persistence_client_library.h"
27 #include "persistence_client_library_backup_filelist.h"
28 #include "persistence_client_library_db_access.h"
31 #include <persistence_file_cache.h>
38 #include <dbus/dbus.h>
40 /// debug log and trace (DLT) setup
41 DLT_DECLARE_CONTEXT(gPclDLTContext);
43 static int gShutdownMode = 0;
45 static int gCancelCounter = 0;
48 int customAsyncInitClbk(int errcode)
50 printf("Dummy async init Callback\n");
54 int pclInitLibrary(const char* appName, int shutdownMode)
58 printf("INIT START\n\n");
60 if(gPclInitialized == PCLnotInitialized)
62 printf("INIT START ==> DO INIT\n\n");
63 gShutdownMode = shutdownMode;
65 DLT_REGISTER_CONTEXT(gPclDLTContext,"PCL","Context for persistence client library logging");
66 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("pclInitLibrary => I N I T Persistence Client Library - "), DLT_STRING(appName),
67 DLT_STRING("- init counter: "), DLT_INT(gPclInitialized) );
69 /// environment variable for max key value data
70 const char *pDataSize = getenv("PERS_MAX_KEY_VAL_DATA_SIZE");
71 /// blacklist path environment variable
72 const char *pBlacklistPath = getenv("PERS_BLACKLIST_PATH");
75 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("Using the filecache!!!"));
76 pfcInitCache(appName);
79 pthread_mutex_lock(&gDbusPendingRegMtx); // block until pending received
83 gMaxKeyValDataSize = atoi(pDataSize);
86 if(pBlacklistPath == NULL)
88 pBlacklistPath = "/etc/pclBackupBlacklist.txt"; // default path
91 if(readBlacklistConfigFile(pBlacklistPath) == -1)
93 DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("pclInitLibrary -> failed to access blacklist:"), DLT_STRING(pBlacklistPath));
96 if(setup_dbus_mainloop() == -1)
98 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pclInitLibrary => Failed to setup main loop"));
99 pthread_mutex_unlock(&gDbusPendingRegMtx);
100 return EPERS_DBUS_MAINLOOP;
104 if(gShutdownMode != PCL_SHUTDOWN_TYPE_NONE)
106 // register for lifecycle dbus messages
107 if(register_lifecycle(shutdownMode) == -1)
109 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pclInitLibrary => Failed to register to lifecycle dbus interface"));
110 pthread_mutex_unlock(&gDbusPendingRegMtx);
111 return EPERS_REGISTER_LIFECYCLE;
114 #if USE_PASINTERFACE == 1
115 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("PAS interface is enabled!!"));
116 if(register_pers_admin_service() == -1)
118 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pclInitLibrary => Failed to register to pers admin dbus interface"));
119 pthread_mutex_unlock(&gDbusPendingRegMtx);
120 return EPERS_REGISTER_ADMIN;
124 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("pclInitLibrary => Successfully established IPC protocol for PCL."));
127 DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("PAS interface is not enabled, enable with \"./configure --enable-pasinterface\""));
131 /// get custom library names to load
132 if(get_custom_libraries() >= 0)
134 // initialize custom library structure
135 for(i = 0; i < PersCustomLib_LastEntry; i++)
137 invalidate_custom_plugin(i);
140 for(i=0; i < PersCustomLib_LastEntry; i++ )
142 if(check_valid_idx(i) != -1)
144 if(getCustomLoadingType(i) == LoadType_PclInit) // check if the plugin must be loaded on plc init
146 if(load_custom_library(i, &gPersCustomFuncs[i] ) == 1)
148 PersInitType_e initType = getCustomInitType(i);
149 if(initType == Init_Synchronous)
151 if( (gPersCustomFuncs[i].custom_plugin_init) != NULL)
153 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("pclInitLibrary => plugin: "), DLT_STRING(get_custom_client_lib_name(i)));
154 gPersCustomFuncs[i].custom_plugin_init();
158 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pclInitLibrary => E r r o r could not load plugin functions: "),
159 DLT_STRING(get_custom_client_lib_name(i)));
162 else if(initType == Init_Asynchronous)
164 if( (gPersCustomFuncs[i].custom_plugin_init_async) != NULL)
166 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("pclInitLibrary => plugin: "), DLT_STRING(get_custom_client_lib_name(i)));
167 gPersCustomFuncs[i].custom_plugin_init_async(customAsyncInitClbk);
171 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pclInitLibrary => E r r o r could not load plugin functions: "),
172 DLT_STRING(get_custom_client_lib_name(i)));
177 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pclInitLibrary => E r r o r unknown init type "), DLT_STRING(get_custom_client_lib_name(i)));
182 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pclInitLibrary => E r r o r could not load plugin: "),
183 DLT_STRING(get_custom_client_lib_name(i)));
195 DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("pclInit => Failed to load custom library config table"));
198 // initialize keyHandle array
199 memset(gKeyHandleArray, 0, MaxPersHandle * sizeof(PersistenceKeyHandle_s));
201 pers_unlock_access();
203 // assign application name
204 strncpy(gAppId, appName, MaxAppNameLen);
205 gAppId[MaxAppNameLen-1] = '\0';
209 else if(gPclInitialized >= PCLinitialized)
211 gPclInitialized++; // increment init counter
212 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("pclInitLibrary => I N I T Persistence Client Library - "), DLT_STRING(gAppId),
213 DLT_STRING("- ONLY INCREMENT init counter: "), DLT_INT(gPclInitialized) );
221 int pclDeinitLibrary(void)
225 if(gPclInitialized == PCLinitialized)
228 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("pclDeinitLibrary -> D E I N I T client library - "), DLT_STRING(gAppId),
229 DLT_STRING("- init counter: "), DLT_INT(gPclInitialized));
231 // unregister for lifecycle dbus messages
232 if(gShutdownMode != PCL_SHUTDOWN_TYPE_NONE)
233 rval = unregister_lifecycle(gShutdownMode);
235 #if USE_PASINTERFACE == 1
236 rval = unregister_pers_admin_service();
239 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pclDeinitLibrary => Failed to de-initialize IPC protocol for PCL."));
243 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("pclDeinitLibrary => Successfully de-initialized IPC protocol for PCL."));
247 // unload custom client libraries
248 for(i=0; i<PersCustomLib_LastEntry; i++)
250 if(gPersCustomFuncs[i].custom_plugin_deinit != NULL)
252 // deinitialize plugin
253 gPersCustomFuncs[i].custom_plugin_deinit();
254 // close library handle
255 dlclose(gPersCustomFuncs[i].handle);
257 invalidate_custom_plugin(i);
261 process_prepare_shutdown(Shutdown_Full); // close all db's and fd's and block access
266 // send quit command to dbus mainloop
267 deliverToMainloop_NM(CMD_QUIT, 0, 0);
269 // wait until the dbus mainloop has ended
270 pthread_join(gMainLoopThread, (void**)&retval);
272 pthread_mutex_unlock(&gDbusPendingRegMtx);
273 pthread_mutex_unlock(&gDbusInitializedMtx);
275 gPclInitialized = PCLnotInitialized;
281 DLT_UNREGISTER_CONTEXT(gPclDLTContext);
283 else if(gPclInitialized > PCLinitialized)
285 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("pclDeinitLibrary -> D E I N I T client library - "), DLT_STRING(gAppId),
286 DLT_STRING("- ONLY DECREMENT init counter: "), DLT_INT(gPclInitialized));
287 gPclInitialized--; // decrement init counter
291 rval = EPERS_NOT_INITIALIZED;
298 int pclLifecycleSet(int shutdown)
302 if(gShutdownMode == PCL_SHUTDOWN_TYPE_NONE)
306 process_prepare_shutdown(Shutdown_Partial); // close all db's and fd's and block access
308 else if(PCL_SHUTDOWN_CANEL)
310 if(gCancelCounter < Shutdown_MaxCount)
312 pers_unlock_access();
316 rval = EPERS_SHUTDOWN_MAX_CANCEL;
326 rval = EPERS_SHUTDOWN_NO_PERMIT;