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 #ifdef _USE_UDS_SOCKET_
129 struct sockaddr_un serv_addr;
131 struct sockaddr_in serv_addr;
133 unsigned int serv_addr_len = -1;
134 int port = MS_DB_UPDATE_PORT;
136 if(msg_type == MS_MSG_DB_UPDATE)
137 port = MS_DB_UPDATE_PORT;
139 port = MS_SCANNER_PORT;
141 if(!MS_STRING_VALID(request_msg))
143 MSAPI_DBG_ERR("invalid query");
144 return MS_MEDIA_ERR_INVALID_PARAMETER;
147 request_msg_size = strlen(request_msg);
148 if(request_msg_size >= MAX_MSG_SIZE)
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;
154 // MSAPI_DBG("querysize[%d] query[%s]", request_msg_size, request_msg);
156 ms_comm_msg_s send_msg;
157 memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s));
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);
164 #ifdef _USE_UDS_SOCKET_
165 ret = ms_ipc_create_client_socket(MS_PROTOCOL_UDP, MS_TIMEOUT_SEC_10, &sockfd, port);
167 ret = ms_ipc_create_client_socket(MS_PROTOCOL_UDP, MS_TIMEOUT_SEC_10, &sockfd);
169 MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
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);
180 ms_comm_msg_s recv_msg;
181 serv_addr_len = sizeof(serv_addr);
182 memset(&recv_msg, 0x0, sizeof(ms_comm_msg_s));
184 err = ms_ipc_wait_message(sockfd, &recv_msg, sizeof(recv_msg), &serv_addr, NULL);
185 if (err != MS_MEDIA_ERR_NONE) {
188 MSAPI_DBG("RECEIVE OK [%d]", recv_msg.result);
189 ret = recv_msg.result;
197 static int g_tcp_client_sock = -1;
199 static int __media_db_get_client_tcp_sock()
201 return g_tcp_client_sock;
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];
210 static int __media_db_prepare_tcp_client_socket()
212 int ret = MS_MEDIA_ERR_NONE;
214 #ifdef _USE_UDS_SOCKET_
215 struct sockaddr_un serv_addr;
216 #elif defined(_USE_UDS_SOCKET_TCP_)
217 struct sockaddr_un serv_addr;
219 struct sockaddr_in serv_addr;
221 int port = MS_DB_BATCH_UPDATE_PORT;
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);
229 ret = ms_ipc_create_client_socket(MS_PROTOCOL_TCP, MS_TIMEOUT_SEC_10, &sockfd);
231 MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
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]);
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);
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));
254 return MS_MEDIA_ERR_SOCKET_CONN;
257 g_tcp_client_sock = sockfd;
259 MSAPI_DBG("Connected successfully");
264 static int __media_db_close_tcp_client_socket()
266 close(g_tcp_client_sock);
267 g_tcp_client_sock = -1;
272 static int __media_db_request_batch_update(ms_msg_type_e msg_type, const char *request_msg)
274 int ret = MS_MEDIA_ERR_NONE;
275 int request_msg_size = 0;
278 if(!MS_STRING_VALID(request_msg))
280 MSAPI_DBG_ERR("invalid query");
281 return MS_MEDIA_ERR_INVALID_PARAMETER;
284 request_msg_size = strlen(request_msg);
285 if(request_msg_size >= MAX_MSG_SIZE)
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;
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));
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);
299 sockfd = __media_db_get_client_tcp_sock();
301 return MS_MEDIA_ERR_SOCKET_CONN;
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;
310 MSAPI_DBG("Sent successfully");
314 int recv_msg_size = -1;
316 if ((recv_msg_size = recv(sockfd, &recv_msg, sizeof(recv_msg), 0)) < 0) {
317 MSAPI_DBG_ERR("recv failed : %s", strerror(errno));
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;
324 MSAPI_DBG_ERR("recv failed : %s", strerror(errno));
325 return MS_MEDIA_ERR_SOCKET_RECEIVE;
329 MSAPI_DBG("RECEIVE OK [%d]", recv_msg);
335 static int _media_db_update_directly(sqlite3 *db_handle, const char *sql_str)
337 int ret = MS_MEDIA_ERR_NONE;
338 char *zErrMsg = NULL;
340 MSAPI_DBG_INFO("SQL = [%s]", sql_str);
342 ret = sqlite3_exec(db_handle, sql_str, NULL, NULL, &zErrMsg);
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;
349 ret = MS_MEDIA_ERR_DB_UPDATE_FAIL;
351 MSAPI_DBG("DB Update Success");
355 sqlite3_free (zErrMsg);
360 int media_db_connect(MediaDBHandle **handle)
362 int ret = MS_MEDIA_ERR_NONE;
363 sqlite3 * db_handle = NULL;
367 ret = __media_db_connect_db_with_handle(&db_handle);
368 MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
371 return MS_MEDIA_ERR_NONE;
374 int media_db_disconnect(MediaDBHandle *handle)
376 sqlite3 * db_handle = (sqlite3 *)handle;
380 MSAPI_RETVM_IF(db_handle == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "Handle is NULL");
382 return __media_db_disconnect_db_with_handle(db_handle);
385 int media_db_request_update_db(const char *query_str)
387 int ret = MS_MEDIA_ERR_NONE;
391 MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
393 ret = __media_db_request_update(MS_MSG_DB_UPDATE, query_str);
398 int media_db_request_update_db_batch_start(const char *query_str)
400 int ret = MS_MEDIA_ERR_NONE;
404 MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
406 ret = __media_db_prepare_tcp_client_socket();
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();
414 ret = __media_db_request_batch_update(MS_MSG_DB_UPDATE_BATCH_START, query_str);
419 int media_db_request_update_db_batch(const char *query_str)
421 int ret = MS_MEDIA_ERR_NONE;
425 MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
427 ret = __media_db_request_batch_update(MS_MSG_DB_UPDATE_BATCH, query_str);
432 int media_db_request_update_db_batch_end(const char *query_str)
434 int ret = MS_MEDIA_ERR_NONE;
438 if (!MS_STRING_VALID(query_str)) {
439 MSAPI_DBG_ERR("Invalid Query");
440 __media_db_close_tcp_client_socket();
444 ret = __media_db_request_batch_update(MS_MSG_DB_UPDATE_BATCH_END, query_str);
446 __media_db_close_tcp_client_socket();
451 int media_db_request_directory_scan(const char *directory_path)
453 int ret = MS_MEDIA_ERR_NONE;
455 MSAPI_RETVM_IF(!MS_STRING_VALID(directory_path), MS_MEDIA_ERR_INVALID_PARAMETER, "Directory Path is NULL");
457 ret = __media_db_request_update(MS_MSG_DIRECTORY_SCANNING, directory_path);
462 int media_db_update_db(MediaDBHandle *handle, const char *query_str)
464 sqlite3 * db_handle = (sqlite3 *)handle;
465 int ret = MS_MEDIA_ERR_NONE;
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");
470 ret = _media_db_update_directly(db_handle, query_str);
475 int media_db_update_db_batch_start(const char *query_str)
477 int ret = MS_MEDIA_ERR_NONE;
479 MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
481 if (g_list_idx != 0) {
482 MSAPI_DBG_ERR("Current idx is not 0");
483 ret = MS_MEDIA_ERR_DB_SERVER_BUSY_FAIL;
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");
494 int media_db_update_db_batch(const char *query_str)
496 int ret = MS_MEDIA_ERR_NONE;
498 MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
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");
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");
509 int media_db_update_db_batch_end(MediaDBHandle *handle, const char *query_str)
511 sqlite3 * db_handle = (sqlite3 *)handle;
512 int ret = MS_MEDIA_ERR_NONE;
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;
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;
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;
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);
541 /* This is fail of "BEGIN" */
542 MSAPI_DBG_ERR("Query failed : %s", current_sql);
544 } else if (i == g_list_idx - 1) {
545 /* This is fail of "COMMIT" */
546 MSAPI_DBG_ERR("Query failed : %s", current_sql);
549 MSAPI_DBG_ERR("Query failed : %s, but keep going to run remaining queries", current_sql);
554 __media_db_destroy_sql_list();