Remove unnecessary libsmack dependency
[platform/core/multimedia/media-server.git] / lib / media-util-db.c
1 /*
2  * Media Utility
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Yong Yeon Kim <yy9875.kim@samsung.com>
7  *
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
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  *
20  */
21
22 #include <unistd.h>
23 #include <sys/stat.h>
24 #include <sys/wait.h>
25
26 #include <dlfcn.h>
27
28 #include <unicode/utypes.h>
29 #include <unicode/ucol.h>
30 #include <unicode/uiter.h>
31 #include <unicode/ustring.h>
32 #include <vconf.h>
33
34 #include "media-server-ipc.h"
35 #include "media-util-dbg.h"
36 #include "media-util-internal.h"
37 #include "media-util.h"
38
39 #define BATCH_START "BEGIN"
40 #define BATCH_END "COMMIT"
41
42 static int __media_db_request_recovery(uid_t uid);
43
44 static int __media_db_busy_handler(void *pData, int count)
45 {
46         usleep(50000);
47
48         MSAPI_DBG("media_db_busy_handler called : %d", count);
49
50         return 200 - count;
51 }
52
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)
55 {
56         UCharIterator uiter1, uiter2;
57         UErrorCode error = U_ZERO_ERROR;
58
59         uiter_setUTF8(&uiter1, (const char *) str1, str1_len);
60         uiter_setUTF8(&uiter2, (const char *) str2, str2_len);
61
62         UCollationResult result = ucol_strcollIter((UCollator *) ucol, &uiter1, &uiter2, &error);
63         if (U_FAILURE(error)) {
64                 MSAPI_DBG_ERR("ucol_strcollIter error: %d", error);
65                 return -1;
66         }
67
68         return result;
69 }
70
71 static void __media_db_collation_cb(void* pArg, sqlite3* handle, int charset, const char* name)
72 {
73         int ret = MS_MEDIA_ERR_NONE;
74         UErrorCode status = U_ZERO_ERROR;
75         const char* locale = NULL;
76         char *lang = NULL;
77         UCollator* ucol = NULL;
78
79         if (handle == NULL || !MS_STRING_VALID(name)) {
80                 MSAPI_DBG_ERR("Input parameter is NULL");
81                 return;
82         }
83
84         if (charset == SQLITE_UTF8 && !sqlite3_stricmp(name, "localized")) {
85                 lang = vconf_get_str(VCONFKEY_LANGSET);
86                 /* get current locale */
87                 if (lang) {
88                         uloc_setDefault(lang, &status);
89                         MS_SAFE_FREE(lang);
90                 } else {
91                         MSAPI_DBG_ERR("Fail to get current language vconf");
92                         return;
93                 }
94                 locale = uloc_getDefault();
95                 if (locale == NULL) {
96                         MSAPI_DBG_ERR("Fail to get current locale");
97                         return;
98                 }
99                 MSAPI_DBG_INFO("locale : %s", locale);
100
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);
106                         return;
107                 }
108
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);
112                         return;
113                 }
114
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);
118                         ucol_close(ucol);
119                 } else {
120                         MSAPI_DBG("sqlite3_create_collation_v2 success");
121                 }
122         } else {
123                 MSAPI_DBG_ERR("No matching collator for %s", name);
124         }
125 }
126
127 static int __media_db_connect_db_with_handle(sqlite3 **db_handle, uid_t uid, bool need_write)
128 {
129         int ret = SQLITE_OK;
130         char *db_path = NULL;
131         char *sql = NULL;
132
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");
135
136         /*Connect DB*/
137         if (need_write)
138                 ret = sqlite3_open_v2(db_path, db_handle, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
139         else
140                 ret = sqlite3_open_v2(db_path, db_handle, SQLITE_OPEN_READONLY, NULL);
141
142         if (SQLITE_OK != ret) {
143                 MSAPI_DBG_ERR("error when db open path[%s],ret[%d]", db_path, ret);
144                 g_free(db_path);
145                 *db_handle = NULL;
146                 return MS_MEDIA_ERR_DB_INTERNAL;
147         }
148         g_free(db_path);
149
150         if (*db_handle == NULL) {
151                 MSAPI_DBG_ERR("*db_handle is NULL");
152                 return MS_MEDIA_ERR_DB_INTERNAL;
153         }
154
155         /*Register busy handler*/
156         ret = sqlite3_busy_handler(*db_handle, __media_db_busy_handler, NULL);
157         if (SQLITE_OK != ret) {
158                 if (*db_handle)
159                         MSAPI_DBG_ERR("[error when register busy handler] %s", sqlite3_errmsg(*db_handle));
160
161                 sqlite3_close_v2(*db_handle);
162                 *db_handle = NULL;
163
164                 return MS_MEDIA_ERR_DB_INTERNAL;
165         }
166
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) {
172                 if (*db_handle)
173                         MSAPI_DBG_ERR("[error when change the journal mode] %s", sqlite3_errmsg(*db_handle));
174
175                 sqlite3_close_v2(*db_handle);
176                 *db_handle = NULL;
177
178                 if (ret == SQLITE_CORRUPT) {
179                         MSAPI_DBG_ERR("MEDIA DB IS CORRUPTED");
180                         return MS_MEDIA_ERR_DB_CORRUPT;
181                 }
182
183                 return MS_MEDIA_ERR_DB_INTERNAL;
184         }
185
186         /* Set for localized collate */
187         sqlite3_collation_needed(*db_handle, NULL, __media_db_collation_cb);
188
189         return MS_MEDIA_ERR_NONE;
190 }
191
192 extern char MEDIA_IPC_PATH[][70];
193 #define MAX_RETRY_COUNT 3
194
195 static int __media_db_request_update_tcp(ms_msg_type_e msg_type, const char *request_msg, uid_t uid)
196 {
197         int ret = MS_MEDIA_ERR_NONE;
198         int sockfd = -1;
199         struct sockaddr_un serv_addr;
200         int retry_count = 0;
201
202         MSAPI_RETVM_IF(!ms_ipc_is_valid_msg(request_msg), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid request_msg");
203
204         ms_comm_msg_s send_msg;
205         memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s));
206
207         send_msg.msg_type = msg_type;
208         SAFE_STRLCPY(send_msg.msg, request_msg, sizeof(send_msg.msg));
209         send_msg.uid = uid;
210
211         /*Create Socket*/
212         ret = ms_ipc_create_client_socket(MS_TIMEOUT_SEC_10, &sockfd);
213         MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
214
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));
219
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");
223                 close(sockfd);
224                 if (errno == EACCES)
225                         return MS_MEDIA_ERR_PERMISSION_DENIED;
226                 else
227                         return MS_MEDIA_ERR_IPC;
228         }
229
230         /* Send request */
231         if (send(sockfd, &send_msg, sizeof(send_msg), 0) != sizeof(send_msg)) {
232                 MSAPI_DBG_STRERROR("send failed");
233                 close(sockfd);
234                 return MS_MEDIA_ERR_IPC;
235         }
236
237         /*Receive Response*/
238         int recv_msg_size = -1;
239         int recv_msg = -1;
240 RETRY:
241         if ((recv_msg_size = recv(sockfd, &recv_msg, sizeof(recv_msg), 0)) < 0) {
242                 MSAPI_DBG_STRERROR("recv failed");
243
244                 if (errno == EINTR || errno == EWOULDBLOCK) {
245                         if (retry_count < MAX_RETRY_COUNT) {
246                                 MSAPI_DBG_ERR("TIME OUT[%d]", retry_count);
247                                 retry_count++;
248                                 goto RETRY;
249                         }
250                 }
251                 close(sockfd);
252                 return MS_MEDIA_ERR_IPC;
253         }
254
255         MSAPI_DBG("RECEIVE OK [%d]", recv_msg);
256         ret = recv_msg;
257
258         close(sockfd);
259
260         return ret;
261 }
262
263 #define RETRY_CNT 9
264 #define SLEEP_TIME 1000 * 1000
265 static int __media_db_update_directly(sqlite3 *db_handle, const char *sql_str)
266 {
267         int ret = MS_MEDIA_ERR_NONE;
268         char *zErrMsg = NULL;
269         int retry_count = 0;
270
271 EXEC_RETRY:
272         ret = sqlite3_exec(db_handle, sql_str, NULL, NULL, &zErrMsg);
273
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);
286                                 retry_count++;
287                                 usleep(SLEEP_TIME);
288                                 goto EXEC_RETRY;
289                         }
290                         ret = MS_MEDIA_ERR_DB_INTERNAL;
291                 } else {
292                         ret = MS_MEDIA_ERR_DB_INTERNAL;
293                 }
294         }
295
296         return ret;
297 }
298
299 int media_db_check_integrity(sqlite3 *handle)
300 {
301         MSAPI_RETVM_IF(handle == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "Handle is NULL");
302
303         int ret = 0;
304         sqlite3_stmt *stmt = NULL;
305         const char integrity_check_query[] = "PRAGMA integrity_check";
306
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;
311         }
312
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;
318         }
319
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;
325         }
326         sqlite3_finalize(stmt);
327
328         return MS_MEDIA_ERR_NONE;
329 }
330
331 int media_db_connect(sqlite3 **handle, uid_t uid, bool need_write)
332 {
333         int ret = MS_MEDIA_ERR_NONE;
334         sqlite3 * db_handle = NULL;
335         int retry_cnt = 0;
336
337         MSAPI_DBG_FUNC();
338
339 RETRY_CONN:
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) {
343                         retry_cnt++;
344
345                         ret = __media_db_request_recovery(uid);
346                         if (ret == MS_MEDIA_ERR_NONE)
347                                 goto RETRY_CONN;
348                         else
349                                 return MS_MEDIA_ERR_DB_CORRUPT;
350                 } else {
351                         return ret;
352                 }
353         }
354
355         *handle = db_handle;
356         return MS_MEDIA_ERR_NONE;
357 }
358
359 void media_db_disconnect(sqlite3 *handle)
360 {
361         MSAPI_DBG_FUNC();
362
363         if (handle)
364                 sqlite3_close_v2(handle);
365 }
366
367 int media_db_request_update_db(const char *query_str, uid_t uid)
368 {
369         int ret = MS_MEDIA_ERR_NONE;
370
371         MSAPI_DBG_FUNC();
372
373         MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
374
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);
378
379         return ret;
380 }
381
382 int media_db_update_db_direct(const char *query_str, uid_t uid)
383 {
384         int ret = MS_MEDIA_ERR_NONE;
385         sqlite3 *handle = NULL;
386
387         MSAPI_DBG_FUNC();
388
389         MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
390
391         ret = media_db_connect(&handle, uid, true);
392         MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, ret, "Connect failed");
393
394         ret = __media_db_update_directly(handle, query_str);
395         if (ret != MS_MEDIA_ERR_NONE)
396                 MSAPI_DBG_ERR("Query failed");
397
398         media_db_disconnect(handle);
399
400         return ret;
401 }
402
403 int media_db_update_db(sqlite3 *handle, const char *query_str)
404 {
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");
407
408         return __media_db_update_directly(handle, query_str);
409 }
410
411 static int __media_db_request_recovery(uid_t uid)
412 {
413         int ret = MS_MEDIA_ERR_NONE;
414         int sockfd = -1;
415         struct sockaddr_un serv_addr;
416         int retry_count = 0;
417         char *db_path = NULL;
418
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");
421
422         if (!ms_ipc_is_valid_msg(db_path)) {
423                 g_free(db_path);
424                 return MS_MEDIA_ERR_INVALID_PARAMETER;
425         }
426
427         ms_comm_msg_s send_msg;
428         memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s));
429
430         send_msg.msg_type = MS_MSG_MEDIA_DB_MALFORMED;
431         SAFE_STRLCPY(send_msg.msg, db_path, sizeof(send_msg.msg));
432         g_free(db_path);
433         send_msg.uid = uid;
434
435         /*Create Socket*/
436         ret = ms_ipc_create_client_socket(MS_TIMEOUT_SEC_10, &sockfd);
437         MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
438
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));
444
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");
448                 close(sockfd);
449                 return MS_MEDIA_ERR_IPC;
450         }
451
452         /* Send request */
453         if (send(sockfd, &send_msg, sizeof(send_msg), 0) != sizeof(send_msg)) {
454                 MSAPI_DBG_STRERROR("send failed");
455                 close(sockfd);
456                 return MS_MEDIA_ERR_IPC;
457         }
458
459         /*Receive Response*/
460         int recv_msg_size = -1;
461         ms_comm_msg_s recv_msg;
462 RETRY:
463         if ((recv_msg_size = recv(sockfd, &recv_msg, sizeof(recv_msg), 0)) < 0) {
464                 MSAPI_DBG_STRERROR("recv failed");
465
466                 if (errno == EINTR || errno == EWOULDBLOCK) {
467                         if (retry_count < MAX_RETRY_COUNT) {
468                                 MSAPI_DBG_ERR("TIME OUT[%d]", retry_count);
469                                 retry_count++;
470                                 goto RETRY;
471                         }
472                 }
473                 close(sockfd);
474                 return MS_MEDIA_ERR_IPC;
475         }
476
477         MSAPI_DBG("RECEIVE OK [%d]", recv_msg.result);
478         ret = recv_msg.result;
479
480         close(sockfd);
481
482         return ret;
483 }
484
485 int media_db_get_result(sqlite3 *handle, char *sql_str, sqlite3_stmt **stmt)
486 {
487         int err = -1;
488
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;
494         }
495
496         MSAPI_DBG_SLOG("[SQL query] : %s", sql_str);
497
498         err = sqlite3_prepare_v2(handle, sql_str, -1, stmt, NULL);
499         MS_SQL_SAFE_FREE(sql_str);
500
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;
505
506                 return MS_MEDIA_ERR_DB_INTERNAL;
507         }
508
509         return MS_MEDIA_ERR_NONE;
510 }