Change from INET tcp to Unix domain socket
[framework/multimedia/media-server.git] / lib / media-util-db.c
1 /*
2  *  Media Utility
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Yong Yeon Kim <yy9875.kim@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 /**
23  * This file defines api utilities of Media DB.
24  *
25  * @file                media-util-db.c
26  * @author      Haejeong Kim(backto.kim@samsung.com)
27  * @version     1.0
28  * @brief
29  */
30
31 #include <unistd.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <db-util.h>
35 #include "media-server-ipc.h"
36 #include "media-util-dbg.h"
37 #include "media-util-internal.h"
38 #include "media-util.h"
39
40 static __thread char **sql_list = NULL;
41 static __thread int g_list_idx = 0;
42
43 static int __media_db_busy_handler(void *pData, int count);
44 static int __media_db_connect_db_with_handle(sqlite3 **db_handle);
45 static int __media_db_disconnect_db_with_handle(sqlite3 *db_handle);
46 static int __media_db_request_update(ms_msg_type_e msg_type, const char *request_msg);
47
48 void __media_db_destroy_sql_list()
49 {
50         int i = 0;
51
52         for (i = 0; i < g_list_idx; i++) {
53                 MS_SAFE_FREE(sql_list[i]);
54         }
55
56         MS_SAFE_FREE(sql_list);
57         g_list_idx = 0;
58 }
59
60 static int __media_db_busy_handler(void *pData, int count)
61 {
62         usleep(50000);
63
64         MSAPI_DBG("media_db_busy_handler called : %d", count);
65
66         return 100 - count;
67 }
68
69 static int __media_db_connect_db_with_handle(sqlite3 **db_handle)
70 {
71         int ret = MS_MEDIA_ERR_NONE;
72
73         /*Connect DB*/
74         ret = db_util_open(MEDIA_DB_NAME, db_handle, DB_UTIL_REGISTER_HOOK_METHOD);
75
76         if (SQLITE_OK != ret) {
77
78                 MSAPI_DBG_ERR("error when db open");
79                 *db_handle = NULL;
80                 return MS_MEDIA_ERR_DB_CONNECT_FAIL;
81         }
82
83         if (*db_handle == NULL) {
84                 MSAPI_DBG_ERR("*db_handle is NULL");
85                 return MS_MEDIA_ERR_DB_CONNECT_FAIL;
86         }
87
88         /*Register busy handler*/
89         ret = sqlite3_busy_handler(*db_handle, __media_db_busy_handler, NULL);
90
91         if (SQLITE_OK != ret) {
92
93                 if (*db_handle) {
94                         MSAPI_DBG_ERR("[error when register busy handler] %s\n", sqlite3_errmsg(*db_handle));
95                 }
96
97                 db_util_close(*db_handle);
98                 *db_handle = NULL;
99
100                 return MS_MEDIA_ERR_DB_CONNECT_FAIL;
101         }
102
103         return MS_MEDIA_ERR_NONE;
104 }
105
106 static int __media_db_disconnect_db_with_handle(sqlite3 *db_handle)
107 {
108         int ret = MS_MEDIA_ERR_NONE;
109
110         ret = db_util_close(db_handle);
111
112         if (SQLITE_OK != ret) {
113                 MSAPI_DBG_ERR("error when db close");
114                 MSAPI_DBG_ERR("Error : %s", sqlite3_errmsg(db_handle));
115                 db_handle = NULL;
116                 return MS_MEDIA_ERR_DB_DISCONNECT_FAIL;
117         }
118
119         return MS_MEDIA_ERR_NONE;
120 }
121
122 static int __media_db_request_update(ms_msg_type_e msg_type, const char *request_msg)
123 {
124         int ret = MS_MEDIA_ERR_NONE;
125         int request_msg_size = 0;
126         int sockfd = -1;
127         int err = -1;
128 #ifdef _USE_UDS_SOCKET_
129         struct sockaddr_un serv_addr;
130 #else
131         struct sockaddr_in serv_addr;
132 #endif
133         unsigned int serv_addr_len = -1;
134         int port = MS_DB_UPDATE_PORT;
135
136         if(msg_type == MS_MSG_DB_UPDATE)
137                 port = MS_DB_UPDATE_PORT;
138         else
139                 port = MS_SCANNER_PORT;
140
141         if(!MS_STRING_VALID(request_msg))
142         {
143                 MSAPI_DBG_ERR("invalid query");
144                 return MS_MEDIA_ERR_INVALID_PARAMETER;
145         }
146
147         request_msg_size = strlen(request_msg);
148         if(request_msg_size >= MAX_MSG_SIZE)
149         {
150                 MSAPI_DBG_ERR("Query is Too long. [%d] query size limit is [%d]", request_msg_size, MAX_MSG_SIZE);
151                 return MS_MEDIA_ERR_INVALID_PARAMETER;
152         }
153
154 //      MSAPI_DBG("querysize[%d] query[%s]", request_msg_size, request_msg);
155
156         ms_comm_msg_s send_msg;
157         memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s));
158
159         send_msg.msg_type = msg_type;
160         send_msg.msg_size = request_msg_size;
161         strncpy(send_msg.msg, request_msg, request_msg_size);
162
163         /*Create Socket*/
164 #ifdef _USE_UDS_SOCKET_
165         ret = ms_ipc_create_client_socket(MS_PROTOCOL_UDP, MS_TIMEOUT_SEC_10, &sockfd, port);
166 #else
167         ret = ms_ipc_create_client_socket(MS_PROTOCOL_UDP, MS_TIMEOUT_SEC_10, &sockfd);
168 #endif
169         MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
170
171         ret = ms_ipc_send_msg_to_server(sockfd, port, &send_msg, &serv_addr);
172         if (ret != MS_MEDIA_ERR_NONE) {
173                 MSAPI_DBG_ERR("ms_ipc_send_msg_to_server failed : %d", ret);
174                 close(sockfd);
175                 return ret;
176         }
177
178
179         /*Receive Response*/
180         ms_comm_msg_s recv_msg;
181         serv_addr_len = sizeof(serv_addr);
182         memset(&recv_msg, 0x0, sizeof(ms_comm_msg_s));
183
184         err = ms_ipc_wait_message(sockfd, &recv_msg, sizeof(recv_msg), &serv_addr, NULL);
185         if (err != MS_MEDIA_ERR_NONE) {
186                 ret = err;
187         } else {
188                 MSAPI_DBG("RECEIVE OK [%d]", recv_msg.result);
189                 ret = recv_msg.result;
190         }
191
192         close(sockfd);
193
194         return ret;
195 }
196
197 static int g_tcp_client_sock = -1;
198
199 static int __media_db_get_client_tcp_sock()
200 {
201         return g_tcp_client_sock;
202 }
203
204 #ifdef _USE_UDS_SOCKET_
205 extern char MEDIA_IPC_PATH[][50];
206 #elif defined(_USE_UDS_SOCKET_TCP_)
207 extern char MEDIA_IPC_PATH[][50];
208 #endif
209
210 static int __media_db_prepare_tcp_client_socket()
211 {
212         int ret = MS_MEDIA_ERR_NONE;
213         int sockfd = -1;
214 #ifdef _USE_UDS_SOCKET_
215         struct sockaddr_un serv_addr;
216 #elif defined(_USE_UDS_SOCKET_TCP_)
217         struct sockaddr_un serv_addr;
218 #else
219         struct sockaddr_in serv_addr;
220 #endif
221         int port = MS_DB_BATCH_UPDATE_PORT;
222
223         /*Create TCP Socket*/
224 #ifdef _USE_UDS_SOCKET_
225         ret = ms_ipc_create_client_socket(MS_PROTOCOL_TCP, MS_TIMEOUT_SEC_10, &sockfd, 0);
226 #elif defined(_USE_UDS_SOCKET_TCP_)
227         ret = ms_ipc_create_client_tcp_socket(MS_PROTOCOL_TCP, MS_TIMEOUT_SEC_10, &sockfd, MS_DB_BATCH_UPDATE_TCP_PORT);
228 #else
229         ret = ms_ipc_create_client_socket(MS_PROTOCOL_TCP, MS_TIMEOUT_SEC_10, &sockfd);
230 #endif
231         MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
232
233         /*Set server Address*/
234         memset(&serv_addr, 0, sizeof(serv_addr));
235 #ifdef _USE_UDS_SOCKET_
236         serv_addr.sun_family = AF_UNIX;
237         MSAPI_DBG("%s", MEDIA_IPC_PATH[port]);
238         strcpy(serv_addr.sun_path, MEDIA_IPC_PATH[port]);
239 #elif defined(_USE_UDS_SOCKET_TCP_)
240         serv_addr.sun_family = AF_UNIX;
241         MSAPI_DBG("%s", MEDIA_IPC_PATH[MS_DB_BATCH_UPDATE_TCP_PORT]);
242         strcpy(serv_addr.sun_path, MEDIA_IPC_PATH[MS_DB_BATCH_UPDATE_TCP_PORT]);
243 #else
244         serv_addr.sin_family = AF_INET;
245         serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
246         //serv_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
247         serv_addr.sin_port = htons(port);
248 #endif
249
250         /* Connecting to the media db server */
251         if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
252                 MSAPI_DBG_ERR("connect error : %s", strerror(errno));
253                 close(sockfd);
254                 return MS_MEDIA_ERR_SOCKET_CONN;
255         }
256
257         g_tcp_client_sock = sockfd;
258
259         MSAPI_DBG("Connected successfully");
260
261         return 0;
262 }
263
264 static int __media_db_close_tcp_client_socket()
265 {
266         close(g_tcp_client_sock);
267         g_tcp_client_sock = -1;
268
269         return 0;
270 }
271
272 static int __media_db_request_batch_update(ms_msg_type_e msg_type, const char *request_msg)
273 {
274         int ret = MS_MEDIA_ERR_NONE;
275         int request_msg_size = 0;
276         int sockfd = -1;
277
278         if(!MS_STRING_VALID(request_msg))
279         {
280                 MSAPI_DBG_ERR("invalid query");
281                 return MS_MEDIA_ERR_INVALID_PARAMETER;
282         }
283
284         request_msg_size = strlen(request_msg);
285         if(request_msg_size >= MAX_MSG_SIZE)
286         {
287                 MSAPI_DBG_ERR("Query is Too long. [%d] query size limit is [%d]", request_msg_size, MAX_MSG_SIZE);
288                 return MS_MEDIA_ERR_INVALID_PARAMETER;
289         }
290
291         MSAPI_DBG("querysize[%d] query[%s]", request_msg_size, request_msg);
292         ms_comm_msg_s send_msg;
293         memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s));
294
295         send_msg.msg_type = msg_type;
296         send_msg.msg_size = request_msg_size;
297         strncpy(send_msg.msg, request_msg, request_msg_size);
298
299         sockfd = __media_db_get_client_tcp_sock();
300         if (sockfd <= 0) {
301                 return  MS_MEDIA_ERR_SOCKET_CONN;
302         }
303
304         /* Send request */
305         if (send(sockfd, &send_msg, sizeof(send_msg), 0) != sizeof(send_msg)) {
306                 MSAPI_DBG_ERR("send failed : %s", strerror(errno));
307                 __media_db_close_tcp_client_socket(sockfd);
308                 return MS_MEDIA_ERR_SOCKET_SEND;
309         } else {
310                 MSAPI_DBG("Sent successfully");
311         }
312
313         /*Receive Response*/
314         int recv_msg_size = -1;
315         int recv_msg = -1;
316         if ((recv_msg_size = recv(sockfd, &recv_msg, sizeof(recv_msg), 0)) < 0) {
317                 MSAPI_DBG_ERR("recv failed : %s", strerror(errno));
318
319                 __media_db_close_tcp_client_socket(sockfd);
320                 if (errno == EWOULDBLOCK) {
321                         MSAPI_DBG_ERR("Timeout. Can't try any more");
322                         return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
323                 } else {
324                         MSAPI_DBG_ERR("recv failed : %s", strerror(errno));
325                         return MS_MEDIA_ERR_SOCKET_RECEIVE;
326                 }
327         }
328
329         MSAPI_DBG("RECEIVE OK [%d]", recv_msg);
330         ret = recv_msg;
331
332         return ret;
333 }
334
335 static int _media_db_update_directly(sqlite3 *db_handle, const char *sql_str)
336 {
337         int ret = MS_MEDIA_ERR_NONE;
338         char *zErrMsg = NULL;
339
340         MSAPI_DBG_INFO("SQL = [%s]", sql_str);
341
342         ret = sqlite3_exec(db_handle, sql_str, NULL, NULL, &zErrMsg);
343
344         if (SQLITE_OK != ret) {
345                 MSAPI_DBG_ERR("DB Update Fail SQL:%s [%s], err[%d]", sql_str, zErrMsg, ret);
346                 if (ret == SQLITE_BUSY)
347                         ret = MS_MEDIA_ERR_DB_BUSY_FAIL;
348                 else
349                         ret = MS_MEDIA_ERR_DB_UPDATE_FAIL;
350         } else {
351                 MSAPI_DBG("DB Update Success");
352         }
353
354         if (zErrMsg)
355                 sqlite3_free (zErrMsg);
356
357         return ret;
358 }
359
360 int media_db_connect(MediaDBHandle **handle)
361 {
362         int ret = MS_MEDIA_ERR_NONE;
363         sqlite3 * db_handle = NULL;
364
365         MSAPI_DBG_FUNC();
366
367         ret = __media_db_connect_db_with_handle(&db_handle);
368         MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
369
370         *handle = db_handle;
371         return MS_MEDIA_ERR_NONE;
372 }
373
374 int media_db_disconnect(MediaDBHandle *handle)
375 {
376         sqlite3 * db_handle = (sqlite3 *)handle;
377
378         MSAPI_DBG_FUNC();
379
380         MSAPI_RETVM_IF(db_handle == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "Handle is NULL");
381
382         return __media_db_disconnect_db_with_handle(db_handle);
383 }
384
385 int media_db_request_update_db(const char *query_str)
386 {
387         int ret = MS_MEDIA_ERR_NONE;
388
389         MSAPI_DBG_FUNC();
390
391         MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
392
393         ret = __media_db_request_update(MS_MSG_DB_UPDATE, query_str);
394
395         return ret;
396 }
397
398 int media_db_request_update_db_batch_start(const char *query_str)
399 {
400         int ret = MS_MEDIA_ERR_NONE;
401
402         MSAPI_DBG_FUNC();
403
404         MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
405
406         ret = __media_db_prepare_tcp_client_socket();
407
408         if (ret < MS_MEDIA_ERR_NONE) {
409                 MSAPI_DBG_ERR("__media_db_prepare_tcp_client_socket failed : %d", ret);
410                 __media_db_close_tcp_client_socket();
411                 return ret;
412         }
413
414         ret = __media_db_request_batch_update(MS_MSG_DB_UPDATE_BATCH_START, query_str);
415
416         return ret;
417 }
418
419 int media_db_request_update_db_batch(const char *query_str)
420 {
421         int ret = MS_MEDIA_ERR_NONE;
422
423         MSAPI_DBG_FUNC();
424
425         MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
426
427         ret = __media_db_request_batch_update(MS_MSG_DB_UPDATE_BATCH, query_str);
428
429         return ret;
430 }
431
432 int media_db_request_update_db_batch_end(const char *query_str)
433 {
434         int ret = MS_MEDIA_ERR_NONE;
435
436         MSAPI_DBG_FUNC();
437
438         if (!MS_STRING_VALID(query_str)) {
439                 MSAPI_DBG_ERR("Invalid Query");
440                 __media_db_close_tcp_client_socket();
441                 return ret;
442         }
443
444         ret = __media_db_request_batch_update(MS_MSG_DB_UPDATE_BATCH_END, query_str);
445
446         __media_db_close_tcp_client_socket();
447
448         return ret;
449 }
450
451 int media_db_request_directory_scan(const char *directory_path)
452 {
453         int ret = MS_MEDIA_ERR_NONE;
454
455         MSAPI_RETVM_IF(!MS_STRING_VALID(directory_path), MS_MEDIA_ERR_INVALID_PARAMETER, "Directory Path is NULL");
456
457         ret = __media_db_request_update(MS_MSG_DIRECTORY_SCANNING, directory_path);
458
459         return ret;
460 }
461
462 int media_db_update_db(MediaDBHandle *handle, const char *query_str)
463 {
464         sqlite3 * db_handle = (sqlite3 *)handle;
465         int ret = MS_MEDIA_ERR_NONE;
466
467         MSAPI_RETVM_IF(db_handle == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "Handle is NULL");
468         MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
469
470         ret = _media_db_update_directly(db_handle, query_str);
471
472         return ret;
473 }
474
475 int media_db_update_db_batch_start(const char *query_str)
476 {
477         int ret = MS_MEDIA_ERR_NONE;
478
479         MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
480
481         if (g_list_idx != 0) {
482                 MSAPI_DBG_ERR("Current idx is not 0");
483                 ret = MS_MEDIA_ERR_DB_SERVER_BUSY_FAIL;
484         } else {
485                 sql_list = (char**)malloc(sizeof(char*));
486                 MSAPI_RETVM_IF(sql_list == NULL, MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL, "Out of memory");
487                 sql_list[g_list_idx++] = strdup(query_str);
488                 MSAPI_RETVM_IF(sql_list[g_list_idx - 1] == NULL, MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL, "Out of memory");
489         }
490
491         return ret;
492 }
493
494 int media_db_update_db_batch(const char *query_str)
495 {
496         int ret = MS_MEDIA_ERR_NONE;
497
498         MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
499
500         sql_list = (char**)realloc(sql_list, (g_list_idx + 1) * sizeof(char*));
501         MSAPI_RETVM_IF(sql_list == NULL, MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL, "Out of memory");
502
503         sql_list[g_list_idx++] = strdup(query_str);
504         MSAPI_RETVM_IF(sql_list[g_list_idx - 1] == NULL, MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL, "Out of memory");
505
506         return ret;
507 }
508
509 int media_db_update_db_batch_end(MediaDBHandle *handle, const char *query_str)
510 {
511         sqlite3 * db_handle = (sqlite3 *)handle;
512         int ret = MS_MEDIA_ERR_NONE;
513
514         if (db_handle == NULL || (!MS_STRING_VALID(query_str))) {
515                 __media_db_destroy_sql_list();
516                 MSAPI_DBG_ERR("Handle is NULL");
517                 return MS_MEDIA_ERR_INVALID_PARAMETER;
518         }
519
520         sql_list = (char**)realloc(sql_list, (g_list_idx + 1) * sizeof(char*));
521         if (sql_list == NULL) {
522                 __media_db_destroy_sql_list();
523                 MSAPI_DBG_ERR("Out of memory");
524                 return MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL;
525         }
526
527         sql_list[g_list_idx++] = strdup(query_str);
528         if (sql_list[g_list_idx - 1] == NULL) {
529                 __media_db_destroy_sql_list();
530                 MSAPI_DBG_ERR("Out of memory");
531                 return MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL;
532         }
533
534         int i = 0;
535         char *current_sql = NULL;
536         for (i = 0; i < g_list_idx; i++) {
537                 current_sql = sql_list[i];
538                 ret = _media_db_update_directly(db_handle, current_sql);
539                 if (ret < 0) {
540                         if (i == 0) {
541                                 /* This is fail of "BEGIN" */
542                                 MSAPI_DBG_ERR("Query failed : %s", current_sql);
543                                 break;
544                         } else if (i == g_list_idx - 1) {
545                                 /* This is fail of "COMMIT" */
546                                 MSAPI_DBG_ERR("Query failed : %s", current_sql);
547                                 break;
548                         } else {
549                                 MSAPI_DBG_ERR("Query failed : %s, but keep going to run remaining queries", current_sql);
550                         }
551                 }
552         }
553
554         __media_db_destroy_sql_list();
555
556         return ret;
557 }