4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Yong Yeon Kim <yy9875.kim@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 * This file defines api utilities of Media DB.
25 * @file media-util-db.c
26 * @author Haejeong Kim(backto.kim@samsung.com)
35 #include "media-server-ipc.h"
36 #include "media-util-dbg.h"
37 #include "media-util-internal.h"
38 #include "media-util.h"
40 static __thread char **sql_list = NULL;
41 static __thread int g_list_idx = 0;
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);
48 void __media_db_destroy_sql_list()
52 for (i = 0; i < g_list_idx; i++) {
53 MS_SAFE_FREE(sql_list[i]);
56 MS_SAFE_FREE(sql_list);
60 static int __media_db_busy_handler(void *pData, int count)
64 MSAPI_DBG("media_db_busy_handler called : %d", count);
69 static int __media_db_connect_db_with_handle(sqlite3 **db_handle)
71 int ret = MS_MEDIA_ERR_NONE;
74 ret = db_util_open(MEDIA_DB_NAME, db_handle, DB_UTIL_REGISTER_HOOK_METHOD);
76 if (SQLITE_OK != ret) {
78 MSAPI_DBG_ERR("error when db open");
80 return MS_MEDIA_ERR_DB_CONNECT_FAIL;
83 if (*db_handle == NULL) {
84 MSAPI_DBG_ERR("*db_handle is NULL");
85 return MS_MEDIA_ERR_DB_CONNECT_FAIL;
88 /*Register busy handler*/
89 ret = sqlite3_busy_handler(*db_handle, __media_db_busy_handler, NULL);
91 if (SQLITE_OK != ret) {
94 MSAPI_DBG_ERR("[error when register busy handler] %s\n", sqlite3_errmsg(*db_handle));
97 db_util_close(*db_handle);
100 return MS_MEDIA_ERR_DB_CONNECT_FAIL;
103 return MS_MEDIA_ERR_NONE;
106 static int __media_db_disconnect_db_with_handle(sqlite3 *db_handle)
108 int ret = MS_MEDIA_ERR_NONE;
110 ret = db_util_close(db_handle);
112 if (SQLITE_OK != ret) {
113 MSAPI_DBG_ERR("error when db close");
114 MSAPI_DBG_ERR("Error : %s", sqlite3_errmsg(db_handle));
116 return MS_MEDIA_ERR_DB_DISCONNECT_FAIL;
119 return MS_MEDIA_ERR_NONE;
122 static int __media_db_request_update(ms_msg_type_e msg_type, const char *request_msg)
124 int ret = MS_MEDIA_ERR_NONE;
125 int request_msg_size = 0;
128 struct sockaddr_in serv_addr;
129 unsigned int serv_addr_len = -1;
130 int port = MS_DB_UPDATE_PORT;
132 if(msg_type == MS_MSG_DB_UPDATE)
133 port = MS_DB_UPDATE_PORT;
135 port = MS_SCANNER_PORT;
137 if(!MS_STRING_VALID(request_msg))
139 MSAPI_DBG_ERR("invalid query");
140 return MS_MEDIA_ERR_INVALID_PARAMETER;
143 request_msg_size = strlen(request_msg);
144 if(request_msg_size >= MAX_MSG_SIZE)
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;
150 // MSAPI_DBG("querysize[%d] query[%s]", request_msg_size, request_msg);
152 ms_comm_msg_s send_msg;
153 memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s));
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);
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);
163 ret = ms_ipc_send_msg_to_server(sockfd, port, &send_msg, &serv_addr);
164 MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
167 ms_comm_msg_s recv_msg;
168 serv_addr_len = sizeof(serv_addr);
169 memset(&recv_msg, 0x0, sizeof(ms_comm_msg_s));
171 err = ms_ipc_wait_message(sockfd, &recv_msg, sizeof(recv_msg), &serv_addr, NULL);
172 if (err != MS_MEDIA_ERR_NONE) {
175 MSAPI_DBG("RECEIVE OK [%d]", recv_msg.result);
176 ret = recv_msg.result;
184 static int g_tcp_client_sock = -1;
186 static int __media_db_get_client_tcp_sock()
188 return g_tcp_client_sock;
191 static int __media_db_prepare_tcp_client_socket()
193 int ret = MS_MEDIA_ERR_NONE;
195 struct sockaddr_in serv_addr;
196 int port = MS_DB_BATCH_UPDATE_PORT;
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);
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);
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));
212 return MS_MEDIA_ERR_SOCKET_CONN;
215 g_tcp_client_sock = sockfd;
217 MSAPI_DBG("Connected successfully");
222 static int __media_db_close_tcp_client_socket()
224 close(g_tcp_client_sock);
225 g_tcp_client_sock = -1;
230 static int __media_db_request_batch_update(ms_msg_type_e msg_type, const char *request_msg)
232 int ret = MS_MEDIA_ERR_NONE;
233 int request_msg_size = 0;
236 if(!MS_STRING_VALID(request_msg))
238 MSAPI_DBG_ERR("invalid query");
239 return MS_MEDIA_ERR_INVALID_PARAMETER;
242 request_msg_size = strlen(request_msg);
243 if(request_msg_size >= MAX_MSG_SIZE)
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;
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));
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);
257 sockfd = __media_db_get_client_tcp_sock();
259 return MS_MEDIA_ERR_SOCKET_CONN;
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;
268 MSAPI_DBG("Sent successfully");
272 int recv_msg_size = -1;
274 if ((recv_msg_size = recv(sockfd, &recv_msg, sizeof(recv_msg), 0)) < 0) {
275 MSAPI_DBG_ERR("recv failed : %s", strerror(errno));
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;
282 MSAPI_DBG_ERR("recv failed : %s", strerror(errno));
283 return MS_MEDIA_ERR_SOCKET_RECEIVE;
287 MSAPI_DBG("RECEIVE OK [%d]", recv_msg);
293 static int _media_db_update_directly(sqlite3 *db_handle, const char *sql_str)
295 int ret = MS_MEDIA_ERR_NONE;
296 char *zErrMsg = NULL;
298 MSAPI_DBG_INFO("SQL = [%s]", sql_str);
300 ret = sqlite3_exec(db_handle, sql_str, NULL, NULL, &zErrMsg);
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;
307 ret = MS_MEDIA_ERR_DB_UPDATE_FAIL;
309 MSAPI_DBG("DB Update Success");
313 sqlite3_free (zErrMsg);
318 int media_db_connect(MediaDBHandle **handle)
320 int ret = MS_MEDIA_ERR_NONE;
321 sqlite3 * db_handle = NULL;
325 ret = __media_db_connect_db_with_handle(&db_handle);
326 MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
329 return MS_MEDIA_ERR_NONE;
332 int media_db_disconnect(MediaDBHandle *handle)
334 sqlite3 * db_handle = (sqlite3 *)handle;
338 MSAPI_RETVM_IF(db_handle == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "Handle is NULL");
340 return __media_db_disconnect_db_with_handle(db_handle);
343 int media_db_request_update_db(const char *query_str)
345 int ret = MS_MEDIA_ERR_NONE;
349 MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
351 ret = __media_db_request_update(MS_MSG_DB_UPDATE, query_str);
356 int media_db_request_update_db_batch_start(const char *query_str)
358 int ret = MS_MEDIA_ERR_NONE;
362 MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
364 ret = __media_db_prepare_tcp_client_socket();
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();
372 ret = __media_db_request_batch_update(MS_MSG_DB_UPDATE_BATCH_START, query_str);
377 int media_db_request_update_db_batch(const char *query_str)
379 int ret = MS_MEDIA_ERR_NONE;
383 MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
385 ret = __media_db_request_batch_update(MS_MSG_DB_UPDATE_BATCH, query_str);
390 int media_db_request_update_db_batch_end(const char *query_str)
392 int ret = MS_MEDIA_ERR_NONE;
396 if (!MS_STRING_VALID(query_str)) {
397 MSAPI_DBG_ERR("Invalid Query");
398 __media_db_close_tcp_client_socket();
402 ret = __media_db_request_batch_update(MS_MSG_DB_UPDATE_BATCH_END, query_str);
404 __media_db_close_tcp_client_socket();
409 int media_db_request_directory_scan(const char *directory_path)
411 int ret = MS_MEDIA_ERR_NONE;
413 MSAPI_RETVM_IF(!MS_STRING_VALID(directory_path), MS_MEDIA_ERR_INVALID_PARAMETER, "Directory Path is NULL");
415 ret = __media_db_request_update(MS_MSG_DIRECTORY_SCANNING, directory_path);
420 int media_db_update_db(MediaDBHandle *handle, const char *query_str)
422 sqlite3 * db_handle = (sqlite3 *)handle;
423 int ret = MS_MEDIA_ERR_NONE;
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");
428 ret = _media_db_update_directly(db_handle, query_str);
433 int media_db_update_db_batch_start(const char *query_str)
435 int ret = MS_MEDIA_ERR_NONE;
437 MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
439 if (g_list_idx != 0) {
440 MSAPI_DBG_ERR("Current idx is not 0");
441 ret = MS_MEDIA_ERR_DB_SERVER_BUSY_FAIL;
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");
452 int media_db_update_db_batch(const char *query_str)
454 int ret = MS_MEDIA_ERR_NONE;
456 MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
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");
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");
467 int media_db_update_db_batch_end(MediaDBHandle *handle, const char *query_str)
469 sqlite3 * db_handle = (sqlite3 *)handle;
470 int ret = MS_MEDIA_ERR_NONE;
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;
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;
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;
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);
499 /* This is fail of "BEGIN" */
500 MSAPI_DBG_ERR("Query failed : %s", current_sql);
502 } else if (i == g_list_idx - 1) {
503 /* This is fail of "COMMIT" */
504 MSAPI_DBG_ERR("Query failed : %s", current_sql);
507 MSAPI_DBG_ERR("Query failed : %s, but keep going to run remaining queries", current_sql);
512 __media_db_destroy_sql_list();