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.
28 #include <unicode/utypes.h>
29 #include <unicode/ucol.h>
30 #include <unicode/uiter.h>
31 #include <unicode/ustring.h>
34 #include "media-server-ipc.h"
35 #include "media-util-dbg.h"
36 #include "media-util-internal.h"
37 #include "media-util.h"
39 #define BATCH_START "BEGIN"
40 #define BATCH_END "COMMIT"
42 static int __media_db_request_recovery(uid_t uid);
44 static int __media_db_busy_handler(void *pData, int count)
48 MSAPI_DBG("media_db_busy_handler called : %d", count);
53 /* The collating function must return an integer that is negative, zero or positive */
54 static int __media_db_collate_icu_8(void *ucol, int str1_len, const void *str1, int str2_len, const void *str2)
56 UCharIterator uiter1, uiter2;
57 UErrorCode error = U_ZERO_ERROR;
59 uiter_setUTF8(&uiter1, (const char *) str1, str1_len);
60 uiter_setUTF8(&uiter2, (const char *) str2, str2_len);
62 UCollationResult result = ucol_strcollIter((UCollator *) ucol, &uiter1, &uiter2, &error);
63 if (U_FAILURE(error)) {
64 MSAPI_DBG_ERR("ucol_strcollIter error: %d", error);
71 static void __media_db_collation_cb(void* pArg, sqlite3* handle, int charset, const char* name)
73 int ret = MS_MEDIA_ERR_NONE;
74 UErrorCode status = U_ZERO_ERROR;
75 const char* locale = NULL;
77 UCollator* ucol = NULL;
79 if (handle == NULL || !MS_STRING_VALID(name)) {
80 MSAPI_DBG_ERR("Input parameter is NULL");
84 if (charset == SQLITE_UTF8 && !sqlite3_stricmp(name, "localized")) {
85 lang = vconf_get_str(VCONFKEY_LANGSET);
86 /* get current locale */
88 uloc_setDefault(lang, &status);
91 MSAPI_DBG_ERR("Fail to get current language vconf");
94 locale = uloc_getDefault();
96 MSAPI_DBG_ERR("Fail to get current locale");
99 MSAPI_DBG_INFO("locale : %s", locale);
101 ucol = ucol_open(locale, &status);
102 if (status == U_USING_DEFAULT_WARNING) {
103 MSAPI_DBG("ucol_open success with default collate option");
104 } else if (U_FAILURE(status)) {
105 MSAPI_DBG_ERR("ucol_open fail : %d", status);
109 ucol_setStrength(ucol, UCOL_SECONDARY); /* NOTICE : MCD sets UCOL_PRIMARY */
110 if (U_FAILURE(status)) {
111 MSAPI_DBG_ERR("ucol_setStrength fail : %d", status);
115 ret = sqlite3_create_collation_v2(handle, name, SQLITE_UTF8, ucol, __media_db_collate_icu_8, (void *)ucol_close);
116 if (ret != SQLITE_OK) {
117 MSAPI_DBG_ERR("sqlite3_create_collation_v2 fail : %d", ret);
120 MSAPI_DBG("sqlite3_create_collation_v2 success");
123 MSAPI_DBG_ERR("No matching collator for %s", name);
127 static int __media_db_connect_db_with_handle(sqlite3 **db_handle, uid_t uid, bool need_write)
130 char *db_path = NULL;
133 ret = ms_user_get_media_db_path(uid, &db_path);
134 MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, MS_MEDIA_ERR_DB_INTERNAL, "ms_user_get_media_db_path failed");
138 ret = sqlite3_open_v2(db_path, db_handle, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
140 ret = sqlite3_open_v2(db_path, db_handle, SQLITE_OPEN_READONLY, NULL);
142 if (SQLITE_OK != ret) {
143 MSAPI_DBG_ERR("error when db open path[%s],ret[%d]", db_path, ret);
146 return MS_MEDIA_ERR_DB_INTERNAL;
150 if (*db_handle == NULL) {
151 MSAPI_DBG_ERR("*db_handle is NULL");
152 return MS_MEDIA_ERR_DB_INTERNAL;
155 /*Register busy handler*/
156 ret = sqlite3_busy_handler(*db_handle, __media_db_busy_handler, NULL);
157 if (SQLITE_OK != ret) {
159 MSAPI_DBG_ERR("[error when register busy handler] %s", sqlite3_errmsg(*db_handle));
161 sqlite3_close_v2(*db_handle);
164 return MS_MEDIA_ERR_DB_INTERNAL;
167 /*For TV internal space issue, change TRUNCATE to OFF */
168 sql = sqlite3_mprintf("%s", "PRAGMA journal_mode = OFF");
169 ret = sqlite3_exec(*db_handle, sql, NULL, NULL, NULL);
170 MS_SQL_SAFE_FREE(sql);
171 if (SQLITE_OK != ret) {
173 MSAPI_DBG_ERR("[error when change the journal mode] %s", sqlite3_errmsg(*db_handle));
175 sqlite3_close_v2(*db_handle);
178 if (ret == SQLITE_CORRUPT) {
179 MSAPI_DBG_ERR("MEDIA DB IS CORRUPTED");
180 return MS_MEDIA_ERR_DB_CORRUPT;
183 return MS_MEDIA_ERR_DB_INTERNAL;
186 /* Set for localized collate */
187 sqlite3_collation_needed(*db_handle, NULL, __media_db_collation_cb);
189 return MS_MEDIA_ERR_NONE;
192 extern char MEDIA_IPC_PATH[][70];
193 #define MAX_RETRY_COUNT 3
195 static int __media_db_request_update_tcp(ms_msg_type_e msg_type, const char *request_msg, uid_t uid)
197 int ret = MS_MEDIA_ERR_NONE;
199 struct sockaddr_un serv_addr;
202 MSAPI_RETVM_IF(!ms_ipc_is_valid_msg(request_msg), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid request_msg");
204 ms_comm_msg_s send_msg;
205 memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s));
207 send_msg.msg_type = msg_type;
208 SAFE_STRLCPY(send_msg.msg, request_msg, sizeof(send_msg.msg));
212 ret = ms_ipc_create_client_socket(MS_TIMEOUT_SEC_10, &sockfd);
213 MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
215 /*Set server Address*/
216 memset(&serv_addr, 0, sizeof(serv_addr));
217 serv_addr.sun_family = AF_UNIX;
218 SAFE_STRLCPY(serv_addr.sun_path, tzplatform_mkpath(TZ_SYS_RUN, MEDIA_IPC_PATH[MS_DB_UPDATE_PORT]), sizeof(serv_addr.sun_path));
220 /* Connecting to the media db server */
221 if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
222 MSAPI_DBG_STRERROR("connect error");
225 return MS_MEDIA_ERR_PERMISSION_DENIED;
227 return MS_MEDIA_ERR_IPC;
231 if (send(sockfd, &send_msg, sizeof(send_msg), 0) != sizeof(send_msg)) {
232 MSAPI_DBG_STRERROR("send failed");
234 return MS_MEDIA_ERR_IPC;
238 int recv_msg_size = -1;
241 if ((recv_msg_size = recv(sockfd, &recv_msg, sizeof(recv_msg), 0)) < 0) {
242 MSAPI_DBG_STRERROR("recv failed");
244 if (errno == EINTR || errno == EWOULDBLOCK) {
245 if (retry_count < MAX_RETRY_COUNT) {
246 MSAPI_DBG_ERR("TIME OUT[%d]", retry_count);
252 return MS_MEDIA_ERR_IPC;
255 MSAPI_DBG("RECEIVE OK [%d]", recv_msg);
264 #define SLEEP_TIME 1000 * 1000
265 static int __media_db_update_directly(sqlite3 *db_handle, const char *sql_str)
267 int ret = MS_MEDIA_ERR_NONE;
268 char *zErrMsg = NULL;
272 ret = sqlite3_exec(db_handle, sql_str, NULL, NULL, &zErrMsg);
274 if (SQLITE_OK != ret) {
275 MSAPI_ERR_SLOG("Error[%s],Query[%s]", zErrMsg, sql_str);
276 MS_SQL_SAFE_FREE(zErrMsg);
277 if (ret == SQLITE_BUSY) {
278 ret = MS_MEDIA_ERR_DB_BUSY_FAIL;
279 } else if (ret == SQLITE_CONSTRAINT) {
280 ret = MS_MEDIA_ERR_DB_CONSTRAINT_FAIL;
281 } else if (ret == SQLITE_FULL) {
282 ret = MS_MEDIA_ERR_DB_FULL_FAIL;
283 } else if (ret == SQLITE_LOCKED) {
284 if (retry_count < RETRY_CNT) {
285 MSAPI_DBG_ERR("Locked retry[%d]", retry_count);
290 ret = MS_MEDIA_ERR_DB_INTERNAL;
292 ret = MS_MEDIA_ERR_DB_INTERNAL;
299 int media_db_check_integrity(sqlite3 *handle)
301 MSAPI_RETVM_IF(handle == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "Handle is NULL");
304 sqlite3_stmt *stmt = NULL;
305 const char integrity_check_query[] = "PRAGMA integrity_check";
307 ret = sqlite3_prepare_v2(handle, integrity_check_query, strlen(integrity_check_query), &stmt, NULL);
308 if (ret != SQLITE_OK) {
309 MSAPI_DBG_ERR("prepare error, ret = %d, error = %s", ret, sqlite3_errmsg(handle));
310 return MS_MEDIA_ERR_DB_CORRUPT;
313 ret = sqlite3_step(stmt);
314 if (ret != SQLITE_ROW) {
315 MSAPI_DBG_ERR("integrity_check failed in step");
316 sqlite3_finalize(stmt);
317 return MS_MEDIA_ERR_DB_CORRUPT;
320 char* check_result = (char*) sqlite3_column_text(stmt, 0);
321 if (check_result == NULL || strncmp(check_result, "ok", strlen(check_result))) {
322 MSAPI_DBG_ERR("integrity_check failed - result(%s)\n", check_result);
323 sqlite3_finalize(stmt);
324 return MS_MEDIA_ERR_DB_CORRUPT;
326 sqlite3_finalize(stmt);
328 return MS_MEDIA_ERR_NONE;
331 int media_db_connect(sqlite3 **handle, uid_t uid, bool need_write)
333 int ret = MS_MEDIA_ERR_NONE;
334 sqlite3 * db_handle = NULL;
340 ret = __media_db_connect_db_with_handle(&db_handle, uid, need_write);
341 if (ret != MS_MEDIA_ERR_NONE) {
342 if (ret == MS_MEDIA_ERR_DB_CORRUPT && retry_cnt == 0) {
345 ret = __media_db_request_recovery(uid);
346 if (ret == MS_MEDIA_ERR_NONE)
349 return MS_MEDIA_ERR_DB_CORRUPT;
356 return MS_MEDIA_ERR_NONE;
359 void media_db_disconnect(sqlite3 *handle)
364 sqlite3_close_v2(handle);
367 int media_db_request_update_db(const char *query_str, uid_t uid)
369 int ret = MS_MEDIA_ERR_NONE;
373 MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
375 ret = __media_db_request_update_tcp(MS_MSG_DB_UPDATE, query_str, uid);
376 if (ret != MS_MEDIA_ERR_NONE)
377 MSAPI_DBG_ERR("__media_db_request_update_tcp failed : %d", ret);
382 int media_db_update_db_direct(const char *query_str, uid_t uid)
384 int ret = MS_MEDIA_ERR_NONE;
385 sqlite3 *handle = NULL;
389 MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
391 ret = media_db_connect(&handle, uid, true);
392 MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, ret, "Connect failed");
394 ret = __media_db_update_directly(handle, query_str);
395 if (ret != MS_MEDIA_ERR_NONE)
396 MSAPI_DBG_ERR("Query failed");
398 media_db_disconnect(handle);
403 int media_db_update_db(sqlite3 *handle, const char *query_str)
405 MSAPI_RETVM_IF(handle == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "Handle is NULL");
406 MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
408 return __media_db_update_directly(handle, query_str);
411 static int __media_db_request_recovery(uid_t uid)
413 int ret = MS_MEDIA_ERR_NONE;
415 struct sockaddr_un serv_addr;
417 char *db_path = NULL;
419 ret = ms_user_get_media_db_path(uid, &db_path);
420 MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, MS_MEDIA_ERR_INVALID_PARAMETER, "ms_user_get_media_db_path failed");
422 if (!ms_ipc_is_valid_msg(db_path)) {
424 return MS_MEDIA_ERR_INVALID_PARAMETER;
427 ms_comm_msg_s send_msg;
428 memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s));
430 send_msg.msg_type = MS_MSG_MEDIA_DB_MALFORMED;
431 SAFE_STRLCPY(send_msg.msg, db_path, sizeof(send_msg.msg));
436 ret = ms_ipc_create_client_socket(MS_TIMEOUT_SEC_10, &sockfd);
437 MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
439 /*Set server Address*/
440 memset(&serv_addr, 0, sizeof(serv_addr));
441 serv_addr.sun_family = AF_UNIX;
442 /* MSAPI_DBG_SLOG("%s", MEDIA_IPC_PATH[port]); */
443 SAFE_STRLCPY(serv_addr.sun_path, MEDIA_IPC_PATH[MS_SCANNER_PORT], sizeof(serv_addr.sun_path));
445 /* Connecting to the media db server */
446 if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
447 MSAPI_DBG_STRERROR("connect error");
449 return MS_MEDIA_ERR_IPC;
453 if (send(sockfd, &send_msg, sizeof(send_msg), 0) != sizeof(send_msg)) {
454 MSAPI_DBG_STRERROR("send failed");
456 return MS_MEDIA_ERR_IPC;
460 int recv_msg_size = -1;
461 ms_comm_msg_s recv_msg;
463 if ((recv_msg_size = recv(sockfd, &recv_msg, sizeof(recv_msg), 0)) < 0) {
464 MSAPI_DBG_STRERROR("recv failed");
466 if (errno == EINTR || errno == EWOULDBLOCK) {
467 if (retry_count < MAX_RETRY_COUNT) {
468 MSAPI_DBG_ERR("TIME OUT[%d]", retry_count);
474 return MS_MEDIA_ERR_IPC;
477 MSAPI_DBG("RECEIVE OK [%d]", recv_msg.result);
478 ret = recv_msg.result;
485 int media_db_get_result(sqlite3 *handle, char *sql_str, sqlite3_stmt **stmt)
489 MSAPI_RETVM_IF(sql_str == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "invalid query");
490 if (handle == NULL) {
491 MSAPI_DBG_ERR("handle is NULL");
492 MS_SQL_SAFE_FREE(sql_str);
493 return MS_MEDIA_ERR_INVALID_PARAMETER;
496 MSAPI_DBG_SLOG("[SQL query] : %s", sql_str);
498 err = sqlite3_prepare_v2(handle, sql_str, -1, stmt, NULL);
499 MS_SQL_SAFE_FREE(sql_str);
501 if (err != SQLITE_OK) {
502 MSAPI_DBG_ERR("prepare error %d[%s]", err, sqlite3_errmsg(handle));
503 if (err == SQLITE_CORRUPT)
504 return MS_MEDIA_ERR_DB_CORRUPT;
506 return MS_MEDIA_ERR_DB_INTERNAL;
509 return MS_MEDIA_ERR_NONE;