Protected global variables with mutex; minor optimizations; corrected doxygen documen...
[profile/ivi/persistence-client-library.git] / src / persistence_client_library_pas_interface.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_pas_interface.c
13  * @ingroup        Persistence client library
14  * @author         Ingo Huerner
15  * @brief          Implementation of the persistence client library persistence
16  *                 administration service interface.
17  * @see
18  */
19
20 #include "persistence_client_library_pas_interface.h"
21 #include "persistence_client_library_dbus_service.h"
22
23 #include "persistence_client_library_data_organization.h"
24
25 #include <errno.h>
26 #include <unistd.h>
27 #include <string.h>
28
29 /// flag if access is locked
30 static int gLockAccess = 0;
31
32 void pers_lock_access(void)
33 {
34    __sync_fetch_and_add(&gLockAccess,1);
35 }
36
37 void pers_unlock_access(void)
38 {
39    __sync_fetch_and_sub(&gLockAccess,1);
40 }
41
42 int isAccessLocked(void)
43 {
44    return gLockAccess;
45 }
46
47
48 int check_pas_request(unsigned int request, unsigned int requestID)
49 {
50    int rval = 0;
51    switch(request)
52    {
53       case (PasMsg_Block|PasMsg_WriteBack):
54       {
55         MainLoopData_u data;
56
57         data.message.cmd = (uint32_t)CMD_PAS_BLOCK_AND_WRITE_BACK;
58         data.message.params[0] = request;
59         data.message.params[1] = requestID;
60         data.message.string[0] = '\0';  // no string parameter, set to 0
61
62          DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("PCL: check_pas_request; case PasMsg_Block o. PasMsg_WriteBack"));
63          if(-1 == deliverToMainloop_NM(&data))
64          {
65             DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("write failed w/ errno "), DLT_INT(errno), DLT_STRING(strerror(errno)));
66             rval = PasErrorStatus_FAIL;
67          }
68          else
69          {
70             rval = PasErrorStatus_RespPend;
71          }
72          break;
73       }
74       case PasMsg_Unblock:
75       {
76          DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("PCL: check_pas_request; case PasMsg_Unblock"));
77          pers_unlock_access();
78          rval = PasErrorStatus_OK;
79          break;
80       }
81       default:
82       {
83          rval = PasErrorStatus_FAIL;
84          break;
85       }
86    }
87    return rval;
88 }
89
90
91
92
93
94 DBusHandlerResult msg_persAdminRequest(DBusConnection *connection, DBusMessage *message)
95 {
96    int request = 0, requestID = 0;
97    int errorReturn = 0;
98
99    DBusMessage *reply;
100    DBusError error;
101    dbus_error_init (&error);
102
103
104    if (!dbus_message_get_args(message, &error, DBUS_TYPE_INT32 , &request,
105                                                DBUS_TYPE_INT32 , &requestID,
106                                                DBUS_TYPE_INVALID))
107    {
108       reply = dbus_message_new_error(message, error.name, error.message);
109
110       if(reply == 0)
111       {
112          DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("msg_persAdminRequest => DBus No memory"));
113       }
114
115       if (!dbus_connection_send(connection, reply, 0))
116       {
117          DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("msg_persAdminRequest => DBus No memory"));
118       }
119
120       dbus_message_unref(reply);
121
122       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
123    }
124    errorReturn = check_pas_request(request, requestID);
125
126
127    reply = dbus_message_new_method_return(message);
128
129    if (reply == 0)
130    {
131       DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("msg_persAdminRequest => DBus No memory"));
132    }
133
134    if (!dbus_message_append_args(reply, DBUS_TYPE_INT32, &errorReturn, DBUS_TYPE_INVALID))
135    {
136       DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("msg_persAdminRequest => DBus No memory"));
137    }
138
139    if (!dbus_connection_send(connection, reply, 0))
140    {
141       DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("msg_persAdminRequest => DBus No memory"));
142    }
143
144    dbus_connection_flush(connection);
145    dbus_message_unref(reply);
146
147    return DBUS_HANDLER_RESULT_HANDLED;
148 }
149
150
151 int signal_persModeChange(DBusConnection *connection, DBusMessage *message)
152 {
153    int persistenceMode = 0;
154    int errorCode = 0;
155
156    DBusMessage *reply;
157    DBusError error;
158    dbus_error_init (&error);
159
160    if (!dbus_message_get_args (message, &error, DBUS_TYPE_INT32 , &persistenceMode,
161                                                 DBUS_TYPE_INVALID))
162    {
163       reply = dbus_message_new_error(message, error.name, error.message);
164
165       if(reply == 0)
166       {
167          DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("signal_persModeChange => DBus No memory"));
168       }
169
170       if (!dbus_connection_send(connection, reply, 0))
171       {
172          DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("signal_persModeChange => DBus No memory"));
173       }
174
175       dbus_message_unref(reply);
176
177       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
178    }
179
180    reply = dbus_message_new_method_return(message);
181
182    if (reply == 0)
183    {
184       DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("signal_persModeChange => DBus No memory"));
185    }
186
187    if (!dbus_message_append_args(reply, DBUS_TYPE_INT32, &errorCode, DBUS_TYPE_INVALID))
188    {
189       DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("signal_persModeChange => DBus No memory"));
190    }
191
192    if (!dbus_connection_send(connection, reply, 0))
193    {
194       DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("signal_persModeChange => DBus No memory"));
195    }
196
197    dbus_connection_flush(connection);
198    dbus_message_unref(reply);
199
200    return DBUS_HANDLER_RESULT_HANDLED;
201 }
202
203
204 DBusHandlerResult checkPersAdminMsg(DBusConnection * connection, DBusMessage * message, void * user_data)
205 {
206    DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
207
208    (void)user_data;
209
210    if((0==strcmp(gDbusPersAdminConsInterface, dbus_message_get_interface(message))))
211    {
212       if((0==strcmp(gDbusPersAdminConsMsg, dbus_message_get_member(message))))
213       {
214          result = msg_persAdminRequest(connection, message);
215       }
216       else
217       {
218          DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("checkPersAdminMsg => unknown message"), DLT_STRING(dbus_message_get_member(message)));
219       }
220    }
221    else
222    {
223       DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("checkPersAdminMsg => unknown message"), DLT_STRING(dbus_message_get_interface(message)));
224    }
225    return result;
226 }
227
228
229
230
231 int register_pers_admin_service(void)
232 {
233    int rval =  0;
234
235         MainLoopData_u data;
236
237         data.message.cmd = (uint32_t)CMD_SEND_PAS_REGISTER;
238         data.message.params[0] = 1;
239         data.message.params[1] = (PasMsg_Block | PasMsg_WriteBack | PasMsg_Unblock);
240         data.message.string[0] = '\0';  // no string parameter, set to 0
241
242    if(-1 == deliverToMainloop(&data))
243    {
244     DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("register_pers_admin_service => failed to write to pipe"), DLT_INT(errno));
245     rval = -1;
246    }
247    else
248    {
249       pthread_mutex_lock(&gDbusPendingRegMtx);   // block until pending received
250       rval = gDbusPendingRvalue;
251    }
252    return rval;
253 }
254
255
256
257 int unregister_pers_admin_service(void)
258 {
259    int rval =  0;
260
261         MainLoopData_u data;
262         data.message.cmd = (uint32_t)CMD_SEND_PAS_REGISTER;
263         data.message.params[0] = 0;
264         data.message.params[1] = (PasMsg_Block | PasMsg_WriteBack | PasMsg_Unblock);
265         data.message.string[0] = '\0';  // no string parameter, set to 0
266
267    if(-1 == deliverToMainloop(&data))
268    {
269      DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("unregister_pers_admin_service => failed to write to pipe"), DLT_INT(errno));
270      rval = -1;
271    }
272    else
273    {
274       pthread_mutex_lock(&gDbusPendingRegMtx);   // block until pending received
275       rval = gDbusPendingRvalue;
276    }
277    return rval;
278 }
279
280