init und deinit is not blocking anymore when they will be called multiple times
[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
29 #include <string.h>
30 #include <errno.h>
31 #include <stdlib.h>
32 #include <dlfcn.h>
33
34 #include <dlt/dlt.h>
35 #include <dlt/dlt_common.h>
36
37 #include <dbus/dbus.h>
38
39 /// debug log and trace (DLT) setup
40 DLT_DECLARE_CONTEXT(gDLTContext);
41
42 static int gShutdownMode = 0;
43
44
45 int pclInitLibrary(const char* appName, int shutdownMode)
46 {
47    int status = 0;
48    int i = 0, rval = 1;
49
50    if(gPclInitialized == PCLnotInitialized)
51    {
52       gShutdownMode = shutdownMode;
53
54       DLT_REGISTER_CONTEXT(gDLTContext,"pers","Context for persistence client library logging");
55       DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclInitLibrary => I N I T  Persistence Client Library - "), DLT_STRING(gAppId),
56                            DLT_STRING("- init counter: "), DLT_INT(gPclInitialized) );
57
58       /// environment variable for on demand loading of custom libraries
59       const char *pOnDemandLoad = getenv("PERS_CUSTOM_LIB_LOAD_ON_DEMAND");
60       /// environment variable for max key value data
61       const char *pDataSize = getenv("PERS_MAX_KEY_VAL_DATA_SIZE");
62       /// blacklist path environment variable
63       const char *pBlacklistPath = getenv("PERS_BLACKLIST_PATH");
64
65 #if USE_PASINTERFACE == 1
66       //printf("* ADMIN INTERFACE is  - e n a b l e d - \n");
67       DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("PAS interface is enabled!!"));
68 #else
69       //printf("* ADMIN INTERFACE is  - d i s a b l e d - enable with \"./configure --enable-pasinterface\"\n");
70       DLT_LOG(gDLTContext, DLT_LOG_WARN, DLT_STRING("PAS interface is not enabled, enable with \"./configure --enable-pasinterface\""));
71 #endif
72
73
74       pthread_mutex_lock(&gDbusPendingRegMtx);   // block until pending received
75
76       if(pDataSize != NULL)
77       {
78          gMaxKeyValDataSize = atoi(pDataSize);
79       }
80
81       if(pBlacklistPath == NULL)
82       {
83          pBlacklistPath = "/etc/pclBackupBlacklist.txt";   // default path
84       }
85
86       if(readBlacklistConfigFile(pBlacklistPath) == -1)
87       {
88          DLT_LOG(gDLTContext, DLT_LOG_WARN, DLT_STRING("pclInitLibrary -> failed to access blacklist:"), DLT_STRING(pBlacklistPath));
89       }
90
91       if(setup_dbus_mainloop() == -1)
92       {
93          DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclInitLibrary => Failed to setup main loop"));
94          pthread_mutex_unlock(&gDbusPendingRegMtx);
95          return EPERS_DBUS_MAINLOOP;
96       }
97
98
99       if(gShutdownMode != PCL_SHUTDOWN_TYPE_NONE)
100       {
101          // register for lifecycle and persistence admin service dbus messages
102          if(register_lifecycle(shutdownMode) == -1)
103          {
104             DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclInitLibrary => Failed to register to lifecycle dbus interface"));
105             pthread_mutex_unlock(&gDbusPendingRegMtx);
106             return EPERS_REGISTER_LIFECYCLE;
107          }
108       }
109 #if USE_PASINTERFACE == 1
110       if(register_pers_admin_service() == -1)
111       {
112          DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclInitLibrary => Failed to register to pers admin dbus interface"));
113          pthread_mutex_unlock(&gDbusPendingRegMtx);
114          return EPERS_REGISTER_ADMIN;
115       }
116 #endif
117
118       /// get custom library names to load
119       status = get_custom_libraries();
120       if(status >= 0)
121       {
122          // initialize custom library structure
123          for(i = 0; i < PersCustomLib_LastEntry; i++)
124          {
125             invalidate_custom_plugin(i);
126          }
127
128          if(pOnDemandLoad == NULL)  // load all available libraries now
129          {
130             for(i=0; i < PersCustomLib_LastEntry; i++ )
131             {
132                if(check_valid_idx(i) != -1)
133                {
134                   if(load_custom_library(i, &gPersCustomFuncs[i] ) == 1)
135                   {
136                      if( (gPersCustomFuncs[i].custom_plugin_init) != NULL)
137                      {
138                         DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclInitLibrary => Loaded plugin: "),
139                                                            DLT_STRING(get_custom_client_lib_name(i)));
140                         gPersCustomFuncs[i].custom_plugin_init();
141                      }
142                      else
143                      {
144                         DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclInitLibrary => E r r o r could not load plugin functions: "),
145                                                             DLT_STRING(get_custom_client_lib_name(i)));
146                      }
147                   }
148                   else
149                   {
150                      DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclInitLibrary => E r r o r could not load plugin: "),
151                                           DLT_STRING(get_custom_client_lib_name(i)));
152                   }
153                }
154                else
155                {
156                   continue;
157                }
158             }
159          }
160       }
161       else
162       {
163          DLT_LOG(gDLTContext, DLT_LOG_WARN, DLT_STRING("pclInit => Failed to load custom library config table => error number:"), DLT_INT(status));
164       }
165
166       // assign application name
167       strncpy(gAppId, appName, MaxAppNameLen);
168       gAppId[MaxAppNameLen-1] = '\0';
169
170       gPclInitialized++;
171    }
172    else if(gPclInitialized >= PCLinitialized)
173    {
174       gPclInitialized++; // increment init counter
175       DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclInitLibrary => I N I T  Persistence Client Library - "), DLT_STRING(gAppId),
176                            DLT_STRING("- ONLY INCREMENT init counter: "), DLT_INT(gPclInitialized) );
177    }
178    return rval;
179 }
180
181
182
183 int pclDeinitLibrary(void)
184 {
185    int i = 0, rval = 1;
186
187    if(gPclInitialized == PCLinitialized)
188    {
189       int* retval;
190       DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclDeinitLibrary -> D E I N I T  client library - "), DLT_STRING(gAppId),
191                                          DLT_STRING("- init counter: "), DLT_INT(gPclInitialized));
192
193       // unregister for lifecycle and persistence admin service dbus messages
194       if(gShutdownMode != PCL_SHUTDOWN_TYPE_NONE)
195          rval = unregister_lifecycle(gShutdownMode);
196
197 #if USE_PASINTERFACE == 1
198       rval = unregister_pers_admin_service();
199 #endif
200
201       // unload custom client libraries
202       for(i=0; i<PersCustomLib_LastEntry; i++)
203       {
204          if(gPersCustomFuncs[i].custom_plugin_deinit != NULL)
205          {
206             // deinitialize plugin
207             gPersCustomFuncs[i].custom_plugin_deinit();
208             // close library handle
209             dlclose(gPersCustomFuncs[i].handle);
210
211             invalidate_custom_plugin(i);
212          }
213       }
214
215       // close all apend rct
216       pers_rct_close_all();
217
218       // close opend database
219       pers_db_close_all();
220       // end dbus library
221       bContinue = 0;
222
223       // send quit command to dbus mainloop
224       deliverToMainloop_NM(CMD_QUIT, 0, 0);
225
226       // wait until the dbus mainloop has ended
227       pthread_join(gMainLoopThread, (void**)&retval);
228
229       pthread_mutex_unlock(&gDbusPendingRegMtx);
230       pthread_mutex_unlock(&gDbusInitializedMtx);
231
232       gPclInitialized = PCLnotInitialized;
233
234       DLT_UNREGISTER_CONTEXT(gDLTContext);
235    }
236    else if(gPclInitialized > PCLinitialized)
237    {
238       DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclDeinitLibrary -> D E I N I T  client library - "), DLT_STRING(gAppId),
239                                            DLT_STRING("- ONLY DECREMENT init counter: "), DLT_INT(gPclInitialized));
240       gPclInitialized--;   // decrement init counter
241    }
242    else
243    {
244       rval = PCLnotInitialized;
245    }
246    return rval;
247 }
248
249
250
251
252
253