Tizen 2.1 base
[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         struct sockaddr_in serv_addr;
129         unsigned int serv_addr_len = -1;
130         int port = MS_DB_UPDATE_PORT;
131
132         if(msg_type == MS_MSG_DB_UPDATE)
133                 port = MS_DB_UPDATE_PORT;
134         else
135                 port = MS_SCANNER_PORT;
136
137         if(!MS_STRING_VALID(request_msg))
138         {
139                 MSAPI_DBG_ERR("invalid query");
140                 return MS_MEDIA_ERR_INVALID_PARAMETER;
141         }
142
143         request_msg_size = strlen(request_msg);
144         if(request_msg_size >= MAX_MSG_SIZE)
145         {
146                 MSAPI_DBG_ERR("Query is Too long. [%d] query size limit is [%d]", request_msg_size, MAX_MSG_SIZE);
147                 return MS_MEDIA_ERR_INVALID_PARAMETER;
148         }
149
150 //      MSAPI_DBG("querysize[%d] query[%s]", request_msg_size, request_msg);
151
152         ms_comm_msg_s send_msg;
153         memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s));
154
155         send_msg.msg_type = msg_type;
156         send_msg.msg_size = request_msg_size;
157         strncpy(send_msg.msg, request_msg, request_msg_size);
158
159         /*Create Socket*/
160         ret = ms_ipc_create_client_socket(MS_PROTOCOL_UDP, MS_TIMEOUT_SEC_3, &sockfd);
161         MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
162
163         ret = ms_ipc_send_msg_to_server(sockfd, port, &send_msg, &serv_addr);
164         MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
165
166         /*Receive Response*/
167         ms_comm_msg_s recv_msg;
168         serv_addr_len = sizeof(serv_addr);
169         memset(&recv_msg, 0x0, sizeof(ms_comm_msg_s));
170
171         err = ms_ipc_wait_message(sockfd, &recv_msg, sizeof(recv_msg), &serv_addr, NULL);
172         if (err != MS_MEDIA_ERR_NONE) {
173                 ret = err;
174         } else {
175                 MSAPI_DBG("RECEIVE OK [%d]", recv_msg.result);
176                 ret = recv_msg.result;
177         }
178
179         close(sockfd);
180
181         return ret;
182 }
183
184 static int g_tcp_client_sock = -1;
185
186 static int __media_db_get_client_tcp_sock()
187 {
188         return g_tcp_client_sock;
189 }
190
191 static int __media_db_prepare_tcp_client_socket()
192 {
193         int ret = MS_MEDIA_ERR_NONE;
194         int sockfd = -1;
195         struct sockaddr_in serv_addr;
196         int port = MS_DB_BATCH_UPDATE_PORT;
197
198         /*Create TCP Socket*/
199         ret = ms_ipc_create_client_socket(MS_PROTOCOL_TCP, MS_TIMEOUT_SEC_3, &sockfd);
200         MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
201
202         /*Set server Address*/
203         memset(&serv_addr, 0, sizeof(serv_addr));
204         serv_addr.sin_family = AF_INET;
205         serv_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
206         serv_addr.sin_port = htons(port);
207
208         /* Connecting to the media db server */
209         if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
210                 MSAPI_DBG_ERR("connect error : %s", strerror(errno));
211                 close(sockfd);
212                 return MS_MEDIA_ERR_SOCKET_CONN;
213         }
214
215         g_tcp_client_sock = sockfd;
216
217         MSAPI_DBG("Connected successfully");
218
219         return 0;
220 }
221
222 static int __media_db_close_tcp_client_socket()
223 {
224         close(g_tcp_client_sock);
225         g_tcp_client_sock = -1;
226
227         return 0;
228 }
229
230 static int __media_db_request_batch_update(ms_msg_type_e msg_type, const char *request_msg)
231 {
232         int ret = MS_MEDIA_ERR_NONE;
233         int request_msg_size = 0;
234         int sockfd = -1;
235
236         if(!MS_STRING_VALID(request_msg))
237         {
238                 MSAPI_DBG_ERR("invalid query");
239                 return MS_MEDIA_ERR_INVALID_PARAMETER;
240         }
241
242         request_msg_size = strlen(request_msg);
243         if(request_msg_size >= MAX_MSG_SIZE)
244         {
245                 MSAPI_DBG_ERR("Query is Too long. [%d] query size limit is [%d]", request_msg_size, MAX_MSG_SIZE);
246                 return MS_MEDIA_ERR_INVALID_PARAMETER;
247         }
248
249         MSAPI_DBG("querysize[%d] query[%s]", request_msg_size, request_msg);
250         ms_comm_msg_s send_msg;
251         memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s));
252
253         send_msg.msg_type = msg_type;
254         send_msg.msg_size = request_msg_size;
255         strncpy(send_msg.msg, request_msg, request_msg_size);
256
257         sockfd = __media_db_get_client_tcp_sock();
258         if (sockfd <= 0) {
259                 return  MS_MEDIA_ERR_SOCKET_CONN;
260         }
261
262         /* Send request */
263         if (send(sockfd, &send_msg, sizeof(send_msg), 0) != sizeof(send_msg)) {
264                 MSAPI_DBG_ERR("send failed : %s", strerror(errno));
265                 __media_db_close_tcp_client_socket(sockfd);
266                 return MS_MEDIA_ERR_SOCKET_SEND;
267         } else {
268                 MSAPI_DBG("Sent successfully");
269         }
270
271         /*Receive Response*/
272         int recv_msg_size = -1;
273         int recv_msg = -1;
274         if ((recv_msg_size = recv(sockfd, &recv_msg, sizeof(recv_msg), 0)) < 0) {
275                 MSAPI_DBG_ERR("recv failed : %s", strerror(errno));
276
277                 __media_db_close_tcp_client_socket(sockfd);
278                 if (errno == EWOULDBLOCK) {
279                         MSAPI_DBG_ERR("Timeout. Can't try any more");
280                         return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
281                 } else {
282                         MSAPI_DBG_ERR("recv failed : %s", strerror(errno));
283                         return MS_MEDIA_ERR_SOCKET_RECEIVE;
284                 }
285         }
286
287         MSAPI_DBG("RECEIVE OK [%d]", recv_msg);
288         ret = recv_msg;
289
290         return ret;
291 }
292
293 static int _media_db_update_directly(sqlite3 *db_handle, const char *sql_str)
294 {
295         int ret = MS_MEDIA_ERR_NONE;
296         char *zErrMsg = NULL;
297
298         MSAPI_DBG_INFO("SQL = [%s]", sql_str);
299
300         ret = sqlite3_exec(db_handle, sql_str, NULL, NULL, &zErrMsg);
301
302         if (SQLITE_OK != ret) {
303                 MSAPI_DBG_ERR("DB Update Fail SQL:%s [%s], err[%d]", sql_str, zErrMsg, ret);
304                 if (ret == SQLITE_BUSY)
305                         ret = MS_MEDIA_ERR_DB_BUSY_FAIL;
306                 else
307                         ret = MS_MEDIA_ERR_DB_UPDATE_FAIL;
308         } else {
309                 MSAPI_DBG("DB Update Success");
310         }
311
312         if (zErrMsg)
313                 sqlite3_free (zErrMsg);
314
315         return ret;
316 }
317
318 int media_db_connect(MediaDBHandle **handle)
319 {
320         int ret = MS_MEDIA_ERR_NONE;
321         sqlite3 * db_handle = NULL;
322
323         MSAPI_DBG_FUNC();
324
325         ret = __media_db_connect_db_with_handle(&db_handle);
326         MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
327
328         *handle = db_handle;
329         return MS_MEDIA_ERR_NONE;
330 }
331
332 int media_db_disconnect(MediaDBHandle *handle)
333 {
334         sqlite3 * db_handle = (sqlite3 *)handle;
335
336         MSAPI_DBG_FUNC();
337
338         MSAPI_RETVM_IF(db_handle == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "Handle is NULL");
339
340         return __media_db_disconnect_db_with_handle(db_handle);
341 }
342
343 int media_db_request_update_db(const char *query_str)
344 {
345         int ret = MS_MEDIA_ERR_NONE;
346
347         MSAPI_DBG_FUNC();
348
349         MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
350
351         ret = __media_db_request_update(MS_MSG_DB_UPDATE, query_str);
352
353         return ret;
354 }
355
356 int media_db_request_update_db_batch_start(const char *query_str)
357 {
358         int ret = MS_MEDIA_ERR_NONE;
359
360         MSAPI_DBG_FUNC();
361
362         MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
363
364         ret = __media_db_prepare_tcp_client_socket();
365
366         if (ret < MS_MEDIA_ERR_NONE) {
367                 MSAPI_DBG_ERR("__media_db_prepare_tcp_client_socket failed : %d", ret);
368                 __media_db_close_tcp_client_socket();
369                 return ret;
370         }
371
372         ret = __media_db_request_batch_update(MS_MSG_DB_UPDATE_BATCH_START, query_str);
373
374         return ret;
375 }
376
377 int media_db_request_update_db_batch(const char *query_str)
378 {
379         int ret = MS_MEDIA_ERR_NONE;
380
381         MSAPI_DBG_FUNC();
382
383         MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
384
385         ret = __media_db_request_batch_update(MS_MSG_DB_UPDATE_BATCH, query_str);
386
387         return ret;
388 }
389
390 int media_db_request_update_db_batch_end(const char *query_str)
391 {
392         int ret = MS_MEDIA_ERR_NONE;
393
394         MSAPI_DBG_FUNC();
395
396         if (!MS_STRING_VALID(query_str)) {
397                 MSAPI_DBG_ERR("Invalid Query");
398                 __media_db_close_tcp_client_socket();
399                 return ret;
400         }
401
402         ret = __media_db_request_batch_update(MS_MSG_DB_UPDATE_BATCH_END, query_str);
403
404         __media_db_close_tcp_client_socket();
405
406         return ret;
407 }
408
409 int media_db_request_directory_scan(const char *directory_path)
410 {
411         int ret = MS_MEDIA_ERR_NONE;
412
413         MSAPI_RETVM_IF(!MS_STRING_VALID(directory_path), MS_MEDIA_ERR_INVALID_PARAMETER, "Directory Path is NULL");
414
415         ret = __media_db_request_update(MS_MSG_DIRECTORY_SCANNING, directory_path);
416
417         return ret;
418 }
419
420 int media_db_update_db(MediaDBHandle *handle, const char *query_str)
421 {
422         sqlite3 * db_handle = (sqlite3 *)handle;
423         int ret = MS_MEDIA_ERR_NONE;
424
425         MSAPI_RETVM_IF(db_handle == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "Handle is NULL");
426         MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
427
428         ret = _media_db_update_directly(db_handle, query_str);
429
430         return ret;
431 }
432
433 int media_db_update_db_batch_start(const char *query_str)
434 {
435         int ret = MS_MEDIA_ERR_NONE;
436
437         MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
438
439         if (g_list_idx != 0) {
440                 MSAPI_DBG_ERR("Current idx is not 0");
441                 ret = MS_MEDIA_ERR_DB_SERVER_BUSY_FAIL;
442         } else {
443                 sql_list = (char**)malloc(sizeof(char*));
444                 MSAPI_RETVM_IF(sql_list == NULL, MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL, "Out of memory");
445                 sql_list[g_list_idx++] = strdup(query_str);
446                 MSAPI_RETVM_IF(sql_list[g_list_idx - 1] == NULL, MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL, "Out of memory");
447         }
448
449         return ret;
450 }
451
452 int media_db_update_db_batch(const char *query_str)
453 {
454         int ret = MS_MEDIA_ERR_NONE;
455
456         MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
457
458         sql_list = (char**)realloc(sql_list, (g_list_idx + 1) * sizeof(char*));
459         MSAPI_RETVM_IF(sql_list == NULL, MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL, "Out of memory");
460
461         sql_list[g_list_idx++] = strdup(query_str);
462         MSAPI_RETVM_IF(sql_list[g_list_idx - 1] == NULL, MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL, "Out of memory");
463
464         return ret;
465 }
466
467 int media_db_update_db_batch_end(MediaDBHandle *handle, const char *query_str)
468 {
469         sqlite3 * db_handle = (sqlite3 *)handle;
470         int ret = MS_MEDIA_ERR_NONE;
471
472         if (db_handle == NULL || (!MS_STRING_VALID(query_str))) {
473                 __media_db_destroy_sql_list();
474                 MSAPI_DBG_ERR("Handle is NULL");
475                 return MS_MEDIA_ERR_INVALID_PARAMETER;
476         }
477
478         sql_list = (char**)realloc(sql_list, (g_list_idx + 1) * sizeof(char*));
479         if (sql_list == NULL) {
480                 __media_db_destroy_sql_list();
481                 MSAPI_DBG_ERR("Out of memory");
482                 return MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL;
483         }
484
485         sql_list[g_list_idx++] = strdup(query_str);
486         if (sql_list[g_list_idx - 1] == NULL) {
487                 __media_db_destroy_sql_list();
488                 MSAPI_DBG_ERR("Out of memory");
489                 return MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL;
490         }
491
492         int i = 0;
493         char *current_sql = NULL;
494         for (i = 0; i < g_list_idx; i++) {
495                 current_sql = sql_list[i];
496                 ret = _media_db_update_directly(db_handle, current_sql);
497                 if (ret < 0) {
498                         if (i == 0) {
499                                 /* This is fail of "BEGIN" */
500                                 MSAPI_DBG_ERR("Query failed : %s", current_sql);
501                                 break;
502                         } else if (i == g_list_idx - 1) {
503                                 /* This is fail of "COMMIT" */
504                                 MSAPI_DBG_ERR("Query failed : %s", current_sql);
505                                 break;
506                         } else {
507                                 MSAPI_DBG_ERR("Query failed : %s, but keep going to run remaining queries", current_sql);
508                         }
509                 }
510         }
511
512         __media_db_destroy_sql_list();
513
514         return ret;
515 }