Implemented on demand/static loading of plugins (part I); ATTENTION: pluginf config...
[profile/ivi/persistence-client-library.git] / src / persistence_client_library.c
1 /******************************************************************************
2  * Project         Persistency
3  * (c) copyright   2012
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 ******************************************************************************/
11  /**
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
17  * @see            
18  */
19
20
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"
29
30 #if USE_FILECACHE
31    #include <persistence_file_cache.h>
32 #endif
33
34 #include <string.h>
35 #include <errno.h>
36 #include <stdlib.h>
37 #include <dlfcn.h>
38 #include <dbus/dbus.h>
39
40 /// debug log and trace (DLT) setup
41 DLT_DECLARE_CONTEXT(gPclDLTContext);
42
43 static int gShutdownMode = 0;
44
45 static int gCancelCounter = 0;
46
47
48 int customAsyncInitClbk(int errcode)
49 {
50         printf("Dummy async init Callback\n");
51 }
52
53
54 int pclInitLibrary(const char* appName, int shutdownMode)
55 {
56    int i = 0, rval = 1;
57
58    printf("INIT START\n\n");
59
60    if(gPclInitialized == PCLnotInitialized)
61    {
62         printf("INIT START ==> DO INIT\n\n");
63       gShutdownMode = shutdownMode;
64
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) );
68
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");
73
74 #if USE_FILECACHE
75    DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("Using the filecache!!!"));
76    pfcInitCache(appName);
77 #endif
78
79       pthread_mutex_lock(&gDbusPendingRegMtx);   // block until pending received
80
81       if(pDataSize != NULL)
82       {
83          gMaxKeyValDataSize = atoi(pDataSize);
84       }
85
86       if(pBlacklistPath == NULL)
87       {
88          pBlacklistPath = "/etc/pclBackupBlacklist.txt";   // default path
89       }
90
91       if(readBlacklistConfigFile(pBlacklistPath) == -1)
92       {
93          DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("pclInitLibrary -> failed to access blacklist:"), DLT_STRING(pBlacklistPath));
94       }
95
96       if(setup_dbus_mainloop() == -1)
97       {
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;
101       }
102
103
104       if(gShutdownMode != PCL_SHUTDOWN_TYPE_NONE)
105       {
106          // register for lifecycle dbus messages
107          if(register_lifecycle(shutdownMode) == -1)
108          {
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;
112          }
113       }
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)
117       {
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;
121       }
122           else
123           {
124          DLT_LOG(gPclDLTContext, DLT_LOG_INFO,  DLT_STRING("pclInitLibrary => Successfully established IPC protocol for PCL."));
125           }
126 #else
127       DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("PAS interface is not enabled, enable with \"./configure --enable-pasinterface\""));
128 #endif
129
130
131       /// get custom library names to load
132       if(get_custom_libraries() >= 0)
133       {
134          // initialize custom library structure
135          for(i = 0; i < PersCustomLib_LastEntry; i++)
136          {
137             invalidate_custom_plugin(i);
138          }
139
140                         for(i=0; i < PersCustomLib_LastEntry; i++ )
141                         {
142                                 if(check_valid_idx(i) != -1)
143                                 {
144                                         if(getCustomLoadingType(i) == LoadType_PclInit) // check if the plugin must be loaded on plc init
145                                         {
146                                                 if(load_custom_library(i, &gPersCustomFuncs[i] ) == 1)
147                                                 {
148                                                         PersInitType_e initType = getCustomInitType(i);
149                                                         if(initType == Init_Synchronous)
150                                                         {
151                                                                 if( (gPersCustomFuncs[i].custom_plugin_init) != NULL)
152                                                                 {
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();
155                                                                 }
156                                                                 else
157                                                                 {
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)));
160                                                                 }
161                                                         }
162                                                         else if(initType == Init_Asynchronous)
163                                                         {
164                                                                 if( (gPersCustomFuncs[i].custom_plugin_init_async) != NULL)
165                                                                 {
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);
168                                                                 }
169                                                                 else
170                                                                 {
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)));
173                                                                 }
174                                                         }
175                                                         else
176                                                         {
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)));
178                                                         }
179                                                 }
180                                                 else
181                                                 {
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)));
184                                                 }
185                                         }
186                                 }
187                                 else
188                                 {
189                                         continue;
190                                 }
191                         }
192       }
193       else
194       {
195          DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("pclInit => Failed to load custom library config table"));
196       }
197
198       // initialize keyHandle array
199       memset(gKeyHandleArray, 0, MaxPersHandle * sizeof(PersistenceKeyHandle_s));
200
201       pers_unlock_access();
202
203       // assign application name
204       strncpy(gAppId, appName, MaxAppNameLen);
205       gAppId[MaxAppNameLen-1] = '\0';
206
207       gPclInitialized++;
208    }
209    else if(gPclInitialized >= PCLinitialized)
210    {
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) );
214    }
215
216    return rval;
217 }
218
219
220
221 int pclDeinitLibrary(void)
222 {
223    int i = 0, rval = 1;
224
225    if(gPclInitialized == PCLinitialized)
226    {
227       int* retval;
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));
230
231       // unregister for lifecycle dbus messages
232       if(gShutdownMode != PCL_SHUTDOWN_TYPE_NONE)
233          rval = unregister_lifecycle(gShutdownMode);
234
235 #if USE_PASINTERFACE == 1
236       rval = unregister_pers_admin_service();
237       if(0 != rval)
238           {
239                   DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pclDeinitLibrary => Failed to de-initialize IPC protocol for PCL."));
240           }
241       else
242       {
243           DLT_LOG(gPclDLTContext, DLT_LOG_INFO,  DLT_STRING("pclDeinitLibrary => Successfully de-initialized IPC protocol for PCL."));
244       }
245 #endif
246
247       // unload custom client libraries
248       for(i=0; i<PersCustomLib_LastEntry; i++)
249       {
250          if(gPersCustomFuncs[i].custom_plugin_deinit != NULL)
251          {
252             // deinitialize plugin
253             gPersCustomFuncs[i].custom_plugin_deinit();
254             // close library handle
255             dlclose(gPersCustomFuncs[i].handle);
256
257             invalidate_custom_plugin(i);
258          }
259       }
260
261       process_prepare_shutdown(Shutdown_Full);  // close all db's and fd's and block access
262
263       // end dbus library
264       bContinue = 0;
265
266       // send quit command to dbus mainloop
267       deliverToMainloop_NM(CMD_QUIT, 0, 0);
268
269       // wait until the dbus mainloop has ended
270       pthread_join(gMainLoopThread, (void**)&retval);
271
272       pthread_mutex_unlock(&gDbusPendingRegMtx);
273       pthread_mutex_unlock(&gDbusInitializedMtx);
274
275       gPclInitialized = PCLnotInitialized;
276
277 #if USE_FILECACHE
278    pfcDeinitCache();
279 #endif
280
281       DLT_UNREGISTER_CONTEXT(gPclDLTContext);
282    }
283    else if(gPclInitialized > PCLinitialized)
284    {
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
288    }
289    else
290    {
291       rval = EPERS_NOT_INITIALIZED;
292    }
293    return rval;
294 }
295
296
297
298 int pclLifecycleSet(int shutdown)
299 {
300         int rval = 0;
301
302         if(gShutdownMode == PCL_SHUTDOWN_TYPE_NONE)
303         {
304                 if(PCL_SHUTDOWN)
305                 {
306                         process_prepare_shutdown(Shutdown_Partial);     // close all db's and fd's and block access
307                 }
308                 else if(PCL_SHUTDOWN_CANEL)
309                 {
310                         if(gCancelCounter < Shutdown_MaxCount)
311                         {
312                                 pers_unlock_access();
313                         }
314                         else
315                         {
316                                 rval = EPERS_SHUTDOWN_MAX_CANCEL;
317                         }
318                 }
319                 else
320                 {
321                         rval = EPERS_COMMON;
322                 }
323         }
324         else
325         {
326                 rval = EPERS_SHUTDOWN_NO_PERMIT;
327         }
328
329         return rval;
330 }
331
332
333