Remove media-util-internal.h
[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  * 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
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  */
19
20 #include <unistd.h>
21 #include <dlfcn.h>
22
23 #include <unicode/utypes.h>
24 #include <unicode/ucol.h>
25 #include <unicode/uiter.h>
26 #include <unicode/ustring.h>
27 #include <vconf.h>
28
29 #include "media-util-dbg.h"
30 #include "media-util.h"
31
32 #define MS_TIMEOUT_SEC 10
33
34 static int __media_db_request_recovery(uid_t uid);
35
36 static int __media_db_busy_handler(void *pData, int count)
37 {
38         usleep(50000);
39
40         MSAPI_DBG("media_db_busy_handler called : %d", count);
41
42         return 200 - count;
43 }
44
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)
47 {
48         UCharIterator uiter1, uiter2;
49         UErrorCode error = U_ZERO_ERROR;
50
51         uiter_setUTF8(&uiter1, (const char *) str1, str1_len);
52         uiter_setUTF8(&uiter2, (const char *) str2, str2_len);
53
54         UCollationResult result = ucol_strcollIter((UCollator *) ucol, &uiter1, &uiter2, &error);
55         if (U_FAILURE(error)) {
56                 MSAPI_DBG_ERR("ucol_strcollIter error: %d", error);
57                 return -1;
58         }
59
60         return result;
61 }
62
63 static void __media_db_collation_cb(void* pArg, sqlite3* handle, int charset, const char* name)
64 {
65         int ret = MS_MEDIA_ERR_NONE;
66         UErrorCode status = U_ZERO_ERROR;
67         const char* locale = NULL;
68         char *lang = NULL;
69         UCollator* ucol = NULL;
70
71         if (handle == NULL || !MS_STRING_VALID(name)) {
72                 MSAPI_DBG_ERR("Input parameter is NULL");
73                 return;
74         }
75
76         if (charset == SQLITE_UTF8 && !sqlite3_stricmp(name, "localized")) {
77                 lang = vconf_get_str(VCONFKEY_LANGSET);
78                 /* get current locale */
79                 if (lang) {
80                         uloc_setDefault(lang, &status);
81                         MS_SAFE_FREE(lang);
82                 } else {
83                         MSAPI_DBG_ERR("Fail to get current language vconf");
84                         return;
85                 }
86                 locale = uloc_getDefault();
87                 if (locale == NULL) {
88                         MSAPI_DBG_ERR("Fail to get current locale");
89                         return;
90                 }
91                 MSAPI_DBG_INFO("locale : %s", locale);
92
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);
98                         return;
99                 }
100
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);
104                         return;
105                 }
106
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);
110                         ucol_close(ucol);
111                 } else {
112                         MSAPI_DBG("sqlite3_create_collation_v2 success");
113                 }
114         } else {
115                 MSAPI_DBG_ERR("No matching collator for %s", name);
116         }
117 }
118
119 static int __media_db_connect_db_with_handle(sqlite3 **db_handle, uid_t uid, bool need_write)
120 {
121         int ret = SQLITE_OK;
122         char *db_path = NULL;
123         char *sql = 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");
127
128         /*Connect DB*/
129         if (need_write)
130                 ret = sqlite3_open_v2(db_path, db_handle, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
131         else
132                 ret = sqlite3_open_v2(db_path, db_handle, SQLITE_OPEN_READONLY, NULL);
133
134         if (SQLITE_OK != ret) {
135                 MSAPI_DBG_ERR("error when db open path[%s],ret[%d]", db_path, ret);
136                 g_free(db_path);
137                 *db_handle = NULL;
138                 return MS_MEDIA_ERR_DB_INTERNAL;
139         }
140         g_free(db_path);
141
142         if (*db_handle == NULL) {
143                 MSAPI_DBG_ERR("*db_handle is NULL");
144                 return MS_MEDIA_ERR_DB_INTERNAL;
145         }
146
147         /*Register busy handler*/
148         ret = sqlite3_busy_handler(*db_handle, __media_db_busy_handler, NULL);
149         if (SQLITE_OK != ret) {
150                 if (*db_handle)
151                         MSAPI_DBG_ERR("[error when register busy handler] %s", sqlite3_errmsg(*db_handle));
152
153                 sqlite3_close_v2(*db_handle);
154                 *db_handle = NULL;
155
156                 return MS_MEDIA_ERR_DB_INTERNAL;
157         }
158
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) {
164                 if (*db_handle)
165                         MSAPI_DBG_ERR("[error when change the journal mode] %s", sqlite3_errmsg(*db_handle));
166
167                 sqlite3_close_v2(*db_handle);
168                 *db_handle = NULL;
169
170                 if (ret == SQLITE_CORRUPT) {
171                         MSAPI_DBG_ERR("MEDIA DB IS CORRUPTED");
172                         return MS_MEDIA_ERR_DB_CORRUPT;
173                 }
174
175                 return MS_MEDIA_ERR_DB_INTERNAL;
176         }
177
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;
182 }
183
184 extern char MEDIA_IPC_PATH[][70];
185 #define MAX_RETRY_COUNT 3
186
187 static int __media_db_request_update_tcp(ms_msg_type_e msg_type, const char *request_msg, uid_t uid)
188 {
189         int ret = MS_MEDIA_ERR_NONE;
190         int sockfd = -1;
191         struct sockaddr_un serv_addr;
192         int retry_count = 0;
193
194         MSAPI_RETVM_IF(!ms_ipc_is_valid_msg(request_msg), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid request_msg");
195
196         ms_comm_msg_s send_msg;
197         memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s));
198
199         send_msg.msg_type = msg_type;
200         SAFE_STRLCPY(send_msg.msg, request_msg, sizeof(send_msg.msg));
201         send_msg.uid = uid;
202
203         /*Create Socket*/
204         ret = ms_ipc_create_client_socket(MS_TIMEOUT_SEC, &sockfd);
205         MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
206
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));
211
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");
215                 close(sockfd);
216                 if (errno == EACCES)
217                         return MS_MEDIA_ERR_PERMISSION_DENIED;
218                 else
219                         return MS_MEDIA_ERR_IPC;
220         }
221
222         /* Send request */
223         if (send(sockfd, &send_msg, sizeof(send_msg), 0) != sizeof(send_msg)) {
224                 MSAPI_DBG_STRERROR("send failed");
225                 close(sockfd);
226                 return MS_MEDIA_ERR_IPC;
227         }
228
229         /*Receive Response*/
230         int recv_msg_size = -1;
231         int recv_msg = -1;
232 RETRY:
233         if ((recv_msg_size = recv(sockfd, &recv_msg, sizeof(recv_msg), 0)) < 0) {
234                 MSAPI_DBG_STRERROR("recv failed");
235
236                 if (errno == EINTR || errno == EWOULDBLOCK) {
237                         if (retry_count < MAX_RETRY_COUNT) {
238                                 MSAPI_DBG_ERR("TIME OUT[%d]", retry_count);
239                                 retry_count++;
240                                 goto RETRY;
241                         }
242                 }
243                 close(sockfd);
244                 return MS_MEDIA_ERR_IPC;
245         }
246
247         MSAPI_DBG("RECEIVE OK [%d]", recv_msg);
248         ret = recv_msg;
249
250         close(sockfd);
251
252         return ret;
253 }
254
255 #define RETRY_CNT 9
256 #define SLEEP_TIME 1000 * 1000
257 static int __media_db_update_directly(sqlite3 *db_handle, const char *sql_str)
258 {
259         int ret = MS_MEDIA_ERR_NONE;
260         char *zErrMsg = NULL;
261         int retry_count = 0;
262
263 EXEC_RETRY:
264         ret = sqlite3_exec(db_handle, sql_str, NULL, NULL, &zErrMsg);
265
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);
278                                 retry_count++;
279                                 usleep(SLEEP_TIME);
280                                 goto EXEC_RETRY;
281                         }
282                         ret = MS_MEDIA_ERR_DB_INTERNAL;
283                 } else {
284                         ret = MS_MEDIA_ERR_DB_INTERNAL;
285                 }
286         }
287
288         return ret;
289 }
290
291 int media_db_check_integrity(sqlite3 *handle)
292 {
293         MSAPI_RETVM_IF(handle == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "Handle is NULL");
294
295         int ret = 0;
296         sqlite3_stmt *stmt = NULL;
297         const char integrity_check_query[] = "PRAGMA integrity_check";
298
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;
303         }
304
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;
310         }
311
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;
317         }
318         sqlite3_finalize(stmt);
319
320         return MS_MEDIA_ERR_NONE;
321 }
322
323 int media_db_connect(sqlite3 **handle, uid_t uid, bool need_write)
324 {
325         int ret = MS_MEDIA_ERR_NONE;
326         sqlite3 * db_handle = NULL;
327         int retry_cnt = 0;
328
329         MSAPI_DBG_FUNC();
330
331 RETRY_CONN:
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) {
335                         retry_cnt++;
336
337                         ret = __media_db_request_recovery(uid);
338                         if (ret == MS_MEDIA_ERR_NONE)
339                                 goto RETRY_CONN;
340                         else
341                                 return MS_MEDIA_ERR_DB_CORRUPT;
342                 } else {
343                         return ret;
344                 }
345         }
346
347         *handle = db_handle;
348         return MS_MEDIA_ERR_NONE;
349 }
350
351 void media_db_disconnect(sqlite3 *handle)
352 {
353         MSAPI_DBG_FUNC();
354
355         if (handle)
356                 sqlite3_close_v2(handle);
357 }
358
359 int media_db_request_update_db(const char *query_str, uid_t uid)
360 {
361         int ret = MS_MEDIA_ERR_NONE;
362
363         MSAPI_DBG_FUNC();
364
365         MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
366
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);
370
371         return ret;
372 }
373
374 int media_db_update_db_direct(const char *query_str, uid_t uid)
375 {
376         int ret = MS_MEDIA_ERR_NONE;
377         sqlite3 *handle = NULL;
378
379         MSAPI_DBG_FUNC();
380
381         MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
382
383         ret = media_db_connect(&handle, uid, true);
384         MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, ret, "Connect failed");
385
386         ret = __media_db_update_directly(handle, query_str);
387         if (ret != MS_MEDIA_ERR_NONE)
388                 MSAPI_DBG_ERR("Query failed");
389
390         media_db_disconnect(handle);
391
392         return ret;
393 }
394
395 static int __media_db_request_recovery(uid_t uid)
396 {
397         int ret = MS_MEDIA_ERR_NONE;
398         int sockfd = -1;
399         struct sockaddr_un serv_addr;
400         int retry_count = 0;
401         char *db_path = NULL;
402
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");
405
406         if (!ms_ipc_is_valid_msg(db_path)) {
407                 g_free(db_path);
408                 return MS_MEDIA_ERR_INVALID_PARAMETER;
409         }
410
411         ms_comm_msg_s send_msg;
412         memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s));
413
414         send_msg.msg_type = MS_MSG_MEDIA_DB_MALFORMED;
415         SAFE_STRLCPY(send_msg.msg, db_path, sizeof(send_msg.msg));
416         g_free(db_path);
417         send_msg.uid = uid;
418
419         /*Create Socket*/
420         ret = ms_ipc_create_client_socket(MS_TIMEOUT_SEC, &sockfd);
421         MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
422
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));
428
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");
432                 close(sockfd);
433                 return MS_MEDIA_ERR_IPC;
434         }
435
436         /* Send request */
437         if (send(sockfd, &send_msg, sizeof(send_msg), 0) != sizeof(send_msg)) {
438                 MSAPI_DBG_STRERROR("send failed");
439                 close(sockfd);
440                 return MS_MEDIA_ERR_IPC;
441         }
442
443         /*Receive Response*/
444         int recv_msg_size = -1;
445         ms_comm_msg_s recv_msg;
446 RETRY:
447         if ((recv_msg_size = recv(sockfd, &recv_msg, sizeof(recv_msg), 0)) < 0) {
448                 MSAPI_DBG_STRERROR("recv failed");
449
450                 if (errno == EINTR || errno == EWOULDBLOCK) {
451                         if (retry_count < MAX_RETRY_COUNT) {
452                                 MSAPI_DBG_ERR("TIME OUT[%d]", retry_count);
453                                 retry_count++;
454                                 goto RETRY;
455                         }
456                 }
457                 close(sockfd);
458                 return MS_MEDIA_ERR_IPC;
459         }
460
461         MSAPI_DBG("RECEIVE OK [%d]", recv_msg.result);
462         ret = recv_msg.result;
463
464         close(sockfd);
465
466         return ret;
467 }
468
469 int media_db_get_result(sqlite3 *handle, char *sql_str, sqlite3_stmt **stmt)
470 {
471         int err = -1;
472
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;
478         }
479
480         MSAPI_DBG_SLOG("[SQL query] : %s", sql_str);
481
482         err = sqlite3_prepare_v2(handle, sql_str, -1, stmt, NULL);
483         MS_SQL_SAFE_FREE(sql_str);
484
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;
489
490                 return MS_MEDIA_ERR_DB_INTERNAL;
491         }
492
493         return MS_MEDIA_ERR_NONE;
494 }