94b11699788a9d93c6fddb263027041c1b16e541
[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 pclInitLibrary(const char* appName, int shutdownMode)
49 {
50    int status = 0;
51    int i = 0, rval = 1;
52
53    if(gPclInitialized == PCLnotInitialized)
54    {
55       gShutdownMode = shutdownMode;
56
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) );
60
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");
67
68 #if USE_FILECACHE
69    DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("Using the filecache!!!"));
70    pfcInitCache(appName);
71 #endif
72
73       pthread_mutex_lock(&gDbusPendingRegMtx);   // block until pending received
74
75       if(pDataSize != NULL)
76       {
77          gMaxKeyValDataSize = atoi(pDataSize);
78       }
79
80       if(pBlacklistPath == NULL)
81       {
82          pBlacklistPath = "/etc/pclBackupBlacklist.txt";   // default path
83       }
84
85       if(readBlacklistConfigFile(pBlacklistPath) == -1)
86       {
87          DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("pclInitLibrary -> failed to access blacklist:"), DLT_STRING(pBlacklistPath));
88       }
89
90       if(setup_dbus_mainloop() == -1)
91       {
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;
95       }
96
97
98       if(gShutdownMode != PCL_SHUTDOWN_TYPE_NONE)
99       {
100          // register for lifecycle dbus messages
101          if(register_lifecycle(shutdownMode) == -1)
102          {
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;
106          }
107       }
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)
111       {
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;
115       }
116           else
117           {
118          DLT_LOG(gPclDLTContext, DLT_LOG_INFO,  DLT_STRING("pclInitLibrary => Successfully established IPC protocol for PCL."));
119           }
120 #else
121       DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("PAS interface is not enabled, enable with \"./configure --enable-pasinterface\""));
122 #endif
123
124       /// get custom library names to load
125       status = get_custom_libraries();
126       if(status >= 0)
127       {
128          // initialize custom library structure
129          for(i = 0; i < PersCustomLib_LastEntry; i++)
130          {
131             invalidate_custom_plugin(i);
132          }
133
134          if(pOnDemandLoad == NULL)  // load all available libraries now
135          {
136             for(i=0; i < PersCustomLib_LastEntry; i++ )
137             {
138                if(check_valid_idx(i) != -1)
139                {
140                   if(load_custom_library(i, &gPersCustomFuncs[i] ) == 1)
141                   {
142                      if( (gPersCustomFuncs[i].custom_plugin_init) != NULL)
143                      {
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();
147                      }
148                      else
149                      {
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)));
152                      }
153                   }
154                   else
155                   {
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)));
158                   }
159                }
160                else
161                {
162                   continue;
163                }
164             }
165          }
166       }
167       else
168       {
169          DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("pclInit => Failed to load custom library config table => error number:"), DLT_INT(status));
170       }
171
172       // initialize keyHandle array
173       memset(gKeyHandleArray, 0, MaxPersHandle * sizeof(PersistenceKeyHandle_s));
174
175       pers_unlock_access();
176
177       // assign application name
178       strncpy(gAppId, appName, MaxAppNameLen);
179       gAppId[MaxAppNameLen-1] = '\0';
180
181       gPclInitialized++;
182    }
183    else if(gPclInitialized >= PCLinitialized)
184    {
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) );
188    }
189    return rval;
190 }
191
192
193
194 int pclDeinitLibrary(void)
195 {
196    int i = 0, rval = 1;
197
198    if(gPclInitialized == PCLinitialized)
199    {
200       int* retval;
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));
203
204       // unregister for lifecycle dbus messages
205       if(gShutdownMode != PCL_SHUTDOWN_TYPE_NONE)
206          rval = unregister_lifecycle(gShutdownMode);
207
208 #if USE_PASINTERFACE == 1
209       rval = unregister_pers_admin_service();
210       if(0 != rval)
211           {
212                   DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pclDeinitLibrary => Failed to de-initialize IPC protocol for PCL."));
213           }
214       else
215       {
216           DLT_LOG(gPclDLTContext, DLT_LOG_INFO,  DLT_STRING("pclDeinitLibrary => Successfully de-initialized IPC protocol for PCL."));
217       }
218 #endif
219
220       // unload custom client libraries
221       for(i=0; i<PersCustomLib_LastEntry; i++)
222       {
223          if(gPersCustomFuncs[i].custom_plugin_deinit != NULL)
224          {
225             // deinitialize plugin
226             gPersCustomFuncs[i].custom_plugin_deinit();
227             // close library handle
228             dlclose(gPersCustomFuncs[i].handle);
229
230             invalidate_custom_plugin(i);
231          }
232       }
233
234       process_prepare_shutdown(Shutdown_Full);  // close all db's and fd's and block access
235
236       // end dbus library
237       bContinue = 0;
238
239       // send quit command to dbus mainloop
240       deliverToMainloop_NM(CMD_QUIT, 0, 0);
241
242       // wait until the dbus mainloop has ended
243       pthread_join(gMainLoopThread, (void**)&retval);
244
245       pthread_mutex_unlock(&gDbusPendingRegMtx);
246       pthread_mutex_unlock(&gDbusInitializedMtx);
247
248       gPclInitialized = PCLnotInitialized;
249
250 #if USE_FILECACHE
251    pfcDeinitCache();
252 #endif
253
254       DLT_UNREGISTER_CONTEXT(gPclDLTContext);
255    }
256    else if(gPclInitialized > PCLinitialized)
257    {
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
261    }
262    else
263    {
264       rval = EPERS_NOT_INITIALIZED;
265    }
266    return rval;
267 }
268
269
270
271 int pclLifecycleSet(int shutdown)
272 {
273         int rval = 0;
274
275         if(gShutdownMode == PCL_SHUTDOWN_TYPE_NONE)
276         {
277                 if(PCL_SHUTDOWN)
278                 {
279                         process_prepare_shutdown(Shutdown_Partial);     // close all db's and fd's and block access
280                 }
281                 else if(PCL_SHUTDOWN_CANEL)
282                 {
283                         if(gCancelCounter < Shutdown_MaxCount)
284                         {
285                                 pers_unlock_access();
286                         }
287                         else
288                         {
289                                 rval = EPERS_SHUTDOWN_MAX_CANCEL;
290                         }
291                 }
292                 else
293                 {
294                         rval = EPERS_COMMON;
295                 }
296         }
297         else
298         {
299                 rval = EPERS_SHUTDOWN_NO_PERMIT;
300         }
301
302         return rval;
303 }
304
305
306