Tizen 2.1 base
[framework/multimedia/media-server.git] / common / scanner / media-scanner-scan.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-scan.c
26  * @author      Yong Yeon Kim(yy9875.kim@samsung.com)
27  * @version     1.0
28  * @brief
29  */
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <dirent.h>
33 #include <errno.h>
34 #include <malloc.h>
35 #include <pmapi.h>
36 #include <vconf.h>
37
38 #include "media-util.h"
39 #include "media-server-ipc.h"
40 #include "media-scanner-dbg.h"
41 #include "media-scanner-utils.h"
42 #include "media-scanner-db-svc.h"
43 #include "media-scanner-socket.h"
44 #include "media-scanner-scan.h"
45
46 typedef struct msc_scan_data {
47         char *name;
48         struct msc_scan_data *next;
49 } msc_scan_data;
50
51 int mmc_state;
52 bool power_off;
53 GAsyncQueue * storage_queue;
54 GAsyncQueue *scan_queue;
55 GAsyncQueue *reg_queue;
56
57 #ifdef FMS_PERF
58 extern struct timeval g_mmc_start_time;
59 extern struct timeval g_mmc_end_time;
60 #endif
61
62 static int
63 _msc_set_power_mode(ms_db_status_type_t status)
64 {
65         int res = MS_MEDIA_ERR_NONE;
66         int err;
67
68         switch (status) {
69         case MS_DB_UPDATING:
70                 err = pm_lock_state(LCD_OFF, STAY_CUR_STATE, 0);
71                 if (err != 0)
72                         res = MS_MEDIA_ERR_INTERNAL;
73                 break;
74         case MS_DB_UPDATED:
75                 err = pm_unlock_state(LCD_OFF, STAY_CUR_STATE);
76                 if (err != 0)
77                         res = MS_MEDIA_ERR_INTERNAL;
78                 break;
79         default:
80                 MSC_DBG_ERR("Unacceptable type : %d", status);
81                 break;
82         }
83
84         return res;
85 }
86
87 static int
88 _msc_set_db_status(ms_scanning_location_t location, ms_db_status_type_t status)
89 {
90         int res = MS_MEDIA_ERR_NONE;
91         int err = 0;
92
93         if (status == MS_DB_UPDATING) {
94                 if (location != MS_SCANNING_DIRECTORY) {
95                         if (!msc_config_set_int(VCONFKEY_FILEMANAGER_DB_STATUS, VCONFKEY_FILEMANAGER_DB_UPDATING)) {
96                                 res = MS_MEDIA_ERR_VCONF_SET_FAIL;
97                                 MSC_DBG_ERR("msc_config_set_int failed");
98                         }
99                 }
100                 /* this is temporay code for tizen 2.0*/
101                 if(location == MS_SCANNING_EXTERNAL) {
102                         if (!msc_config_set_int(VCONFKEY_FILEMANAGER_MMC_STATUS, VCONFKEY_FILEMANAGER_MMC_LOADING)) {
103                                 res = MS_MEDIA_ERR_VCONF_SET_FAIL;
104                                 MSC_DBG_ERR("msc_config_set_int failed");
105                         }
106                 }
107
108                 /* Update private vconf key for media server*/
109                 if (location == MS_SCANNING_INTERNAL) {
110                         if (!msc_config_set_int(MS_SCAN_STATUS_INTERNAL, P_VCONF_SCAN_DOING)) {
111                                 res = MS_MEDIA_ERR_VCONF_SET_FAIL;
112                                 MSC_DBG_ERR("msc_config_set_int failed");
113                         }
114                 } else if (location == MS_SCANNING_DIRECTORY) {
115                         if (!msc_config_set_int(MS_SCAN_STATUS_DIRECTORY, P_VCONF_SCAN_DOING)) {
116                                 res = MS_MEDIA_ERR_VCONF_SET_FAIL;
117                                 MSC_DBG_ERR("msc_config_set_int failed");
118                         }
119                 }
120         } else if (status == MS_DB_UPDATED) {
121                 if (location != MS_SCANNING_DIRECTORY) {
122                         if(!msc_config_set_int(VCONFKEY_FILEMANAGER_DB_STATUS,  VCONFKEY_FILEMANAGER_DB_UPDATED)) {
123                                 res = MS_MEDIA_ERR_VCONF_SET_FAIL;
124                                 MSC_DBG_ERR("msc_config_set_int failed");
125                         }
126                 }
127
128                 /* this is temporay code for tizen 2.0*/
129                 if(location == MS_SCANNING_EXTERNAL) {
130                         if (!msc_config_set_int(VCONFKEY_FILEMANAGER_MMC_STATUS, VCONFKEY_FILEMANAGER_MMC_LOADED)) {
131                                 res = MS_MEDIA_ERR_VCONF_SET_FAIL;
132                                 MSC_DBG_ERR("msc_config_set_int failed");
133                         }
134                 }
135
136                 /* Update private vconf key for media server*/
137                 if (location == MS_SCANNING_INTERNAL) {
138                         if (!msc_config_set_int(MS_SCAN_STATUS_INTERNAL, P_VCONF_SCAN_DONE)) {
139                                 res = MS_MEDIA_ERR_VCONF_SET_FAIL;
140                                 MSC_DBG_ERR("msc_config_set_int failed");
141                         }
142                 } else if (location == MS_SCANNING_DIRECTORY) {
143                         if (!msc_config_set_int(MS_SCAN_STATUS_DIRECTORY, P_VCONF_SCAN_DONE)) {
144                                 res = MS_MEDIA_ERR_VCONF_SET_FAIL;
145                                 MSC_DBG_ERR("msc_config_set_int failed");
146                         }
147                 }
148         }
149
150         err = _msc_set_power_mode(status);
151         if (err != MS_MEDIA_ERR_NONE) {
152                 MSC_DBG_ERR("_msc_set_power_mode fail");
153                 res = err;
154         }
155
156         return res;
157 }
158
159 static int _msc_scan_get_next_path_from_current_node(int find_folder,
160                                    ms_dir_scan_info **current_root,
161                                    ms_dir_scan_info **real_root, char **path, int *depth)
162 {
163         int err = MS_MEDIA_ERR_NONE;
164         char get_path[FAT_FILEPATH_LEN_MAX] = { 0 };
165
166         if (find_folder == 0) {
167                 if ((*current_root)->Rbrother != NULL) {
168                         *current_root = (*current_root)->Rbrother;
169                 } else {
170                         while (1) {
171                                 if ((*current_root)->parent == *real_root
172                                     || (*current_root)->parent == NULL) {
173                                         *current_root = NULL;
174                                         *depth = 0;
175                                         return MS_MEDIA_ERR_NONE;
176                                 } else if ((*current_root)->parent->Rbrother == NULL) {
177                                         *current_root = (*current_root)->parent;
178                                         (*depth) --;
179                                 } else {
180                                         *current_root = (*current_root)->parent->Rbrother;
181                                         (*depth) --;
182                                         break;
183                                 }
184                         }
185                 }
186                 (*depth) --;
187         }
188
189         err = msc_get_full_path_from_node(*current_root, get_path, *depth);
190         if (err != MS_MEDIA_ERR_NONE)
191                 return MS_MEDIA_ERR_INVALID_PATH;
192
193         *path = strdup(get_path);
194
195         return err;
196 }
197
198 static int _msc_scan_add_node(msc_scan_data **first_node, ms_dir_scan_info *const node, int depth)
199 {
200         int err;
201         char full_path[MS_FILE_PATH_LEN_MAX] = { 0 };
202         msc_scan_data *current_dir = NULL;
203         msc_scan_data *prv_node = NULL;
204         msc_scan_data *last_node = NULL;
205
206         err = msc_get_full_path_from_node(node, full_path, depth);
207         if (err != MS_MEDIA_ERR_NONE)
208                 return MS_MEDIA_ERR_INVALID_PATH;
209
210         last_node = *first_node;
211         while (last_node != NULL) {
212                 last_node = last_node->next;
213         }
214
215         /*find same folder */
216         if (*first_node != NULL) {
217                 last_node = *first_node;
218                 while (last_node != NULL) {
219                         if (strcmp(full_path, last_node->name) == 0) {
220                                 return MS_MEDIA_ERR_NONE;
221                         }
222                         prv_node = last_node;
223                         last_node = last_node->next;
224                 }
225         }
226
227         MS_MALLOC(current_dir, sizeof(msc_scan_data));
228         current_dir->name = strdup(full_path);
229         current_dir->next = NULL;
230
231         if (*first_node == NULL) {
232                 *first_node = current_dir;
233         } else {
234                 /*if next node of current node is NULL, it is the lastest node. */
235                 prv_node->next = current_dir;
236         }
237
238 //      MSC_DBG_INFO("scan path : %s %x %p", full_path, first_node, first_node);
239
240         return MS_MEDIA_ERR_NONE;
241 }
242
243 static bool _msc_check_scan_ignore(char * path)
244 {
245         DIR *dp = NULL;
246         struct dirent entry;
247         struct dirent *result;
248         char *ignore_path = ".scan_ignore";
249
250         dp = opendir(path);
251         if (dp == NULL) {
252                 MSC_DBG_ERR("%s folder opendir fails", path);
253                 return true;
254         }
255
256         while (!readdir_r(dp, &entry, &result)) {
257                 if (result == NULL)
258                         break;
259
260                 if (strcmp(entry.d_name, ignore_path) == 0) {
261                         closedir(dp);
262                         return true;
263                 }
264         }
265
266         closedir(dp);
267         return false;
268 }
269
270 static int _ms_check_stop_status(ms_storage_type_t storage_type)
271 {
272         int ret = MS_MEDIA_ERR_NONE;
273
274         /*check poweroff status*/
275         if (power_off) {
276                 MSC_DBG_INFO("Power off");
277                 ret = MS_MEDIA_ERR_SCANNER_FORCE_STOP;
278         }
279
280         /*check SD card in out */
281         if ((mmc_state != VCONFKEY_SYSMAN_MMC_MOUNTED) && (storage_type == MS_STORAGE_EXTERNAL)) {
282                 MSC_DBG_INFO("Directory scanning is stopped");
283                 ret = MS_MEDIA_ERR_SCANNER_FORCE_STOP;
284         }
285
286         return ret;
287 }
288
289 static void _msc_dir_check(msc_scan_data **first_node, const ms_comm_msg_s *scan_data)
290 {
291         int err = 0;
292         int depth = 0;
293         int find_folder = 0;
294         char get_path[MS_FILE_PATH_LEN_MAX] = { 0 };
295         char *path = NULL;
296         DIR *dp = NULL;
297         struct dirent entry;
298         struct dirent *result;
299         ms_storage_type_t storage_type;
300
301         ms_dir_scan_info *root = NULL;
302         ms_dir_scan_info *tmp_root = NULL;
303         ms_dir_scan_info *cur_node = NULL; /*current node*/
304         ms_dir_scan_info *prv_node = NULL; /*previous node*/
305         ms_dir_scan_info *next_node = NULL;
306
307         MS_MALLOC(root, sizeof(ms_dir_scan_info));
308         if (root == NULL) {
309                 MSC_DBG_ERR("malloc fail");
310                 return;
311         }
312
313         storage_type = msc_get_storage_type_by_full(scan_data->msg);
314
315         root->name = strndup(scan_data->msg, scan_data->msg_size);
316         if (root->name == NULL) {
317                 MSC_DBG_ERR("strdup fail");
318                 MS_SAFE_FREE(root);
319                 return;
320         }
321
322         root->parent = NULL;
323         root->Rbrother = NULL;
324         root->next = NULL;
325         tmp_root = root;
326         prv_node = root;
327
328         MS_MALLOC(path, sizeof(char) * MS_FILE_PATH_LEN_MAX);
329
330         err = msc_get_full_path_from_node(tmp_root, path, depth);
331         if (err != MS_MEDIA_ERR_NONE) {
332                 MS_SAFE_FREE(path);
333                 MS_SAFE_FREE(root);
334                 return;
335         }
336
337         _msc_scan_add_node(first_node, root, depth);
338
339         while (1) {
340                 /*check poweroff status*/
341                 err = _ms_check_stop_status(storage_type);
342                 if (err != MS_MEDIA_ERR_NONE) {
343                         goto FREE_RESOURCES;
344                 }
345
346                 depth ++;
347                 dp = opendir(path);
348                 if (dp == NULL) {
349                         MSC_DBG_ERR("%s folder opendir fails", path);
350                         goto NEXT_DIR;
351                 }
352
353                 while (!readdir_r(dp, &entry, &result)) {
354                         /*check poweroff status*/
355                         err = _ms_check_stop_status(storage_type);
356                         if (err != MS_MEDIA_ERR_NONE) {
357                                 goto FREE_RESOURCES;
358                         }
359
360                         if (result == NULL)
361                                 break;
362
363                         if (entry.d_name[0] == '.')
364                                 continue;
365
366                         if (entry.d_type & DT_DIR) {
367                                 err = msc_strappend(get_path, sizeof(get_path), "%s/%s",path, entry.d_name);
368                                 if (err != MS_MEDIA_ERR_NONE) {
369                                         MSC_DBG_ERR("msc_strappend error");
370                                         continue;
371                                 }
372
373                                 if (_msc_check_scan_ignore(get_path)) {
374                                         MSC_DBG_ERR("%s is ignore", get_path);
375                                         continue;
376                                 }
377
378                                 MS_MALLOC(cur_node, sizeof(ms_dir_scan_info));
379                                 if (cur_node == NULL) {
380                                         MSC_DBG_ERR("malloc fail");
381
382                                         goto FREE_RESOURCES;
383                                 }
384
385                                 cur_node->name = strdup(entry.d_name);
386                                 cur_node->Rbrother = NULL;
387                                 cur_node->next = NULL;
388
389                                 /*1. 1st folder */
390                                 if (find_folder == 0) {
391                                         cur_node->parent = tmp_root;
392                                         tmp_root = cur_node;
393                                 } else {
394                                         cur_node->parent = tmp_root->parent;
395                                         prv_node->Rbrother = cur_node;
396                                 }
397                                 prv_node->next = cur_node;
398
399                                 /*add watch */
400                                 _msc_scan_add_node(first_node, cur_node, depth);
401
402                                 /*change previous */
403                                 prv_node = cur_node;
404                                 find_folder++;
405                         }
406                 }
407 NEXT_DIR:
408                 MS_SAFE_FREE(path);
409                 if (dp) closedir(dp);
410                 dp = NULL;
411
412                 err = _msc_scan_get_next_path_from_current_node(find_folder, &tmp_root, &root, &path, &depth);
413                 if (err != MS_MEDIA_ERR_NONE)
414                         break;
415
416                 if (tmp_root == NULL)
417                         break;
418
419                 find_folder = 0;
420         }
421
422 FREE_RESOURCES:
423         /*free allocated memory */
424         MS_SAFE_FREE(path);
425         if (dp) closedir(dp);
426         dp = NULL;
427
428         cur_node = root;
429         while (cur_node != NULL) {
430                 next_node = cur_node->next;
431                 MS_SAFE_FREE(cur_node->name);
432                 MS_SAFE_FREE(cur_node);
433                 cur_node = next_node;
434         }
435 }
436
437 static int _msc_dir_scan(void **handle, msc_scan_data **first_node, const ms_comm_msg_s * scan_data)
438 {
439         DIR *dp = NULL;
440         int scan_type;
441         int ret = MS_MEDIA_ERR_NONE;
442         int err = 0;
443         char path[MS_FILE_PATH_LEN_MAX] = { 0 };
444         msc_scan_data *node;
445         ms_storage_type_t storage_type;
446
447         err = msc_strcopy(path, sizeof(path), "%s", scan_data->msg);
448         if (err != MS_MEDIA_ERR_NONE) {
449                 MSC_DBG_ERR("error : %d", err );
450                 return err;
451         }
452
453         storage_type = msc_get_storage_type_by_full(scan_data->msg);
454         scan_type = scan_data->msg_type;
455
456         /*if scan type is not MS_SCAN_NONE, check data in db. */
457         if (scan_type != MS_MSG_STORAGE_INVALID) {
458                 struct dirent entry;
459                 struct dirent *result = NULL;
460
461                 if (scan_data->msg_type != MS_MSG_DIRECTORY_SCANNING_NON_RECURSIVE) {
462                         _msc_dir_check(first_node, scan_data);
463                 } else {
464                         msc_scan_data *scan_node;
465
466                         MS_MALLOC(scan_node, sizeof(msc_scan_data));
467
468                         scan_node->name = strdup(scan_data->msg);
469                         scan_node->next = NULL;
470
471                         *first_node = scan_node;
472                 }
473
474                 node = *first_node;
475
476                 /*start db update. If node is null, db update is done.*/
477                 while (node != NULL) {
478                         /*check poweroff status*/
479                         ret = _ms_check_stop_status(storage_type);
480                         if (ret != MS_MEDIA_ERR_NONE) {
481                                 goto STOP_SCAN;
482                         }
483
484                         dp = opendir(node->name);
485                         if (dp != NULL) {
486                                 while (!readdir_r(dp, &entry, &result)) {
487                                         /*check poweroff status*/
488                                         ret = _ms_check_stop_status(storage_type);
489                                         if (ret != MS_MEDIA_ERR_NONE) {
490                                                 goto STOP_SCAN;
491                                         }
492
493                                         if (result == NULL)
494                                                 break;
495
496                                         if (entry.d_name[0] == '.')
497                                                 continue;
498
499                                         if (entry.d_type & DT_REG) {
500                                                 err = msc_strappend(path, sizeof(path), "%s/%s", node->name, entry.d_name);
501                                                 if (err < 0) {
502                                                         MSC_DBG_ERR("error : %d", err);
503                                                         continue;
504                                                 }
505
506                                                 if (scan_type == MS_MSG_STORAGE_ALL)
507                                                         err = msc_insert_item_batch(handle, path);
508                                                 else
509                                                         err = msc_validate_item(handle,path);
510                                                 if (err < 0) {
511                                                         MSC_DBG_ERR("failed to update db : %d , %d\n", err, scan_type);
512                                                         continue;
513                                                 }
514                                         }
515                                 }
516                         } else {
517                                 MSC_DBG_ERR("%s folder opendir fails", node->name);
518                         }
519                         if (dp) closedir(dp);
520                         dp = NULL;
521
522                         node = node->next;
523                 }               /*db update while */
524         } else if ( scan_type == MS_MSG_STORAGE_INVALID) {
525                 /*In this case, update just validation record*/
526                 /*update just valid type*/
527                 err = msc_invalidate_all_items(handle, storage_type);
528                 if (err != MS_MEDIA_ERR_NONE)
529                         MSC_DBG_ERR("error : %d", err);
530         }
531 STOP_SCAN:
532         if (dp) closedir(dp);
533
534         /*delete all node*/
535         node = *first_node;
536
537         while (node != NULL) {
538                 MS_SAFE_FREE(node->name);
539                 MS_SAFE_FREE(node);
540         }
541
542         *first_node = NULL;
543
544         sync();
545
546         MSC_DBG_INFO("ret : %d", ret);
547
548         return ret;
549 }
550
551
552 static void _msc_insert_array(GArray *garray, ms_comm_msg_s *insert_data)
553 {
554         ms_scan_data_t *data;
555         bool insert_ok = false;
556         int len = garray->len;
557         int i;
558
559         MSC_DBG_INFO("the length of array : %d", len);
560         MSC_DBG_INFO("path : %s", insert_data->msg);
561         MSC_DBG_INFO("scan_type : %d", insert_data->msg_type);
562
563         if (insert_data->pid == POWEROFF) {
564                 g_array_prepend_val(garray, insert_data);
565         } else {
566                 for (i=0; i < len; i++) {
567                         data = g_array_index(garray, ms_scan_data_t*, i);
568 /*
569                         if (data->pid != POWEROFF) {
570                                 if (data->storage_type == insert_data->storage_type) {
571                                         if(data->scan_type > insert_data->scan_type) {
572                                                 g_array_remove_index (garray, i);
573                                                 g_array_insert_val(garray, i, insert_data);
574                                                 insert_ok =  true;
575                                         }
576                                 }
577                         }
578 */
579                 }
580
581                 if (insert_ok == false)
582                         g_array_append_val(garray, insert_data);
583         }
584 }
585
586 void _msc_check_dir_path(char *dir_path)
587 {
588         int len = strlen(dir_path);
589
590         if (dir_path[len -1] == '/')
591                 dir_path[len -1] = '\0';
592 }
593
594 gboolean msc_directory_scan_thread(void *data)
595 {
596         ms_comm_msg_s *scan_data = NULL;
597         ms_comm_msg_s *insert_data = NULL;
598         GArray *garray = NULL;
599         int length;
600         int err;
601         int ret;
602         void **handle = NULL;
603         ms_storage_type_t storage_type;
604         int scan_type;
605         msc_scan_data *first_node = NULL;
606
607         /*create array for processing overlay data*/
608         garray = g_array_new (FALSE, FALSE, sizeof (ms_comm_msg_s *));
609         if (garray == NULL) {
610                 MSC_DBG_ERR("g_array_new error");
611                 return false;
612         }
613
614         while (1) {
615                 length  = g_async_queue_length(scan_queue);
616
617                 /*updating requests remain*/
618                 if (garray->len != 0 && length == 0) {
619                         scan_data = g_array_index(garray, ms_comm_msg_s*, 0);
620                         g_array_remove_index (garray, 0);
621                         if (scan_data->pid == POWEROFF) {
622                                 MSC_DBG_INFO("power off");
623                                 goto _POWEROFF;
624                         }
625                 } else if (length != 0) {
626                         insert_data = g_async_queue_pop(scan_queue);
627                         _msc_insert_array(garray, insert_data);
628                         continue;
629                 } else if (garray->len == 0 && length == 0) {
630                         /*Threre is no request, Wait until pushung new request*/
631                         insert_data = g_async_queue_pop(scan_queue);
632                         _msc_insert_array(garray, insert_data);
633                         continue;
634                 }
635
636                 MSC_DBG_INFO("DIRECTORY SCAN START");
637
638                 /*connect to media db, if conneting is failed, db updating is stopped*/
639                 err = msc_connect_db(&handle);
640                 if (err != MS_MEDIA_ERR_NONE)
641                         continue;
642
643                 storage_type = msc_get_storage_type_by_full(scan_data->msg);
644                 scan_type = scan_data->msg_type;
645
646                 if (scan_type != MS_MSG_DIRECTORY_SCANNING
647                         && scan_type != MS_MSG_DIRECTORY_SCANNING_NON_RECURSIVE) {
648                         MSC_DBG_ERR("Invalid request");
649                         ret = MS_MEDIA_ERR_INVALID_PARAMETER;
650                         goto NEXT;
651                 }
652
653                 /*start db updating */
654 //              _msc_set_db_status(MS_SCANNING_DIRECTORY, MS_DB_UPDATING);
655
656                 _msc_check_dir_path(scan_data->msg);
657
658                 /*change validity before scanning*/
659                 if (scan_type == MS_MSG_DIRECTORY_SCANNING)
660                         err = msc_set_folder_validity(handle, scan_data->msg, MS_INVALID, MS_RECURSIVE);
661                 else
662                         err = msc_set_folder_validity(handle, scan_data->msg, MS_INVALID, MS_NON_RECURSIVE);
663                 if (err != MS_MEDIA_ERR_NONE)
664                         MSC_DBG_ERR("error : %d", err);
665
666                 /*call for bundle commit*/
667                 msc_register_start(handle);
668                 msc_validate_start(handle);
669
670                 /*insert data into media db */
671                 ret = _msc_dir_scan(handle, &first_node, scan_data);
672
673                 /*call for bundle commit*/
674                 msc_register_end(handle);
675                 msc_validate_end(handle);
676
677                 if (ret == MS_MEDIA_ERR_NONE) {
678                         MSC_DBG_INFO("working normally");
679                         msc_delete_invalid_items_in_folder(handle, scan_data->msg);
680                 }
681
682                 /*set vconf key mmc loading for indicator */
683 //              _msc_set_db_status(MS_SCANNING_DIRECTORY, MS_DB_UPDATED);
684
685                 if (power_off) {
686                         MSC_DBG_INFO("power off");
687                         goto _POWEROFF;
688                 }
689
690                 /*disconnect form media db*/
691                 if (handle) msc_disconnect_db(&handle);
692 NEXT:
693                 /*Active flush */
694                 malloc_trim(0);
695
696                 msc_send_scan_result(ret, scan_data);
697
698 //              MS_SAFE_FREE(scan_data->msg);
699                 MS_SAFE_FREE(scan_data);
700
701                 MSC_DBG_INFO("DIRECTORY SCAN END");
702         }                       /*thread while*/
703
704 _POWEROFF:
705 //      MS_SAFE_FREE(scan_data->msg);
706         MS_SAFE_FREE(scan_data);
707         if (garray) g_array_free (garray, TRUE);
708         if (handle) msc_disconnect_db(&handle);
709
710         return false;
711 }
712
713 /* this thread process only the request of media-server */
714 gboolean msc_storage_scan_thread(void *data)
715 {
716         ms_comm_msg_s *scan_data = NULL;
717         ms_comm_msg_s *insert_data = NULL;
718         GArray *garray = NULL;
719         bool res;
720         int ret;
721         int length;
722         int err;
723         void **handle = NULL;
724         ms_storage_type_t storage_type;
725         int scan_type;
726         msc_scan_data *first_node = NULL;
727
728         /*create array for processing overlay data*/
729         garray = g_array_new (FALSE, FALSE, sizeof (ms_comm_msg_s *));
730         if (garray == NULL) {
731                 MSC_DBG_ERR("g_array_new error");
732                 return false;
733         }
734
735         while (1) {
736                 length  = g_async_queue_length(storage_queue);
737
738                 /*updating requests remain*/
739                 if (garray->len != 0 && length == 0) {
740                         scan_data = g_array_index(garray, ms_comm_msg_s*, 0);
741                         g_array_remove_index (garray, 0);
742                         if (scan_data->pid == POWEROFF) {
743                                 MSC_DBG_INFO("power off");
744                                 goto _POWEROFF;
745                         }
746                 } else if (length != 0) {
747                         insert_data = g_async_queue_pop(storage_queue);
748                         _msc_insert_array(garray, insert_data);
749                         continue;
750                 } else if (garray->len == 0 && length == 0) {
751                         /*Threre is no request, Wait until pushing new request*/
752                         insert_data = g_async_queue_pop(storage_queue);
753                         _msc_insert_array(garray, insert_data);
754                         continue;
755                 }
756
757                 MSC_DBG_INFO("STORAGE SCAN START");
758
759                 scan_type = scan_data->msg_type;
760                 if (scan_type != MS_MSG_STORAGE_ALL
761                         && scan_type != MS_MSG_STORAGE_PARTIAL
762                         && scan_type != MS_MSG_STORAGE_INVALID) {
763                         MSC_DBG_ERR("Invalid request");
764                         ret = MS_MEDIA_ERR_INVALID_PARAMETER;
765                         goto NEXT;
766                 }
767
768                 storage_type = msc_get_storage_type_by_full(scan_data->msg);
769                 MSC_DBG_INFO("%d", storage_type);
770
771                 /*connect to media db, if conneting is failed, db updating is stopped*/
772                 err = msc_connect_db(&handle);
773                 if (err != MS_MEDIA_ERR_NONE)
774                         continue;
775
776                 /*start db updating */
777                 if (storage_type == MS_STORAGE_INTERNAL)
778                         _msc_set_db_status(MS_SCANNING_INTERNAL, MS_DB_UPDATING);
779                 else if (storage_type == MS_STORAGE_EXTERNAL)
780                         _msc_set_db_status(MS_SCANNING_EXTERNAL, MS_DB_UPDATING);
781
782                 /*Delete all data before full scanning*/
783                 if (scan_type == MS_MSG_STORAGE_ALL) {
784                         res = msc_delete_all_items(handle, storage_type);
785                         if (res != true) {
786                                 MSC_DBG_ERR("msc_delete_all_record fails");
787                         }
788                 } else if (scan_type == MS_MSG_STORAGE_PARTIAL) {
789                         err = msc_invalidate_all_items(handle, storage_type);
790                         if (err != MS_MEDIA_ERR_NONE)
791                                 MSC_DBG_ERR("error : %d", err);
792                 }
793
794                 if (storage_type == MS_STORAGE_EXTERNAL && scan_type == MS_MSG_STORAGE_ALL) {
795                         msc_update_mmc_info();
796                 }
797
798 #ifdef FMS_PERF
799                 if (storage_type == MS_STORAGE_EXTERNAL) {
800                         msc_check_start_time(&g_mmc_start_time);
801                 }
802 #endif
803                 /*call for bundle commit*/
804                 msc_register_start(handle);
805                 if (scan_type == MS_MSG_STORAGE_PARTIAL) {
806                         /*enable bundle commit*/
807                         msc_validate_start(handle);
808                 }
809
810                 /*add inotify watch and insert data into media db */
811                 ret = _msc_dir_scan(handle, &first_node, scan_data);
812
813                 /*call for bundle commit*/
814                 msc_register_end(handle);
815                 if (scan_type == MS_MSG_STORAGE_PARTIAL) {
816                         /*disable bundle commit*/
817                         msc_validate_end(handle);
818                         if (ret == MS_MEDIA_ERR_NONE) {
819                                 MSC_DBG_INFO("working normally");
820                                 msc_delete_invalid_items(handle, storage_type);
821                         }
822                 }
823
824 #ifdef FMS_PERF
825                 if (storage_type == MS_STORAGE_EXTERNAL) {
826                         msc_check_end_time(&g_mmc_end_time);
827                         msc_check_time_diff(&g_mmc_start_time, &g_mmc_end_time);
828                 }
829 #endif
830
831                 /*set vconf key mmc loading for indicator */
832                 if (storage_type == MS_STORAGE_INTERNAL)
833                         _msc_set_db_status(MS_SCANNING_INTERNAL, MS_DB_UPDATED);
834                 else if (storage_type == MS_STORAGE_EXTERNAL)
835                         _msc_set_db_status(MS_SCANNING_EXTERNAL, MS_DB_UPDATED);
836
837                 if (power_off) {
838                         MSC_DBG_INFO("power off");
839                         goto _POWEROFF;
840                 }
841
842                 /*disconnect form media db*/
843                 if (handle) msc_disconnect_db(&handle);
844
845 NEXT:
846                 /*Active flush */
847                 malloc_trim(0);
848
849                 msc_send_scan_result(ret, scan_data);
850
851 //              MS_SAFE_FREE(scan_data->msg);
852                 MS_SAFE_FREE(scan_data);
853
854                 MSC_DBG_INFO("STORAGE SCAN END");
855         }                       /*thread while*/
856
857 _POWEROFF:
858 //      MS_SAFE_FREE(scan_data->msg);
859         MS_SAFE_FREE(scan_data);
860         if (garray) g_array_free (garray, TRUE);
861         if (handle) msc_disconnect_db(&handle);
862
863         return false;
864 }
865
866 static void _msc_insert_register_request(GArray *register_array, ms_comm_msg_s *insert_data)
867 {
868         MSC_DBG_INFO("path : %s", insert_data->msg);
869
870         if (insert_data->pid == POWEROFF) {
871                 g_array_prepend_val(register_array, insert_data);
872         } else {
873                 g_array_append_val(register_array, insert_data);
874         }
875 }
876
877 static bool _is_valid_path(const char *path)
878 {
879         if (path == NULL)
880                 return false;
881
882         if (strncmp(path, MEDIA_ROOT_PATH_INTERNAL, strlen(MEDIA_ROOT_PATH_INTERNAL)) == 0) {
883                 return true;
884         } else if (strncmp(path, MEDIA_ROOT_PATH_SDCARD, strlen(MEDIA_ROOT_PATH_SDCARD)) == 0) {
885                 return true;
886         } else
887                 return false;
888
889         return true;
890 }
891
892 static int _check_file_path(const char *file_path)
893 {
894         int exist;
895         struct stat file_st;
896
897         /* check location of file */
898         /* file must exists under "/opt/usr/media" or "/opt/storage/sdcard" */
899         if(!_is_valid_path(file_path)) {
900                 MSC_DBG_ERR("Invalid path : %s", file_path);
901                 return MS_MEDIA_ERR_INVALID_PATH;
902         }
903
904         /* check the file exits actually */
905         exist = open(file_path, O_RDONLY);
906         if(exist < 0) {
907                 MSC_DBG_ERR("Not exist path : %s", file_path);
908                 return MS_MEDIA_ERR_INVALID_PATH;
909         }
910         close(exist);
911
912         /* check type of the path */
913         /* It must be a regular file */
914         memset(&file_st, 0, sizeof(struct stat));
915         if(stat(file_path, &file_st) == 0) {
916                 if(!S_ISREG(file_st.st_mode)) {
917                         /* In this case, it is not a regula file */
918                         MSC_DBG_ERR("this path is not a file");
919                         return MS_MEDIA_ERR_INVALID_PATH;
920                 }
921         } else {
922                 MSC_DBG_ERR("stat failed [%s]", strerror(errno));
923                 return MS_MEDIA_ERR_INVALID_PATH;
924         }
925
926         return MS_MEDIA_ERR_NONE;
927 }
928
929 gboolean msc_register_thread(void *data)
930 {
931         ms_comm_msg_s *register_data = NULL;
932         ms_comm_msg_s *insert_data = NULL;
933         GArray *register_array = NULL;
934         GArray *path_array = NULL;
935         FILE *fp = NULL;
936         char buf[MS_FILE_PATH_LEN_MAX];
937         char *insert_path = NULL;
938         char *path = NULL;
939         char *file_path = NULL;
940         int path_size;
941         int length;
942         int err;
943         int i;
944         int ret;
945         void **handle = NULL;
946
947         /*create array for processing overlay data*/
948         register_array = g_array_new (FALSE, FALSE, sizeof (ms_comm_msg_s *));
949         if (register_array == NULL) {
950                 MSC_DBG_ERR("g_array_new error");
951                 return false;
952         }
953
954         while (1) {
955                 length  = g_async_queue_length(reg_queue);
956
957                 /*updating requests remain*/
958                 if (register_array->len != 0 && length == 0) {
959                         register_data = g_array_index(register_array, ms_comm_msg_s*, 0);
960                         g_array_remove_index (register_array, 0);
961                         if (register_data->pid == POWEROFF) {
962                                 MSC_DBG_INFO("power off");
963                                 goto _POWEROFF;
964                         }
965                 } else if (length != 0) {
966                         insert_data = g_async_queue_pop(reg_queue);
967                         _msc_insert_register_request(register_array, insert_data);
968                         continue;
969                 } else if (register_array->len == 0 && length == 0) {
970                         /*Threre is no request, Wait until pushung new request*/
971                         insert_data = g_async_queue_pop(reg_queue);
972                         _msc_insert_register_request(register_array, insert_data);
973                         continue;
974                 }
975
976                 if((register_data->msg_size <= 0) ||(register_data->msg_size > MS_FILE_PATH_LEN_MAX)) {
977                         MSC_DBG_ERR("message size[%d] is wrong", register_data->msg_size);
978                         goto FREE_RESOURCE;
979                 } else {
980                         path_size = register_data->msg_size + 1;
981                 }
982
983                 /* copy from received data */
984                 MS_MALLOC(file_path, path_size);
985                 if (file_path == NULL) {
986                         MSC_DBG_ERR("MS_MALLOC failed");
987                         goto FREE_RESOURCE;
988                 }
989
990                 ret = msc_strcopy(file_path, path_size, "%s", register_data->msg);
991                 if (ret != MS_MEDIA_ERR_NONE){
992                         MSC_DBG_ERR("msc_strcopy failed : %d", ret);
993                         goto FREE_RESOURCE;
994                 }
995
996                 /* load the file list from file */
997                 fp = fopen(register_data->msg, "rt");
998                 if (fp == NULL) {
999                         MSC_DBG_ERR("fopen failed [%s]", strerror(errno));
1000                         goto FREE_RESOURCE;
1001                 }
1002
1003                 memset(buf, 0x0, MS_FILE_PATH_LEN_MAX);
1004                 /* This is an array for storing the path of insert datas*/
1005                 path_array = g_array_new (FALSE, FALSE, sizeof (char *));
1006                 if (path_array == NULL) {
1007                         MSC_DBG_ERR("g_array_new failed");
1008                         goto FREE_RESOURCE;
1009                 }
1010
1011                 /* read registering file path from stored file */
1012                 while(fgets(buf, MS_FILE_PATH_LEN_MAX, fp) != NULL) {
1013                         length = strlen(buf);
1014                         buf[length - 1] = '\0';
1015                         path = strdup(buf);
1016                         MSC_DBG_INFO("insert path : %s [%d]", path, strlen(path));
1017                         /* insert getted path to the list */
1018                         if (g_array_append_val(path_array, path)  == NULL) {
1019                                 MSC_DBG_ERR("g_array_append_val failed");
1020                                 goto FREE_RESOURCE;
1021                         }
1022                 }
1023
1024                 /* connect to media db, if conneting is failed, db updating is stopped */
1025                 err = msc_connect_db(&handle);
1026                 if (err != MS_MEDIA_ERR_NONE)
1027                         goto FREE_RESOURCE;
1028
1029                 /*start db updating */
1030                 /*call for bundle commit*/
1031                 msc_register_start(handle);
1032
1033                 /* get the inserting file path from array  and insert to db */
1034                 for (i = 0; i < path_array->len; i++) {
1035
1036                         insert_path =  g_array_index(path_array, char*, i);
1037                         /* check the file */
1038                         /* it is really existing */
1039                         /* it is in /opt/usr/media or /opt/storage/sdcard */
1040                         /* it is really regular file */
1041                         ret = _check_file_path(insert_path);
1042                         if (ret != MS_MEDIA_ERR_NONE) {
1043                                 MSC_DBG_ERR("Can't insert the meta of the path");
1044                                 continue;
1045                         }
1046
1047                         /* insert to db */
1048                         err = msc_insert_item_batch(handle, insert_path);
1049
1050                         if (power_off) {
1051                                 MSC_DBG_INFO("power off");
1052                                 /*call for bundle commit*/
1053                                 msc_register_end(handle);
1054                                 goto _POWEROFF;
1055                         }
1056                 }
1057
1058                 /*call for bundle commit*/
1059                 msc_register_end(handle);
1060
1061                 /*disconnect form media db*/
1062                 if (handle) msc_disconnect_db(&handle);
1063
1064                 /*Active flush */
1065                 malloc_trim(0);
1066
1067                 msc_send_register_result(MS_MEDIA_ERR_NONE, register_data);
1068 FREE_RESOURCE:
1069                 if (path_array) {
1070                         g_array_free(path_array, TRUE);
1071                         path_array = NULL;
1072                 }
1073
1074                 MS_SAFE_FREE(file_path);
1075                 MS_SAFE_FREE(register_data);
1076
1077                 if(fp) fclose(fp);
1078                 fp = NULL;
1079         }                       /*thread while*/
1080
1081 _POWEROFF:
1082         MS_SAFE_FREE(file_path);
1083         MS_SAFE_FREE(register_data);
1084         if (register_array) g_array_free (register_array, TRUE);
1085         if (path_array) g_array_free (path_array, TRUE);
1086         if (handle) msc_disconnect_db(&handle);
1087
1088         if(fp) fclose(fp);
1089
1090         return false;
1091 }