Protected global variables with mutex; minor optimizations; corrected doxygen documen...
[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 #include "persistence_client_library_dbus_cmd.h"
30
31 #if USE_FILECACHE
32    #include <persistence_file_cache.h>
33 #endif
34
35 #include <string.h>
36 #include <errno.h>
37 #include <stdlib.h>
38 #include <dlfcn.h>
39 #include <dbus/dbus.h>
40
41 /// debug log and trace (DLT) setup
42 DLT_DECLARE_CONTEXT(gPclDLTContext);
43
44
45 /// global variable to store lifecycle shutdown mode
46 static int gShutdownMode = 0;
47 /// global shutdown cancel counter
48 static int gCancelCounter = 0;
49
50
51 int customAsyncInitClbk(int errcode)
52 {
53         printf("Dummy async init Callback\n");
54
55         return 1;
56 }
57
58
59 int pclInitLibrary(const char* appName, int shutdownMode)
60 {
61    int rval = 1;
62
63    if(gPclInitialized == PCLnotInitialized)
64    {
65       gShutdownMode = shutdownMode;
66
67       DLT_REGISTER_CONTEXT(gPclDLTContext,"PCL","Context for persistence client library logging");
68       DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("pclInitLibrary => I N I T  Persistence Client Library - "), DLT_STRING(appName),
69                               DLT_STRING("- init counter: "), DLT_INT(gPclInitialized) );
70
71       /// environment variable for max key value data
72       const char *pDataSize = getenv("PERS_MAX_KEY_VAL_DATA_SIZE");
73       /// blacklist path environment variable
74       const char *pBlacklistPath = getenv("PERS_BLACKLIST_PATH");
75
76 #if USE_FILECACHE
77    DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("Using the filecache!!!"));
78    pfcInitCache(appName);
79 #endif
80
81       pthread_mutex_lock(&gDbusPendingRegMtx);   // block until pending received
82
83       if(pDataSize != NULL)
84       {
85          gMaxKeyValDataSize = atoi(pDataSize);
86       }
87
88       if(pBlacklistPath == NULL)
89       {
90          pBlacklistPath = "/etc/pclBackupBlacklist.txt";   // default path
91       }
92
93       if(readBlacklistConfigFile(pBlacklistPath) == -1)
94       {
95          DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("pclInitLibrary -> failed to access blacklist:"), DLT_STRING(pBlacklistPath));
96       }
97
98       if(setup_dbus_mainloop() == -1)
99       {
100          DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pclInitLibrary => Failed to setup main loop"));
101          pthread_mutex_unlock(&gDbusPendingRegMtx);
102          return EPERS_DBUS_MAINLOOP;
103       }
104
105
106       if(gShutdownMode != PCL_SHUTDOWN_TYPE_NONE)
107       {
108          // register for lifecycle dbus messages
109          if(register_lifecycle(shutdownMode) == -1)
110          {
111             DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pclInitLibrary => Failed to register to lifecycle dbus interface"));
112             pthread_mutex_unlock(&gDbusPendingRegMtx);
113             return EPERS_REGISTER_LIFECYCLE;
114          }
115       }
116 #if USE_PASINTERFACE == 1
117       DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("PAS interface is enabled!!"));
118       if(register_pers_admin_service() == -1)
119       {
120          DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pclInitLibrary => Failed to register to pers admin dbus interface"));
121          pthread_mutex_unlock(&gDbusPendingRegMtx);
122          return EPERS_REGISTER_ADMIN;
123       }
124           else
125           {
126          DLT_LOG(gPclDLTContext, DLT_LOG_INFO,  DLT_STRING("pclInitLibrary => Successfully established IPC protocol for PCL."));
127           }
128 #else
129       DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("PAS interface is not enabled, enable with \"./configure --enable-pasinterface\""));
130 #endif
131
132       // load custom plugins
133       if(load_custom_plugins(customAsyncInitClbk) < 0)
134       {
135         DLT_LOG(gPclDLTContext, DLT_LOG_WARN, DLT_STRING("Failed to load custom plugins"));
136       }
137
138       // initialize keyHandle array
139       init_key_handle_array();
140
141       pers_unlock_access();
142
143       // assign application name
144       strncpy(gAppId, appName, MaxAppNameLen);
145       gAppId[MaxAppNameLen-1] = '\0';
146
147       gPclInitialized++;
148    }
149    else if(gPclInitialized >= PCLinitialized)
150    {
151       gPclInitialized++; // increment init counter
152       DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("pclInitLibrary => I N I T  Persistence Client Library - "), DLT_STRING(gAppId),
153                            DLT_STRING("- ONLY INCREMENT init counter: "), DLT_INT(gPclInitialized) );
154    }
155
156    return rval;
157 }
158
159
160
161 int pclDeinitLibrary(void)
162 {
163    int i = 0, rval = 1;
164
165    if(gPclInitialized == PCLinitialized)
166    {
167       int* retval;
168         MainLoopData_u data;
169         data.message.cmd = (uint32_t)CMD_QUIT;
170         data.message.string[0] = '\0';  // no string parameter, set to 0
171
172       DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("pclDeinitLibrary -> D E I N I T  client library - "), DLT_STRING(gAppId),
173                                          DLT_STRING("- init counter: "), DLT_INT(gPclInitialized));
174
175       // unregister for lifecycle dbus messages
176       if(gShutdownMode != PCL_SHUTDOWN_TYPE_NONE)
177          rval = unregister_lifecycle(gShutdownMode);
178
179 #if USE_PASINTERFACE == 1
180       rval = unregister_pers_admin_service();
181       if(0 != rval)
182           {
183                   DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pclDeinitLibrary => Failed to de-initialize IPC protocol for PCL."));
184           }
185       else
186       {
187           DLT_LOG(gPclDLTContext, DLT_LOG_INFO,  DLT_STRING("pclDeinitLibrary => Successfully de-initialized IPC protocol for PCL."));
188       }
189 #endif
190
191       // unload custom client libraries
192       for(i=0; i<PersCustomLib_LastEntry; i++)
193       {
194          if(gPersCustomFuncs[i].custom_plugin_deinit != NULL)
195          {
196             // deinitialize plugin
197             gPersCustomFuncs[i].custom_plugin_deinit();
198             // close library handle
199             dlclose(gPersCustomFuncs[i].handle);
200
201             invalidate_custom_plugin(i);
202          }
203       }
204
205       process_prepare_shutdown(Shutdown_Full);  // close all db's and fd's and block access
206
207       // send quit command to dbus mainloop
208       deliverToMainloop_NM(&data);
209
210       // wait until the dbus mainloop has ended
211       pthread_join(gMainLoopThread, (void**)&retval);
212
213       pthread_mutex_unlock(&gDbusPendingRegMtx);
214       pthread_mutex_unlock(&gDbusInitializedMtx);
215
216       gPclInitialized = PCLnotInitialized;
217
218 #if USE_FILECACHE
219    pfcDeinitCache();
220 #endif
221
222       DLT_UNREGISTER_CONTEXT(gPclDLTContext);
223    }
224    else if(gPclInitialized > PCLinitialized)
225    {
226       DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("pclDeinitLibrary -> D E I N I T  client library - "), DLT_STRING(gAppId),
227                                            DLT_STRING("- ONLY DECREMENT init counter: "), DLT_INT(gPclInitialized));
228       gPclInitialized--;   // decrement init counter
229    }
230    else
231    {
232       rval = EPERS_NOT_INITIALIZED;
233    }
234    return rval;
235 }
236
237
238
239 int pclLifecycleSet(int shutdown)
240 {
241         int rval = 0;
242
243         if(gShutdownMode == PCL_SHUTDOWN_TYPE_NONE)
244         {
245                 if(shutdown == PCL_SHUTDOWN)
246                 {
247                         process_prepare_shutdown(Shutdown_Partial);     // close all db's and fd's and block access
248                 }
249                 else if(shutdown == PCL_SHUTDOWN_CANEL)
250                 {
251                         if(gCancelCounter < Shutdown_MaxCount)
252                         {
253                                 pers_unlock_access();
254                         }
255                         else
256                         {
257                                 rval = EPERS_SHUTDOWN_MAX_CANCEL;
258                         }
259                 }
260                 else
261                 {
262                         rval = EPERS_COMMON;
263                 }
264         }
265         else
266         {
267                 rval = EPERS_SHUTDOWN_NO_PERMIT;
268         }
269
270         return rval;
271 }
272
273
274