free current_path when stop scan
[platform/core/multimedia/media-server.git] / src / scanner-v2 / media-scanner-scan-v2.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 #include <dirent.h>     /* Defines DT_* constants */
23 #include <fcntl.h>
24 #include <stdio.h>
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <sys/stat.h>
28 #include <sys/syscall.h>
29
30 #include <dirent.h>
31 #include <malloc.h>
32 #include <vconf.h>
33 #include <usb-device.h>
34
35 #include "media-util.h"
36 #include "media-server-ipc.h"
37 #include "media-common-utils.h"
38 #include "media-common-external-storage.h"
39 #include "media-common-db-svc.h"
40 #include "media-scanner-dbg-v2.h"
41 #include "media-scanner-common-v2.h"
42 #include "media-scanner-socket-v2.h"
43 #include "media-scanner-scan-v2.h"
44 #include "media-scanner-extract-v2.h"
45 #include "media-scanner-db-manage-v2.h"
46
47 #define MAX_SCAN_COUNT 300
48
49 #define DIR_SCAN_NON_SCAN               0
50 #define DIR_SCAN_RECURSIVE              1
51 #define DIR_SCAN_NON_RECURSIVE 2
52
53 extern bool power_off2;
54 GAsyncQueue *storage_queue2;
55 GAsyncQueue *scan_queue2;
56 GAsyncQueue *reg_queue2;
57 GMutex scan_req_mutex2;
58 static GMutex blocked_mutex2;
59 static GMutex storage_scan_mutex2;
60 static GMutex dir_scan_mutex2;
61 static GCond data_cond2;        /* Must be initialized somewhere */
62 static GMutex data_mutex2;      /* Must be initialized somewhere */
63 static GMutex scan_item_mutex;
64
65 static char *g_blocked_path2;
66
67 static s_scan_item* cancel_scan_item = NULL;
68 static s_scan_item* cur_scan_item = NULL;
69
70 int g_directory_scan_processing2 = DIR_SCAN_NON_SCAN;
71 static char *g_storage_scan_path;
72 static char* g_dir_scan_path;
73 static unsigned int io_err_folder;
74 static unsigned int io_err_storage;
75
76 typedef int (*DIR_SCAN_CB)();
77 static DIR_SCAN_CB g_dir_scan_cb;
78
79 struct linux_dirent {
80         ino64_t                 d_ino;   /* 64-bit inode number */
81         off64_t                 d_off;   /* 64-bit offset to next structure */
82         unsigned short  d_reclen; /* Size of this dirent */
83         unsigned char   d_type;  /* File type */
84         char                            d_name[]; /* Filename (null-terminated) */
85 };
86
87 #define BUF_SIZE 1024
88
89 static int __msc_check_stop_status(int scan_type, const char *start_path, int pid);
90 static int __msc_db_update(sqlite3 *handle, const char *storage_id, const ms_comm_msg_s * scan_data);
91 static int __msc_make_file_list(char *file_path, GArray **path_array, uid_t uid);
92 static int __msc_batch_insert(int pid, GArray *path_array, uid_t uid);
93 static int __msc_pop_register_request(GArray *register_array, ms_comm_msg_s **register_data);
94 static void __msc_clear_file_list(GArray *path_array);
95 static void __msc_insert_register_request(GArray *register_array, ms_comm_msg_s *insert_data);
96 static int __msc_dir_scan_for_folder(sqlite3 *handle, const char *storage_id, const char*start_path, ms_user_storage_type_e storage_type, int scan_type, int pid, uid_t uid);
97 static int __msc_dir_scan_for_storage(sqlite3 *handle, const char *storage_id, const char*start_path, ms_user_storage_type_e storage_type, int scan_type, int pid, uid_t uid);
98 static int __msc_get_null_scan_folder_list(sqlite3 *handle, const char *stroage_id, char *path, GArray *dir_array);
99 static int __msc_dir_scan_cb(void);
100 static int __msc_check_scan_same_path(char *scan_path);
101 static void __msc_set_storage_scan_cur_path(char *scan_path);
102 static void __msc_set_dir_scan_cur_path(char *scan_path);
103 static int __msc_dir_and_storage_scan_same_path(char *start_path);
104 static int __msc_check_memory_status(uid_t uid);
105 static int __msc_check_remain_space(uid_t uid);
106 static void __msc_del_cancel_scan_item(void);
107 static void msc_set_cur_scan_item(const char* cur_scan_path, int pid);
108 static void __msc_del_cur_scan_item(void);
109 static void __msc_del_blocked_path(void);
110
111 static int __msc_set_dir_scan_cb(DIR_SCAN_CB cb)
112 {
113         g_dir_scan_cb = cb;
114
115         return MS_MEDIA_ERR_NONE;
116 }
117
118 static int __msc_call_dir_scan_cb(void)
119 {
120         if (g_dir_scan_cb != NULL) {
121                 g_dir_scan_cb();
122
123                 return MS_MEDIA_ERR_NONE;
124         }
125
126         return MS_MEDIA_ERR_INTERNAL;
127 }
128
129 static int __msc_remove_dir_scan_cb(void)
130 {
131         g_dir_scan_cb = NULL;
132
133         return MS_MEDIA_ERR_NONE;
134 }
135
136 void msc_init_scan_thread(void)
137 {
138         g_mutex_init(&data_mutex2);
139         g_mutex_init(&blocked_mutex2);
140         g_mutex_init(&scan_req_mutex2);
141         g_mutex_init(&storage_scan_mutex2);
142         g_mutex_init(&dir_scan_mutex2);
143         g_mutex_init(&scan_item_mutex);
144
145         g_cond_init(&data_cond2);
146 }
147
148 void msc_deinit_scan_thread(void)
149 {
150         g_mutex_clear(&data_mutex2);
151         g_mutex_clear(&blocked_mutex2);
152         g_mutex_clear(&scan_req_mutex2);
153         g_mutex_clear(&storage_scan_mutex2);
154         g_mutex_clear(&dir_scan_mutex2);
155         g_mutex_clear(&scan_item_mutex);
156
157         g_cond_clear(&data_cond2);
158 }
159
160 static int __msc_resume_scan(void)
161 {
162         g_mutex_lock(&data_mutex2);
163
164         g_cond_signal(&data_cond2);
165
166         g_mutex_unlock(&data_mutex2);
167
168         return MS_MEDIA_ERR_NONE;
169 }
170
171 static void __msc_pause_scan(void)
172 {
173         g_mutex_lock(&data_mutex2);
174
175         g_cond_wait(&data_cond2, &data_mutex2);
176
177         g_mutex_unlock(&data_mutex2);
178 }
179
180 static int __msc_check_stop_status(int scan_type, const char *start_path, int pid)
181 {
182         int ret = MS_MEDIA_ERR_NONE;
183
184         /*check poweroff status*/
185         if (power_off2) {
186                 MS_DBG_ERR("Power off");
187                 ret = MS_MEDIA_ERR_SCANNER_FORCE_STOP;
188                 goto END;
189         }
190
191         if (strncmp(start_path, MEDIA_ROOT_PATH_DISC, strlen(MEDIA_ROOT_PATH_DISC)) == 0) {
192                 int disc_state = 0;
193                 ms_config_get_int(MS_DISC_STATE, &disc_state);
194                 if (disc_state == 0) {
195                         MS_DBG_ERR("[DISC IS NOT INSERTED]");
196                         ret = MS_MEDIA_ERR_SCANNER_FORCE_STOP;
197                         goto END;
198                 }
199         }
200         if (scan_type == MS_MSG_DIRECTORY_SCANNING || scan_type == MS_MSG_DIRECTORY_SCANNING_NON_RECURSIVE) {
201                 g_mutex_lock(&scan_req_mutex2);
202                 /* check cancel path */
203                 //MS_DBG_ERR("__msc_check_stop_status...");
204                 if ((cancel_scan_item != NULL) && (cancel_scan_item->path != NULL)) {
205                         MS_DBG_SWARN("check blocked storage [%s][%s]", cancel_scan_item->path, start_path);
206                         if ((strncmp(cancel_scan_item->path, start_path, strlen(cancel_scan_item->path)) == 0)
207                                 && (cancel_scan_item->pid == -1 || cancel_scan_item->pid == pid)) {
208                                 MS_DBG_SWARN("Receive cancel request [%s][%s]. STOP scan!!", cancel_scan_item->path, start_path);
209                                 unsigned int path_len = strlen(cancel_scan_item->path);
210
211                                 if (strlen(start_path) > path_len) {
212                                         if (start_path[path_len] == '/') {
213                                                 MS_DBG_ERR("start path is same as cancel path");
214                                                 ret = MS_MEDIA_ERR_SCANNER_FORCE_STOP;
215                                         } else {
216                                                 MS_DBG_ERR("start path is not same as cancel path");
217                                         }
218                                 } else {
219                                         ret = MS_MEDIA_ERR_SCANNER_FORCE_STOP;
220                                 }
221                         }
222                 }
223
224                 g_mutex_unlock(&scan_req_mutex2);
225         }
226
227         if (scan_type == MS_MSG_STORAGE_ALL || scan_type == MS_MSG_STORAGE_PARTIAL) {
228                 g_mutex_lock(&blocked_mutex2);
229                 /* check cancel path */
230                 if (g_blocked_path2 != NULL) {
231                         MS_DBG_SWARN("check blocked storage [%s][%s]", g_blocked_path2, start_path);
232                         if (strncmp(start_path, g_blocked_path2, strlen(start_path)) == 0) {
233                                 MS_DBG_ERR("Receive blocked message[%s][%s]. STOP scan!!",
234                                 g_blocked_path2, start_path);
235                                 ret = MS_MEDIA_ERR_SCANNER_FORCE_STOP;
236                         }
237
238                         MS_SAFE_FREE(g_blocked_path2);
239                 }
240
241                 g_mutex_unlock(&blocked_mutex2);
242         }
243 END:
244         return ret;
245 }
246
247 static int __msc_dir_scan_for_folder(sqlite3 *handle, const char *storage_id, const char*start_path, ms_user_storage_type_e storage_type, int scan_type, int pid, uid_t uid)
248 {
249         GArray *dir_array = NULL;
250         int ret = MS_MEDIA_ERR_NONE;
251         char *new_path = NULL;
252         char *current_path = NULL;
253         char path[MS_FILE_PATH_LEN_MAX] = {0, };
254         bool is_recursive = true;
255         char *new_start_path = NULL;
256
257         int fd = -1;
258         int nread = 0;
259         char buf[BUF_SIZE] = {0,};
260         struct linux_dirent *d;
261         int bpos = 0;
262         int scan_count = 0;
263         int sleep_count = 0;
264
265         const char *trash = "$RECYCLE.BIN";
266
267
268         MS_DBG_SWARN("storage id [%s] start path [%s]", storage_id, start_path);
269
270         /* make new array for storing directory */
271         dir_array = g_array_new(FALSE, FALSE, sizeof(char*));
272
273         /* add first direcotiry to directory array */
274         new_start_path = g_strdup(start_path);
275
276         //MS_DBG_ERR("new start path [%s]", new_start_path);
277         g_array_append_val(dir_array, start_path);
278         ms_insert_folder_end(uid);
279
280         is_recursive = (scan_type == MS_MSG_DIRECTORY_SCANNING_NON_RECURSIVE) ? false : true;
281
282         /* fix timing issue, folder uuid of start path mismatch in folder and media table*/
283         /*if (ms_set_folder_validity(handle, storage_id, new_start_path, MS_INVALID, is_recursive, uid) != MS_MEDIA_ERR_NONE)
284                 MS_DBG_ERR("set_folder_validity failed [%d] ", scan_type);*/
285
286         if (g_file_test(new_start_path, G_FILE_TEST_IS_DIR)) {
287                 if (ms_insert_folder(handle, storage_id, new_start_path, uid) != MS_MEDIA_ERR_NONE)
288                         MS_DBG_ERR("insert folder failed");
289
290                 MS_DBG_SWARN("ms_insert_folder insert path[%s]", new_start_path);
291         } else {
292                 if (ms_set_folder_validity(handle, storage_id, new_start_path, MS_INVALID, is_recursive, uid) != MS_MEDIA_ERR_NONE)
293                         MS_DBG_ERR("set_folder_validity failed [%d] ", scan_type);
294         }
295
296         /*start db update. the number of element in the array , db update is complete.*/
297         while (dir_array->len != 0) {
298                 /*check poweroff status*/
299                 ret = __msc_check_stop_status(scan_type, new_start_path, pid);
300                 if (ret != MS_MEDIA_ERR_NONE) {
301                         if (is_recursive == true)
302                                 ms_change_validity_item_batch(handle, storage_id, new_start_path, 1, 2, uid);
303
304                         goto STOP_SCAN;
305                 }
306
307                 ms_batch_commit_disable(true, true, uid);
308                 ms_batch_commit_enable(true, true, false, pid);
309                 /* get the current path from directory array */
310                 current_path = g_array_index(dir_array , char*, 0);
311                 g_array_remove_index(dir_array, 0);
312
313                 __msc_set_dir_scan_cur_path(current_path);
314
315                 if (strncmp(current_path, MEDIA_ROOT_PATH_DISC, strlen(MEDIA_ROOT_PATH_DISC)) != 0) {
316                         ret = ms_check_scan_ignore(current_path, uid);
317                         if (ret != MS_MEDIA_ERR_NONE) {
318                                 MS_DBG_SERR("%s is ignore", current_path);
319                                 MS_SAFE_FREE(current_path);
320                                 if (ret == MS_MEDIA_ERR_USB_UNMOUNTED)
321                                         goto STOP_SCAN;
322                                 else
323                                         ret = MS_MEDIA_ERR_NONE;
324
325                                 continue;
326                         }
327                 } else {
328                         MS_DBG_ERR("[DATA DISC] PASS IGNORE");
329                 }
330
331                 ret = msc_check_db_size(uid, scan_type);
332                 if (ret != MS_MEDIA_ERR_NONE) {
333                         if (ret == MS_MEDIA_ERR_DB_FULL_FAIL)
334                                 ret = MS_MEDIA_ERR_NONE;
335
336                         if (is_recursive == true)
337                                 ms_change_validity_item_batch(handle, storage_id, new_start_path, 1, 2, uid);
338
339                         goto STOP_SCAN;
340                 }
341
342                 ms_insert_folder_start();
343                 ms_set_folder_scan_status(handle, storage_id, current_path, MS_DIR_SCAN_PROCESSING, uid);
344                 sleep_count = 0;
345
346                 fd = open(current_path, O_RDONLY | O_DIRECTORY);
347                 if (fd == -1) {
348                         MS_DBG_STRERROR("open fails");
349                         ms_set_folder_scan_status(handle, storage_id, current_path, MS_DIR_SCAN_STOP, uid);
350                         continue;
351                 }
352
353                 for ( ; ; ) {
354                         if (strncmp(current_path, MEDIA_ROOT_PATH_DISC, strlen(MEDIA_ROOT_PATH_DISC)) == 0) {
355                                 int disc_state = 0;
356                                 ms_config_get_int(MS_DISC_STATE, &disc_state);
357                                 if (disc_state == 0) {
358                                         MS_DBG_ERR("[DISC IS NOT INSERTED]");
359                                         ret = MS_MEDIA_ERR_SCANNER_FORCE_STOP;
360                                         break;
361                                 }
362                         }
363                         nread = syscall(SYS_getdents64, fd, buf, BUF_SIZE);
364                         if (nread == -1) {
365                                 MS_DBG_STRERROR("getdents");
366                                 break;
367                         }
368
369                         /*check poweroff status*/
370                         ret = __msc_check_stop_status(scan_type, new_start_path, pid);
371                         if (ret != MS_MEDIA_ERR_NONE) {
372                                 if (is_recursive == true)
373                                         ms_change_validity_item_batch(handle, storage_id, new_start_path, 1, 2, uid);
374
375                                 goto STOP_SCAN;
376                         }
377
378                         ret = msc_check_db_size(uid, scan_type);
379                         if (ret != MS_MEDIA_ERR_NONE) {
380                                 //ms_set_folder_scan_status(handle, storage_id, current_path, MS_DIR_SCAN_STOP, ui);
381                                 if (ret == MS_MEDIA_ERR_DB_FULL_FAIL)
382                                         ret = MS_MEDIA_ERR_NONE;
383
384                                 goto STOP_SCAN;
385                         }
386 #if 0
387                         if (io_err_folder == MS_MAX_IO_ERR_COUNT) {
388                                 MS_DBG_ERR("REACH I/O MAX COUNT[%d]", io_err_folder);
389                                 if (is_recursive == true)
390                                         ms_change_validity_item_batch(handle, storage_id, new_start_path, 1, 2, uid);
391
392                                 goto STOP_SCAN;
393                         }
394 #endif
395                         if (nread == 0)
396                                 break;
397
398                         for (bpos = 0; bpos < nread;) {
399                                 sleep_count++;
400                                 if (sleep_count % 5 == 0) {
401                                         sleep_count = 0;
402                                         usleep(SCAN_SLEEP_TIME);
403                                 }
404                                 /*check poweroff status*/
405                                 ret = __msc_check_stop_status(scan_type, new_start_path, pid);
406                                 if (ret != MS_MEDIA_ERR_NONE) {
407                                         if (is_recursive == true)
408                                                 ms_change_validity_item_batch(handle, storage_id, new_start_path, 1, 2, uid);
409
410                                         goto STOP_SCAN;
411                                 }
412
413                                 ret = msc_check_db_size(uid, scan_type);
414                                 if (ret != MS_MEDIA_ERR_NONE) {
415                                         if (ret == MS_MEDIA_ERR_DB_FULL_FAIL)
416                                                 ret = MS_MEDIA_ERR_NONE;
417
418                                         if (is_recursive == true)
419                                                 ms_change_validity_item_batch(handle, storage_id, new_start_path, 1, 2, uid);
420
421                                         //ms_set_folder_scan_status(handle, storage_id, current_path, MS_DIR_SCAN_STOP, uid);
422                                         goto STOP_SCAN;
423                                 }
424 #if 0
425                                 if (io_err_folder == MS_MAX_IO_ERR_COUNT) {
426                                         MS_DBG_ERR("REACH I/O MAX COUNT[%d]", io_err_folder);
427                                         if (is_recursive == true)
428                                                 ms_change_validity_item_batch(handle, storage_id, new_start_path, 1, 2, uid);
429
430                                         goto STOP_SCAN;
431                                 }
432 #endif
433                                 d = (struct linux_dirent *) (buf + bpos);
434
435                                 if (d->d_name[0] == '.') {
436                                         bpos += d->d_reclen;
437                                         continue;
438                                 }
439
440                                 if (strcmp(d->d_name, trash) == 0) {
441                                         MS_DBG_ERR("trash directory");
442                                         bpos += d->d_reclen;
443                                         continue;
444                                 }
445
446                                 if (ms_strappend(path, sizeof(path), "%s/%s", current_path, d->d_name) != MS_MEDIA_ERR_NONE) {
447                                         MS_DBG_ERR("ms_strappend failed");
448                                         bpos += d->d_reclen;
449                                         continue;
450                                 }
451
452                                 if (d->d_type == DT_UNKNOWN) {
453                                         struct stat st;
454                                         if (stat(path, &st) == 0) {
455                                                 if (S_ISREG(st.st_mode))
456                                                         d->d_type = DT_REG;
457                                                 else if (S_ISDIR(st.st_mode))
458                                                         d->d_type = DT_DIR;
459                                         }
460                                 }
461
462                                 if (d->d_type == DT_REG) {
463                                         if (!ms_check_support_media_type(path)) {
464                                                 bpos += d->d_reclen;
465                                                 continue;
466                                         }
467
468                                         /* insert into media DB */
469                                         ret = ms_scan_validate_item(handle, storage_id, path, uid);
470                                         if (ret != MS_MEDIA_ERR_NONE) {
471                                                 MS_DBG_ERR("failed to update db : %d", ret);
472                                                 if (ret == MS_MEDIA_ERR_INTERNAL)
473                                                         MS_DBG_ERR("I/O ERROR COUNT[%d]", io_err_folder++);
474
475                                                 bpos += d->d_reclen;
476                                                 continue;
477                                         } else {
478                                                 ++scan_count;
479                                                 //MS_DBG_ERR("insert count %d", nScanCount);
480                                                 if (scan_count >= MAX_SCAN_COUNT) {
481                                                         scan_count = 0;
482                                                         //MS_DBG_ERR("storage_id = [%s]", storage_id);
483                                                         ret = __msc_check_stop_status(scan_type, new_start_path, pid);
484                                                         if (ret == MS_MEDIA_ERR_NONE) {
485                                                                 msc_insert_exactor_request(scan_type, false, storage_id, current_path, pid, uid, MS_ITEM_UPDATE);
486                                                         } else {
487                                                                 if (is_recursive == true)
488                                                                         ms_change_validity_item_batch(handle, storage_id, new_start_path, 1, 2, uid);
489                                                                 goto STOP_SCAN;
490                                                         }
491                                                 }
492                                         }
493                                 } else if (d->d_type == DT_DIR) {
494                                         if (scan_type != MS_MSG_DIRECTORY_SCANNING_NON_RECURSIVE) {
495                                                 /* this request is recursive scanning */
496                                                 /* add new directory to dir_array */
497                                                 new_path = g_strdup(path);
498                                                 g_array_append_val(dir_array, new_path);
499
500                                                 if (ms_insert_folder(handle, storage_id, new_path, uid) != MS_MEDIA_ERR_NONE)
501                                                         MS_DBG_ERR("insert folder failed");
502
503                                         } else {
504                                                 /* this request is non-recursive scanning */
505                                                 /* don't add new directory to dir_array */
506                                                 if (ms_insert_folder(handle, storage_id, path, uid) != MS_MEDIA_ERR_NONE) {
507                                                         MS_DBG_ERR("insert folder failed");
508                                                         bpos += d->d_reclen;
509                                                         continue;
510                                                 }
511                                         }
512                                 }
513
514                                 bpos += d->d_reclen;
515                         }
516                         /*update modifiec type for the internal storage*/
517                         if (scan_type == MS_MSG_DIRECTORY_SCANNING_NON_RECURSIVE) {
518                                 if (storage_type == MS_USER_STORAGE_INTERNAL)
519                                         ms_update_folder_time(handle, INTERNAL_STORAGE_ID, current_path, uid);
520                                 else
521                                         ms_update_folder_time(handle, storage_id, current_path, uid);
522                         }
523                 }
524
525                 ms_insert_folder_end(uid);
526                 ms_set_folder_scan_status(handle, storage_id, current_path, MS_DIR_SCAN_DONE, uid);
527
528                 if (fd != -1) {
529                         close(fd);
530                         fd = -1;
531                 }
532
533                 MS_SAFE_FREE(current_path);
534                 __msc_set_dir_scan_cur_path(NULL);
535                 usleep(SCAN_SLEEP_TIME);
536         }
537
538         goto END_SCAN;
539
540 STOP_SCAN:
541         MS_DBG_ERR("stop folder scan...");
542         ms_insert_folder_end(uid);
543         ms_set_folder_scan_status(handle, storage_id, current_path, MS_DIR_SCAN_STOP, uid);
544         MS_SAFE_FREE(current_path);
545
546 END_SCAN:
547         if (fd != -1) {
548                 close(fd);
549                 fd = -1;
550         }
551
552         g_free(new_start_path);
553         __msc_set_dir_scan_cur_path(NULL);
554
555         __msc_clear_file_list(dir_array);
556
557         ms_batch_commit_disable(true, true, uid);
558
559         if (ret != MS_MEDIA_ERR_NONE) MS_DBG_INFO("ret : %d", ret);
560
561         return ret;
562 }
563
564 static int __msc_dir_scan_for_storage(sqlite3 *handle, const char *storage_id, const char*start_path, ms_user_storage_type_e storage_type, int scan_type, int pid, uid_t uid)
565 {
566         GArray *dir_array = NULL;
567         int ret = MS_MEDIA_ERR_NONE;
568         char *new_path = NULL;
569         char *current_path = NULL;
570         char path[MS_FILE_PATH_LEN_MAX] = { 0 };
571         int (*scan_function)(sqlite3 *, const char*, const char*, uid_t) = NULL;
572         char *new_start_path = NULL;
573
574         int fd = -1;
575         int nread = 0;
576         char buf[BUF_SIZE] = {0,};
577         struct linux_dirent *d;
578         int bpos = 0;
579         int scan_count = 0;
580         int sleep_count = 0;
581
582         const char *trash = "$RECYCLE.BIN";
583
584         bool is_missing = false;
585         ms_dir_scan_status_e scan_status = MS_DIR_SCAN_NONE;
586
587         MS_DBG_SWARN("storage id [%s] start path [%s]", storage_id, start_path);
588
589         /* make new array for storing directory */
590         dir_array = g_array_new(FALSE, FALSE, sizeof(char*));
591
592         /* add first direcotiry to directory array */
593         new_start_path = g_strdup(start_path);
594
595         g_array_append_val(dir_array, start_path);
596         ms_insert_folder_end(uid);
597         if (ms_insert_folder(handle, storage_id, new_start_path, uid) != MS_MEDIA_ERR_NONE)
598                 MS_DBG_ERR("insert folder failed");
599
600         scan_function = (scan_type == MS_MSG_STORAGE_ALL) ? ms_scan_item_batch : ms_scan_validate_item;
601
602         ms_batch_commit_disable(true, true, uid);
603         /*start db update. the number of element in the array , db update is complete.*/
604         while (dir_array->len != 0) {
605                 /*check poweroff status*/
606                 ret = __msc_check_stop_status(scan_type, new_start_path, pid);
607                 if (ret != MS_MEDIA_ERR_NONE)
608                         goto STOP_SCAN;
609
610                 /*ms_batch_commit_disable(true, true, uid);*/
611                 ms_batch_commit_enable(true, true, false, pid);
612
613                 /* get the current path from directory array */
614                 current_path = g_array_index(dir_array , char*, 0);
615                 g_array_remove_index(dir_array, 0);
616
617                 __msc_set_storage_scan_cur_path(current_path);
618
619                 ret = ms_check_scan_ignore(current_path, uid);
620                 if (ret != MS_MEDIA_ERR_NONE) {
621                         MS_DBG_SERR("%s is ignore", current_path);
622                         MS_SAFE_FREE(current_path);
623                         if (ret == MS_MEDIA_ERR_USB_UNMOUNTED)
624                                 goto STOP_SCAN;
625                         else
626                                 ret = MS_MEDIA_ERR_NONE;
627
628                         continue;
629                 }
630
631                 ret = msc_check_db_size(uid, scan_type);
632                 if (ret != MS_MEDIA_ERR_NONE)
633                         goto STOP_SCAN;
634
635                 ms_get_folder_scan_status(handle, storage_id, current_path, (int *)&scan_status);
636
637                 if (scan_status == MS_DIR_SCAN_PROCESSING && g_directory_scan_processing2 != DIR_SCAN_NON_SCAN) {
638
639                         MS_DBG_SERR("%s is scanning, ignore current path, scan next path !!", current_path);
640
641                         is_missing = true;
642                         goto NEXT_SCAN;
643
644                 } else if (scan_status == MS_DIR_SCAN_DONE) {
645                         if (g_directory_scan_processing2 == DIR_SCAN_NON_RECURSIVE) {
646                                 MS_DBG_SERR("%s is scan done, ignore current path, get subfolder list!!", current_path);
647
648                                 __msc_get_null_scan_folder_list(handle, storage_id, current_path, dir_array);
649
650                                 continue;
651
652                         } else if (g_directory_scan_processing2 == DIR_SCAN_RECURSIVE) {
653                                 MS_DBG_SERR("%s is scan done, ignore current path, scan next path!!", current_path);
654
655                                 is_missing = true;
656                                 goto NEXT_SCAN;
657                         }
658                 }
659
660                 ms_insert_folder_start();
661                 ms_set_folder_scan_status(handle, storage_id, current_path, MS_DIR_SCAN_PROCESSING, uid);
662                 sleep_count = 0;
663
664                 fd = open(current_path, O_RDONLY | O_DIRECTORY);
665                 if (fd == -1) {
666                         MS_DBG_STRERROR("open fails");
667                         ms_set_folder_scan_status(handle, storage_id, current_path, MS_DIR_SCAN_STOP, uid);
668                         continue;
669                 }
670
671                 for ( ; ; ) {
672                         nread = syscall(SYS_getdents64, fd, buf, BUF_SIZE);
673                         if (nread == -1) {
674                                 MS_DBG_STRERROR("getdents");
675                                 break;
676                         }
677
678                         /*check poweroff status*/
679                         ret = __msc_check_stop_status(scan_type, new_start_path, pid);
680                         if (ret != MS_MEDIA_ERR_NONE)
681                                 goto STOP_SCAN;
682
683                         ret = msc_check_db_size(uid, scan_type);
684                         if (ret != MS_MEDIA_ERR_NONE) {
685                                 //ms_set_folder_scan_status(handle, storage_id, current_path, MS_DIR_SCAN_STOP, uid);
686                                 goto STOP_SCAN;
687                         }
688 #if 0
689                         if (io_err_storage == MS_MAX_IO_ERR_COUNT) {
690                                 MS_DBG_ERR("REACH I/O MAX COUNT[%d]", io_err_storage);
691                                 goto STOP_SCAN;
692                         }
693 #endif
694                         if (nread == 0)
695                                 break;
696
697                         for (bpos = 0; bpos < nread;) {
698                                 sleep_count++;
699                                 if (sleep_count % 5 == 0) {
700                                         sleep_count = 0;
701                                         usleep(SCAN_SLEEP_TIME);
702                                 }
703                                 /*check poweroff status*/
704                                 ret = __msc_check_stop_status(scan_type, new_start_path, pid);
705                                 if (ret != MS_MEDIA_ERR_NONE)
706                                         goto STOP_SCAN;
707
708                                 ret = msc_check_db_size(uid, scan_type);
709                                 if (ret != MS_MEDIA_ERR_NONE) {
710                                         //ms_set_folder_scan_status(handle, storage_id, current_path, MS_DIR_SCAN_STOP, uid);
711                                         goto STOP_SCAN;
712                                 }
713 #if 0
714                                 if (io_err_storage == MS_MAX_IO_ERR_COUNT) {
715                                         MS_DBG_ERR("REACH I/O MAX COUNT[%d]", io_err_storage);
716                                         goto STOP_SCAN;
717                                 }
718 #endif
719                                 d = (struct linux_dirent *) (buf + bpos);
720
721                                 if (d->d_name[0] == '.') {
722                                         bpos += d->d_reclen;
723                                         continue;
724                                 }
725
726                                 if (strcmp(d->d_name, trash) == 0) {
727                                         MS_DBG_ERR("trash directory");
728                                         bpos += d->d_reclen;
729                                         continue;
730                                 }
731
732                                 if (ms_strappend(path, sizeof(path), "%s/%s", current_path, d->d_name) != MS_MEDIA_ERR_NONE) {
733                                         MS_DBG_ERR("ms_strappend failed");
734                                         bpos += d->d_reclen;
735                                         continue;
736                                 }
737
738                                 if (d->d_type == DT_UNKNOWN) {
739                                         struct stat st;
740                                         if (stat(path, &st) == 0) {
741                                                 if (S_ISREG(st.st_mode))
742                                                         d->d_type = DT_REG;
743                                                 else if (S_ISDIR(st.st_mode))
744                                                         d->d_type = DT_DIR;
745                                         }
746                                 }
747
748                                 if (d->d_type == DT_REG) {
749                                         /* check media type */
750                                         if (!ms_check_support_media_type(path)) {
751                                                 bpos += d->d_reclen;
752                                                 continue;
753                                         }
754
755                                         /* insert into media DB */
756                                         ret = scan_function(handle, storage_id, path, uid);
757                                         if (ret != MS_MEDIA_ERR_NONE) {
758                                                 MS_DBG_ERR("failed to update db : %d", scan_type);
759                                                 if (ret == MS_MEDIA_ERR_INTERNAL)
760                                                         MS_DBG_ERR("I/O ERROR COUNT[%d]", io_err_storage++);
761
762                                                 bpos += d->d_reclen;
763                                                 continue;
764                                         } else {
765                                                 ++scan_count;
766                                                 //MS_DBG_ERR("insert count %d", nScanCount);
767                                                 if (scan_count >= MAX_SCAN_COUNT) {
768                                                         scan_count = 0;
769                                                         //MS_DBG_ERR("storage_id = [%s]", storage_id);
770                                                         msc_insert_exactor_request(scan_type, false, storage_id, current_path, 0, uid, MS_ITEM_UPDATE);
771                                                 }
772                                         }
773                                 } else if (d->d_type == DT_DIR) {
774                                         /* this request is recursive scanning */
775                                         /* add new directory to dir_array */
776                                         new_path = g_strdup(path);
777                                         g_array_append_val(dir_array, new_path);
778
779                                         if (ms_insert_folder(handle, storage_id, new_path, uid) != MS_MEDIA_ERR_NONE)
780                                                 MS_DBG_ERR("insert folder failed");
781                                 }
782
783                                 bpos += d->d_reclen;
784                         }
785                 }
786
787                 ms_insert_folder_end(uid);
788                 /*commit to db before set scan done, fix timing issue storage scan, then folder scan for same folder*/
789                 ms_batch_commit_disable(true, true, uid);
790                 ms_set_folder_scan_status(handle, storage_id, current_path, MS_DIR_SCAN_DONE, uid);
791
792                 if (fd != -1) {
793                         close(fd);
794                         fd = -1;
795                 }
796
797 NEXT_SCAN:
798                 MS_SAFE_FREE(current_path);
799                 __msc_set_storage_scan_cur_path(NULL);
800
801                 if (dir_array->len == 0 && is_missing) {
802                         is_missing = false;
803
804                         if (g_directory_scan_processing2 == DIR_SCAN_NON_SCAN) {
805                                 ret = __msc_get_null_scan_folder_list(handle, storage_id, NULL, dir_array);
806
807                                 MS_DBG_WARN("no wait folder scan callback");
808
809                                 if (ret != MS_MEDIA_ERR_NONE)
810                                         break;
811                         } else {
812                                 __msc_set_dir_scan_cb(__msc_dir_scan_cb);
813
814                                 __msc_pause_scan();
815
816                                 MS_DBG_WARN("wait folder scan callback");
817
818                                 __msc_remove_dir_scan_cb();
819
820                                 ret = __msc_get_null_scan_folder_list(handle, storage_id, NULL, dir_array);
821
822                                 if (ret != MS_MEDIA_ERR_NONE)
823                                         break;
824                         }
825                 }
826                 usleep(SCAN_SLEEP_TIME);
827         }
828
829         if (!MS_STRING_VALID(MEDIA_ROOT_PATH_USB)) {
830                 MS_DBG_ERR("Fail to get USB path");
831                 goto EXIT;
832         }
833
834         if (strstr(new_start_path, MEDIA_ROOT_PATH_USB) != NULL) {
835                 if (!ms_storage_mount_status(new_start_path)) {
836                         MS_DBG_ERR("start path is unmounted");
837                         goto EXIT;
838                 }
839         }
840
841         if ((g_directory_scan_processing2 != DIR_SCAN_NON_SCAN)
842                 && (__msc_dir_and_storage_scan_same_path(new_start_path) == MS_MEDIA_ERR_NONE)) {
843                 __msc_set_dir_scan_cb(__msc_dir_scan_cb);
844                 MS_DBG_WARN("storage scan pause");
845                 __msc_pause_scan();
846
847                 MS_DBG_WARN("wait folder scan callback");
848
849                 __msc_remove_dir_scan_cb();
850         }
851
852         /*remove invalid folder in folder table.*/
853         /*if (ms_delete_invalid_folder(handle, storage_id, storage_type, uid) != MS_MEDIA_ERR_NONE) {
854                 MS_DBG_ERR("delete invalid folder failed");
855                 ret = MS_MEDIA_ERR_DB_DELETE_FAIL;
856         }*/
857
858         goto EXIT;
859
860 STOP_SCAN:
861         ms_insert_folder_end(uid);
862         if (current_path != NULL)
863                 ms_set_folder_scan_status(handle, storage_id, current_path, MS_DIR_SCAN_STOP, uid);
864         MS_SAFE_FREE(current_path);
865
866 EXIT:
867
868         if (fd != -1) {
869                 close(fd);
870                 fd = -1;
871         }
872
873         g_free(new_start_path);
874         __msc_set_storage_scan_cur_path(NULL);
875         __msc_clear_file_list(dir_array);
876
877         ms_batch_commit_disable(true, true, uid);
878
879         if (ret != MS_MEDIA_ERR_NONE) MS_DBG_INFO("ret : %d", ret);
880
881         return ret;
882 }
883
884 static int __msc_get_null_scan_folder_list(sqlite3 *handle, const char *stroage_id, char *path, GArray *dir_array)
885 {
886         int ret = MS_MEDIA_ERR_NONE;
887         char *new_path = NULL;
888         char *current_path = NULL;
889         GArray *cur_dir_array = NULL;
890
891         ret = ms_get_null_scan_folder_list(handle, stroage_id, path, &cur_dir_array);
892
893         if (ret == MS_MEDIA_ERR_NONE) {
894                 MS_DBG_WARN("cur_dir_array->len = [%d]", cur_dir_array->len);
895                 while (cur_dir_array->len != 0) {
896                         current_path = g_array_index(cur_dir_array , char*, 0);
897                         g_array_remove_index(cur_dir_array, 0);
898                         MS_DBG_SLOG("current_path = [%s]", current_path);
899
900                         new_path = g_strdup(current_path);
901                         g_array_append_val(dir_array, new_path);
902                         g_free(current_path);
903                 }
904         }
905
906         __msc_clear_file_list(cur_dir_array);
907
908         return ret;
909 }
910
911 static int __msc_check_scan_same_path(char *scan_path)
912 {
913         int ret = MS_MEDIA_ERR_NONE;
914         unsigned int storage_len, folder_len, min_len;
915
916         g_mutex_lock(&storage_scan_mutex2);
917
918         if (NULL == scan_path || NULL == g_storage_scan_path) {
919                 g_mutex_unlock(&storage_scan_mutex2);
920
921                 return MS_MEDIA_ERR_INTERNAL;
922         }
923
924         storage_len = strlen(g_storage_scan_path);
925         folder_len = strlen(scan_path);
926         min_len = storage_len > folder_len ? folder_len : storage_len;
927
928         ret = strncmp(g_storage_scan_path, scan_path, min_len);
929
930         g_mutex_unlock(&storage_scan_mutex2);
931
932         return abs(ret);
933 }
934
935 static void __msc_set_storage_scan_cur_path(char *scan_path)
936 {
937         g_mutex_lock(&storage_scan_mutex2);
938
939         g_free(g_storage_scan_path);
940         g_storage_scan_path = g_strdup(scan_path);
941
942         g_mutex_unlock(&storage_scan_mutex2);
943 }
944
945 static int __msc_dir_and_storage_scan_same_path(char *start_path)
946 {
947         int ret = MS_MEDIA_ERR_NONE;
948         unsigned int storage_len, folder_len;
949
950         char *storage_path = NULL;
951         char *remain_path = NULL;
952         int remain_len = 0;
953
954         if (!MS_STRING_VALID(MEDIA_ROOT_PATH_USB)) {
955                 MS_DBG_ERR("Fail to get USB path");
956                 return MS_MEDIA_ERR_INTERNAL;
957         }
958
959         remain_path = strstr(start_path+strlen(MEDIA_ROOT_PATH_USB) +1, "/");
960         if (remain_path != NULL)
961                 remain_len = strlen(remain_path);
962
963         storage_path = g_strndup(start_path, strlen(start_path) - remain_len);
964
965         g_mutex_lock(&dir_scan_mutex2);
966
967         if (NULL == g_dir_scan_path || NULL == storage_path) {
968                 g_free(storage_path);
969                 g_mutex_unlock(&dir_scan_mutex2);
970
971                 return MS_MEDIA_ERR_INTERNAL;
972         }
973
974         storage_len = strlen(storage_path);
975         folder_len = strlen(g_dir_scan_path);
976
977         if (folder_len < storage_len)
978                 ret = -1;
979         else
980                 ret = strncmp(storage_path, g_dir_scan_path, storage_len);
981
982         g_free(storage_path);
983         g_mutex_unlock(&dir_scan_mutex2);
984
985         return abs(ret);
986 }
987
988
989 static void __msc_set_dir_scan_cur_path(char *scan_path)
990 {
991         g_mutex_lock(&dir_scan_mutex2);
992
993         g_free(g_dir_scan_path);
994         g_dir_scan_path = g_strdup(scan_path);
995
996         g_mutex_unlock(&dir_scan_mutex2);
997 }
998
999 static int __msc_db_update(sqlite3 *handle, const char *storage_id, const ms_comm_msg_s * scan_data)
1000 {
1001         int scan_type;
1002         int err = MS_MEDIA_ERR_NONE;
1003         char *start_path = NULL;
1004         ms_user_storage_type_e storage_type;
1005
1006         err = ms_user_get_storage_type(scan_data->uid, scan_data->msg, &storage_type);
1007         if (err != MS_MEDIA_ERR_NONE)
1008                 MS_DBG_ERR("ms_user_get_storage_type failed");
1009
1010         scan_type = scan_data->msg_type;
1011
1012         /*if scan type is not MS_SCAN_NONE, check data in db. */
1013         if (scan_type != MS_MSG_STORAGE_INVALID) {
1014                 MS_DBG_WARN("INSERT");
1015                 start_path = g_strdup(scan_data->msg);
1016                 if (scan_type == MS_MSG_DIRECTORY_SCANNING || scan_type == MS_MSG_DIRECTORY_SCANNING_NON_RECURSIVE)
1017                         err = __msc_dir_scan_for_folder(handle, storage_id, start_path, storage_type, scan_type, scan_data->pid, scan_data->uid);
1018                 else if (scan_type == MS_MSG_STORAGE_ALL || scan_type == MS_MSG_STORAGE_PARTIAL)
1019                         err = __msc_dir_scan_for_storage(handle, storage_id, start_path, storage_type, scan_type, scan_data->pid, scan_data->uid);
1020
1021                 if (err != MS_MEDIA_ERR_NONE)
1022                         MS_DBG_ERR("error : %d", err);
1023
1024         } else if (scan_type == MS_MSG_STORAGE_INVALID) {
1025                 MS_DBG_WARN("INVALID");
1026                 msc_remove_extract_request(scan_data);
1027         }
1028
1029         sync();
1030
1031         return err;
1032 }
1033
1034 static void __msc_pop_new_request(ms_comm_msg_s **scan_data)
1035 {
1036         *scan_data = g_async_queue_pop(scan_queue2);
1037 }
1038
1039 gpointer msc_directory_scan_thread(gpointer data)
1040 {
1041         ms_comm_msg_s *scan_data = NULL;
1042         int err;
1043         int ret = MS_MEDIA_ERR_NONE;
1044         sqlite3 *handle = NULL;
1045         int scan_type;
1046         char *storage_id = NULL;
1047         bool modified = false;
1048         ms_user_storage_type_e storage_type = MS_USER_STORAGE_INTERNAL;
1049         ms_dir_scan_status_e scan_status = MS_DIR_SCAN_NONE;
1050         ms_noti_type_e noti_type = MS_ITEM_INSERT;
1051         char *folder_uuid = NULL;
1052         bool is_recursive = true;
1053         uid_t uid = MEDIA_DEFAULT_UID;
1054
1055         while (1) {
1056                 __msc_pop_new_request(&scan_data);
1057                 ret = MS_MEDIA_ERR_NONE;
1058
1059                 if (scan_data->pid == POWEROFF) {
1060                         MS_DBG_ERR("power off");
1061                         goto _POWEROFF;
1062                 }
1063
1064                 MS_DBG_WARN("DIRECTORY SCAN START [%.*s, %d]", MAX_MSG_SIZE, scan_data->msg, scan_data->msg_type);
1065
1066                 msc_set_cur_scan_item(scan_data->msg, scan_data->pid);
1067                 g_directory_scan_processing2 = DIR_SCAN_NON_RECURSIVE;
1068                 uid = scan_data->uid;
1069
1070                 /*connect to media db, if conneting is failed, db updating is stopped*/
1071                 ret = ms_connect_db(&handle, uid);
1072                 if (ret != MS_MEDIA_ERR_NONE) {
1073                         MS_DBG_ERR("ms_connect_db failed");
1074                         goto NEXT;
1075                 }
1076
1077                 /*check remain space*/
1078                 err = __msc_check_remain_space(uid);
1079                 if (err == MS_MEDIA_ERR_NOT_ENOUGH_SPACE
1080                         || err == MS_MEDIA_ERR_DB_FULL_FAIL){
1081                         ret = MS_MEDIA_ERR_NONE;
1082                         goto SCAN_DONE;
1083                 }
1084
1085                 scan_type = scan_data->msg_type;
1086                 ret = ms_user_get_storage_type(uid, scan_data->msg, &storage_type);
1087                 if (ret != MS_MEDIA_ERR_NONE) {
1088                         MS_DBG_ERR("ms_user_get_storage_type failed");
1089                         goto NEXT;
1090                 }
1091
1092                 storage_id = g_strdup(scan_data->storage_id);
1093
1094                 MS_DBG("path [%.*s], storage_id [%s], scan_type [%d]", MAX_MSG_SIZE, scan_data->msg, storage_id, scan_type);
1095
1096                 if (strlen(storage_id) == 0) {
1097                         MS_DBG_ERR("storage_id length is 0. There is no information of your request [%.*s]", MAX_MSG_SIZE, scan_data->msg);
1098                         ret = MS_MEDIA_ERR_INVALID_PARAMETER;
1099                         goto NEXT;
1100                 }
1101
1102                 if (scan_type != MS_MSG_DIRECTORY_SCANNING
1103                         && scan_type != MS_MSG_DIRECTORY_SCANNING_NON_RECURSIVE) {
1104                         MS_DBG_ERR("Invalid request");
1105                         ret = MS_MEDIA_ERR_INVALID_PARAMETER;
1106                         goto NEXT;
1107                 }
1108
1109                 ms_trim_dir_path(scan_data->msg);
1110
1111                 if (g_file_test(scan_data->msg, G_FILE_TEST_IS_DIR)) {
1112                         is_recursive = (scan_type == MS_MSG_DIRECTORY_SCANNING_NON_RECURSIVE) ? false : true;
1113                         if (ms_check_folder_exist(handle, storage_id, scan_data->msg) == MS_MEDIA_ERR_NONE) {
1114                                 /*already exist in media DB*/
1115                                 noti_type = MS_ITEM_UPDATE;
1116                                 MS_DBG_WARN("[%.*s] already exist", MAX_MSG_SIZE, scan_data->msg);
1117                         } else {
1118                                 noti_type = MS_ITEM_INSERT;
1119                                 MS_DBG_WARN("[%.*s] new insert path", MAX_MSG_SIZE, scan_data->msg);
1120                         }
1121                 } else {
1122                         /*directory is deleted*/
1123                         is_recursive = true;
1124                         noti_type = MS_ITEM_DELETE;
1125                         scan_type = MS_MSG_DIRECTORY_SCANNING;
1126                         scan_data->msg_type = MS_MSG_DIRECTORY_SCANNING;
1127
1128                         /*get the UUID of deleted folder*/
1129                         ms_get_folder_id(handle, storage_id, scan_data->msg, &folder_uuid);
1130
1131                         MS_DBG_SWARN("[%.*s][%s] delete path", MAX_MSG_SIZE, scan_data->msg, folder_uuid);
1132                 }
1133
1134                 if (scan_type == MS_MSG_DIRECTORY_SCANNING) {
1135
1136                         MS_DBG_WARN("start recursive dir scan!!");
1137
1138                         g_directory_scan_processing2 = DIR_SCAN_RECURSIVE;
1139                         err = __msc_check_scan_same_path(scan_data->msg);
1140
1141                         if (MS_MEDIA_ERR_NONE == err) {
1142                                 MS_DBG_WARN("[%.*s] is scanning recursive, waiting...", MAX_MSG_SIZE, scan_data->msg);
1143                                 msc_send_result_partial(ret, MS_MSG_RECURSIVE_START, scan_data->pid, scan_data->msg);
1144                                 while (1) {
1145                                         sleep(1);
1146
1147                                         ret = __msc_check_stop_status(scan_type, scan_data->msg, scan_data->pid);
1148                                         if (ret != MS_MEDIA_ERR_NONE)
1149                                                 goto NEXT;
1150
1151
1152                                         err = __msc_check_scan_same_path(scan_data->msg);
1153                                         if (err != MS_MEDIA_ERR_NONE)
1154                                                 break;
1155                                 }
1156
1157                                 MS_DBG_WARN("[%.*s] scan done, wait finished", MAX_MSG_SIZE, scan_data->msg);
1158                                 goto SCAN_DONE;
1159
1160                         } else {
1161                                 ms_get_folder_scan_status(handle, storage_id, scan_data->msg, (int*)&scan_status);
1162
1163                                 if (scan_status == MS_DIR_SCAN_DONE)
1164                                         ms_set_folder_item_validity(handle, storage_id, scan_data->msg, MS_VALID_V2, MS_RECURSIVE, uid);
1165                                 else
1166                                         ms_set_folder_item_validity(handle, storage_id, scan_data->msg, MS_INVALID, MS_RECURSIVE, uid);
1167
1168                                 msc_send_result_partial(ret, MS_MSG_RECURSIVE_START, scan_data->pid, scan_data->msg);
1169                         }
1170                 } else {
1171                         MS_DBG_WARN("start non recursive dir scan!!");
1172
1173                         g_directory_scan_processing2 = DIR_SCAN_NON_RECURSIVE;
1174                         ms_check_folder_modified(handle, scan_data->msg, storage_id, &modified);
1175
1176                         if (!modified) {
1177                                 MS_DBG_WARN("check [%.*s] has not been modified !!", MAX_MSG_SIZE, scan_data->msg);
1178                                 ms_get_folder_scan_status(handle, storage_id, scan_data->msg, (int*)&scan_status);
1179                                 MS_DBG_WARN("folder scan status = [%d]", scan_status);
1180
1181                                 if (scan_status == MS_DIR_SCAN_DONE) {
1182                                         /* do nothing */
1183                                         MS_DBG_WARN("[%.*s] scan done", MAX_MSG_SIZE, scan_data->msg);
1184                                         /*fix timing issue, deleted items scanned by storage scan is set validity 1 again*/
1185                                         /*err = ms_set_folder_item_validity(handle, storage_id, scan_data->msg, MS_VALID, MS_NON_RECURSIVE, uid);*/
1186                                         goto SCAN_DONE;
1187                                 } else if (scan_status == MS_DIR_SCAN_PROCESSING) {
1188                                         MS_DBG_WARN("[%.*s] scanning, waiting...", MAX_MSG_SIZE, scan_data->msg);
1189
1190                                         while (1) {
1191                                                 sleep(1);
1192
1193                                                 ret = __msc_check_stop_status(scan_type, scan_data->msg, scan_data->pid);
1194                                                 if (ret != MS_MEDIA_ERR_NONE)
1195                                                         goto NEXT;
1196
1197
1198                                                 ms_get_folder_scan_status(handle, storage_id, scan_data->msg, (int*)&scan_status);
1199                                                 if ((scan_status == MS_DIR_SCAN_DONE) || (scan_status == MS_DIR_SCAN_STOP)) {
1200                                                         MS_DBG_WARN("[%.*s] scan status [%d]!!!", MAX_MSG_SIZE, scan_data->msg, scan_status);
1201                                                         break;
1202                                                 }
1203                                         }
1204
1205                                         if (scan_status == MS_DIR_SCAN_DONE) {
1206                                                 MS_DBG_WARN("[%.*s] scan done, wait finished", MAX_MSG_SIZE, scan_data->msg);
1207                                                 goto SCAN_DONE;
1208                                         } else {
1209                                                 MS_DBG_WARN("set folder item invalid");
1210                                                 err = ms_set_folder_item_validity(handle, storage_id, scan_data->msg, MS_INVALID, MS_NON_RECURSIVE, uid);
1211                                         }
1212                                 } else {
1213                                         err = ms_set_folder_item_validity(handle, storage_id, scan_data->msg, MS_INVALID, MS_NON_RECURSIVE, uid);
1214                                 }
1215                         } else {
1216                                 MS_DBG_WARN("check [%.*s] has been modified !!", MAX_MSG_SIZE, scan_data->msg);
1217                                 err = ms_set_folder_item_validity(handle, storage_id, scan_data->msg, MS_INVALID, MS_NON_RECURSIVE, uid);
1218                         }
1219                 }
1220
1221                 if (err != MS_MEDIA_ERR_NONE)
1222                         MS_DBG_ERR("error : %d", err);
1223
1224                 /*call for bundle commit*/
1225                 ms_batch_commit_enable(true, true, false, 0);
1226
1227                 if (strcmp(scan_data->msg, MEDIA_ROOT_PATH_DISC) == 0) {
1228                         MS_DBG("[DATA DISC]");
1229                         msc_set_disc_dir_scan_status(true);
1230                 }
1231
1232                 /*insert data into media db */
1233                 ret = __msc_db_update(handle, storage_id, scan_data);
1234
1235                 /*call for bundle commit*/
1236                 ms_batch_commit_disable(true, true, uid);
1237
1238                 MS_DBG_WARN("folder scan done, sent cb event path = [%.*s]", MAX_MSG_SIZE, scan_data->msg);
1239                 __msc_call_dir_scan_cb();
1240
1241                 /*delete invalid folder first, then delete invalid item, avoid to folder was deleted but item not when unmount*/
1242                 /*if (ms_delete_invalid_folder(handle, storage_id, storage_type, scan_data->uid) != MS_MEDIA_ERR_NONE)
1243                         MS_DBG_ERR("deleting invalid folders in storage failed");
1244
1245                 if (!ms_delete_invalid_items(handle, storage_id, storage_type, scan_data->uid))
1246                         MS_DBG_ERR("deleting invalid items in storage failed");*/
1247
1248                 /*revert to 3.0,folder scan should only delete invalid in folder instead of delete invalid in storage*/
1249                 if (ms_delete_invalid_items_in_folder(handle, storage_id, scan_data->msg, is_recursive, uid)  != MS_MEDIA_ERR_NONE) {
1250                         MS_DBG_ERR("deleting invalid items in folder failed");
1251                 }
1252
1253                 /*if (ret != MS_MEDIA_ERR_SCANNER_FORCE_STOP) {
1254                         ms_send_dir_update_noti(scan_data->msg, folder_uuid, noti_type, scan_data->pid);
1255                 }*/
1256
1257 SCAN_DONE:
1258                 MS_DBG_WARN("storage_id = [%s], dir Path = [%.*s], pid = [%d]", storage_id, MAX_MSG_SIZE, scan_data->msg, scan_data->pid);
1259                 if (ret != MS_MEDIA_ERR_SCANNER_FORCE_STOP) {
1260                         /*remove invalid folder in folder table.*/
1261                         if (is_recursive == true) {
1262                                 if (ms_delete_invalid_folder_by_path(handle, storage_id, scan_data->msg, uid) != MS_MEDIA_ERR_NONE) {
1263                                         MS_DBG_ERR("deleting invalid folder failed");
1264                                 }
1265                         }
1266                         if (noti_type == MS_ITEM_DELETE) {
1267                                 ms_send_dir_update_noti(scan_data->msg, folder_uuid, noti_type, scan_data->pid);
1268                         }
1269                         msc_insert_exactor_request(scan_data->msg_type, true, scan_data->storage_id, scan_data->msg, scan_data->pid, uid, noti_type);
1270                 }
1271                 if (power_off2) {
1272                         MS_DBG_ERR("power off");
1273                         goto _POWEROFF;
1274                 }
1275
1276 NEXT:
1277                 /*Active flush */
1278                 malloc_trim(0);
1279
1280                 scan_data->msg_type = MS_MSG_SCANNER_COMPLETE;
1281                 msc_send_result(ret, scan_data);
1282
1283                 g_free(scan_data);
1284                 scan_data = NULL;
1285                 g_free(storage_id);
1286                 storage_id = NULL;
1287                 g_free(folder_uuid);
1288                 folder_uuid = NULL;
1289
1290                 g_directory_scan_processing2 = DIR_SCAN_NON_SCAN;
1291                 __msc_del_cur_scan_item();
1292                 __msc_del_cancel_scan_item();
1293
1294                 MS_DBG_WARN("DIRECTORY SCAN END [%d]", ret);
1295
1296                 io_err_folder = 0;
1297
1298                 /*disconnect form media db*/
1299                 if (handle) ms_disconnect_db(handle);
1300                 usleep(SCAN_SLEEP_TIME);
1301         }                       /*thread while*/
1302
1303 _POWEROFF:
1304         g_free(scan_data);
1305         if (handle) ms_disconnect_db(handle);
1306
1307         return NULL;
1308 }
1309
1310 static int __msc_dir_scan_cb(void)
1311 {
1312         return __msc_resume_scan();
1313 }
1314
1315 static void __msc_check_pvr_svc(void)
1316 {
1317 #ifdef _USE_RECORDED_CONTENT
1318         if (ms_is_support_pvr()) {
1319                 MS_DBG_ERR("Waiting PVR service");
1320                 while (!power_off2) {
1321                         FILE* file = fopen("/run/pvr_ready", "rb");
1322
1323                         if (file != NULL) {
1324                                 fclose(file);
1325                                 MS_DBG_WARN("PVR service is ready");
1326                                 break;
1327                         } else {
1328                                 sleep(1);
1329                         }
1330                 }
1331         }
1332 #else
1333         MS_DBG("NOT SUPPORT RECORED CONTENT");
1334 #endif
1335 }
1336
1337 gpointer msc_storage_scan_thread(gpointer data)
1338 {
1339         ms_comm_msg_s *scan_data = NULL;
1340         int ret = MS_MEDIA_ERR_NONE;
1341         sqlite3 *handle = NULL;
1342         ms_user_storage_type_e storage_type = MS_USER_STORAGE_INTERNAL;
1343         int scan_type;
1344         bool valid_status = true;
1345         char *update_path = NULL;
1346         uid_t uid = MEDIA_DEFAULT_UID;
1347
1348         while (1) {
1349                 scan_data = g_async_queue_pop(storage_queue2);
1350                 if (scan_data->pid == POWEROFF) {
1351                         MS_DBG_ERR("power off");
1352                         goto _POWEROFF;
1353                 }
1354
1355                 MS_DBG_WARN("STORAGE SCAN START [%.*s]", MAX_MSG_SIZE, scan_data->msg);
1356
1357                 scan_type = scan_data->msg_type;
1358                 if (scan_type != MS_MSG_STORAGE_ALL
1359                         && scan_type != MS_MSG_STORAGE_PARTIAL
1360                         && scan_type != MS_MSG_STORAGE_INVALID) {
1361                         MS_DBG_ERR("Invalid request[%d]", scan_type);
1362                         ret = MS_MEDIA_ERR_INVALID_PARAMETER;
1363                         goto NEXT;
1364                 }
1365
1366                 __msc_check_pvr_svc();
1367
1368                 uid = scan_data->uid;
1369
1370                 /*connect to media db, if conneting is failed, db updating is stopped*/
1371                 ret = ms_connect_db(&handle, uid);
1372                 if (ret != MS_MEDIA_ERR_NONE) {
1373                         MS_DBG_ERR("ms_connect_db failed");
1374                         goto NEXT;
1375                 }
1376
1377                 ret = ms_user_get_storage_type(uid, scan_data->msg, &storage_type);
1378                 if (ret != MS_MEDIA_ERR_NONE) {
1379                         MS_DBG_ERR("ms_user_get_storage_type failed");
1380                         goto NEXT;
1381                 }
1382
1383                 update_path = g_strdup(scan_data->msg);
1384
1385                 ret = __msc_check_memory_status(uid);
1386                 if (ret != MS_MEDIA_ERR_NONE) {
1387                         ms_set_storage_scan_status(handle, scan_data->storage_id, MEDIA_SCAN_STOP, uid);
1388                         MS_DBG_ERR("storage_id = [%s]", scan_data->storage_id);
1389                         msc_insert_exactor_request(scan_type, true, scan_data->storage_id, scan_data->msg, scan_data->pid, uid, MS_ITEM_UPDATE);
1390                         goto NEXT;
1391                 }
1392
1393                 ms_set_storage_scan_status(handle, scan_data->storage_id, MEDIA_SCAN_PROCESSING, uid);
1394
1395                 /*start db updating */
1396                 ms_set_db_status(MS_DB_UPDATING, storage_type);
1397
1398                 if (strcmp(update_path, MEDIA_ROOT_PATH_DISC) == 0) {
1399                         MS_DBG("[DATA DISC]");
1400                         msc_set_disc_stg_scan_status(true);
1401                 }
1402
1403                 valid_status = (scan_type == MS_MSG_STORAGE_PARTIAL || MS_MSG_STORAGE_ALL == scan_type) ? true : false;
1404
1405                 if (scan_type != MS_MSG_STORAGE_INVALID)
1406                         ms_batch_commit_enable(true, valid_status, false, 0);
1407
1408                 if (scan_type == MS_MSG_STORAGE_ALL) {
1409                         /* Delete all data before full scanning */
1410                         if (ms_delete_invalid_items(handle, scan_data->storage_id, uid) != MS_MEDIA_ERR_NONE)
1411                                 MS_DBG_ERR("ms_delete_invalid_items fails");
1412                 }
1413
1414                 ret = __msc_db_update(handle, scan_data->storage_id, scan_data);
1415
1416                 /*call for bundle commit*/
1417                 if (scan_type != MS_MSG_STORAGE_INVALID)
1418                         ms_batch_commit_disable(true, valid_status, uid);
1419
1420                 if (scan_type == MS_MSG_STORAGE_PARTIAL && ret == MS_MEDIA_ERR_NONE) {
1421                         /*delete invalid folder first, then delete invalid item, avoid to folder was deleted but item not when unmount*/
1422                         ms_delete_invalid_folder(scan_data->storage_id, uid);
1423                         ms_delete_invalid_items(handle, scan_data->storage_id, uid);
1424                 }
1425
1426                 /* send notification */
1427                 /*ms_send_dir_update_noti(update_path, NULL, MS_ITEM_UPDATE, scan_data->pid);*/
1428
1429                 if (ret == MS_MEDIA_ERR_SCANNER_FORCE_STOP) {
1430                         ms_set_storage_scan_status(handle, scan_data->storage_id, MEDIA_SCAN_STOP, uid);
1431                         /*set vconf key mmc loading for indicator */
1432                         ms_set_db_status(MS_DB_STOPPED, storage_type);
1433                 } else {
1434                         ms_set_storage_scan_status(handle, scan_data->storage_id, MEDIA_SCAN_COMPLETE, uid);
1435                         /*set vconf key mmc loading for indicator */
1436                         ms_set_db_status(MS_DB_UPDATED, storage_type);
1437                 }
1438
1439                 MS_DBG_WARN("storage_id = [%s]", scan_data->storage_id);
1440                 msc_insert_exactor_request(scan_type, true, scan_data->storage_id, scan_data->msg, scan_data->pid, uid, MS_ITEM_UPDATE);
1441
1442 NEXT:
1443                 __msc_del_blocked_path();
1444
1445                 g_free(update_path);
1446                 update_path = NULL;
1447
1448                 if (power_off2) {
1449                         MS_DBG_ERR("power off");
1450                         goto _POWEROFF;
1451                 }
1452
1453                 /*disconnect from media db*/
1454                 if (handle) ms_disconnect_db(handle);
1455
1456                 /*Active flush */
1457                 malloc_trim(0);
1458
1459                 scan_data->msg_type = MS_MSG_SCANNER_COMPLETE;
1460                 msc_send_result(ret, scan_data);
1461
1462                 g_free(scan_data);
1463                 scan_data = NULL;
1464
1465                 MS_DBG_WARN("STORAGE SCAN END[%d]", ret);
1466
1467                 io_err_storage = 0;
1468                 usleep(SCAN_SLEEP_TIME);
1469         }                       /*thread while*/
1470
1471 _POWEROFF:
1472         g_free(scan_data);
1473         if (handle) ms_disconnect_db(handle);
1474
1475         return NULL;
1476 }
1477
1478 static void __msc_insert_register_request(GArray *register_array, ms_comm_msg_s *insert_data)
1479 {
1480         MS_DBG_SLOG("path : %.*s", MAX_MSG_SIZE, insert_data->msg);
1481
1482         if (insert_data->pid == POWEROFF)
1483                 g_array_prepend_val(register_array, insert_data);
1484         else
1485                 g_array_append_val(register_array, insert_data);
1486
1487 }
1488
1489 static void __msc_clear_file_list(GArray *path_array)
1490 {
1491         if (path_array) {
1492                 while (path_array->len != 0) {
1493                         char *data = NULL;
1494                         data = g_array_index(path_array , char*, 0);
1495                         g_array_remove_index(path_array, 0);
1496                         g_free(data);
1497                 }
1498                 g_array_free(path_array, FALSE);
1499                 path_array = NULL;
1500         }
1501 }
1502
1503 static int __msc_make_file_list(char *file_path, GArray **path_array, uid_t uid)
1504 {
1505         FILE *fp = NULL;
1506         char buf[MS_FILE_PATH_LEN_MAX] = {0,};
1507         char *path = NULL;
1508         int length;
1509         int res = MS_MEDIA_ERR_NONE;
1510         int ret = MS_MEDIA_ERR_NONE;
1511
1512         /* load the file list from file */
1513         fp = fopen(file_path, "rt");
1514         if (fp == NULL) {
1515                 MS_DBG_STRERROR("fopen failed");
1516                 res = MS_MEDIA_ERR_INTERNAL;
1517                 goto FREE_RESOURCE;
1518         }
1519
1520         memset(buf, 0x0, MS_FILE_PATH_LEN_MAX);
1521         /* This is an array for storing the path of insert datas*/
1522         *path_array = g_array_new(FALSE, FALSE, sizeof(char *));
1523
1524         /* read registering file path from stored file */
1525         while (fgets(buf, MS_FILE_PATH_LEN_MAX, fp) != NULL) {
1526                 length = strlen(buf); /*the return value of function, strlen(), includes "\n" */
1527                 path = g_strndup(buf, length - 1); /*copying except "\n" and strndup fuction adds "\0" at the end of the copying string */
1528
1529                 /* check valid path */
1530                 ret = ms_check_ignore_dir(path, uid);
1531                 if (ret != MS_MEDIA_ERR_NONE) {
1532                         MS_DBG_SERR("invalide path : %s", path);
1533                         g_free(path);
1534                         continue;
1535                 }
1536                 /* insert getted path to the list */
1537                 g_array_append_val(*path_array, path);
1538         }
1539
1540         if (fp) fclose(fp);
1541         fp = NULL;
1542
1543         return MS_MEDIA_ERR_NONE;
1544
1545 FREE_RESOURCE:
1546
1547         __msc_clear_file_list(*path_array);
1548
1549         if (fp) fclose(fp);
1550         fp = NULL;
1551
1552         return res;
1553 }
1554
1555 static int __msc_batch_insert(int pid, GArray *path_array, uid_t uid)
1556 {
1557         int err;
1558         unsigned int i;
1559         sqlite3 *handle = NULL;
1560         char *insert_path = NULL;
1561         char storage_id[MS_UUID_SIZE] = {0,};
1562         bool power_off_status = false;
1563
1564         /* connect to media db, if conneting is failed, db updating is stopped */
1565         err = ms_connect_db(&handle, uid);
1566         if (err != MS_MEDIA_ERR_NONE)
1567                 return MS_MEDIA_ERR_DB_INTERNAL;
1568
1569         /*start db updating */
1570         /*call for bundle commit*/
1571         ms_batch_commit_enable(true, false, true, pid);
1572
1573         MS_DBG_WARN("BULK REGISTER START");
1574
1575         /* get the inserting file path from array and insert to db */
1576         for (i = 0; i < path_array->len; i++) {
1577
1578                 insert_path = g_array_index(path_array, char*, i);
1579
1580                 /* get storage list */
1581                 memset(storage_id, 0x0, MS_UUID_SIZE);
1582                 if (ms_get_storage_id(handle, insert_path, storage_id, uid) < 0) {
1583                         MS_DBG_ERR("There is no storage id in media db");
1584                         continue;
1585                 }
1586
1587                 /* insert to db */
1588                 err = ms_insert_item_batch(handle, storage_id, insert_path, uid);
1589
1590                 msc_get_power_status(&power_off_status);
1591                 if (power_off_status) {
1592                         MS_DBG_ERR("power off");
1593                         /*call for bundle commit*/
1594                         break;
1595                 }
1596         }
1597
1598         /*call for bundle commit*/
1599         ms_batch_commit_disable(true, false, uid);
1600
1601         /*disconnect form media db*/
1602         if (handle) ms_disconnect_db(handle);
1603
1604         return MS_MEDIA_ERR_NONE;
1605 }
1606
1607 static int __msc_pop_register_request(GArray *register_array, ms_comm_msg_s **register_data)
1608 {
1609         int remain_request;
1610         ms_comm_msg_s *insert_data = NULL;
1611
1612         while (1) {
1613                 remain_request = g_async_queue_length(reg_queue2);
1614
1615                 /*updating requests remain*/
1616                 if (register_array->len != 0 && remain_request == 0) {
1617                         *register_data = g_array_index(register_array, ms_comm_msg_s*, 0);
1618                         g_array_remove_index(register_array, 0);
1619                         if (*register_data == NULL)
1620                                 continue;
1621
1622                         break;
1623                 } else if (remain_request != 0) {
1624                         insert_data = g_async_queue_pop(reg_queue2);
1625                         __msc_insert_register_request(register_array, insert_data);
1626                         continue;
1627                 } else if (register_array->len == 0 && remain_request == 0) {
1628                 /*Threre is no request, Wait until pushung new request*/
1629                         insert_data = g_async_queue_pop(reg_queue2);
1630                         __msc_insert_register_request(register_array, insert_data);
1631                         continue;
1632                 }
1633         }
1634
1635         if ((strlen((*register_data)->msg) <= 0) || (strlen((*register_data)->msg) >= MS_FILE_PATH_LEN_MAX)) {
1636                 MS_DBG_ERR("message size[%zu] is wrong", strlen((*register_data)->msg));
1637                 return MS_MEDIA_ERR_IPC;
1638         }
1639
1640         return MS_MEDIA_ERR_NONE;
1641
1642 }
1643
1644 gpointer msc_register_thread(gpointer data)
1645 {
1646         ms_comm_msg_s *register_data = NULL;
1647         GArray *register_array = NULL;
1648         GArray *path_array = NULL;
1649         char *file_path = NULL;
1650         int ret;
1651         int pid = 0;
1652         uid_t uid = MEDIA_DEFAULT_UID;
1653         ms_comm_msg_s *msg_data = NULL;
1654
1655         /*create array for processing overlay data*/
1656         register_array = g_array_new(FALSE, FALSE, sizeof(ms_comm_msg_s *));
1657         if (register_array == NULL) {
1658                 MS_DBG_ERR("g_array_new error");
1659                 return false;
1660         }
1661
1662         while (1) {
1663                 ret = __msc_pop_register_request(register_array, &register_data);
1664                 if (register_data == NULL) {
1665                         MS_DBG_ERR("register_data is NULL");
1666                         continue;
1667                 }
1668                 if (register_data->pid == POWEROFF) {
1669                         MS_DBG_ERR("power off");
1670                         goto _POWEROFF;
1671                 }
1672
1673                 if (ret != MS_MEDIA_ERR_NONE) {
1674                         MS_DBG_ERR("__msc_pop_register_request failed [%d]", ret);
1675                         goto FREE_RESOURCE;
1676                 }
1677
1678                 /* check current request */
1679                 pid = register_data->pid;
1680                 uid = register_data->uid;
1681
1682                 if (register_data->msg_type != MS_MSG_BULK_INSERT) {
1683                         MS_DBG_ERR("wrong message type");
1684                         goto FREE_RESOURCE;
1685                 }
1686
1687                 file_path = g_strdup(register_data->msg);
1688
1689                 ret = __msc_make_file_list(file_path, &path_array, uid);
1690                 if (ret != MS_MEDIA_ERR_NONE) {
1691                         MS_DBG_ERR("__msc_make_file_list failed [%d]", ret);
1692                         goto FREE_RESOURCE;
1693                 }
1694
1695                 ret = __msc_batch_insert(pid, path_array, uid);
1696
1697 FREE_RESOURCE:
1698                 /*Active flush */
1699                 malloc_trim(0);
1700
1701                 /* If register_files operation is stopped, there is no necessrty for sending result. */
1702                 msc_send_result(ret, register_data);
1703
1704                 MS_DBG_WARN("BULK REGISTER END [%d |%.*s]", ret, MAX_MSG_SIZE, register_data->msg);
1705
1706                 __msc_clear_file_list(path_array);
1707
1708                 g_free(file_path);
1709                 file_path = NULL;
1710                 g_free(register_data);
1711                 register_data = NULL;
1712                 usleep(SCAN_SLEEP_TIME);
1713         }                       /*thread while*/
1714
1715 _POWEROFF:
1716         g_free(file_path);
1717         g_free(register_data);
1718         if (register_array) {
1719                 while (register_array->len != 0) {
1720                         msg_data = g_array_index(register_array , ms_comm_msg_s*, 0);
1721                         g_array_remove_index(register_array, 0);
1722                         g_free(msg_data);
1723                 }
1724                 g_array_free(register_array, FALSE);
1725                 register_array = NULL;
1726         }
1727
1728         __msc_clear_file_list(path_array);
1729
1730         return NULL;
1731 }
1732
1733 static int __msc_set_scan_item(s_scan_item** item, const char* path, int pid)
1734 {
1735         s_scan_item* scan_item = *item;
1736
1737         if (!scan_item)
1738                 scan_item = g_new0(s_scan_item, 1);
1739
1740         g_free(scan_item->path);
1741
1742         scan_item->path = g_strdup(path);
1743         scan_item->pid = pid;
1744
1745         *item = scan_item;
1746
1747         MS_DBG_SWARN("path[%s],pid[%d]", scan_item->path, scan_item->pid);
1748
1749         return MS_MEDIA_ERR_NONE;
1750 }
1751
1752 static void __msc_del_scan_item(s_scan_item** item)
1753 {
1754         if (*item != NULL) {
1755                 g_free((*item)->path);
1756                 g_free(*item);
1757                 *item = NULL;
1758         }
1759 }
1760
1761 int msc_set_cancel_scan_item(const char* cancel_path, int pid)
1762 {
1763         int ret = -1;
1764         MS_DBG_WARN("msc_set_cancel_scan_item begin");
1765         g_mutex_lock(&scan_item_mutex);
1766         if (cancel_path == NULL) {
1767                 MS_DBG_ERR("cancel_path invalid...");
1768                 return ret;
1769         }
1770
1771         if (cur_scan_item != NULL && cur_scan_item->path != NULL) {
1772                 MS_DBG_SWARN("cur_scan_item->path[%s], cur_scan_item->pid[%d]", cur_scan_item->path, cur_scan_item->pid);
1773                 MS_DBG_SWARN("cancel_path[%s], pid[%d]", cancel_path, pid);
1774                 if ((strcmp(cur_scan_item->path, cancel_path) == 0) && (pid == cur_scan_item->pid))
1775                         ret = __msc_set_scan_item(&cancel_scan_item, cancel_path, pid);
1776                 else if ((pid == -1) && (strncmp(cur_scan_item->path, cancel_path, strlen(cancel_path)) == 0))
1777                         ret = __msc_set_scan_item(&cancel_scan_item, cancel_path, pid);
1778         } else {
1779                 MS_DBG_ERR("cur_scan_item == NULL || cur_scan_item->path == NULL");
1780         }
1781         g_mutex_unlock(&scan_item_mutex);
1782
1783         MS_DBG_WARN("msc_set_cancel_scan_item end");
1784         return ret;
1785 }
1786
1787 static void __msc_del_cancel_scan_item(void)
1788 {
1789         g_mutex_lock(&scan_item_mutex);
1790         __msc_del_scan_item(&cancel_scan_item);
1791         g_mutex_unlock(&scan_item_mutex);
1792 }
1793
1794 static void msc_set_cur_scan_item(const char* cur_scan_path, int pid)
1795 {
1796         g_mutex_lock(&scan_item_mutex);
1797         __msc_set_scan_item(&cur_scan_item, cur_scan_path, pid);
1798         g_mutex_unlock(&scan_item_mutex);
1799 }
1800
1801 static void __msc_del_cur_scan_item(void)
1802 {
1803         g_mutex_lock(&scan_item_mutex);
1804         __msc_del_scan_item(&cur_scan_item);
1805         g_mutex_unlock(&scan_item_mutex);
1806 }
1807
1808 void msc_set_blocked_path(const char *blocked_path)
1809 {
1810         MS_DBG_FENTER();
1811
1812         g_mutex_lock(&blocked_mutex2);
1813
1814         if (g_blocked_path2 != NULL) {
1815                 MS_DBG_SWARN("g_blocked_path is not NULL [%s]", g_blocked_path2);
1816                 g_free(g_blocked_path2);
1817         }
1818
1819         g_blocked_path2 = g_strdup(blocked_path);
1820
1821         g_mutex_unlock(&blocked_mutex2);
1822
1823         MS_DBG_FLEAVE();
1824 }
1825
1826 static void __msc_del_blocked_path(void)
1827 {
1828         MS_DBG_FENTER();
1829
1830         g_mutex_lock(&blocked_mutex2);
1831
1832         if (g_blocked_path2 != NULL) {
1833                 MS_DBG_SWARN("g_blocked_path is not NULL [%s]", g_blocked_path2);
1834                 MS_SAFE_FREE(g_blocked_path2);
1835         }
1836
1837         g_mutex_unlock(&blocked_mutex2);
1838
1839         MS_DBG_FLEAVE();
1840 }
1841
1842 static int __msc_check_memory_status(uid_t uid)
1843 {
1844         int ret = MS_MEDIA_ERR_NONE;
1845         double db_size = 0.0;
1846
1847         /*check remain space*/
1848         ret = __msc_check_remain_space(uid);
1849         if (ret == MS_MEDIA_ERR_NOT_ENOUGH_SPACE || ret == MS_MEDIA_ERR_DB_FULL_FAIL){
1850                 return ret;
1851         }
1852
1853         /*check db size*/
1854         ms_check_size_mediadb(uid, &db_size);
1855         if (db_size >= MEDIA_DB_SIZE_LIMIT_1) {
1856                 MS_DBG_ERR("DB SIZE [%lf] REACH THE FIRST LIMIT [%lf]", db_size, MEDIA_DB_SIZE_LIMIT_1);
1857                 return MS_MEDIA_ERR_DB_LIMIT_1;
1858         }
1859
1860         return MS_MEDIA_ERR_NONE;
1861 }
1862
1863 static int __msc_check_remain_space(uid_t uid)
1864 {
1865         int err = MS_MEDIA_ERR_NONE;
1866         double free_space = 0.0;
1867         double db_size = 0.0;
1868
1869         err = ms_get_remain_space(&free_space);
1870         if (err != MS_MEDIA_ERR_NONE) {
1871                 MS_DBG_ERR("ms_get_remain_space failed");
1872         } else {
1873                 if (free_space < MEDIA_DB_SPACE_LIMIT) {
1874                         MS_DBG_ERR("NOT ENOUGH SPACE WE DO NOT UPDATE MEDIA DB FREE SPACE [%lf]", free_space);
1875 #ifdef _USE_TVPD_MODE
1876                         ms_config_set_int(MS_DB_LIMIT, 0);
1877 #endif
1878                         return MS_MEDIA_ERR_NOT_ENOUGH_SPACE;
1879                 }
1880         }
1881
1882         err = ms_check_size_mediadb(uid, &db_size);
1883         if (err != MS_MEDIA_ERR_NONE) {
1884                 MS_DBG_ERR("msc_check_dbsize failed");
1885         } else {
1886                 if (db_size >= MEDIA_DB_SIZE_LIMIT_2) {
1887                         MS_DBG_ERR("REACH LIMIT DB SIZE [%lf]", db_size);
1888
1889                         MS_DBG_ERR("START REMOVE INVALID DATA");
1890                         msc_cleanup_invalid_values(uid);
1891                         MS_DBG_ERR("END REMOVE INVALID DATA");
1892
1893                         ms_check_size_mediadb(uid, &db_size);
1894                         if (db_size >= MEDIA_DB_SIZE_LIMIT_2) {
1895 #ifdef _USE_TVPD_MODE
1896                                 ms_config_set_int(MS_DB_LIMIT, 0);
1897 #endif
1898                                 MS_DBG_ERR("DB IS FULL. CANNOT UPDATE[%lf]", db_size);
1899                                 return MS_MEDIA_ERR_DB_FULL_FAIL;
1900                         }
1901                 }
1902         }
1903
1904         return MS_MEDIA_ERR_NONE;
1905 }
1906
1907 void msc_init_scanner(void)
1908 {
1909         if (!scan_queue2) scan_queue2 = g_async_queue_new();
1910         if (!reg_queue2) reg_queue2 = g_async_queue_new();
1911         if (!storage_queue2) storage_queue2 = g_async_queue_new();
1912
1913         /*Init mutex variable*/
1914         g_mutex_init(&scan_req_mutex2);
1915
1916 }
1917
1918 void msc_deinit_scanner(void)
1919 {
1920         if (scan_queue2) g_async_queue_unref(scan_queue2);
1921         if (reg_queue2) g_async_queue_unref(reg_queue2);
1922         if (storage_queue2) g_async_queue_unref(storage_queue2);
1923
1924         /*Clear db mutex variable*/
1925         g_mutex_clear(&scan_req_mutex2);
1926
1927 }
1928
1929 int msc_push_scan_request(ms_scan_type_e scan_type, ms_comm_msg_s *recv_msg)
1930 {
1931         int ret = MS_MEDIA_ERR_NONE;
1932
1933         switch (scan_type) {
1934         case MS_SCAN_STORAGE:
1935                 g_async_queue_push(storage_queue2, recv_msg);
1936                 break;
1937         case MS_SCAN_DIRECTORY:
1938                 g_async_queue_push(scan_queue2, recv_msg);
1939                 break;
1940         case MS_SCAN_REGISTER:
1941                 g_async_queue_push(reg_queue2, recv_msg);
1942                 break;
1943         default:
1944                 MS_DBG_ERR("invalid parameter");
1945                 ret = MS_MEDIA_ERR_INVALID_PARAMETER;
1946                 break;
1947         }
1948
1949         return ret;
1950 }
1951
1952 void msc_stop_scan_thread(void)
1953 {
1954         ms_comm_msg_s *data = NULL;
1955
1956         msc_set_power_status(true);
1957
1958         if (scan_queue2) {
1959                 /*notify to scannig thread*/
1960                 data = g_new0(ms_comm_msg_s, 1);
1961
1962                 data->pid = POWEROFF;
1963                 msc_push_scan_request(MS_SCAN_DIRECTORY, data);
1964         }
1965
1966         if (reg_queue2) {
1967                 /*notify to register thread*/
1968                 data = g_new0(ms_comm_msg_s, 1);
1969
1970                 data->pid = POWEROFF;
1971                 msc_push_scan_request(MS_SCAN_REGISTER, data);
1972         }
1973
1974         if (storage_queue2) {
1975                 /*notify to register thread*/
1976                 data = g_new0(ms_comm_msg_s, 1);
1977
1978                 data->pid = POWEROFF;
1979                 msc_push_scan_request(MS_SCAN_STORAGE, data);
1980         }
1981 }
1982
1983 int msc_get_remain_scan_request(ms_scan_type_e scan_type, int *remain_request)
1984 {
1985         int ret = MS_MEDIA_ERR_NONE;
1986
1987         switch (scan_type) {
1988         case MS_SCAN_STORAGE:
1989                 *remain_request = g_async_queue_length(storage_queue2);
1990                 break;
1991         case MS_SCAN_DIRECTORY:
1992                 *remain_request = g_async_queue_length(scan_queue2);
1993                 break;
1994         case MS_SCAN_REGISTER:
1995                 *remain_request = g_async_queue_length(reg_queue2);
1996                 break;
1997         default:
1998                 MS_DBG_ERR("invalid parameter");
1999                 ret = MS_MEDIA_ERR_INVALID_PARAMETER;
2000                 break;
2001         }
2002
2003         return ret;
2004 }
2005
2006 int msc_get_dir_scan_status(bool *scan_status)
2007 {
2008         *scan_status = g_directory_scan_processing2;
2009
2010         return MS_MEDIA_ERR_NONE;
2011 }
2012