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.
26 #include <sys/smack.h>
27 #include "media-server-ipc.h"
28 #include "media-util-dbg.h"
29 #include "media-util-internal.h"
30 #include "media-util.h"
32 #define BATCH_START "BEGIN"
33 #define BATCH_END "COMMIT"
35 static __thread GArray *sql_list = NULL;
37 static int __media_db_request_recovery(uid_t uid);
39 static void __media_db_destroy_sql_list()
41 if (sql_list != NULL) {
42 while (sql_list->len != 0) {
43 char *sql = g_array_index(sql_list, char *, 0);
44 g_array_remove_index(sql_list, 0);
49 g_array_unref(sql_list);
54 static int __media_db_busy_handler(void *pData, int count)
58 MSAPI_DBG("media_db_busy_handler called : %d", count);
63 static int __media_db_connect_db_with_handle(sqlite3 **db_handle, uid_t uid, bool need_write)
69 ret = ms_user_get_media_db_path(uid, &db_path);
70 MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, MS_MEDIA_ERR_DB_CONNECT_FAIL, "ms_user_get_media_db_path failed");
74 ret = db_util_open_with_options(db_path, db_handle, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
76 ret = db_util_open_with_options(db_path, db_handle, SQLITE_OPEN_READONLY, NULL);
79 if (SQLITE_OK != ret) {
80 MSAPI_DBG_ERR("error when db open path[%s],ret[%d]", db_path, ret);
81 MS_SAFE_FREE(db_path);
83 return MS_MEDIA_ERR_DB_CONNECT_FAIL;
85 MS_SAFE_FREE(db_path);
87 if (*db_handle == NULL) {
88 MSAPI_DBG_ERR("*db_handle is NULL");
89 return MS_MEDIA_ERR_DB_CONNECT_FAIL;
92 /*Register busy handler*/
93 ret = sqlite3_busy_handler(*db_handle, __media_db_busy_handler, NULL);
94 if (SQLITE_OK != ret) {
96 MSAPI_DBG_ERR("[error when register busy handler] %s", sqlite3_errmsg(*db_handle));
98 db_util_close(*db_handle);
101 return MS_MEDIA_ERR_DB_CONNECT_FAIL;
104 /*For TV internal space issue, change TRUNCATE to OFF */
105 sql = sqlite3_mprintf("%s", "PRAGMA journal_mode = OFF");
106 ret = sqlite3_exec(*db_handle, sql, NULL, NULL, NULL);
107 MS_SQL_SAFE_FREE(sql);
108 if (SQLITE_OK != ret) {
110 MSAPI_DBG_ERR("[error when change the journal mode] %s", sqlite3_errmsg(*db_handle));
112 db_util_close(*db_handle);
115 if (ret == SQLITE_CORRUPT) {
116 MSAPI_DBG_ERR("MEDIA DB IS CORRUPTED");
117 return MS_MEDIA_ERR_DB_CORRUPT;
120 return MS_MEDIA_ERR_DB_CONNECT_FAIL;
123 return MS_MEDIA_ERR_NONE;
126 static int __media_db_disconnect_db_with_handle(sqlite3 *db_handle)
128 int ret = MS_MEDIA_ERR_NONE;
130 ret = db_util_close(db_handle);
131 if (SQLITE_OK != ret) {
132 MSAPI_DBG_ERR("error when db close [%s]", sqlite3_errmsg(db_handle));
134 return MS_MEDIA_ERR_DB_DISCONNECT_FAIL;
137 return MS_MEDIA_ERR_NONE;
140 extern char MEDIA_IPC_PATH[][70];
141 #define MAX_RETRY_COUNT 3
143 static int __media_db_request_update_tcp(ms_msg_type_e msg_type, const char *request_msg, uid_t uid)
145 int ret = MS_MEDIA_ERR_NONE;
146 int request_msg_size = 0;
148 struct sockaddr_un serv_addr;
151 if (!MS_STRING_VALID(request_msg)) {
152 MSAPI_DBG_ERR("invalid query");
153 return MS_MEDIA_ERR_INVALID_PARAMETER;
156 request_msg_size = strlen(request_msg);
157 if (request_msg_size >= MAX_MSG_SIZE) {
158 MSAPI_DBG_ERR("Too long query[%d] limit[%d]", request_msg_size, MAX_MSG_SIZE);
159 return MS_MEDIA_ERR_INVALID_PARAMETER;
162 ms_comm_msg_s send_msg;
163 memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s));
165 send_msg.msg_type = msg_type;
166 SAFE_STRLCPY(send_msg.msg, request_msg, sizeof(send_msg.msg));
170 ret = ms_ipc_create_client_socket(MS_TIMEOUT_SEC_10, &sockfd);
171 MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
173 /*Set server Address*/
174 memset(&serv_addr, 0, sizeof(serv_addr));
175 serv_addr.sun_family = AF_UNIX;
176 SAFE_STRLCPY(serv_addr.sun_path, tzplatform_mkpath(TZ_SYS_RUN, MEDIA_IPC_PATH[MS_DB_UPDATE_PORT]), sizeof(serv_addr.sun_path));
178 /* Connecting to the media db server */
179 if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
180 MSAPI_DBG_STRERROR("connect error");
183 return MS_MEDIA_ERR_PERMISSION_DENIED;
185 return MS_MEDIA_ERR_SOCKET_CONN;
189 if (send(sockfd, &send_msg, sizeof(send_msg), 0) != sizeof(send_msg)) {
190 MSAPI_DBG_STRERROR("send failed");
192 return MS_MEDIA_ERR_SOCKET_SEND;
196 int recv_msg_size = -1;
199 if ((recv_msg_size = recv(sockfd, &recv_msg, sizeof(recv_msg), 0)) < 0) {
200 MSAPI_DBG_ERR("recv failed : [%d]", sockfd);
202 if (errno == EINTR) {
203 MSAPI_DBG_STRERROR("catch interrupt");
207 if (errno == EWOULDBLOCK) {
208 if (retry_count < MAX_RETRY_COUNT) {
209 MSAPI_DBG_ERR("TIME OUT[%d]", retry_count);
215 MSAPI_DBG_ERR("Timeout. Can't try any more");
216 return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
218 MSAPI_DBG_STRERROR("recv failed");
222 return MS_MEDIA_ERR_SOCKET_RECEIVE;
226 MSAPI_DBG("RECEIVE OK [%d]", recv_msg);
234 static __thread int g_tcp_client_sock = -1;
236 static int __media_db_get_client_tcp_sock()
238 return g_tcp_client_sock;
241 static int __media_db_prepare_tcp_client_socket()
243 int ret = MS_MEDIA_ERR_NONE;
245 struct sockaddr_un serv_addr;
247 /*Create TCP Socket*/
248 ret = ms_ipc_create_client_socket(MS_TIMEOUT_SEC_10, &sockfd);
249 MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
251 /*Set server Address*/
252 memset(&serv_addr, 0, sizeof(serv_addr));
253 serv_addr.sun_family = AF_UNIX;
254 SAFE_STRLCPY(serv_addr.sun_path, tzplatform_mkpath(TZ_SYS_RUN, MEDIA_IPC_PATH[MS_DB_BATCH_UPDATE_PORT]), sizeof(serv_addr.sun_path));
256 /* Connecting to the media db server */
257 if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
258 MSAPI_DBG_STRERROR("connect error");
260 return MS_MEDIA_ERR_SOCKET_CONN;
263 g_tcp_client_sock = sockfd;
265 MSAPI_DBG("Connected successfully");
270 static int __media_db_close_tcp_client_socket()
272 if (g_tcp_client_sock != -1) {
273 if (close(g_tcp_client_sock) < 0) {
274 MSAPI_DBG_STRERROR("socket close failed");
275 return MS_MEDIA_ERR_SOCKET_INTERNAL;
277 g_tcp_client_sock = -1;
280 return MS_MEDIA_ERR_NONE;
283 static int __media_db_request_batch_update(ms_msg_type_e msg_type, const char *request_msg, uid_t uid)
285 int ret = MS_MEDIA_ERR_NONE;
286 int request_msg_size = 0;
289 if (!MS_STRING_VALID(request_msg)) {
290 MSAPI_DBG_ERR("invalid query");
291 return MS_MEDIA_ERR_INVALID_PARAMETER;
294 request_msg_size = strlen(request_msg);
295 if (request_msg_size >= MAX_MSG_SIZE) {
296 MSAPI_DBG_ERR("Too long query[%d] limit[%d]", request_msg_size, MAX_MSG_SIZE);
297 return MS_MEDIA_ERR_INVALID_PARAMETER;
300 MSAPI_DBG_SLOG("querysize[%d] query[%s]", request_msg_size, request_msg);
301 ms_comm_msg_s send_msg;
302 memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s));
304 send_msg.msg_type = msg_type;
306 SAFE_STRLCPY(send_msg.msg, request_msg, sizeof(send_msg.msg));
308 sockfd = __media_db_get_client_tcp_sock();
309 MSAPI_RETV_IF(sockfd <= 0, MS_MEDIA_ERR_SOCKET_CONN);
312 if (send(sockfd, &send_msg, sizeof(send_msg), 0) != sizeof(send_msg)) {
313 MSAPI_DBG_STRERROR("send failed");
314 return MS_MEDIA_ERR_SOCKET_SEND;
318 int recv_msg_size = -1;
320 if ((recv_msg_size = recv(sockfd, &recv_msg, sizeof(recv_msg), 0)) < 0) {
321 MSAPI_DBG_ERR("recv failed : [%d]", sockfd);
322 if (errno == EWOULDBLOCK) {
323 MSAPI_DBG_ERR("Timeout. Can't try any more");
324 return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
326 MSAPI_DBG_STRERROR("recv failed");
327 return MS_MEDIA_ERR_SOCKET_RECEIVE;
331 MSAPI_DBG("RECEIVE OK [%d]", recv_msg);
334 if (ret != MS_MEDIA_ERR_NONE)
335 MSAPI_DBG_ERR("batch updated[%d] failed, error [%d]", msg_type, ret);
341 #define SLEEP_TIME 1000 * 1000
342 static int _media_db_update_directly(sqlite3 *db_handle, const char *sql_str)
344 int ret = MS_MEDIA_ERR_NONE;
345 char *zErrMsg = NULL;
349 ret = sqlite3_exec(db_handle, sql_str, NULL, NULL, &zErrMsg);
351 if (SQLITE_OK != ret) {
352 MSAPI_ERR_SLOG("Error[%s],Query[%s]", zErrMsg, sql_str);
353 MS_SQL_SAFE_FREE(zErrMsg);
354 if (ret == SQLITE_BUSY) {
355 ret = MS_MEDIA_ERR_DB_BUSY_FAIL;
356 } else if (ret == SQLITE_CONSTRAINT) {
357 ret = MS_MEDIA_ERR_DB_CONSTRAINT_FAIL;
358 } else if (ret == SQLITE_FULL) {
359 ret = MS_MEDIA_ERR_DB_FULL_FAIL;
360 } else if (ret == SQLITE_LOCKED) {
361 if (retry_count < RETRY_CNT) {
362 MSAPI_DBG_ERR("Locked retry[%d]", retry_count);
367 ret = MS_MEDIA_ERR_DB_UPDATE_FAIL;
369 ret = MS_MEDIA_ERR_DB_UPDATE_FAIL;
376 int media_db_check_integrity(MediaDBHandle *handle)
378 sqlite3 * db_handle = (sqlite3 *)handle;
380 MSAPI_RETVM_IF(db_handle == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "Handle is NULL");
383 sqlite3_stmt *stmt = NULL;
384 const char integrity_check_query[] = "PRAGMA integrity_check";
386 ret = sqlite3_prepare_v2(db_handle, integrity_check_query, strlen(integrity_check_query), &stmt, NULL);
387 if (ret != SQLITE_OK) {
388 MSAPI_DBG_ERR("prepare error, ret = %d, error = %s", ret, sqlite3_errmsg(db_handle));
389 return MS_MEDIA_ERR_DB_CORRUPT;
392 ret = sqlite3_step(stmt);
393 if (ret != SQLITE_ROW) {
394 MSAPI_DBG_ERR("integrity_check failed in step");
395 sqlite3_finalize(stmt);
396 return MS_MEDIA_ERR_DB_CORRUPT;
399 char* check_result = (char*) sqlite3_column_text(stmt, 0);
400 if (check_result == NULL || strncmp(check_result, "ok", strlen(check_result))) {
401 MSAPI_DBG_ERR("integrity_check failed - result(%s)\n", check_result);
402 sqlite3_finalize(stmt);
403 return MS_MEDIA_ERR_DB_CORRUPT;
405 sqlite3_finalize(stmt);
407 return MS_MEDIA_ERR_NONE;
410 int media_db_connect(MediaDBHandle **handle, uid_t uid, bool need_write)
412 int ret = MS_MEDIA_ERR_NONE;
413 sqlite3 * db_handle = NULL;
419 ret = __media_db_connect_db_with_handle(&db_handle, uid, need_write);
420 if (ret != MS_MEDIA_ERR_NONE) {
421 if (ret == MS_MEDIA_ERR_DB_CORRUPT && retry_cnt == 0) {
424 ret = __media_db_request_recovery(uid);
425 if (ret == MS_MEDIA_ERR_NONE)
428 return MS_MEDIA_ERR_DB_CORRUPT;
435 return MS_MEDIA_ERR_NONE;
438 int media_db_disconnect(MediaDBHandle *handle)
440 sqlite3 * db_handle = (sqlite3 *)handle;
444 MSAPI_RETVM_IF(db_handle == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "Handle is NULL");
446 return __media_db_disconnect_db_with_handle(db_handle);
449 int media_db_request_update_db(const char *query_str, uid_t uid)
451 int ret = MS_MEDIA_ERR_NONE;
455 MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
457 ret = __media_db_request_update_tcp(MS_MSG_DB_UPDATE, query_str, uid);
458 if (ret != MS_MEDIA_ERR_NONE)
459 MSAPI_DBG_ERR("__media_db_request_update_tcp failed : %d", ret);
464 int media_db_request_update_db_batch_start(const char *query_str, uid_t uid)
466 int ret = MS_MEDIA_ERR_NONE;
470 MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
472 ret = __media_db_prepare_tcp_client_socket();
473 if (ret != MS_MEDIA_ERR_NONE) {
474 MSAPI_DBG_ERR("__media_db_prepare_tcp_client_socket failed : %d", ret);
475 __media_db_close_tcp_client_socket();
479 ret = __media_db_request_batch_update(MS_MSG_DB_UPDATE_BATCH_START, query_str, uid);
480 if (ret != MS_MEDIA_ERR_NONE)
481 __media_db_close_tcp_client_socket();
486 int media_db_request_update_db_batch(const char *query_str, uid_t uid)
488 int ret = MS_MEDIA_ERR_NONE;
492 MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
494 ret = __media_db_request_batch_update(MS_MSG_DB_UPDATE_BATCH, query_str, uid);
495 if (ret != MS_MEDIA_ERR_NONE)
496 __media_db_close_tcp_client_socket();
501 int media_db_request_update_db_batch_end(const char *query_str, uid_t uid)
503 int ret = MS_MEDIA_ERR_NONE;
507 if (!MS_STRING_VALID(query_str)) {
508 MSAPI_DBG_ERR("Invalid Query");
509 __media_db_close_tcp_client_socket();
513 ret = __media_db_request_batch_update(MS_MSG_DB_UPDATE_BATCH_END, query_str, uid);
515 __media_db_close_tcp_client_socket();
520 int media_db_update_db(MediaDBHandle *handle, const char *query_str)
522 sqlite3 * db_handle = (sqlite3 *)handle;
523 int ret = MS_MEDIA_ERR_NONE;
525 MSAPI_RETVM_IF(db_handle == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "Handle is NULL");
526 MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
528 ret = _media_db_update_directly(db_handle, query_str);
533 int media_db_update_db_batch_start(const char *query_str)
535 int ret = MS_MEDIA_ERR_NONE;
539 MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
541 if (sql_list != NULL) {
542 MSAPI_DBG_ERR("sql_list is already allocated");
543 ret = MS_MEDIA_ERR_DB_SERVER_BUSY_FAIL;
545 sql_list = g_array_new(FALSE, FALSE, sizeof(char*));
546 MSAPI_RETVM_IF(sql_list == NULL, MS_MEDIA_ERR_OUT_OF_MEMORY, "Out of memory");
548 query = g_strdup(query_str);
549 if (MS_STRING_VALID(query)) {
550 g_array_append_val(sql_list, query);
552 MSAPI_DBG_ERR("query is null");
553 __media_db_destroy_sql_list();
554 ret = MS_MEDIA_ERR_OUT_OF_MEMORY;
562 int media_db_update_db_batch(const char *query_str)
564 int ret = MS_MEDIA_ERR_NONE;
567 MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
570 query = g_strdup(query_str);
571 if (MS_STRING_VALID(query)) {
572 g_array_append_val(sql_list, query);
574 MSAPI_DBG_ERR("query is null");
575 ret = MS_MEDIA_ERR_OUT_OF_MEMORY;
582 int media_db_update_db_batch_end(MediaDBHandle *handle, const char *query_str)
584 sqlite3 * db_handle = (sqlite3 *)handle;
585 int ret = MS_MEDIA_ERR_NONE;
589 /* Unused (!MS_STRING_VALID(query_str)) */
590 if (db_handle == NULL) {
591 __media_db_destroy_sql_list();
592 MSAPI_DBG_ERR("Handle is NULL");
593 return MS_MEDIA_ERR_INVALID_PARAMETER;
598 query = g_strdup(query_str);
599 if (MS_STRING_VALID(query)) {
600 g_array_append_val(sql_list, query);
602 __media_db_destroy_sql_list();
603 MSAPI_DBG_ERR("query is null");
604 return MS_MEDIA_ERR_OUT_OF_MEMORY;
607 while (sql_list->len != 0) {
608 char *current_sql = NULL;
610 current_sql = g_array_index(sql_list, char *, 0);
611 g_array_remove_index(sql_list, 0);
613 if (MS_STRING_VALID(current_sql)) {
614 ret = _media_db_update_directly(db_handle, current_sql);
617 if (strncmp(current_sql, BATCH_START, strlen(BATCH_START)) == 0 || strncmp(current_sql, BATCH_END, strlen(BATCH_END)) == 0) {
618 MSAPI_DBG_ERR("Query failed : %s", current_sql);
619 MS_SAFE_FREE(current_sql);
622 MSAPI_DBG_ERR("Query failed : %s, but keep going to run remaining queries", current_sql);
625 MSAPI_DBG_ERR("Query failed : %s, but keep going to run remaining queries", current_sql);
629 MS_SAFE_FREE(current_sql);
633 __media_db_destroy_sql_list();
635 return MS_MEDIA_ERR_NONE;
638 int media_db_request_update_db_batch_clear(void)
640 int ret = MS_MEDIA_ERR_NONE;
642 __media_db_destroy_sql_list();
647 static int __media_db_request_recovery(uid_t uid)
649 int ret = MS_MEDIA_ERR_NONE;
650 int request_msg_size = 0;
652 struct sockaddr_un serv_addr;
654 char *db_path = NULL;
656 ret = ms_user_get_media_db_path(uid, &db_path);
657 MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, MS_MEDIA_ERR_INVALID_PARAMETER, "ms_user_get_media_db_path failed");
659 request_msg_size = strlen(db_path);
660 if (request_msg_size >= MAX_MSG_SIZE) {
661 MSAPI_DBG_ERR("Too long query[%d] limit[%d]", request_msg_size, MAX_MSG_SIZE);
662 MS_SAFE_FREE(db_path);
663 return MS_MEDIA_ERR_INVALID_PARAMETER;
666 /* MSAPI_DBG("querysize[%d] query[%s]", request_msg_size, request_msg); */
668 ms_comm_msg_s send_msg;
669 memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s));
671 send_msg.msg_type = MS_MSG_MEDIA_DB_MALFORMED;
672 SAFE_STRLCPY(send_msg.msg, db_path, sizeof(send_msg.msg));
673 MS_SAFE_FREE(db_path);
677 ret = ms_ipc_create_client_socket(MS_TIMEOUT_SEC_10, &sockfd);
678 MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
680 /*Set server Address*/
681 memset(&serv_addr, 0, sizeof(serv_addr));
682 serv_addr.sun_family = AF_UNIX;
683 /* MSAPI_DBG_SLOG("%s", MEDIA_IPC_PATH[port]); */
684 SAFE_STRLCPY(serv_addr.sun_path, MEDIA_IPC_PATH[MS_SCANNER_PORT], sizeof(serv_addr.sun_path));
686 /* Connecting to the media db server */
687 if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
688 MSAPI_DBG_STRERROR("connect error");
690 return MS_MEDIA_ERR_SOCKET_CONN;
694 if (send(sockfd, &send_msg, sizeof(send_msg), 0) != sizeof(send_msg)) {
695 MSAPI_DBG_STRERROR("send failed");
697 return MS_MEDIA_ERR_SOCKET_SEND;
701 int recv_msg_size = -1;
702 ms_comm_msg_s recv_msg;
704 if ((recv_msg_size = recv(sockfd, &recv_msg, sizeof(recv_msg), 0)) < 0) {
705 MSAPI_DBG_ERR("recv failed : [%d]", sockfd);
707 if (errno == EINTR) {
708 MSAPI_DBG_STRERROR("catch interrupt");
712 if (errno == EWOULDBLOCK) {
713 if (retry_count < MAX_RETRY_COUNT) {
714 MSAPI_DBG_ERR("TIME OUT[%d]", retry_count);
720 MSAPI_DBG_ERR("Timeout. Can't try any more");
721 return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
723 MSAPI_DBG_STRERROR("recv failed");
727 return MS_MEDIA_ERR_SOCKET_RECEIVE;
731 MSAPI_DBG("RECEIVE OK [%d]", recv_msg.result);
732 ret = recv_msg.result;