Tizen 2.1 base
[framework/multimedia/media-server.git] / common / scanner / media-scanner-db-svc.c
1 /*
2  *  Media Server
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 /**
23  * This file defines api utilities of contents manager engines.
24  *
25  * @file                media-server-db-svc.c
26  * @author      Yong Yeon Kim(yy9875.kim@samsung.com)
27  * @version     1.0
28  * @brief       This file implements main database operation.
29  */
30
31 #include <dlfcn.h>
32 #include <aul/aul.h>
33
34 #include "media-util.h"
35
36 #include "media-scanner-dbg.h"
37 #include "media-scanner-utils.h"
38 #include "media-scanner-drm.h"
39 #include "media-scanner-db-svc.h"
40
41 #define CONFIG_PATH "/opt/usr/data/file-manager-service/plugin-config"
42 #define EXT ".so"
43 #define EXT_LEN 3
44 #define MSC_REGISTER_COUNT 100 /*For bundle commit*/
45 #define MSC_VALID_COUNT 100 /*For bundle commit*/
46
47 GMutex * db_mutex;
48 GArray *so_array;
49 void ***func_array;
50 int lib_num;
51 void **scan_func_handle = NULL; /*dlopen handel*/
52
53 enum func_list {
54         eCHECK,
55         eCONNECT,
56         eDISCONNECT,
57         eEXIST,
58         eINSERT_BEGIN,
59         eINSERT_END,
60         eINSERT_BATCH,
61         eSET_ALL_VALIDITY,
62         eSET_VALIDITY_BEGIN,
63         eSET_VALIDITY_END,
64         eSET_VALIDITY,
65         eDELETE_ALL,
66         eDELETE_INVALID_ITEMS,
67         eUPDATE_BEGIN,
68         eUPDATE_END,
69         eSET_FOLDER_VALIDITY,
70         eDELETE_FOLDER,
71         eFUNC_MAX
72 };
73
74
75 static int
76 _msc_get_mime(const char *path, char *mimetype)
77 {
78         int ret = 0;
79
80         if (path == NULL)
81                 return MS_MEDIA_ERR_INVALID_PARAMETER;
82
83         /*get content type and mime type from file. */
84         /*in case of drm file. */
85         if (msc_is_drm_file(path)) {
86                 ret =  msc_get_mime_in_drm_info(path, mimetype);
87                 if (ret != MS_MEDIA_ERR_NONE) {
88                         MSC_DBG_ERR("Fail to get mime");
89                         return MS_MEDIA_ERR_MIME_GET_FAIL;
90                 }
91         } else {
92                 /*in case of normal files */
93                 if (aul_get_mime_from_file(path, mimetype, 255) < 0) {
94                         MSC_DBG_ERR("aul_get_mime_from_file fail");
95                         return MS_MEDIA_ERR_MIME_GET_FAIL;
96                 }
97         }
98
99         return MS_MEDIA_ERR_NONE;
100 }
101
102 static int
103 _msc_check_category(const char *path, const char *mimetype, int index)
104 {
105         int ret;
106         char *err_msg = NULL;
107
108         ret = ((CHECK_ITEM)func_array[index][eCHECK])(path, mimetype, &err_msg);
109         if (ret != 0) {
110                 MSC_DBG_ERR("error : %s [%s] %s", g_array_index(so_array, char*, index), err_msg, path);
111                 MS_SAFE_FREE(err_msg);
112         }
113
114         return ret;
115 }
116
117 static int
118 _msc_token_data(char *buf, char **name)
119 {
120         int len;
121         char* pos = NULL;
122
123         pos = strstr(buf, EXT);
124         if (pos == NULL) {
125                 MSC_DBG_ERR("This is not shared object library.");
126                 name = NULL;
127                 return -1;
128         } else {
129                 len = pos - buf + EXT_LEN;
130                 *name = strndup(buf, len);
131                 MSC_DBG_INFO("%s", *name);
132         }
133
134         return 0;
135 }
136
137 static bool
138 _msc_load_config()
139 {
140         int ret;
141         FILE *fp;
142         char *so_name = NULL;
143         char buf[256] = {0};
144
145         fp = fopen(CONFIG_PATH, "rt");
146         if (fp == NULL) {
147                 MSC_DBG_ERR("fp is NULL");
148                 return MS_MEDIA_ERR_FILE_OPEN_FAIL;
149         }
150         while(1) {
151                 if (fgets(buf, 256, fp) == NULL)
152                         break;
153
154                 ret = _msc_token_data(buf, &so_name);
155                 if (ret == 0) {
156                         /*add to array*/
157                         g_array_append_val(so_array, so_name);
158                         so_name = NULL;
159                 }
160         }
161
162         fclose(fp);
163
164         return MS_MEDIA_ERR_NONE;
165 }
166
167 int
168 msc_load_functions(void)
169 {
170         int lib_index = 0, func_index;
171         char func_list[eFUNC_MAX][40] = {
172                 "check_item",
173                 "connect",
174                 "disconnect",
175                 "check_item_exist",
176                 "insert_item_begin",
177                 "insert_item_end",
178                 "insert_item",
179                 "set_all_storage_items_validity",
180                 "set_item_validity_begin",
181                 "set_item_validity_end",
182                 "set_item_validity",
183                 "delete_all_items_in_storage",
184                 "delete_all_invalid_items_in_storage",
185                 "update_begin",
186                 "update_end",
187                 "set_folder_item_validity",
188                 "delete_all_invalid_items_in_folder",
189                 };
190         /*init array for adding name of so*/
191         so_array = g_array_new(FALSE, FALSE, sizeof(char*));
192
193         /*load information of so*/
194         _msc_load_config();
195
196         if(so_array->len == 0) {
197                 MSC_DBG_INFO("There is no information for functions");
198                 return MS_MEDIA_ERR_DYNAMIC_LINK;
199         }
200
201         /*the number of functions*/
202         lib_num = so_array->len;
203
204         MSC_DBG_INFO("The number of information of so : %d", lib_num);
205         MS_MALLOC(scan_func_handle, sizeof(void*) * lib_num);
206         if (scan_func_handle == NULL) {
207                 MSC_DBG_ERR("malloc failed");
208                 return MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL;
209         }
210
211         while(lib_index < lib_num) {
212                 /*get handle*/
213                 MSC_DBG_INFO("[name of so : %s]", g_array_index(so_array, char*, lib_index));
214                 scan_func_handle[lib_index] = dlopen(g_array_index(so_array, char*, lib_index), RTLD_LAZY);
215                 if (!scan_func_handle[lib_index]) {
216                         MSC_DBG_ERR("%s", dlerror());
217                         MS_SAFE_FREE(scan_func_handle);
218                         return MS_MEDIA_ERR_DYNAMIC_LINK;
219                 }
220                 lib_index++;
221         }
222
223         dlerror();    /* Clear any existing error */
224
225         /*allocate for array of functions*/
226         MS_MALLOC(func_array, sizeof(void*) * lib_num);
227         if (func_array == NULL) {
228                 MSC_DBG_ERR("malloc failed");
229                 MS_SAFE_FREE(scan_func_handle);
230                 return MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL;
231         }
232
233         for(lib_index = 0 ; lib_index < lib_num; lib_index ++) {
234                 MS_MALLOC(func_array[lib_index], sizeof(void*) * eFUNC_MAX);
235                 if (func_array[lib_index] == NULL) {
236                         int index;
237
238                         for (index = 0; index < lib_index; index ++) {
239                                 MS_SAFE_FREE(func_array[index]);
240                         }
241                         MS_SAFE_FREE(func_array);
242                         MS_SAFE_FREE(scan_func_handle);
243
244                         MSC_DBG_ERR("malloc failed");
245                         return MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL;
246                 }
247         }
248
249         /*add functions to array */
250         for (lib_index = 0; lib_index < lib_num; lib_index++) {
251                 for (func_index = 0; func_index < eFUNC_MAX ; func_index++) {
252                         func_array[lib_index][func_index] = dlsym(scan_func_handle[lib_index], func_list[func_index]);
253                         if (func_array[lib_index][func_index] == NULL) {
254                                 int index;
255
256                                 for (index = 0; index < lib_index; index ++) {
257                                         MS_SAFE_FREE(func_array[index]);
258                                 }
259                                 MS_SAFE_FREE(func_array);
260                                 MS_SAFE_FREE(scan_func_handle);
261
262                                 MSC_DBG_ERR("dlsym failed");
263                                 return MS_MEDIA_ERR_DYNAMIC_LINK;
264                         }
265                 }
266         }
267
268         return MS_MEDIA_ERR_NONE;
269 }
270
271 void
272 msc_unload_functions(void)
273 {
274         int lib_index;
275
276         for (lib_index = 0; lib_index < lib_num; lib_index ++)
277                 dlclose(scan_func_handle[lib_index]);
278
279         for (lib_index = 0; lib_index < lib_num; lib_index++) {
280                         if (func_array[lib_index]) {
281                                 MS_SAFE_FREE(func_array[lib_index]);
282                         }
283         }
284
285         MS_SAFE_FREE (func_array);
286         MS_SAFE_FREE (scan_func_handle);
287         if (so_array) g_array_free(so_array, TRUE);
288 }
289
290 int
291 msc_connect_db(void ***handle)
292 {
293         int lib_index;
294         int ret;
295         char * err_msg = NULL;
296
297         /*Lock mutex for openning db*/
298         g_mutex_lock(db_mutex);
299
300         MS_MALLOC(*handle, sizeof (void*) * lib_num);
301
302         for (lib_index = 0; lib_index < lib_num; lib_index++) {
303                 ret = ((CONNECT)func_array[lib_index][eCONNECT])(&((*handle)[lib_index]), &err_msg); /*dlopen*/
304                 if (ret != 0) {
305                         MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg);
306                         MS_SAFE_FREE(err_msg);
307                         g_mutex_unlock(db_mutex);
308
309                         return MS_MEDIA_ERR_DB_CONNECT_FAIL;
310                 }
311         }
312
313         MSC_DBG_INFO("connect Media DB");
314
315         g_mutex_unlock(db_mutex);
316
317         return MS_MEDIA_ERR_NONE;
318 }
319
320 int
321 msc_disconnect_db(void ***handle)
322 {
323         int lib_index;
324         int ret;
325         char * err_msg = NULL;
326
327         for (lib_index = 0; lib_index < lib_num; lib_index++) {
328                 ret = ((DISCONNECT)func_array[lib_index][eDISCONNECT])((*handle)[lib_index], &err_msg); /*dlopen*/
329                 if (ret != 0) {
330                         MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg);
331                         MS_SAFE_FREE(err_msg);
332                         return MS_MEDIA_ERR_DB_DISCONNECT_FAIL;
333                 }
334         }
335
336         MS_SAFE_FREE(*handle);
337
338         MSC_DBG_INFO("Disconnect Media DB");
339
340         return MS_MEDIA_ERR_NONE;
341 }
342
343 int
344 msc_validate_item(void **handle, char *path)
345 {
346         int lib_index;
347         int res = MS_MEDIA_ERR_NONE;
348         int ret;
349         char *err_msg = NULL;
350         char mimetype[255] = {0};
351         ms_storage_type_t storage_type;
352
353         ret = _msc_get_mime(path, mimetype);
354         if (ret != MS_MEDIA_ERR_NONE) {
355                 MSC_DBG_ERR("err : _msc_get_mime [%d]", ret);
356                 return ret;
357         }
358         storage_type = msc_get_storage_type_by_full(path);
359
360         for (lib_index = 0; lib_index < lib_num; lib_index++) {
361                 if (!_msc_check_category(path, mimetype, lib_index)) {
362                         /*check exist in Media DB, If file is not exist, insert data in DB. */
363                         ret = ((CHECK_ITEM_EXIST)func_array[lib_index][eEXIST])(handle[lib_index], path, storage_type, &err_msg); /*dlopen*/
364                         if (ret != 0) {
365                                 MSC_DBG_ERR("not exist in %d. insert data", lib_index);
366                                 MS_SAFE_FREE(err_msg);
367
368                                 ret = ((INSERT_ITEM)func_array[lib_index][eINSERT_BATCH])(handle[lib_index], path, storage_type, mimetype, &err_msg); /*dlopen*/
369                                 if (ret != 0) {
370                                         MSC_DBG_ERR("error : %s [%s] %s", g_array_index(so_array, char*, lib_index), err_msg, path);
371                                         MSC_DBG_ERR("[%s] %s", mimetype, path);
372                                         MS_SAFE_FREE(err_msg);
373                                         res = MS_MEDIA_ERR_DB_INSERT_FAIL;
374                                 }
375                         } else {
376                                 /*if meta data of file exist, change valid field to "1" */
377                                 ret = ((SET_ITEM_VALIDITY)func_array[lib_index][eSET_VALIDITY])(handle[lib_index], path, true, mimetype, true, &err_msg); /*dlopen*/
378                                 if (ret != 0) {
379                                         MSC_DBG_ERR("error : %s [%s] %s", g_array_index(so_array, char*, lib_index), err_msg, path);
380                                         MSC_DBG_ERR("[%s] %s", mimetype, path);
381                                         MS_SAFE_FREE(err_msg);
382                                         res = MS_MEDIA_ERR_DB_UPDATE_FAIL;
383                                 }
384                         }
385                 } else {
386                         MSC_DBG_ERR("check category failed");
387                         MSC_DBG_ERR("[%s] %s", mimetype, path);
388                 }
389         }
390
391         if (msc_is_drm_file(path)) {
392                 ret = msc_drm_register(path);
393         }
394
395         return res;
396 }
397
398 int
399 msc_invalidate_all_items(void **handle, ms_storage_type_t store_type)
400 {
401         int lib_index;
402         int res = MS_MEDIA_ERR_NONE;
403         int ret;
404         char *err_msg = NULL;
405
406         for (lib_index = 0; lib_index < lib_num; lib_index++) {
407                 ret = ((SET_ALL_STORAGE_ITEMS_VALIDITY)func_array[lib_index][eSET_ALL_VALIDITY])(handle[lib_index], store_type, false, &err_msg); /*dlopen*/
408                 if (ret != 0) {
409                         MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg);
410                         MS_SAFE_FREE(err_msg);
411                         res = MS_MEDIA_ERR_DB_UPDATE_FAIL;
412                 }
413         }
414
415         return res;
416 }
417
418 int
419 msc_insert_item_batch(void **handle, const char *path)
420 {
421         int lib_index;
422         int res = MS_MEDIA_ERR_NONE;
423         int ret;
424         char mimetype[255] = {0};
425         char *err_msg = NULL;
426         ms_storage_type_t storage_type;
427
428         ret = _msc_get_mime(path, mimetype);
429         if (ret != MS_MEDIA_ERR_NONE) {
430                 MSC_DBG_ERR("err : _msc_get_mime [%d]", ret);
431                 return ret;
432         }
433         storage_type = msc_get_storage_type_by_full(path);
434
435         for (lib_index = 0; lib_index < lib_num; lib_index++) {
436                 if (!_msc_check_category(path, mimetype, lib_index)) {
437                         ret = ((INSERT_ITEM)func_array[lib_index][eINSERT_BATCH])(handle[lib_index], path, storage_type, mimetype, &err_msg); /*dlopen*/
438                         if (ret != 0) {
439                                 MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg);
440                                 MSC_DBG_ERR("[%s] %s", mimetype, path);
441                                 MS_SAFE_FREE(err_msg);
442                                 res = MS_MEDIA_ERR_DB_INSERT_FAIL;
443                         }
444                 } else {
445                         MSC_DBG_ERR("check category failed");
446                         MSC_DBG_ERR("[%s] %s", mimetype, path);
447                 }
448         }
449
450         if (msc_is_drm_file(path)) {
451                 ret = msc_drm_register(path);
452                 res = ret;
453         }
454
455         return res;
456 }
457
458 bool
459 msc_delete_all_items(void **handle, ms_storage_type_t store_type)
460 {
461         int lib_index;
462         int ret = 0;
463         char *err_msg = NULL;
464
465         /* To reset media db when differnet mmc is inserted. */
466         for (lib_index = 0; lib_index < lib_num; lib_index++) {
467                 ret = ((DELETE_ALL_ITEMS_IN_STORAGE)func_array[lib_index][eDELETE_ALL])(handle[lib_index], store_type, &err_msg); /*dlopen*/
468                 if (ret != 0) {
469                         MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg);
470                         MS_SAFE_FREE(err_msg);
471                         return false;
472                 }
473         }
474
475         return true;
476 }
477
478 bool
479 msc_delete_invalid_items(void **handle, ms_storage_type_t store_type)
480 {
481         int lib_index;
482         int ret;
483         char *err_msg = NULL;
484
485         for (lib_index = 0; lib_index < lib_num; lib_index++) {
486                 ret = ((DELETE_ALL_INVALID_ITMES_IN_STORAGE)func_array[lib_index][eDELETE_INVALID_ITEMS])(handle[lib_index], store_type, &err_msg); /*dlopen*/
487                 if (ret != 0) {
488                         MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg);
489                         MS_SAFE_FREE(err_msg);
490                         return false;
491                 }
492         }
493
494         return true;
495 }
496
497 int
498 msc_set_folder_validity(void **handle, const char *path, int validity, int recursive)
499 {
500         int lib_index;
501         int ret;
502         char *err_msg = NULL;
503
504         for (lib_index = 0; lib_index < lib_num; lib_index++) {
505                 ret = ((SET_FOLDER_ITEM_VALIDITY)func_array[lib_index][eSET_FOLDER_VALIDITY])(handle[lib_index], path, validity, recursive,&err_msg); /*dlopen*/
506                 if (ret != 0) {
507                         MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg);
508                         MS_SAFE_FREE(err_msg);
509                         return MS_MEDIA_ERR_DB_UPDATE_FAIL;
510                 }
511         }
512
513         return MS_MEDIA_ERR_NONE;
514 }
515
516 int
517 msc_delete_invalid_items_in_folder(void **handle, const char*path)
518 {
519         int lib_index;
520         int ret;
521         char *err_msg = NULL;
522
523         for (lib_index = 0; lib_index < lib_num; lib_index++) {
524                 ret = ((DELETE_ALL_INVALID_ITEMS_IN_FOLDER)func_array[lib_index][eDELETE_FOLDER])(handle[lib_index], path, &err_msg); /*dlopen*/
525                 if (ret != 0) {
526                         MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg);
527                         MS_SAFE_FREE(err_msg);
528                         return MS_MEDIA_ERR_DB_UPDATE_FAIL;
529                 }
530         }
531
532         return MS_MEDIA_ERR_NONE;
533 }
534
535 /****************************************************************************************************
536 FOR BULK COMMIT
537 *****************************************************************************************************/
538
539 void
540 msc_register_start(void **handle)
541 {
542         int lib_index;
543         int ret = 0;
544         char *err_msg = NULL;
545
546         for (lib_index = 0; lib_index < lib_num; lib_index++) {
547                 ret = ((INSERT_ITEM_BEGIN)func_array[lib_index][eINSERT_BEGIN])(handle[lib_index], MSC_REGISTER_COUNT, &err_msg);/*dlopen*/
548                 if (ret != 0) {
549                         MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg);
550                         MS_SAFE_FREE(err_msg);
551                 }
552         }
553 }
554
555 void
556 msc_register_end(void **handle)
557 {
558         int lib_index;
559         int ret = 0;
560         char *err_msg = NULL;
561
562         for (lib_index = 0; lib_index < lib_num; lib_index++) {
563                 ret = ((INSERT_ITEM_END)func_array[lib_index][eINSERT_END])(handle[lib_index], &err_msg);/*dlopen*/
564                 if (ret != 0) {
565                         MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg);
566                         MS_SAFE_FREE(err_msg);
567                 }
568         }
569
570         for (lib_index = 0; lib_index < lib_num; lib_index++) {
571                 ret = ((UPDATE_END)func_array[lib_index][eUPDATE_END])();/*dlopen*/
572                 if (ret != 0) {
573                         MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg);
574                         MS_SAFE_FREE(err_msg);
575                 }
576         }
577 }
578
579 void
580 msc_validate_start(void **handle)
581 {
582         int lib_index;
583         int ret = 0;
584         char *err_msg = NULL;
585
586         for (lib_index = 0; lib_index < lib_num; lib_index++) {
587                 ret = ((SET_ITEM_VALIDITY_BEGIN)func_array[lib_index][eSET_VALIDITY_BEGIN])(handle[lib_index], MSC_VALID_COUNT, &err_msg);/*dlopen*/
588                 if (ret != 0) {
589                         MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg);
590                         MS_SAFE_FREE(err_msg);
591                 }
592         }
593 }
594
595 void
596 msc_validate_end(void **handle)
597 {
598         int lib_index;
599         int ret = 0;
600         char *err_msg = NULL;
601
602         for (lib_index = 0; lib_index < lib_num; lib_index++) {
603                 ret = ((SET_ITEM_VALIDITY_END)func_array[lib_index][eSET_VALIDITY_END])(handle[lib_index], &err_msg);/*dlopen*/
604                 if (ret != 0) {
605                         MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg);
606                         MS_SAFE_FREE(err_msg);
607                 }
608         }
609 }
610