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.
25 #include <sys/smack.h>
29 #include <unicode/utypes.h>
30 #include <unicode/ucol.h>
31 #include <unicode/uiter.h>
32 #include <unicode/ustring.h>
35 #include "media-server-ipc.h"
36 #include "media-util-dbg.h"
37 #include "media-util-internal.h"
38 #include "media-util.h"
40 #define BATCH_START "BEGIN"
41 #define BATCH_END "COMMIT"
43 static int __media_db_request_recovery(uid_t uid);
45 static int __media_db_busy_handler(void *pData, int count)
49 MSAPI_DBG("media_db_busy_handler called : %d", count);
54 /* The collating function must return an integer that is negative, zero or positive */
55 static int __media_db_collate_icu_8(void *ucol, int str1_len, const void *str1, int str2_len, const void *str2)
57 UCharIterator uiter1, uiter2;
58 UErrorCode error = U_ZERO_ERROR;
60 uiter_setUTF8(&uiter1, (const char *) str1, str1_len);
61 uiter_setUTF8(&uiter2, (const char *) str2, str2_len);
63 UCollationResult result = ucol_strcollIter((UCollator *) ucol, &uiter1, &uiter2, &error);
64 if (U_FAILURE(error)) {
65 MSAPI_DBG_ERR("ucol_strcollIter error: %d", error);
72 static void __media_db_collation_cb(void* pArg, sqlite3* handle, int charset, const char* name)
74 int ret = MS_MEDIA_ERR_NONE;
75 UErrorCode status = U_ZERO_ERROR;
76 const char* locale = NULL;
78 UCollator* ucol = NULL;
80 if (handle == NULL || !MS_STRING_VALID(name)) {
81 MSAPI_DBG_ERR("Input parameter is NULL");
85 if (charset == SQLITE_UTF8 && !sqlite3_stricmp(name, "localized")) {
86 lang = vconf_get_str(VCONFKEY_LANGSET);
87 /* get current locale */
89 uloc_setDefault(lang, &status);
92 MSAPI_DBG_ERR("Fail to get current language vconf");
95 locale = uloc_getDefault();
97 MSAPI_DBG_ERR("Fail to get current locale");
100 MSAPI_DBG_INFO("locale : %s", locale);
102 ucol = ucol_open(locale, &status);
103 if (status == U_USING_DEFAULT_WARNING) {
104 MSAPI_DBG("ucol_open success with default collate option");
105 } else if (U_FAILURE(status)) {
106 MSAPI_DBG_ERR("ucol_open fail : %d", status);
110 ucol_setStrength(ucol, UCOL_SECONDARY); /* NOTICE : MCD sets UCOL_PRIMARY */
111 if (U_FAILURE(status)) {
112 MSAPI_DBG_ERR("ucol_setStrength fail : %d", status);
116 ret = sqlite3_create_collation_v2(handle, name, SQLITE_UTF8, ucol, __media_db_collate_icu_8, (void *)ucol_close);
117 if (ret != SQLITE_OK) {
118 MSAPI_DBG_ERR("sqlite3_create_collation_v2 fail : %d", ret);
121 MSAPI_DBG("sqlite3_create_collation_v2 success");
124 MSAPI_DBG_ERR("No matching collator for %s", name);
128 static int __media_db_connect_db_with_handle(sqlite3 **db_handle, uid_t uid, bool need_write)
131 char *db_path = NULL;
134 ret = ms_user_get_media_db_path(uid, &db_path);
135 MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, MS_MEDIA_ERR_DB_INTERNAL, "ms_user_get_media_db_path failed");
139 ret = sqlite3_open_v2(db_path, db_handle, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
141 ret = sqlite3_open_v2(db_path, db_handle, SQLITE_OPEN_READONLY, NULL);
143 if (SQLITE_OK != ret) {
144 MSAPI_DBG_ERR("error when db open path[%s],ret[%d]", db_path, ret);
147 return MS_MEDIA_ERR_DB_INTERNAL;
151 if (*db_handle == NULL) {
152 MSAPI_DBG_ERR("*db_handle is NULL");
153 return MS_MEDIA_ERR_DB_INTERNAL;
156 /*Register busy handler*/
157 ret = sqlite3_busy_handler(*db_handle, __media_db_busy_handler, NULL);
158 if (SQLITE_OK != ret) {
160 MSAPI_DBG_ERR("[error when register busy handler] %s", sqlite3_errmsg(*db_handle));
162 sqlite3_close_v2(*db_handle);
165 return MS_MEDIA_ERR_DB_INTERNAL;
168 /*For TV internal space issue, change TRUNCATE to OFF */
169 sql = sqlite3_mprintf("%s", "PRAGMA journal_mode = OFF");
170 ret = sqlite3_exec(*db_handle, sql, NULL, NULL, NULL);
171 MS_SQL_SAFE_FREE(sql);
172 if (SQLITE_OK != ret) {
174 MSAPI_DBG_ERR("[error when change the journal mode] %s", sqlite3_errmsg(*db_handle));
176 sqlite3_close_v2(*db_handle);
179 if (ret == SQLITE_CORRUPT) {
180 MSAPI_DBG_ERR("MEDIA DB IS CORRUPTED");
181 return MS_MEDIA_ERR_DB_CORRUPT;
184 return MS_MEDIA_ERR_DB_INTERNAL;
187 /* Set for localized collate */
188 sqlite3_collation_needed(*db_handle, NULL, __media_db_collation_cb);
190 return MS_MEDIA_ERR_NONE;
193 extern char MEDIA_IPC_PATH[][70];
194 #define MAX_RETRY_COUNT 3
196 static int __media_db_request_update_tcp(ms_msg_type_e msg_type, const char *request_msg, uid_t uid)
198 int ret = MS_MEDIA_ERR_NONE;
200 struct sockaddr_un serv_addr;
203 MSAPI_RETVM_IF(!ms_ipc_is_valid_msg(request_msg), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid request_msg");
205 ms_comm_msg_s send_msg;
206 memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s));
208 send_msg.msg_type = msg_type;
209 SAFE_STRLCPY(send_msg.msg, request_msg, sizeof(send_msg.msg));
213 ret = ms_ipc_create_client_socket(MS_TIMEOUT_SEC_10, &sockfd);
214 MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
216 /*Set server Address*/
217 memset(&serv_addr, 0, sizeof(serv_addr));
218 serv_addr.sun_family = AF_UNIX;
219 SAFE_STRLCPY(serv_addr.sun_path, tzplatform_mkpath(TZ_SYS_RUN, MEDIA_IPC_PATH[MS_DB_UPDATE_PORT]), sizeof(serv_addr.sun_path));
221 /* Connecting to the media db server */
222 if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
223 MSAPI_DBG_STRERROR("connect error");
226 return MS_MEDIA_ERR_PERMISSION_DENIED;
228 return MS_MEDIA_ERR_IPC;
232 if (send(sockfd, &send_msg, sizeof(send_msg), 0) != sizeof(send_msg)) {
233 MSAPI_DBG_STRERROR("send failed");
235 return MS_MEDIA_ERR_IPC;
239 int recv_msg_size = -1;
242 if ((recv_msg_size = recv(sockfd, &recv_msg, sizeof(recv_msg), 0)) < 0) {
243 MSAPI_DBG_STRERROR("recv failed");
245 if (errno == EINTR || errno == EWOULDBLOCK) {
246 if (retry_count < MAX_RETRY_COUNT) {
247 MSAPI_DBG_ERR("TIME OUT[%d]", retry_count);
253 return MS_MEDIA_ERR_IPC;
256 MSAPI_DBG("RECEIVE OK [%d]", recv_msg);
265 #define SLEEP_TIME 1000 * 1000
266 static int __media_db_update_directly(sqlite3 *db_handle, const char *sql_str)
268 int ret = MS_MEDIA_ERR_NONE;
269 char *zErrMsg = NULL;
273 ret = sqlite3_exec(db_handle, sql_str, NULL, NULL, &zErrMsg);
275 if (SQLITE_OK != ret) {
276 MSAPI_ERR_SLOG("Error[%s],Query[%s]", zErrMsg, sql_str);
277 MS_SQL_SAFE_FREE(zErrMsg);
278 if (ret == SQLITE_BUSY) {
279 ret = MS_MEDIA_ERR_DB_BUSY_FAIL;
280 } else if (ret == SQLITE_CONSTRAINT) {
281 ret = MS_MEDIA_ERR_DB_CONSTRAINT_FAIL;
282 } else if (ret == SQLITE_FULL) {
283 ret = MS_MEDIA_ERR_DB_FULL_FAIL;
284 } else if (ret == SQLITE_LOCKED) {
285 if (retry_count < RETRY_CNT) {
286 MSAPI_DBG_ERR("Locked retry[%d]", retry_count);
291 ret = MS_MEDIA_ERR_DB_INTERNAL;
293 ret = MS_MEDIA_ERR_DB_INTERNAL;
300 int media_db_check_integrity(sqlite3 *handle)
302 MSAPI_RETVM_IF(handle == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "Handle is NULL");
305 sqlite3_stmt *stmt = NULL;
306 const char integrity_check_query[] = "PRAGMA integrity_check";
308 ret = sqlite3_prepare_v2(handle, integrity_check_query, strlen(integrity_check_query), &stmt, NULL);
309 if (ret != SQLITE_OK) {
310 MSAPI_DBG_ERR("prepare error, ret = %d, error = %s", ret, sqlite3_errmsg(handle));
311 return MS_MEDIA_ERR_DB_CORRUPT;
314 ret = sqlite3_step(stmt);
315 if (ret != SQLITE_ROW) {
316 MSAPI_DBG_ERR("integrity_check failed in step");
317 sqlite3_finalize(stmt);
318 return MS_MEDIA_ERR_DB_CORRUPT;
321 char* check_result = (char*) sqlite3_column_text(stmt, 0);
322 if (check_result == NULL || strncmp(check_result, "ok", strlen(check_result))) {
323 MSAPI_DBG_ERR("integrity_check failed - result(%s)\n", check_result);
324 sqlite3_finalize(stmt);
325 return MS_MEDIA_ERR_DB_CORRUPT;
327 sqlite3_finalize(stmt);
329 return MS_MEDIA_ERR_NONE;
332 int media_db_connect(sqlite3 **handle, uid_t uid, bool need_write)
334 int ret = MS_MEDIA_ERR_NONE;
335 sqlite3 * db_handle = NULL;
341 ret = __media_db_connect_db_with_handle(&db_handle, uid, need_write);
342 if (ret != MS_MEDIA_ERR_NONE) {
343 if (ret == MS_MEDIA_ERR_DB_CORRUPT && retry_cnt == 0) {
346 ret = __media_db_request_recovery(uid);
347 if (ret == MS_MEDIA_ERR_NONE)
350 return MS_MEDIA_ERR_DB_CORRUPT;
357 return MS_MEDIA_ERR_NONE;
360 void media_db_disconnect(sqlite3 *handle)
365 sqlite3_close_v2(handle);
368 int media_db_request_update_db(const char *query_str, uid_t uid)
370 int ret = MS_MEDIA_ERR_NONE;
374 MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
376 ret = __media_db_request_update_tcp(MS_MSG_DB_UPDATE, query_str, uid);
377 if (ret != MS_MEDIA_ERR_NONE)
378 MSAPI_DBG_ERR("__media_db_request_update_tcp failed : %d", ret);
383 int media_db_update_db_direct(const char *query_str, uid_t uid)
385 int ret = MS_MEDIA_ERR_NONE;
386 sqlite3 *handle = NULL;
390 MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
392 ret = media_db_connect(&handle, uid, true);
393 MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, ret, "Connect failed");
395 ret = __media_db_update_directly(handle, query_str);
396 if (ret != MS_MEDIA_ERR_NONE)
397 MSAPI_DBG_ERR("Query failed");
399 media_db_disconnect(handle);
404 int media_db_update_db(sqlite3 *handle, const char *query_str)
406 MSAPI_RETVM_IF(handle == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "Handle is NULL");
407 MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
409 return __media_db_update_directly(handle, query_str);
412 static int __media_db_request_recovery(uid_t uid)
414 int ret = MS_MEDIA_ERR_NONE;
416 struct sockaddr_un serv_addr;
418 char *db_path = NULL;
420 ret = ms_user_get_media_db_path(uid, &db_path);
421 MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, MS_MEDIA_ERR_INVALID_PARAMETER, "ms_user_get_media_db_path failed");
423 if (!ms_ipc_is_valid_msg(db_path)) {
425 return MS_MEDIA_ERR_INVALID_PARAMETER;
428 ms_comm_msg_s send_msg;
429 memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s));
431 send_msg.msg_type = MS_MSG_MEDIA_DB_MALFORMED;
432 SAFE_STRLCPY(send_msg.msg, db_path, sizeof(send_msg.msg));
437 ret = ms_ipc_create_client_socket(MS_TIMEOUT_SEC_10, &sockfd);
438 MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
440 /*Set server Address*/
441 memset(&serv_addr, 0, sizeof(serv_addr));
442 serv_addr.sun_family = AF_UNIX;
443 /* MSAPI_DBG_SLOG("%s", MEDIA_IPC_PATH[port]); */
444 SAFE_STRLCPY(serv_addr.sun_path, MEDIA_IPC_PATH[MS_SCANNER_PORT], sizeof(serv_addr.sun_path));
446 /* Connecting to the media db server */
447 if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
448 MSAPI_DBG_STRERROR("connect error");
450 return MS_MEDIA_ERR_IPC;
454 if (send(sockfd, &send_msg, sizeof(send_msg), 0) != sizeof(send_msg)) {
455 MSAPI_DBG_STRERROR("send failed");
457 return MS_MEDIA_ERR_IPC;
461 int recv_msg_size = -1;
462 ms_comm_msg_s recv_msg;
464 if ((recv_msg_size = recv(sockfd, &recv_msg, sizeof(recv_msg), 0)) < 0) {
465 MSAPI_DBG_STRERROR("recv failed");
467 if (errno == EINTR || errno == EWOULDBLOCK) {
468 if (retry_count < MAX_RETRY_COUNT) {
469 MSAPI_DBG_ERR("TIME OUT[%d]", retry_count);
475 return MS_MEDIA_ERR_IPC;
478 MSAPI_DBG("RECEIVE OK [%d]", recv_msg.result);
479 ret = recv_msg.result;
486 int media_db_get_result(sqlite3 *handle, char *sql_str, sqlite3_stmt **stmt)
490 MSAPI_RETVM_IF(sql_str == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "invalid query");
491 if (handle == NULL) {
492 MSAPI_DBG_ERR("handle is NULL");
493 MS_SQL_SAFE_FREE(sql_str);
494 return MS_MEDIA_ERR_INVALID_PARAMETER;
497 MSAPI_DBG_SLOG("[SQL query] : %s", sql_str);
499 err = sqlite3_prepare_v2(handle, sql_str, -1, stmt, NULL);
500 MS_SQL_SAFE_FREE(sql_str);
502 if (err != SQLITE_OK) {
503 MSAPI_DBG_ERR("prepare error %d[%s]", err, sqlite3_errmsg(handle));
504 if (err == SQLITE_CORRUPT)
505 return MS_MEDIA_ERR_DB_CORRUPT;
507 return MS_MEDIA_ERR_DB_INTERNAL;
510 return MS_MEDIA_ERR_NONE;