4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
23 #include <unicode/utypes.h>
24 #include <unicode/ucol.h>
25 #include <unicode/uiter.h>
26 #include <unicode/ustring.h>
29 #include "media-util-dbg.h"
30 #include "media-util.h"
32 #define MS_TIMEOUT_SEC 10
34 static int __media_db_request_recovery(uid_t uid);
36 static int __media_db_busy_handler(void *pData, int count)
40 MSAPI_DBG("media_db_busy_handler called : %d", count);
45 /* The collating function must return an integer that is negative, zero or positive */
46 static int __media_db_collate_icu_8(void *ucol, int str1_len, const void *str1, int str2_len, const void *str2)
48 UCharIterator uiter1, uiter2;
49 UErrorCode error = U_ZERO_ERROR;
51 uiter_setUTF8(&uiter1, (const char *) str1, str1_len);
52 uiter_setUTF8(&uiter2, (const char *) str2, str2_len);
54 UCollationResult result = ucol_strcollIter((UCollator *) ucol, &uiter1, &uiter2, &error);
55 if (U_FAILURE(error)) {
56 MSAPI_DBG_ERR("ucol_strcollIter error: %d", error);
63 static void __media_db_collation_cb(void* pArg, sqlite3* handle, int charset, const char* name)
65 int ret = MS_MEDIA_ERR_NONE;
66 UErrorCode status = U_ZERO_ERROR;
67 const char* locale = NULL;
69 UCollator* ucol = NULL;
71 if (handle == NULL || !MS_STRING_VALID(name)) {
72 MSAPI_DBG_ERR("Input parameter is NULL");
76 if (charset == SQLITE_UTF8 && !sqlite3_stricmp(name, "localized")) {
77 lang = vconf_get_str(VCONFKEY_LANGSET);
78 /* get current locale */
80 uloc_setDefault(lang, &status);
83 MSAPI_DBG_ERR("Fail to get current language vconf");
86 locale = uloc_getDefault();
88 MSAPI_DBG_ERR("Fail to get current locale");
91 MSAPI_DBG_INFO("locale : %s", locale);
93 ucol = ucol_open(locale, &status);
94 if (status == U_USING_DEFAULT_WARNING) {
95 MSAPI_DBG("ucol_open success with default collate option");
96 } else if (U_FAILURE(status)) {
97 MSAPI_DBG_ERR("ucol_open fail : %d", status);
101 ucol_setStrength(ucol, UCOL_SECONDARY); /* NOTICE : MCD sets UCOL_PRIMARY */
102 if (U_FAILURE(status)) {
103 MSAPI_DBG_ERR("ucol_setStrength fail : %d", status);
107 ret = sqlite3_create_collation_v2(handle, name, SQLITE_UTF8, ucol, __media_db_collate_icu_8, (void *)ucol_close);
108 if (ret != SQLITE_OK) {
109 MSAPI_DBG_ERR("sqlite3_create_collation_v2 fail : %d", ret);
112 MSAPI_DBG("sqlite3_create_collation_v2 success");
115 MSAPI_DBG_ERR("No matching collator for %s", name);
119 static int __media_db_connect_db_with_handle(sqlite3 **db_handle, uid_t uid, bool need_write)
122 char *db_path = NULL;
124 MSAPI_DBG_ERR("need_write[%d]", need_write);
125 ret = ms_user_get_media_db_path(uid, &db_path);
126 MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, MS_MEDIA_ERR_DB_INTERNAL, "ms_user_get_media_db_path failed");
130 ret = sqlite3_open_v2(db_path, db_handle, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
132 ret = sqlite3_open_v2(db_path, db_handle, SQLITE_OPEN_READONLY, NULL);
134 if (SQLITE_OK != ret) {
135 MSAPI_DBG_ERR("error when db open path[%s],ret[%d]", db_path, ret);
138 return MS_MEDIA_ERR_DB_INTERNAL;
142 if (*db_handle == NULL) {
143 MSAPI_DBG_ERR("*db_handle is NULL");
144 return MS_MEDIA_ERR_DB_INTERNAL;
147 /*Register busy handler*/
148 ret = sqlite3_busy_handler(*db_handle, __media_db_busy_handler, NULL);
149 if (SQLITE_OK != ret) {
151 MSAPI_DBG_ERR("[error when register busy handler] %s", sqlite3_errmsg(*db_handle));
153 sqlite3_close_v2(*db_handle);
156 return MS_MEDIA_ERR_DB_INTERNAL;
159 /*For TV internal space issue, change TRUNCATE to OFF */
160 sql = sqlite3_mprintf("%s", "PRAGMA journal_mode = OFF");
161 ret = sqlite3_exec(*db_handle, sql, NULL, NULL, NULL);
162 MS_SQL_SAFE_FREE(sql);
163 if (SQLITE_OK != ret) {
165 MSAPI_DBG_ERR("[error when change the journal mode] %s", sqlite3_errmsg(*db_handle));
167 sqlite3_close_v2(*db_handle);
170 if (ret == SQLITE_CORRUPT) {
171 MSAPI_DBG_ERR("MEDIA DB IS CORRUPTED");
172 return MS_MEDIA_ERR_DB_CORRUPT;
175 return MS_MEDIA_ERR_DB_INTERNAL;
178 /* Set for localized collate */
179 sqlite3_collation_needed(*db_handle, NULL, __media_db_collation_cb);
180 MSAPI_DBG_ERR("Finish");
181 return MS_MEDIA_ERR_NONE;
184 extern char MEDIA_IPC_PATH[][70];
185 #define MAX_RETRY_COUNT 3
187 static int __media_db_request_update_tcp(ms_msg_type_e msg_type, const char *request_msg, uid_t uid)
189 int ret = MS_MEDIA_ERR_NONE;
191 struct sockaddr_un serv_addr;
194 MSAPI_RETVM_IF(!ms_ipc_is_valid_msg(request_msg), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid request_msg");
196 ms_comm_msg_s send_msg;
197 memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s));
199 send_msg.msg_type = msg_type;
200 SAFE_STRLCPY(send_msg.msg, request_msg, sizeof(send_msg.msg));
204 ret = ms_ipc_create_client_socket(MS_TIMEOUT_SEC, &sockfd);
205 MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
207 /*Set server Address*/
208 memset(&serv_addr, 0, sizeof(serv_addr));
209 serv_addr.sun_family = AF_UNIX;
210 SAFE_STRLCPY(serv_addr.sun_path, tzplatform_mkpath(TZ_SYS_RUN, MEDIA_IPC_PATH[MS_DB_UPDATE_PORT]), sizeof(serv_addr.sun_path));
212 /* Connecting to the media db server */
213 if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
214 MSAPI_DBG_STRERROR("connect error");
217 return MS_MEDIA_ERR_PERMISSION_DENIED;
219 return MS_MEDIA_ERR_IPC;
223 if (send(sockfd, &send_msg, sizeof(send_msg), 0) != sizeof(send_msg)) {
224 MSAPI_DBG_STRERROR("send failed");
226 return MS_MEDIA_ERR_IPC;
230 int recv_msg_size = -1;
233 if ((recv_msg_size = recv(sockfd, &recv_msg, sizeof(recv_msg), 0)) < 0) {
234 MSAPI_DBG_STRERROR("recv failed");
236 if (errno == EINTR || errno == EWOULDBLOCK) {
237 if (retry_count < MAX_RETRY_COUNT) {
238 MSAPI_DBG_ERR("TIME OUT[%d]", retry_count);
244 return MS_MEDIA_ERR_IPC;
247 MSAPI_DBG("RECEIVE OK [%d]", recv_msg);
256 #define SLEEP_TIME 1000 * 1000
257 static int __media_db_update_directly(sqlite3 *db_handle, const char *sql_str)
259 int ret = MS_MEDIA_ERR_NONE;
260 char *zErrMsg = NULL;
264 ret = sqlite3_exec(db_handle, sql_str, NULL, NULL, &zErrMsg);
266 if (SQLITE_OK != ret) {
267 MSAPI_ERR_SLOG("Error[%s],Query[%s]", zErrMsg, sql_str);
268 MS_SQL_SAFE_FREE(zErrMsg);
269 if (ret == SQLITE_BUSY) {
270 ret = MS_MEDIA_ERR_DB_BUSY_FAIL;
271 } else if (ret == SQLITE_CONSTRAINT) {
272 ret = MS_MEDIA_ERR_DB_CONSTRAINT_FAIL;
273 } else if (ret == SQLITE_FULL) {
274 ret = MS_MEDIA_ERR_DB_FULL_FAIL;
275 } else if (ret == SQLITE_LOCKED) {
276 if (retry_count < RETRY_CNT) {
277 MSAPI_DBG_ERR("Locked retry[%d]", retry_count);
282 ret = MS_MEDIA_ERR_DB_INTERNAL;
284 ret = MS_MEDIA_ERR_DB_INTERNAL;
291 int media_db_check_integrity(sqlite3 *handle)
293 MSAPI_RETVM_IF(handle == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "Handle is NULL");
296 sqlite3_stmt *stmt = NULL;
297 const char integrity_check_query[] = "PRAGMA integrity_check";
299 ret = sqlite3_prepare_v2(handle, integrity_check_query, strlen(integrity_check_query), &stmt, NULL);
300 if (ret != SQLITE_OK) {
301 MSAPI_DBG_ERR("prepare error, ret = %d, error = %s", ret, sqlite3_errmsg(handle));
302 return MS_MEDIA_ERR_DB_CORRUPT;
305 ret = sqlite3_step(stmt);
306 if (ret != SQLITE_ROW) {
307 MSAPI_DBG_ERR("integrity_check failed in step");
308 sqlite3_finalize(stmt);
309 return MS_MEDIA_ERR_DB_CORRUPT;
312 char* check_result = (char*) sqlite3_column_text(stmt, 0);
313 if (check_result == NULL || strncmp(check_result, "ok", strlen(check_result))) {
314 MSAPI_DBG_ERR("integrity_check failed - result(%s)\n", check_result);
315 sqlite3_finalize(stmt);
316 return MS_MEDIA_ERR_DB_CORRUPT;
318 sqlite3_finalize(stmt);
320 return MS_MEDIA_ERR_NONE;
323 int media_db_connect(sqlite3 **handle, uid_t uid, bool need_write)
325 int ret = MS_MEDIA_ERR_NONE;
326 sqlite3 * db_handle = NULL;
332 ret = __media_db_connect_db_with_handle(&db_handle, uid, need_write);
333 if (ret != MS_MEDIA_ERR_NONE) {
334 if (ret == MS_MEDIA_ERR_DB_CORRUPT && retry_cnt == 0) {
337 ret = __media_db_request_recovery(uid);
338 if (ret == MS_MEDIA_ERR_NONE)
341 return MS_MEDIA_ERR_DB_CORRUPT;
348 return MS_MEDIA_ERR_NONE;
351 void media_db_disconnect(sqlite3 *handle)
356 sqlite3_close_v2(handle);
359 int media_db_request_update_db(const char *query_str, uid_t uid)
361 int ret = MS_MEDIA_ERR_NONE;
365 MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
367 ret = __media_db_request_update_tcp(MS_MSG_DB_UPDATE, query_str, uid);
368 if (ret != MS_MEDIA_ERR_NONE)
369 MSAPI_DBG_ERR("__media_db_request_update_tcp failed : %d", ret);
374 int media_db_update_db_direct(const char *query_str, uid_t uid)
376 int ret = MS_MEDIA_ERR_NONE;
377 sqlite3 *handle = NULL;
381 MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
383 ret = media_db_connect(&handle, uid, true);
384 MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, ret, "Connect failed");
386 ret = __media_db_update_directly(handle, query_str);
387 if (ret != MS_MEDIA_ERR_NONE)
388 MSAPI_DBG_ERR("Query failed");
390 media_db_disconnect(handle);
395 static int __media_db_request_recovery(uid_t uid)
397 int ret = MS_MEDIA_ERR_NONE;
399 struct sockaddr_un serv_addr;
401 char *db_path = NULL;
403 ret = ms_user_get_media_db_path(uid, &db_path);
404 MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, MS_MEDIA_ERR_INVALID_PARAMETER, "ms_user_get_media_db_path failed");
406 if (!ms_ipc_is_valid_msg(db_path)) {
408 return MS_MEDIA_ERR_INVALID_PARAMETER;
411 ms_comm_msg_s send_msg;
412 memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s));
414 send_msg.msg_type = MS_MSG_MEDIA_DB_MALFORMED;
415 SAFE_STRLCPY(send_msg.msg, db_path, sizeof(send_msg.msg));
420 ret = ms_ipc_create_client_socket(MS_TIMEOUT_SEC, &sockfd);
421 MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
423 /*Set server Address*/
424 memset(&serv_addr, 0, sizeof(serv_addr));
425 serv_addr.sun_family = AF_UNIX;
426 /* MSAPI_DBG_SLOG("%s", MEDIA_IPC_PATH[port]); */
427 SAFE_STRLCPY(serv_addr.sun_path, MEDIA_IPC_PATH[MS_SCANNER_PORT], sizeof(serv_addr.sun_path));
429 /* Connecting to the media db server */
430 if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
431 MSAPI_DBG_STRERROR("connect error");
433 return MS_MEDIA_ERR_IPC;
437 if (send(sockfd, &send_msg, sizeof(send_msg), 0) != sizeof(send_msg)) {
438 MSAPI_DBG_STRERROR("send failed");
440 return MS_MEDIA_ERR_IPC;
444 int recv_msg_size = -1;
445 ms_comm_msg_s recv_msg;
447 if ((recv_msg_size = recv(sockfd, &recv_msg, sizeof(recv_msg), 0)) < 0) {
448 MSAPI_DBG_STRERROR("recv failed");
450 if (errno == EINTR || errno == EWOULDBLOCK) {
451 if (retry_count < MAX_RETRY_COUNT) {
452 MSAPI_DBG_ERR("TIME OUT[%d]", retry_count);
458 return MS_MEDIA_ERR_IPC;
461 MSAPI_DBG("RECEIVE OK [%d]", recv_msg.result);
462 ret = recv_msg.result;
469 int media_db_get_result(sqlite3 *handle, char *sql_str, sqlite3_stmt **stmt)
473 MSAPI_RETVM_IF(sql_str == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "invalid query");
474 if (handle == NULL) {
475 MSAPI_DBG_ERR("handle is NULL");
476 MS_SQL_SAFE_FREE(sql_str);
477 return MS_MEDIA_ERR_INVALID_PARAMETER;
480 MSAPI_DBG_SLOG("[SQL query] : %s", sql_str);
482 err = sqlite3_prepare_v2(handle, sql_str, -1, stmt, NULL);
483 MS_SQL_SAFE_FREE(sql_str);
485 if (err != SQLITE_OK) {
486 MSAPI_DBG_ERR("prepare error %d[%s]", err, sqlite3_errmsg(handle));
487 if (err == SQLITE_CORRUPT)
488 return MS_MEDIA_ERR_DB_CORRUPT;
490 return MS_MEDIA_ERR_DB_INTERNAL;
493 return MS_MEDIA_ERR_NONE;