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 pclInitLibrary(const char* appName, int shutdownMode)
53 if(gPclInitialized == PCLnotInitialized)
55 gShutdownMode = shutdownMode;
57 DLT_REGISTER_CONTEXT(gPclDLTContext,"PCL","Context for persistence client library logging");
58 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("pclInitLibrary => I N I T Persistence Client Library - "), DLT_STRING(appName),
59 DLT_STRING("- init counter: "), DLT_INT(gPclInitialized) );
61 /// environment variable for on demand loading of custom libraries
62 const char *pOnDemandLoad = getenv("PERS_CUSTOM_LIB_LOAD_ON_DEMAND");
63 /// environment variable for max key value data
64 const char *pDataSize = getenv("PERS_MAX_KEY_VAL_DATA_SIZE");
65 /// blacklist path environment variable
66 const char *pBlacklistPath = getenv("PERS_BLACKLIST_PATH");
69 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("Using the filecache!!!"));
70 pfcInitCache(appName);
73 pthread_mutex_lock(&gDbusPendingRegMtx); // block until pending received
77 gMaxKeyValDataSize = atoi(pDataSize);
80 if(pBlacklistPath == NULL)
82 pBlacklistPath = "/etc/pclBackupBlacklist.txt"; // default path
85 if(readBlacklistConfigFile(pBlacklistPath) == -1)
87 DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("pclInitLibrary -> failed to access blacklist:"), DLT_STRING(pBlacklistPath));
90 if(setup_dbus_mainloop() == -1)
92 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pclInitLibrary => Failed to setup main loop"));
93 pthread_mutex_unlock(&gDbusPendingRegMtx);
94 return EPERS_DBUS_MAINLOOP;
98 if(gShutdownMode != PCL_SHUTDOWN_TYPE_NONE)
100 // register for lifecycle dbus messages
101 if(register_lifecycle(shutdownMode) == -1)
103 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pclInitLibrary => Failed to register to lifecycle dbus interface"));
104 pthread_mutex_unlock(&gDbusPendingRegMtx);
105 return EPERS_REGISTER_LIFECYCLE;
108 #if USE_PASINTERFACE == 1
109 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("PAS interface is enabled!!"));
110 if(register_pers_admin_service() == -1)
112 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pclInitLibrary => Failed to register to pers admin dbus interface"));
113 pthread_mutex_unlock(&gDbusPendingRegMtx);
114 return EPERS_REGISTER_ADMIN;
118 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("pclInitLibrary => Successfully established IPC protocol for PCL."));
121 DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("PAS interface is not enabled, enable with \"./configure --enable-pasinterface\""));
124 /// get custom library names to load
125 status = get_custom_libraries();
128 // initialize custom library structure
129 for(i = 0; i < PersCustomLib_LastEntry; i++)
131 invalidate_custom_plugin(i);
134 if(pOnDemandLoad == NULL) // load all available libraries now
136 for(i=0; i < PersCustomLib_LastEntry; i++ )
138 if(check_valid_idx(i) != -1)
140 if(load_custom_library(i, &gPersCustomFuncs[i] ) == 1)
142 if( (gPersCustomFuncs[i].custom_plugin_init) != NULL)
144 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("pclInitLibrary => Loaded plugin: "),
145 DLT_STRING(get_custom_client_lib_name(i)));
146 gPersCustomFuncs[i].custom_plugin_init();
150 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pclInitLibrary => E r r o r could not load plugin functions: "),
151 DLT_STRING(get_custom_client_lib_name(i)));
156 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pclInitLibrary => E r r o r could not load plugin: "),
157 DLT_STRING(get_custom_client_lib_name(i)));
169 DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("pclInit => Failed to load custom library config table => error number:"), DLT_INT(status));
172 // initialize keyHandle array
173 memset(gKeyHandleArray, 0, MaxPersHandle * sizeof(PersistenceKeyHandle_s));
175 pers_unlock_access();
177 // assign application name
178 strncpy(gAppId, appName, MaxAppNameLen);
179 gAppId[MaxAppNameLen-1] = '\0';
183 else if(gPclInitialized >= PCLinitialized)
185 gPclInitialized++; // increment init counter
186 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("pclInitLibrary => I N I T Persistence Client Library - "), DLT_STRING(gAppId),
187 DLT_STRING("- ONLY INCREMENT init counter: "), DLT_INT(gPclInitialized) );
194 int pclDeinitLibrary(void)
198 if(gPclInitialized == PCLinitialized)
201 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("pclDeinitLibrary -> D E I N I T client library - "), DLT_STRING(gAppId),
202 DLT_STRING("- init counter: "), DLT_INT(gPclInitialized));
204 // unregister for lifecycle dbus messages
205 if(gShutdownMode != PCL_SHUTDOWN_TYPE_NONE)
206 rval = unregister_lifecycle(gShutdownMode);
208 #if USE_PASINTERFACE == 1
209 rval = unregister_pers_admin_service();
212 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pclDeinitLibrary => Failed to de-initialize IPC protocol for PCL."));
216 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("pclDeinitLibrary => Successfully de-initialized IPC protocol for PCL."));
220 // unload custom client libraries
221 for(i=0; i<PersCustomLib_LastEntry; i++)
223 if(gPersCustomFuncs[i].custom_plugin_deinit != NULL)
225 // deinitialize plugin
226 gPersCustomFuncs[i].custom_plugin_deinit();
227 // close library handle
228 dlclose(gPersCustomFuncs[i].handle);
230 invalidate_custom_plugin(i);
234 process_prepare_shutdown(Shutdown_Full); // close all db's and fd's and block access
239 // send quit command to dbus mainloop
240 deliverToMainloop_NM(CMD_QUIT, 0, 0);
242 // wait until the dbus mainloop has ended
243 pthread_join(gMainLoopThread, (void**)&retval);
245 pthread_mutex_unlock(&gDbusPendingRegMtx);
246 pthread_mutex_unlock(&gDbusInitializedMtx);
248 gPclInitialized = PCLnotInitialized;
254 DLT_UNREGISTER_CONTEXT(gPclDLTContext);
256 else if(gPclInitialized > PCLinitialized)
258 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("pclDeinitLibrary -> D E I N I T client library - "), DLT_STRING(gAppId),
259 DLT_STRING("- ONLY DECREMENT init counter: "), DLT_INT(gPclInitialized));
260 gPclInitialized--; // decrement init counter
264 rval = EPERS_NOT_INITIALIZED;
271 int pclLifecycleSet(int shutdown)
275 if(gShutdownMode == PCL_SHUTDOWN_TYPE_NONE)
279 process_prepare_shutdown(Shutdown_Partial); // close all db's and fd's and block access
281 else if(PCL_SHUTDOWN_CANEL)
283 if(gCancelCounter < Shutdown_MaxCount)
285 pers_unlock_access();
289 rval = EPERS_SHUTDOWN_MAX_CANCEL;
299 rval = EPERS_SHUTDOWN_NO_PERMIT;