4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Yong Yeon Kim <yy9875.kim@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <dirent.h> /* Defines DT_* constants */
28 #include <sys/syscall.h>
33 #include <usb-device.h>
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"
47 #define MAX_SCAN_COUNT 300
49 #define DIR_SCAN_NON_SCAN 0
50 #define DIR_SCAN_RECURSIVE 1
51 #define DIR_SCAN_NON_RECURSIVE 2
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;
65 static char *g_blocked_path2;
67 static s_scan_item* cancel_scan_item = NULL;
68 static s_scan_item* cur_scan_item = NULL;
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;
76 typedef int (*DIR_SCAN_CB)();
77 static DIR_SCAN_CB g_dir_scan_cb;
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) */
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);
111 static int __msc_set_dir_scan_cb(DIR_SCAN_CB cb)
115 return MS_MEDIA_ERR_NONE;
118 static int __msc_call_dir_scan_cb(void)
120 if (g_dir_scan_cb != NULL) {
123 return MS_MEDIA_ERR_NONE;
126 return MS_MEDIA_ERR_INTERNAL;
129 static int __msc_remove_dir_scan_cb(void)
131 g_dir_scan_cb = NULL;
133 return MS_MEDIA_ERR_NONE;
136 void msc_init_scan_thread(void)
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);
145 g_cond_init(&data_cond2);
148 void msc_deinit_scan_thread(void)
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);
157 g_cond_clear(&data_cond2);
160 static int __msc_resume_scan(void)
162 g_mutex_lock(&data_mutex2);
164 g_cond_signal(&data_cond2);
166 g_mutex_unlock(&data_mutex2);
168 return MS_MEDIA_ERR_NONE;
171 static void __msc_pause_scan(void)
173 g_mutex_lock(&data_mutex2);
175 g_cond_wait(&data_cond2, &data_mutex2);
177 g_mutex_unlock(&data_mutex2);
180 static int __msc_check_stop_status(int scan_type, const char *start_path, int pid)
182 int ret = MS_MEDIA_ERR_NONE;
184 /*check poweroff status*/
186 MS_DBG_ERR("Power off");
187 ret = MS_MEDIA_ERR_SCANNER_FORCE_STOP;
191 if (strncmp(start_path, MEDIA_ROOT_PATH_DISC, strlen(MEDIA_ROOT_PATH_DISC)) == 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;
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);
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;
216 MS_DBG_ERR("start path is not same as cancel path");
219 ret = MS_MEDIA_ERR_SCANNER_FORCE_STOP;
224 g_mutex_unlock(&scan_req_mutex2);
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;
238 MS_SAFE_FREE(g_blocked_path2);
241 g_mutex_unlock(&blocked_mutex2);
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)
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;
259 char buf[BUF_SIZE] = {0,};
260 struct linux_dirent *d;
265 const char *trash = "$RECYCLE.BIN";
268 MS_DBG_SWARN("storage id [%s] start path [%s]", storage_id, start_path);
270 /* make new array for storing directory */
271 dir_array = g_array_new(FALSE, FALSE, sizeof(char*));
273 /* add first direcotiry to directory array */
274 new_start_path = g_strdup(start_path);
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);
280 is_recursive = (scan_type == MS_MSG_DIRECTORY_SCANNING_NON_RECURSIVE) ? false : true;
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);*/
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");
290 MS_DBG_SWARN("ms_insert_folder insert path[%s]", new_start_path);
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);
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);
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);
313 __msc_set_dir_scan_cur_path(current_path);
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)
323 ret = MS_MEDIA_ERR_NONE;
328 MS_DBG_ERR("[DATA DISC] PASS IGNORE");
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;
336 if (is_recursive == true)
337 ms_change_validity_item_batch(handle, storage_id, new_start_path, 1, 2, uid);
342 ms_insert_folder_start();
343 ms_set_folder_scan_status(handle, storage_id, current_path, MS_DIR_SCAN_PROCESSING, uid);
346 fd = open(current_path, O_RDONLY | O_DIRECTORY);
348 MS_DBG_STRERROR("open fails");
349 ms_set_folder_scan_status(handle, storage_id, current_path, MS_DIR_SCAN_STOP, uid);
354 if (strncmp(current_path, MEDIA_ROOT_PATH_DISC, strlen(MEDIA_ROOT_PATH_DISC)) == 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;
363 nread = syscall(SYS_getdents64, fd, buf, BUF_SIZE);
365 MS_DBG_STRERROR("getdents");
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);
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;
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);
398 for (bpos = 0; bpos < nread;) {
400 if (sleep_count % 5 == 0) {
402 usleep(SCAN_SLEEP_TIME);
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);
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;
418 if (is_recursive == true)
419 ms_change_validity_item_batch(handle, storage_id, new_start_path, 1, 2, uid);
421 //ms_set_folder_scan_status(handle, storage_id, current_path, MS_DIR_SCAN_STOP, uid);
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);
433 d = (struct linux_dirent *) (buf + bpos);
435 if (d->d_name[0] == '.') {
440 if (strcmp(d->d_name, trash) == 0) {
441 MS_DBG_ERR("trash directory");
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");
452 if (d->d_type == DT_UNKNOWN) {
454 if (stat(path, &st) == 0) {
455 if (S_ISREG(st.st_mode))
457 else if (S_ISDIR(st.st_mode))
462 if (d->d_type == DT_REG) {
463 if (!ms_check_support_media_type(path)) {
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++);
479 //MS_DBG_ERR("insert count %d", nScanCount);
480 if (scan_count >= MAX_SCAN_COUNT) {
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);
487 if (is_recursive == true)
488 ms_change_validity_item_batch(handle, storage_id, new_start_path, 1, 2, uid);
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);
500 if (ms_insert_folder(handle, storage_id, new_path, uid) != MS_MEDIA_ERR_NONE)
501 MS_DBG_ERR("insert folder failed");
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");
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);
521 ms_update_folder_time(handle, storage_id, current_path, uid);
525 ms_insert_folder_end(uid);
526 ms_set_folder_scan_status(handle, storage_id, current_path, MS_DIR_SCAN_DONE, uid);
533 MS_SAFE_FREE(current_path);
534 __msc_set_dir_scan_cur_path(NULL);
535 usleep(SCAN_SLEEP_TIME);
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);
552 g_free(new_start_path);
553 __msc_set_dir_scan_cur_path(NULL);
555 __msc_clear_file_list(dir_array);
557 ms_batch_commit_disable(true, true, uid);
559 if (ret != MS_MEDIA_ERR_NONE) MS_DBG_INFO("ret : %d", ret);
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)
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;
576 char buf[BUF_SIZE] = {0,};
577 struct linux_dirent *d;
582 const char *trash = "$RECYCLE.BIN";
584 bool is_missing = false;
585 ms_dir_scan_status_e scan_status = MS_DIR_SCAN_NONE;
587 MS_DBG_SWARN("storage id [%s] start path [%s]", storage_id, start_path);
589 /* make new array for storing directory */
590 dir_array = g_array_new(FALSE, FALSE, sizeof(char*));
592 /* add first direcotiry to directory array */
593 new_start_path = g_strdup(start_path);
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");
600 scan_function = (scan_type == MS_MSG_STORAGE_ALL) ? ms_scan_item_batch : ms_scan_validate_item;
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)
610 /*ms_batch_commit_disable(true, true, uid);*/
611 ms_batch_commit_enable(true, true, false, pid);
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);
617 __msc_set_storage_scan_cur_path(current_path);
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)
626 ret = MS_MEDIA_ERR_NONE;
631 ret = msc_check_db_size(uid, scan_type);
632 if (ret != MS_MEDIA_ERR_NONE)
635 ms_get_folder_scan_status(handle, storage_id, current_path, (int *)&scan_status);
637 if (scan_status == MS_DIR_SCAN_PROCESSING && g_directory_scan_processing2 != DIR_SCAN_NON_SCAN) {
639 MS_DBG_SERR("%s is scanning, ignore current path, scan next path !!", current_path);
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);
648 __msc_get_null_scan_folder_list(handle, storage_id, current_path, dir_array);
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);
660 ms_insert_folder_start();
661 ms_set_folder_scan_status(handle, storage_id, current_path, MS_DIR_SCAN_PROCESSING, uid);
664 fd = open(current_path, O_RDONLY | O_DIRECTORY);
666 MS_DBG_STRERROR("open fails");
667 ms_set_folder_scan_status(handle, storage_id, current_path, MS_DIR_SCAN_STOP, uid);
672 nread = syscall(SYS_getdents64, fd, buf, BUF_SIZE);
674 MS_DBG_STRERROR("getdents");
678 /*check poweroff status*/
679 ret = __msc_check_stop_status(scan_type, new_start_path, pid);
680 if (ret != MS_MEDIA_ERR_NONE)
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);
689 if (io_err_storage == MS_MAX_IO_ERR_COUNT) {
690 MS_DBG_ERR("REACH I/O MAX COUNT[%d]", io_err_storage);
697 for (bpos = 0; bpos < nread;) {
699 if (sleep_count % 5 == 0) {
701 usleep(SCAN_SLEEP_TIME);
703 /*check poweroff status*/
704 ret = __msc_check_stop_status(scan_type, new_start_path, pid);
705 if (ret != MS_MEDIA_ERR_NONE)
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);
714 if (io_err_storage == MS_MAX_IO_ERR_COUNT) {
715 MS_DBG_ERR("REACH I/O MAX COUNT[%d]", io_err_storage);
719 d = (struct linux_dirent *) (buf + bpos);
721 if (d->d_name[0] == '.') {
726 if (strcmp(d->d_name, trash) == 0) {
727 MS_DBG_ERR("trash directory");
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");
738 if (d->d_type == DT_UNKNOWN) {
740 if (stat(path, &st) == 0) {
741 if (S_ISREG(st.st_mode))
743 else if (S_ISDIR(st.st_mode))
748 if (d->d_type == DT_REG) {
749 /* check media type */
750 if (!ms_check_support_media_type(path)) {
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++);
766 //MS_DBG_ERR("insert count %d", nScanCount);
767 if (scan_count >= MAX_SCAN_COUNT) {
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);
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);
779 if (ms_insert_folder(handle, storage_id, new_path, uid) != MS_MEDIA_ERR_NONE)
780 MS_DBG_ERR("insert folder failed");
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);
798 MS_SAFE_FREE(current_path);
799 __msc_set_storage_scan_cur_path(NULL);
801 if (dir_array->len == 0 && is_missing) {
804 if (g_directory_scan_processing2 == DIR_SCAN_NON_SCAN) {
805 ret = __msc_get_null_scan_folder_list(handle, storage_id, NULL, dir_array);
807 MS_DBG_WARN("no wait folder scan callback");
809 if (ret != MS_MEDIA_ERR_NONE)
812 __msc_set_dir_scan_cb(__msc_dir_scan_cb);
816 MS_DBG_WARN("wait folder scan callback");
818 __msc_remove_dir_scan_cb();
820 ret = __msc_get_null_scan_folder_list(handle, storage_id, NULL, dir_array);
822 if (ret != MS_MEDIA_ERR_NONE)
826 usleep(SCAN_SLEEP_TIME);
829 if (!MS_STRING_VALID(MEDIA_ROOT_PATH_USB)) {
830 MS_DBG_ERR("Fail to get USB path");
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");
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");
847 MS_DBG_WARN("wait folder scan callback");
849 __msc_remove_dir_scan_cb();
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;
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);
873 g_free(new_start_path);
874 __msc_set_storage_scan_cur_path(NULL);
875 __msc_clear_file_list(dir_array);
877 ms_batch_commit_disable(true, true, uid);
879 if (ret != MS_MEDIA_ERR_NONE) MS_DBG_INFO("ret : %d", ret);
884 static int __msc_get_null_scan_folder_list(sqlite3 *handle, const char *stroage_id, char *path, GArray *dir_array)
886 int ret = MS_MEDIA_ERR_NONE;
887 char *new_path = NULL;
888 char *current_path = NULL;
889 GArray *cur_dir_array = NULL;
891 ret = ms_get_null_scan_folder_list(handle, stroage_id, path, &cur_dir_array);
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);
900 new_path = g_strdup(current_path);
901 g_array_append_val(dir_array, new_path);
902 g_free(current_path);
906 __msc_clear_file_list(cur_dir_array);
911 static int __msc_check_scan_same_path(char *scan_path)
913 int ret = MS_MEDIA_ERR_NONE;
914 unsigned int storage_len, folder_len, min_len;
916 g_mutex_lock(&storage_scan_mutex2);
918 if (NULL == scan_path || NULL == g_storage_scan_path) {
919 g_mutex_unlock(&storage_scan_mutex2);
921 return MS_MEDIA_ERR_INTERNAL;
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;
928 ret = strncmp(g_storage_scan_path, scan_path, min_len);
930 g_mutex_unlock(&storage_scan_mutex2);
935 static void __msc_set_storage_scan_cur_path(char *scan_path)
937 g_mutex_lock(&storage_scan_mutex2);
939 g_free(g_storage_scan_path);
940 g_storage_scan_path = g_strdup(scan_path);
942 g_mutex_unlock(&storage_scan_mutex2);
945 static int __msc_dir_and_storage_scan_same_path(char *start_path)
947 int ret = MS_MEDIA_ERR_NONE;
948 unsigned int storage_len, folder_len;
950 char *storage_path = NULL;
951 char *remain_path = NULL;
954 if (!MS_STRING_VALID(MEDIA_ROOT_PATH_USB)) {
955 MS_DBG_ERR("Fail to get USB path");
956 return MS_MEDIA_ERR_INTERNAL;
959 remain_path = strstr(start_path+strlen(MEDIA_ROOT_PATH_USB) +1, "/");
960 if (remain_path != NULL)
961 remain_len = strlen(remain_path);
963 storage_path = g_strndup(start_path, strlen(start_path) - remain_len);
965 g_mutex_lock(&dir_scan_mutex2);
967 if (NULL == g_dir_scan_path || NULL == storage_path) {
968 g_free(storage_path);
969 g_mutex_unlock(&dir_scan_mutex2);
971 return MS_MEDIA_ERR_INTERNAL;
974 storage_len = strlen(storage_path);
975 folder_len = strlen(g_dir_scan_path);
977 if (folder_len < storage_len)
980 ret = strncmp(storage_path, g_dir_scan_path, storage_len);
982 g_free(storage_path);
983 g_mutex_unlock(&dir_scan_mutex2);
989 static void __msc_set_dir_scan_cur_path(char *scan_path)
991 g_mutex_lock(&dir_scan_mutex2);
993 g_free(g_dir_scan_path);
994 g_dir_scan_path = g_strdup(scan_path);
996 g_mutex_unlock(&dir_scan_mutex2);
999 static int __msc_db_update(sqlite3 *handle, const char *storage_id, const ms_comm_msg_s * scan_data)
1002 int err = MS_MEDIA_ERR_NONE;
1003 char *start_path = NULL;
1004 ms_user_storage_type_e storage_type;
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");
1010 scan_type = scan_data->msg_type;
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);
1021 if (err != MS_MEDIA_ERR_NONE)
1022 MS_DBG_ERR("error : %d", err);
1024 } else if (scan_type == MS_MSG_STORAGE_INVALID) {
1025 MS_DBG_WARN("INVALID");
1026 msc_remove_extract_request(scan_data);
1034 static void __msc_pop_new_request(ms_comm_msg_s **scan_data)
1036 *scan_data = g_async_queue_pop(scan_queue2);
1039 gpointer msc_directory_scan_thread(gpointer data)
1041 ms_comm_msg_s *scan_data = NULL;
1043 int ret = MS_MEDIA_ERR_NONE;
1044 sqlite3 *handle = NULL;
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;
1056 __msc_pop_new_request(&scan_data);
1057 ret = MS_MEDIA_ERR_NONE;
1059 if (scan_data->pid == POWEROFF) {
1060 MS_DBG_ERR("power off");
1064 MS_DBG_WARN("DIRECTORY SCAN START [%.*s, %d]", MAX_MSG_SIZE, scan_data->msg, scan_data->msg_type);
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;
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");
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;
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");
1092 storage_id = g_strdup(scan_data->storage_id);
1094 MS_DBG("path [%.*s], storage_id [%s], scan_type [%d]", MAX_MSG_SIZE, scan_data->msg, storage_id, scan_type);
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;
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;
1109 ms_trim_dir_path(scan_data->msg);
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);
1118 noti_type = MS_ITEM_INSERT;
1119 MS_DBG_WARN("[%.*s] new insert path", MAX_MSG_SIZE, scan_data->msg);
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;
1128 /*get the UUID of deleted folder*/
1129 ms_get_folder_id(handle, storage_id, scan_data->msg, &folder_uuid);
1131 MS_DBG_SWARN("[%.*s][%s] delete path", MAX_MSG_SIZE, scan_data->msg, folder_uuid);
1134 if (scan_type == MS_MSG_DIRECTORY_SCANNING) {
1136 MS_DBG_WARN("start recursive dir scan!!");
1138 g_directory_scan_processing2 = DIR_SCAN_RECURSIVE;
1139 err = __msc_check_scan_same_path(scan_data->msg);
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);
1147 ret = __msc_check_stop_status(scan_type, scan_data->msg, scan_data->pid);
1148 if (ret != MS_MEDIA_ERR_NONE)
1152 err = __msc_check_scan_same_path(scan_data->msg);
1153 if (err != MS_MEDIA_ERR_NONE)
1157 MS_DBG_WARN("[%.*s] scan done, wait finished", MAX_MSG_SIZE, scan_data->msg);
1161 ms_get_folder_scan_status(handle, storage_id, scan_data->msg, (int*)&scan_status);
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);
1166 ms_set_folder_item_validity(handle, storage_id, scan_data->msg, MS_INVALID, MS_RECURSIVE, uid);
1168 msc_send_result_partial(ret, MS_MSG_RECURSIVE_START, scan_data->pid, scan_data->msg);
1171 MS_DBG_WARN("start non recursive dir scan!!");
1173 g_directory_scan_processing2 = DIR_SCAN_NON_RECURSIVE;
1174 ms_check_folder_modified(handle, scan_data->msg, storage_id, &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);
1181 if (scan_status == MS_DIR_SCAN_DONE) {
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);*/
1187 } else if (scan_status == MS_DIR_SCAN_PROCESSING) {
1188 MS_DBG_WARN("[%.*s] scanning, waiting...", MAX_MSG_SIZE, scan_data->msg);
1193 ret = __msc_check_stop_status(scan_type, scan_data->msg, scan_data->pid);
1194 if (ret != MS_MEDIA_ERR_NONE)
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);
1205 if (scan_status == MS_DIR_SCAN_DONE) {
1206 MS_DBG_WARN("[%.*s] scan done, wait finished", MAX_MSG_SIZE, scan_data->msg);
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);
1213 err = ms_set_folder_item_validity(handle, storage_id, scan_data->msg, MS_INVALID, MS_NON_RECURSIVE, uid);
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);
1221 if (err != MS_MEDIA_ERR_NONE)
1222 MS_DBG_ERR("error : %d", err);
1224 /*call for bundle commit*/
1225 ms_batch_commit_enable(true, true, false, 0);
1227 if (strcmp(scan_data->msg, MEDIA_ROOT_PATH_DISC) == 0) {
1228 MS_DBG("[DATA DISC]");
1229 msc_set_disc_dir_scan_status(true);
1232 /*insert data into media db */
1233 ret = __msc_db_update(handle, storage_id, scan_data);
1235 /*call for bundle commit*/
1236 ms_batch_commit_disable(true, true, uid);
1238 MS_DBG_WARN("folder scan done, sent cb event path = [%.*s]", MAX_MSG_SIZE, scan_data->msg);
1239 __msc_call_dir_scan_cb();
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");
1245 if (!ms_delete_invalid_items(handle, storage_id, storage_type, scan_data->uid))
1246 MS_DBG_ERR("deleting invalid items in storage failed");*/
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");
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);
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");
1266 if (noti_type == MS_ITEM_DELETE) {
1267 ms_send_dir_update_noti(scan_data->msg, folder_uuid, noti_type, scan_data->pid);
1269 msc_insert_exactor_request(scan_data->msg_type, true, scan_data->storage_id, scan_data->msg, scan_data->pid, uid, noti_type);
1272 MS_DBG_ERR("power off");
1280 scan_data->msg_type = MS_MSG_SCANNER_COMPLETE;
1281 msc_send_result(ret, scan_data);
1287 g_free(folder_uuid);
1290 g_directory_scan_processing2 = DIR_SCAN_NON_SCAN;
1291 __msc_del_cur_scan_item();
1292 __msc_del_cancel_scan_item();
1294 MS_DBG_WARN("DIRECTORY SCAN END [%d]", ret);
1298 /*disconnect form media db*/
1299 if (handle) ms_disconnect_db(handle);
1300 usleep(SCAN_SLEEP_TIME);
1305 if (handle) ms_disconnect_db(handle);
1310 static int __msc_dir_scan_cb(void)
1312 return __msc_resume_scan();
1315 static void __msc_check_pvr_svc(void)
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");
1325 MS_DBG_WARN("PVR service is ready");
1333 MS_DBG("NOT SUPPORT RECORED CONTENT");
1337 gpointer msc_storage_scan_thread(gpointer data)
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;
1344 bool valid_status = true;
1345 char *update_path = NULL;
1346 uid_t uid = MEDIA_DEFAULT_UID;
1349 scan_data = g_async_queue_pop(storage_queue2);
1350 if (scan_data->pid == POWEROFF) {
1351 MS_DBG_ERR("power off");
1355 MS_DBG_WARN("STORAGE SCAN START [%.*s]", MAX_MSG_SIZE, scan_data->msg);
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;
1366 __msc_check_pvr_svc();
1368 uid = scan_data->uid;
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");
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");
1383 update_path = g_strdup(scan_data->msg);
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);
1393 ms_set_storage_scan_status(handle, scan_data->storage_id, MEDIA_SCAN_PROCESSING, uid);
1395 /*start db updating */
1396 ms_set_db_status(MS_DB_UPDATING, storage_type);
1398 if (strcmp(update_path, MEDIA_ROOT_PATH_DISC) == 0) {
1399 MS_DBG("[DATA DISC]");
1400 msc_set_disc_stg_scan_status(true);
1403 valid_status = (scan_type == MS_MSG_STORAGE_PARTIAL || MS_MSG_STORAGE_ALL == scan_type) ? true : false;
1405 if (scan_type != MS_MSG_STORAGE_INVALID)
1406 ms_batch_commit_enable(true, valid_status, false, 0);
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");
1414 ret = __msc_db_update(handle, scan_data->storage_id, scan_data);
1416 /*call for bundle commit*/
1417 if (scan_type != MS_MSG_STORAGE_INVALID)
1418 ms_batch_commit_disable(true, valid_status, uid);
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);
1426 /* send notification */
1427 /*ms_send_dir_update_noti(update_path, NULL, MS_ITEM_UPDATE, scan_data->pid);*/
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);
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);
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);
1443 __msc_del_blocked_path();
1445 g_free(update_path);
1449 MS_DBG_ERR("power off");
1453 /*disconnect from media db*/
1454 if (handle) ms_disconnect_db(handle);
1459 scan_data->msg_type = MS_MSG_SCANNER_COMPLETE;
1460 msc_send_result(ret, scan_data);
1465 MS_DBG_WARN("STORAGE SCAN END[%d]", ret);
1468 usleep(SCAN_SLEEP_TIME);
1473 if (handle) ms_disconnect_db(handle);
1478 static void __msc_insert_register_request(GArray *register_array, ms_comm_msg_s *insert_data)
1480 MS_DBG_SLOG("path : %.*s", MAX_MSG_SIZE, insert_data->msg);
1482 if (insert_data->pid == POWEROFF)
1483 g_array_prepend_val(register_array, insert_data);
1485 g_array_append_val(register_array, insert_data);
1489 static void __msc_clear_file_list(GArray *path_array)
1492 while (path_array->len != 0) {
1494 data = g_array_index(path_array , char*, 0);
1495 g_array_remove_index(path_array, 0);
1498 g_array_free(path_array, FALSE);
1503 static int __msc_make_file_list(char *file_path, GArray **path_array, uid_t uid)
1506 char buf[MS_FILE_PATH_LEN_MAX] = {0,};
1509 int res = MS_MEDIA_ERR_NONE;
1510 int ret = MS_MEDIA_ERR_NONE;
1512 /* load the file list from file */
1513 fp = fopen(file_path, "rt");
1515 MS_DBG_STRERROR("fopen failed");
1516 res = MS_MEDIA_ERR_INTERNAL;
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 *));
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 */
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);
1536 /* insert getted path to the list */
1537 g_array_append_val(*path_array, path);
1543 return MS_MEDIA_ERR_NONE;
1547 __msc_clear_file_list(*path_array);
1555 static int __msc_batch_insert(int pid, GArray *path_array, uid_t uid)
1559 sqlite3 *handle = NULL;
1560 char *insert_path = NULL;
1561 char storage_id[MS_UUID_SIZE] = {0,};
1562 bool power_off_status = false;
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;
1569 /*start db updating */
1570 /*call for bundle commit*/
1571 ms_batch_commit_enable(true, false, true, pid);
1573 MS_DBG_WARN("BULK REGISTER START");
1575 /* get the inserting file path from array and insert to db */
1576 for (i = 0; i < path_array->len; i++) {
1578 insert_path = g_array_index(path_array, char*, i);
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");
1588 err = ms_insert_item_batch(handle, storage_id, insert_path, uid);
1590 msc_get_power_status(&power_off_status);
1591 if (power_off_status) {
1592 MS_DBG_ERR("power off");
1593 /*call for bundle commit*/
1598 /*call for bundle commit*/
1599 ms_batch_commit_disable(true, false, uid);
1601 /*disconnect form media db*/
1602 if (handle) ms_disconnect_db(handle);
1604 return MS_MEDIA_ERR_NONE;
1607 static int __msc_pop_register_request(GArray *register_array, ms_comm_msg_s **register_data)
1610 ms_comm_msg_s *insert_data = NULL;
1613 remain_request = g_async_queue_length(reg_queue2);
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)
1623 } else if (remain_request != 0) {
1624 insert_data = g_async_queue_pop(reg_queue2);
1625 __msc_insert_register_request(register_array, insert_data);
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);
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;
1640 return MS_MEDIA_ERR_NONE;
1644 gpointer msc_register_thread(gpointer data)
1646 ms_comm_msg_s *register_data = NULL;
1647 GArray *register_array = NULL;
1648 GArray *path_array = NULL;
1649 char *file_path = NULL;
1652 uid_t uid = MEDIA_DEFAULT_UID;
1653 ms_comm_msg_s *msg_data = NULL;
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");
1663 ret = __msc_pop_register_request(register_array, ®ister_data);
1664 if (register_data == NULL) {
1665 MS_DBG_ERR("register_data is NULL");
1668 if (register_data->pid == POWEROFF) {
1669 MS_DBG_ERR("power off");
1673 if (ret != MS_MEDIA_ERR_NONE) {
1674 MS_DBG_ERR("__msc_pop_register_request failed [%d]", ret);
1678 /* check current request */
1679 pid = register_data->pid;
1680 uid = register_data->uid;
1682 if (register_data->msg_type != MS_MSG_BULK_INSERT) {
1683 MS_DBG_ERR("wrong message type");
1687 file_path = g_strdup(register_data->msg);
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);
1695 ret = __msc_batch_insert(pid, path_array, uid);
1701 /* If register_files operation is stopped, there is no necessrty for sending result. */
1702 msc_send_result(ret, register_data);
1704 MS_DBG_WARN("BULK REGISTER END [%d |%.*s]", ret, MAX_MSG_SIZE, register_data->msg);
1706 __msc_clear_file_list(path_array);
1710 g_free(register_data);
1711 register_data = NULL;
1712 usleep(SCAN_SLEEP_TIME);
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);
1724 g_array_free(register_array, FALSE);
1725 register_array = NULL;
1728 __msc_clear_file_list(path_array);
1733 static int __msc_set_scan_item(s_scan_item** item, const char* path, int pid)
1735 s_scan_item* scan_item = *item;
1738 scan_item = g_new0(s_scan_item, 1);
1740 g_free(scan_item->path);
1742 scan_item->path = g_strdup(path);
1743 scan_item->pid = pid;
1747 MS_DBG_SWARN("path[%s],pid[%d]", scan_item->path, scan_item->pid);
1749 return MS_MEDIA_ERR_NONE;
1752 static void __msc_del_scan_item(s_scan_item** item)
1754 if (*item != NULL) {
1755 g_free((*item)->path);
1761 int msc_set_cancel_scan_item(const char* cancel_path, int pid)
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...");
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);
1779 MS_DBG_ERR("cur_scan_item == NULL || cur_scan_item->path == NULL");
1781 g_mutex_unlock(&scan_item_mutex);
1783 MS_DBG_WARN("msc_set_cancel_scan_item end");
1787 static void __msc_del_cancel_scan_item(void)
1789 g_mutex_lock(&scan_item_mutex);
1790 __msc_del_scan_item(&cancel_scan_item);
1791 g_mutex_unlock(&scan_item_mutex);
1794 static void msc_set_cur_scan_item(const char* cur_scan_path, int pid)
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);
1801 static void __msc_del_cur_scan_item(void)
1803 g_mutex_lock(&scan_item_mutex);
1804 __msc_del_scan_item(&cur_scan_item);
1805 g_mutex_unlock(&scan_item_mutex);
1808 void msc_set_blocked_path(const char *blocked_path)
1812 g_mutex_lock(&blocked_mutex2);
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);
1819 g_blocked_path2 = g_strdup(blocked_path);
1821 g_mutex_unlock(&blocked_mutex2);
1826 static void __msc_del_blocked_path(void)
1830 g_mutex_lock(&blocked_mutex2);
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);
1837 g_mutex_unlock(&blocked_mutex2);
1842 static int __msc_check_memory_status(uid_t uid)
1844 int ret = MS_MEDIA_ERR_NONE;
1845 double db_size = 0.0;
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){
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;
1860 return MS_MEDIA_ERR_NONE;
1863 static int __msc_check_remain_space(uid_t uid)
1865 int err = MS_MEDIA_ERR_NONE;
1866 double free_space = 0.0;
1867 double db_size = 0.0;
1869 err = ms_get_remain_space(&free_space);
1870 if (err != MS_MEDIA_ERR_NONE) {
1871 MS_DBG_ERR("ms_get_remain_space failed");
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);
1878 return MS_MEDIA_ERR_NOT_ENOUGH_SPACE;
1882 err = ms_check_size_mediadb(uid, &db_size);
1883 if (err != MS_MEDIA_ERR_NONE) {
1884 MS_DBG_ERR("msc_check_dbsize failed");
1886 if (db_size >= MEDIA_DB_SIZE_LIMIT_2) {
1887 MS_DBG_ERR("REACH LIMIT DB SIZE [%lf]", db_size);
1889 MS_DBG_ERR("START REMOVE INVALID DATA");
1890 msc_cleanup_invalid_values(uid);
1891 MS_DBG_ERR("END REMOVE INVALID DATA");
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);
1898 MS_DBG_ERR("DB IS FULL. CANNOT UPDATE[%lf]", db_size);
1899 return MS_MEDIA_ERR_DB_FULL_FAIL;
1904 return MS_MEDIA_ERR_NONE;
1907 void msc_init_scanner(void)
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();
1913 /*Init mutex variable*/
1914 g_mutex_init(&scan_req_mutex2);
1918 void msc_deinit_scanner(void)
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);
1924 /*Clear db mutex variable*/
1925 g_mutex_clear(&scan_req_mutex2);
1929 int msc_push_scan_request(ms_scan_type_e scan_type, ms_comm_msg_s *recv_msg)
1931 int ret = MS_MEDIA_ERR_NONE;
1933 switch (scan_type) {
1934 case MS_SCAN_STORAGE:
1935 g_async_queue_push(storage_queue2, recv_msg);
1937 case MS_SCAN_DIRECTORY:
1938 g_async_queue_push(scan_queue2, recv_msg);
1940 case MS_SCAN_REGISTER:
1941 g_async_queue_push(reg_queue2, recv_msg);
1944 MS_DBG_ERR("invalid parameter");
1945 ret = MS_MEDIA_ERR_INVALID_PARAMETER;
1952 void msc_stop_scan_thread(void)
1954 ms_comm_msg_s *data = NULL;
1956 msc_set_power_status(true);
1959 /*notify to scannig thread*/
1960 data = g_new0(ms_comm_msg_s, 1);
1962 data->pid = POWEROFF;
1963 msc_push_scan_request(MS_SCAN_DIRECTORY, data);
1967 /*notify to register thread*/
1968 data = g_new0(ms_comm_msg_s, 1);
1970 data->pid = POWEROFF;
1971 msc_push_scan_request(MS_SCAN_REGISTER, data);
1974 if (storage_queue2) {
1975 /*notify to register thread*/
1976 data = g_new0(ms_comm_msg_s, 1);
1978 data->pid = POWEROFF;
1979 msc_push_scan_request(MS_SCAN_STORAGE, data);
1983 int msc_get_remain_scan_request(ms_scan_type_e scan_type, int *remain_request)
1985 int ret = MS_MEDIA_ERR_NONE;
1987 switch (scan_type) {
1988 case MS_SCAN_STORAGE:
1989 *remain_request = g_async_queue_length(storage_queue2);
1991 case MS_SCAN_DIRECTORY:
1992 *remain_request = g_async_queue_length(scan_queue2);
1994 case MS_SCAN_REGISTER:
1995 *remain_request = g_async_queue_length(reg_queue2);
1998 MS_DBG_ERR("invalid parameter");
1999 ret = MS_MEDIA_ERR_INVALID_PARAMETER;
2006 int msc_get_dir_scan_status(bool *scan_status)
2008 *scan_status = g_directory_scan_processing2;
2010 return MS_MEDIA_ERR_NONE;