diff options
author | William Wilgus <wilgus.william@gmail.com> | 2023-10-06 10:57:05 -0400 |
---|---|---|
committer | William Wilgus <me.theuser@yahoo.com> | 2023-10-10 05:48:37 -0400 |
commit | a0c29d8857ee3c697a9c7f8b396b3a25c88acab4 (patch) | |
tree | a047267e3f34b24a6f31d00046aba5ae685006a5 /apps/plugins/tagcache | |
parent | eb13628bb86084bdf822e109c1301277d88d23d7 (diff) | |
download | rockbox-a0c29d8857ee3c697a9c7f8b396b3a25c88acab4.tar.gz rockbox-a0c29d8857ee3c697a9c7f8b396b3a25c88acab4.zip |
db_commit swap threads, add ability to cancel, backup/restore
extends the db_commit plugin with the ability to delete the database
backup, restore, dis/enable auto-commit
Change-Id: Id61546e463d151399d2ac8459480e6adc5d6fac6
Diffstat (limited to 'apps/plugins/tagcache')
-rw-r--r-- | apps/plugins/tagcache/tagcache.c | 583 |
1 files changed, 511 insertions, 72 deletions
diff --git a/apps/plugins/tagcache/tagcache.c b/apps/plugins/tagcache/tagcache.c index 55ca2e2695..cce9efbed9 100644 --- a/apps/plugins/tagcache/tagcache.c +++ b/apps/plugins/tagcache/tagcache.c | |||
@@ -22,16 +22,19 @@ | |||
22 | /*Plugin Includes*/ | 22 | /*Plugin Includes*/ |
23 | 23 | ||
24 | #include "plugin.h" | 24 | #include "plugin.h" |
25 | #include "errno.h" | ||
26 | |||
25 | /* Redefinitons of ANSI C functions. */ | 27 | /* Redefinitons of ANSI C functions. */ |
26 | #include "lib/wrappers.h" | 28 | #include "lib/wrappers.h" |
27 | #include "lib/helper.h" | 29 | #include "lib/helper.h" |
28 | 30 | ||
29 | static void thread_create(void); | 31 | static void thread_create(void); |
30 | static void thread(void); /* the thread running it all */ | 32 | static void thread(void); /* the thread running commit*/ |
31 | static void allocate_tempbuf(void); | 33 | static void allocate_tempbuf(void); |
32 | static void free_tempbuf(void); | 34 | static void free_tempbuf(void); |
33 | static bool do_timed_yield(void); | 35 | static bool do_timed_yield(void); |
34 | static void _log(const char *fmt, ...); | 36 | static void _log(const char *fmt, ...); |
37 | static bool logdump(bool append); | ||
35 | /*Aliases*/ | 38 | /*Aliases*/ |
36 | #if 0 | 39 | #if 0 |
37 | #ifdef ROCKBOX_HAS_LOGF | 40 | #ifdef ROCKBOX_HAS_LOGF |
@@ -41,7 +44,6 @@ static void _log(const char *fmt, ...); | |||
41 | #endif | 44 | #endif |
42 | #endif | 45 | #endif |
43 | 46 | ||
44 | |||
45 | #define logf _log | 47 | #define logf _log |
46 | #define sleep rb->sleep | 48 | #define sleep rb->sleep |
47 | #define qsort rb->qsort | 49 | #define qsort rb->qsort |
@@ -49,6 +51,7 @@ static void _log(const char *fmt, ...); | |||
49 | #define write(x,y,z) rb->write(x,y,z) | 51 | #define write(x,y,z) rb->write(x,y,z) |
50 | #define ftruncate rb->ftruncate | 52 | #define ftruncate rb->ftruncate |
51 | #define remove rb->remove | 53 | #define remove rb->remove |
54 | #define rename rb->rename | ||
52 | 55 | ||
53 | #define vsnprintf rb->vsnprintf | 56 | #define vsnprintf rb->vsnprintf |
54 | #define mkdir rb->mkdir | 57 | #define mkdir rb->mkdir |
@@ -60,20 +63,26 @@ static void _log(const char *fmt, ...); | |||
60 | 63 | ||
61 | #define current_tick (*rb->current_tick) | 64 | #define current_tick (*rb->current_tick) |
62 | #define crc_32(x,y,z) rb->crc_32(x,y,z) | 65 | #define crc_32(x,y,z) rb->crc_32(x,y,z) |
66 | #define plugin_get_buffer rb->plugin_get_buffer | ||
63 | 67 | ||
64 | |||
65 | #if !defined(SIMULATOR) && !defined(APPLICATION) | ||
66 | |||
67 | #define errno (*rb->__errno()) | ||
68 | #endif | ||
69 | #define ENOENT 2 /* No such file or directory */ | ||
70 | #define EEXIST 17 /* File exists */ | ||
71 | #define MAX_LOG_SIZE 16384 | 68 | #define MAX_LOG_SIZE 16384 |
72 | 69 | ||
73 | #define EV_EXIT MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0xFF) | 70 | #define EV_EXIT MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0xFF) |
74 | #define EV_ACTION MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0x02) | ||
75 | #define EV_STARTUP MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0x01) | 71 | #define EV_STARTUP MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0x01) |
76 | 72 | ||
73 | #define BACKUP_DIRECTORY PLUGIN_APPS_DATA_DIR "/db_commit" | ||
74 | |||
75 | #define RC_SUCCESS 0 | ||
76 | #define RC_USER_CANCEL 2 | ||
77 | |||
78 | enum fcpy_op_flags | ||
79 | { | ||
80 | FCPY_MOVE = 0x00, /* Is a move operation (default) */ | ||
81 | FCPY_COPY = 0x01, /* Is a copy operation */ | ||
82 | FCPY_OVERWRITE = 0x02, /* Overwrite destination */ | ||
83 | FCPY_EXDEV = 0x04, /* Actually copy/move across volumes */ | ||
84 | }; | ||
85 | |||
77 | /* communication to the worker thread */ | 86 | /* communication to the worker thread */ |
78 | static struct | 87 | static struct |
79 | { | 88 | { |
@@ -85,6 +94,23 @@ static struct | |||
85 | long last_useraction_tick; | 94 | long last_useraction_tick; |
86 | } gThread; | 95 | } gThread; |
87 | 96 | ||
97 | /* status of db and commit */ | ||
98 | static struct | ||
99 | { | ||
100 | long last_check; | ||
101 | bool do_commit; | ||
102 | bool auto_commit; | ||
103 | bool commit_ready; | ||
104 | bool db_exists; | ||
105 | bool have_backup; | ||
106 | bool bu_exists; | ||
107 | } gStatus; | ||
108 | |||
109 | static unsigned char logbuffer[MAX_LOG_SIZE + 1]; | ||
110 | static int log_font_h = -1; | ||
111 | static int logindex; | ||
112 | static bool logwrap; | ||
113 | static bool logenabled = true; | ||
88 | 114 | ||
89 | /*Support Fns*/ | 115 | /*Support Fns*/ |
90 | /* open but with a builtin printf for assembling the path */ | 116 | /* open but with a builtin printf for assembling the path */ |
@@ -103,8 +129,6 @@ int open_pathfmt(char *buf, size_t size, int oflag, const char *pathfmt, ...) | |||
103 | 129 | ||
104 | static void sleep_yield(void) | 130 | static void sleep_yield(void) |
105 | { | 131 | { |
106 | rb->queue_remove_from_head(&gThread.queue, EV_ACTION); | ||
107 | rb->queue_post(&gThread.queue, EV_ACTION, 0); | ||
108 | sleep(1); | 132 | sleep(1); |
109 | #undef yield | 133 | #undef yield |
110 | rb->yield(); | 134 | rb->yield(); |
@@ -159,18 +183,10 @@ bool user_check_tag(int index_type, char* build_idx_buf) | |||
159 | /* paste the whole tagcache.c file */ | 183 | /* paste the whole tagcache.c file */ |
160 | #include "../tagcache.c" | 184 | #include "../tagcache.c" |
161 | 185 | ||
162 | static bool logdump(bool append); | ||
163 | static unsigned char logbuffer[MAX_LOG_SIZE + 1]; | ||
164 | static int log_font_h = -1; | ||
165 | static int logindex; | ||
166 | static bool logwrap; | ||
167 | static bool logenabled = true; | ||
168 | |||
169 | static void check_logindex(void) | 186 | static void check_logindex(void) |
170 | { | 187 | { |
171 | if(logindex >= MAX_LOG_SIZE) | 188 | if(logindex >= MAX_LOG_SIZE) |
172 | { | 189 | { |
173 | /* wrap */ | ||
174 | logdump(true); | 190 | logdump(true); |
175 | //logwrap = true; | 191 | //logwrap = true; |
176 | logindex = 0; | 192 | logindex = 0; |
@@ -196,7 +212,6 @@ static void _log(const char *fmt, ...) | |||
196 | return; | 212 | return; |
197 | } | 213 | } |
198 | 214 | ||
199 | |||
200 | #ifdef USB_ENABLE_SERIAL | 215 | #ifdef USB_ENABLE_SERIAL |
201 | int old_logindex = logindex; | 216 | int old_logindex = logindex; |
202 | #endif | 217 | #endif |
@@ -291,13 +306,11 @@ static bool logdisplay(void) | |||
291 | /* if negative, will be set 0 to zero later */ | 306 | /* if negative, will be set 0 to zero later */ |
292 | } | 307 | } |
293 | 308 | ||
294 | |||
295 | rb->lcd_clear_display(); | 309 | rb->lcd_clear_display(); |
296 | 310 | ||
297 | if(gThread.user_index < 0 || gThread.user_index >= MAX_LOG_SIZE) | 311 | if(gThread.user_index < 0 || gThread.user_index >= MAX_LOG_SIZE) |
298 | gThread.user_index = 0; | 312 | gThread.user_index = 0; |
299 | 313 | ||
300 | |||
301 | if(logwrap) | 314 | if(logwrap) |
302 | i = logindex; | 315 | i = logindex; |
303 | else | 316 | else |
@@ -373,7 +386,7 @@ static bool logdump(bool append) | |||
373 | /* nothing is logged just yet */ | 386 | /* nothing is logged just yet */ |
374 | return false; | 387 | return false; |
375 | } | 388 | } |
376 | if (!append) | 389 | if (append) |
377 | { | 390 | { |
378 | flags = O_CREAT|O_WRONLY|O_APPEND; | 391 | flags = O_CREAT|O_WRONLY|O_APPEND; |
379 | } | 392 | } |
@@ -431,7 +444,6 @@ static bool do_timed_yield(void) | |||
431 | static long wakeup_tick = 0; | 444 | static long wakeup_tick = 0; |
432 | if (TIME_AFTER(current_tick, wakeup_tick)) | 445 | if (TIME_AFTER(current_tick, wakeup_tick)) |
433 | { | 446 | { |
434 | |||
435 | yield(); | 447 | yield(); |
436 | 448 | ||
437 | wakeup_tick = current_tick + (HZ/5); | 449 | wakeup_tick = current_tick + (HZ/5); |
@@ -440,6 +452,402 @@ static bool do_timed_yield(void) | |||
440 | return false; | 452 | return false; |
441 | } | 453 | } |
442 | 454 | ||
455 | /* copy/move a file */ | ||
456 | static int fcpy(const char *src, const char *target, | ||
457 | unsigned int flags, bool (*poll_cancel)(const char *)) | ||
458 | { | ||
459 | int rc = -1; | ||
460 | |||
461 | while (!(flags & (FCPY_COPY | FCPY_EXDEV))) { | ||
462 | if ((flags & FCPY_OVERWRITE) || !file_exists(target)) { | ||
463 | /* Rename and possibly overwrite the file */ | ||
464 | if (poll_cancel && poll_cancel(src)) { | ||
465 | rc = RC_USER_CANCEL; | ||
466 | } else { | ||
467 | rc = rename(src, target); | ||
468 | } | ||
469 | |||
470 | #ifdef HAVE_MULTIVOLUME | ||
471 | if (rc < 0 && errno == EXDEV) { | ||
472 | /* Failed because cross volume rename doesn't work; force | ||
473 | a move instead */ | ||
474 | flags |= FCPY_EXDEV; | ||
475 | break; | ||
476 | } | ||
477 | #endif /* HAVE_MULTIVOLUME */ | ||
478 | } | ||
479 | |||
480 | return rc; | ||
481 | } | ||
482 | |||
483 | /* See if we can get the plugin buffer for the file copy buffer */ | ||
484 | size_t buffersize; | ||
485 | char *buffer = (char *) plugin_get_buffer(&buffersize); | ||
486 | if (buffer == NULL || buffersize < 512) { | ||
487 | /* Not large enough, try for a disk sector worth of stack | ||
488 | instead */ | ||
489 | buffersize = 512; | ||
490 | buffer = (char *)alloca(buffersize); | ||
491 | } | ||
492 | |||
493 | if (buffer == NULL) { | ||
494 | return -1; | ||
495 | } | ||
496 | |||
497 | buffersize &= ~0x1ff; /* Round buffer size to multiple of sector | ||
498 | size */ | ||
499 | |||
500 | int src_fd = open(src, O_RDONLY); | ||
501 | if (src_fd >= 0) { | ||
502 | int oflag = O_WRONLY|O_CREAT; | ||
503 | |||
504 | if (!(flags & FCPY_OVERWRITE)) { | ||
505 | oflag |= O_EXCL; | ||
506 | } | ||
507 | |||
508 | int target_fd = open(target, oflag, 0666); | ||
509 | if (target_fd >= 0) { | ||
510 | off_t total_size = 0; | ||
511 | off_t next_cancel_test = 0; /* No excessive button polling */ | ||
512 | |||
513 | rc = RC_SUCCESS; | ||
514 | |||
515 | while (rc == RC_SUCCESS) { | ||
516 | if (total_size >= next_cancel_test) { | ||
517 | next_cancel_test = total_size + 0x10000; | ||
518 | if (poll_cancel && poll_cancel(src)) { | ||
519 | rc = RC_USER_CANCEL; | ||
520 | break; | ||
521 | } | ||
522 | } | ||
523 | |||
524 | ssize_t bytesread = read(src_fd, buffer, buffersize); | ||
525 | if (bytesread <= 0) { | ||
526 | if (bytesread < 0) { | ||
527 | rc = -1; | ||
528 | } | ||
529 | /* else eof on buffer boundary; nothing to write */ | ||
530 | break; | ||
531 | } | ||
532 | |||
533 | ssize_t byteswritten = write(target_fd, buffer, bytesread); | ||
534 | if (byteswritten < bytesread) { | ||
535 | /* Some I/O error */ | ||
536 | rc = -1; | ||
537 | break; | ||
538 | } | ||
539 | |||
540 | total_size += byteswritten; | ||
541 | |||
542 | if (bytesread < (ssize_t)buffersize) { | ||
543 | /* EOF with trailing bytes */ | ||
544 | break; | ||
545 | } | ||
546 | } | ||
547 | |||
548 | if (rc == RC_SUCCESS) { | ||
549 | /* If overwriting, set the correct length if original was | ||
550 | longer */ | ||
551 | rc = ftruncate(target_fd, total_size); | ||
552 | } | ||
553 | |||
554 | close(target_fd); | ||
555 | |||
556 | if (rc != RC_SUCCESS) { | ||
557 | /* Copy failed. Cleanup. */ | ||
558 | remove(target); | ||
559 | } | ||
560 | } | ||
561 | |||
562 | close(src_fd); | ||
563 | } | ||
564 | |||
565 | if (rc == RC_SUCCESS && !(flags & FCPY_COPY)) { | ||
566 | /* Remove the source file */ | ||
567 | rc = remove(src); | ||
568 | } | ||
569 | |||
570 | return rc; | ||
571 | } | ||
572 | |||
573 | static bool backup_restore_tagcache(bool backup) | ||
574 | { | ||
575 | struct master_header tcmh; | ||
576 | char path[MAX_PATH]; | ||
577 | char bu_path[MAX_PATH]; | ||
578 | int fd; | ||
579 | int rc; | ||
580 | |||
581 | if (backup) | ||
582 | { | ||
583 | if (!rb->dir_exists(BACKUP_DIRECTORY)) | ||
584 | mkdir(BACKUP_DIRECTORY); | ||
585 | snprintf(path, sizeof(path), "%s/"TAGCACHE_FILE_MASTER, tc_stat.db_path); | ||
586 | snprintf(bu_path, sizeof(bu_path), "%s/"TAGCACHE_FILE_MASTER, BACKUP_DIRECTORY); | ||
587 | } | ||
588 | else | ||
589 | { | ||
590 | if (!rb->dir_exists(BACKUP_DIRECTORY)) | ||
591 | return false; | ||
592 | snprintf(path, sizeof(path), "%s/"TAGCACHE_FILE_MASTER, BACKUP_DIRECTORY); | ||
593 | snprintf(bu_path, sizeof(bu_path), "%s/"TAGCACHE_FILE_MASTER, tc_stat.db_path); | ||
594 | } | ||
595 | |||
596 | fd = open(path, O_RDONLY, 0666); | ||
597 | |||
598 | if (fd >= 0) | ||
599 | { | ||
600 | rc = read(fd, &tcmh, sizeof(struct master_header)); | ||
601 | close(fd); | ||
602 | if (rc != sizeof(struct master_header)) | ||
603 | { | ||
604 | logf("master file read failed"); | ||
605 | return false; | ||
606 | } | ||
607 | int entries = tcmh.tch.entry_count; | ||
608 | |||
609 | logf("master file %d entries", entries); | ||
610 | if (backup) | ||
611 | logf("backup db to %s", BACKUP_DIRECTORY); | ||
612 | else | ||
613 | logf("restore db to %s", tc_stat.db_path); | ||
614 | |||
615 | if (entries > 0) | ||
616 | { | ||
617 | logf("%s", path); | ||
618 | fcpy(path, bu_path, FCPY_COPY|FCPY_OVERWRITE, NULL); | ||
619 | |||
620 | for (int i = 0; i < TAG_COUNT; i++) | ||
621 | { | ||
622 | if (TAGCACHE_IS_NUMERIC(i)) | ||
623 | continue; | ||
624 | snprintf(path, sizeof(path), | ||
625 | "%s/"TAGCACHE_FILE_INDEX, tc_stat.db_path, i); | ||
626 | |||
627 | snprintf(bu_path, sizeof(bu_path), | ||
628 | "%s/"TAGCACHE_FILE_INDEX, BACKUP_DIRECTORY, i); | ||
629 | /* Note: above we swapped paths in the snprintf call here we swap variables */ | ||
630 | if (backup) | ||
631 | { | ||
632 | logf("%s", path); | ||
633 | if (fcpy(path, bu_path, FCPY_COPY|FCPY_OVERWRITE, NULL) < 0) | ||
634 | goto failed; | ||
635 | gStatus.have_backup = true; | ||
636 | } | ||
637 | else | ||
638 | { | ||
639 | logf("%s", bu_path); | ||
640 | if (fcpy(bu_path, path, FCPY_COPY|FCPY_OVERWRITE, NULL) < 0) | ||
641 | goto failed; | ||
642 | } | ||
643 | } | ||
644 | } | ||
645 | return true; | ||
646 | } | ||
647 | failed: | ||
648 | if (backup) | ||
649 | { | ||
650 | logf("failed backup"); | ||
651 | } | ||
652 | |||
653 | return false; | ||
654 | } | ||
655 | |||
656 | /* asks the user if they wish to quit */ | ||
657 | static bool confirm_quit(void) | ||
658 | { | ||
659 | const struct text_message prompt = | ||
660 | { (const char*[]) {"Are you sure?", "This will abort commit."}, 2}; | ||
661 | enum yesno_res response = rb->gui_syncyesno_run(&prompt, NULL, NULL); | ||
662 | return (response == YESNO_YES); | ||
663 | } | ||
664 | |||
665 | /* asks the user if they wish to backup/restore */ | ||
666 | static bool prompt_backup_restore(bool backup) | ||
667 | { | ||
668 | const struct text_message bu_prompt = { (const char*[]) {"Backup database?"}, 1}; | ||
669 | const struct text_message re_prompt = | ||
670 | { (const char*[]) {"Error committing,", "Restore database?"}, 2}; | ||
671 | enum yesno_res response = | ||
672 | rb->gui_syncyesno_run(backup ? &bu_prompt:&re_prompt, NULL, NULL); | ||
673 | if(response == YESNO_YES) | ||
674 | return backup_restore_tagcache(backup); | ||
675 | return true; | ||
676 | } | ||
677 | |||
678 | static const char* list_get_name_cb(int selected_item, void* data, | ||
679 | char* buf, size_t buf_len) | ||
680 | { | ||
681 | (void) data; | ||
682 | (void) buf; | ||
683 | (void) buf_len; | ||
684 | |||
685 | /* buf supplied isn't used so lets use it for a filename buffer */ | ||
686 | if (TIME_AFTER(current_tick, gStatus.last_check)) | ||
687 | { | ||
688 | snprintf(buf, buf_len, "%s/"TAGCACHE_FILE_NOCOMMIT, tc_stat.db_path); | ||
689 | gStatus.auto_commit = !file_exists(buf); | ||
690 | snprintf(buf, buf_len, "%s/"TAGCACHE_FILE_TEMP, tc_stat.db_path); | ||
691 | gStatus.commit_ready = file_exists(buf); | ||
692 | snprintf(buf, buf_len, "%s/"TAGCACHE_FILE_MASTER, tc_stat.db_path); | ||
693 | gStatus.db_exists = file_exists(buf); | ||
694 | snprintf(buf, buf_len, "%s/"TAGCACHE_FILE_MASTER, BACKUP_DIRECTORY); | ||
695 | gStatus.bu_exists = file_exists(buf); | ||
696 | gStatus.last_check = current_tick + HZ; | ||
697 | buf[0] = '\0'; | ||
698 | } | ||
699 | |||
700 | switch(selected_item) | ||
701 | { | ||
702 | |||
703 | case 0: /* exit */ | ||
704 | return ID2P(LANG_MENU_QUIT); | ||
705 | case 1: /*sep*/ | ||
706 | return ID2P(VOICE_BLANK); | ||
707 | case 2: /*backup*/ | ||
708 | if (!gStatus.db_exists) | ||
709 | return ID2P(VOICE_BLANK); | ||
710 | return "Backup"; | ||
711 | case 3: /*restore*/ | ||
712 | if (!gStatus.bu_exists) | ||
713 | return ID2P(VOICE_BLANK); | ||
714 | return "Restore"; | ||
715 | case 4: /*sep*/ | ||
716 | return ID2P(VOICE_BLANK); | ||
717 | case 5: /*auto commit*/ | ||
718 | if (gStatus.auto_commit) | ||
719 | return "Disable auto commit"; | ||
720 | else | ||
721 | return "Enable auto commit"; | ||
722 | case 6: /*destroy*/ | ||
723 | if (gStatus.db_exists) | ||
724 | return "Delete database"; | ||
725 | /*fall through*/ | ||
726 | case 7: /*sep*/ | ||
727 | return ID2P(VOICE_BLANK); | ||
728 | case 8: /*commit*/ | ||
729 | if (gStatus.commit_ready) | ||
730 | return "Commit"; | ||
731 | else | ||
732 | return "Nothing to commit"; | ||
733 | default: | ||
734 | return "?"; | ||
735 | } | ||
736 | } | ||
737 | |||
738 | static int list_voice_cb(int list_index, void* data) | ||
739 | { | ||
740 | #define MAX_MENU_NAME 32 | ||
741 | if (!rb->global_settings->talk_menu) | ||
742 | return -1; | ||
743 | else | ||
744 | { | ||
745 | char buf[MAX_MENU_NAME]; | ||
746 | const char* name = list_get_name_cb(list_index, data, buf, sizeof(buf)); | ||
747 | long id = P2ID((const unsigned char *)name); | ||
748 | if(id>=0) | ||
749 | rb->talk_id(id, true); | ||
750 | else | ||
751 | rb->talk_spell(name, true); | ||
752 | } | ||
753 | return 0; | ||
754 | } | ||
755 | |||
756 | static int commit_menu(void) | ||
757 | { | ||
758 | struct gui_synclist lists; | ||
759 | bool exit = false; | ||
760 | int button,i; | ||
761 | int selection, ret = 0; | ||
762 | |||
763 | rb->gui_synclist_init(&lists,list_get_name_cb,0, false, 1, NULL); | ||
764 | rb->gui_synclist_set_icon_callback(&lists, NULL); | ||
765 | rb->gui_synclist_set_nb_items(&lists, 9); | ||
766 | rb->gui_synclist_select_item(&lists, 0); | ||
767 | |||
768 | while (!exit) | ||
769 | { | ||
770 | rb->gui_synclist_draw(&lists); | ||
771 | button = rb->get_action(CONTEXT_LIST,TIMEOUT_BLOCK); | ||
772 | if (rb->gui_synclist_do_button(&lists, &button)) | ||
773 | continue; | ||
774 | selection = rb->gui_synclist_get_sel_pos(&lists); | ||
775 | |||
776 | if (button == ACTION_STD_CANCEL) | ||
777 | return 0; | ||
778 | else if (button == ACTION_STD_OK) | ||
779 | { | ||
780 | switch(selection) | ||
781 | { | ||
782 | case 0: /* exit */ | ||
783 | exit = true; | ||
784 | break; | ||
785 | case 1: /*sep*/ | ||
786 | continue; | ||
787 | case 2: /*backup*/ | ||
788 | if (!gStatus.db_exists) | ||
789 | break; | ||
790 | if (!backup_restore_tagcache(true)) | ||
791 | rb->splash(HZ, "Backup failed!"); | ||
792 | else | ||
793 | { | ||
794 | rb->splash(HZ, "Backup success!"); | ||
795 | gStatus.bu_exists = true; | ||
796 | } | ||
797 | break; | ||
798 | case 3: /*restore*/ | ||
799 | if (!gStatus.bu_exists) | ||
800 | break; | ||
801 | if (!backup_restore_tagcache(false)) | ||
802 | rb->splash(HZ, "Restore failed!"); | ||
803 | else | ||
804 | rb->splash(HZ, "Restore success!"); | ||
805 | break; | ||
806 | case 4: /*sep*/ | ||
807 | continue; | ||
808 | case 5: /*auto commit*/ | ||
809 | { | ||
810 | /* build_idx_buf supplied by tagcache.c isn't being used | ||
811 | * so lets use it for a filename buffer */ | ||
812 | snprintf(build_idx_buf, build_idx_bufsz, | ||
813 | "%s/" TAGCACHE_FILE_NOCOMMIT, tc_stat.db_path); | ||
814 | if(gStatus.auto_commit) | ||
815 | close(open(build_idx_buf, O_WRONLY | O_CREAT | O_TRUNC, 0666)); | ||
816 | else | ||
817 | remove(build_idx_buf); | ||
818 | gStatus.auto_commit = !file_exists(build_idx_buf); | ||
819 | break; | ||
820 | } | ||
821 | case 6: /*destroy*/ | ||
822 | { | ||
823 | if (!gStatus.db_exists) | ||
824 | break; | ||
825 | const struct text_message prompt = | ||
826 | { (const char*[]) {"Are you sure?", "This will destroy database."}, 2}; | ||
827 | if (rb->gui_syncyesno_run(&prompt, NULL, NULL) == YESNO_YES) | ||
828 | remove_files(); | ||
829 | break; | ||
830 | } | ||
831 | case 7: /*sep*/ | ||
832 | continue; | ||
833 | case 8: /*commit*/ | ||
834 | if (gStatus.commit_ready) | ||
835 | { | ||
836 | gStatus.do_commit = true; | ||
837 | exit = true; | ||
838 | } | ||
839 | break; | ||
840 | |||
841 | case MENU_ATTACHED_USB: | ||
842 | return PLUGIN_USB_CONNECTED; | ||
843 | default: | ||
844 | return 0; | ||
845 | } | ||
846 | } | ||
847 | } /*while*/ | ||
848 | return ret; | ||
849 | } | ||
850 | |||
443 | /*-----------------------------------------------------------------------------*/ | 851 | /*-----------------------------------------------------------------------------*/ |
444 | /******* plugin_start ******* */ | 852 | /******* plugin_start ******* */ |
445 | /*-----------------------------------------------------------------------------*/ | 853 | /*-----------------------------------------------------------------------------*/ |
@@ -451,6 +859,8 @@ enum plugin_status plugin_start(const void* parameter) | |||
451 | /* Turn off backlight timeout */ | 859 | /* Turn off backlight timeout */ |
452 | backlight_ignore_timeout(); | 860 | backlight_ignore_timeout(); |
453 | 861 | ||
862 | memset(&gThread, 0, sizeof(gThread)); | ||
863 | memset(&gStatus, 0, sizeof(gStatus)); | ||
454 | memset(&tc_stat, 0, sizeof(struct tagcache_stat)); | 864 | memset(&tc_stat, 0, sizeof(struct tagcache_stat)); |
455 | memset(¤t_tcmh, 0, sizeof(struct master_header)); | 865 | memset(¤t_tcmh, 0, sizeof(struct master_header)); |
456 | filenametag_fd = -1; | 866 | filenametag_fd = -1; |
@@ -459,62 +869,32 @@ enum plugin_status plugin_start(const void* parameter) | |||
459 | if (!rb->dir_exists(tc_stat.db_path)) /* on fail use default DB path */ | 869 | if (!rb->dir_exists(tc_stat.db_path)) /* on fail use default DB path */ |
460 | strlcpy(tc_stat.db_path, ROCKBOX_DIR, sizeof(tc_stat.db_path)); | 870 | strlcpy(tc_stat.db_path, ROCKBOX_DIR, sizeof(tc_stat.db_path)); |
461 | tc_stat.initialized = true; | 871 | tc_stat.initialized = true; |
872 | tc_stat.commit_step = -1; | ||
462 | 873 | ||
463 | memset(&gThread, 0, sizeof(gThread)); | ||
464 | logf("started"); | 874 | logf("started"); |
465 | logdump(false); | ||
466 | 875 | ||
876 | int result = commit_menu(); | ||
877 | |||
878 | if (!gStatus.do_commit) | ||
879 | { | ||
880 | /* Turn on backlight timeout (revert to settings) */ | ||
881 | backlight_use_settings(); | ||
882 | return PLUGIN_OK; | ||
883 | } | ||
884 | |||
885 | logdump(false); | ||
886 | allocate_tempbuf(); | ||
887 | if (gStatus.db_exists && !gStatus.have_backup && !prompt_backup_restore(true)) | ||
888 | rb->splash(HZ, "Backup failed!"); | ||
467 | thread_create(); | 889 | thread_create(); |
468 | gThread.user_index = 0; | 890 | gThread.user_index = 0; |
469 | logdisplay(); /* get something on the screen while user waits */ | 891 | logdisplay(); /* get something on the screen while user waits */ |
470 | 892 | ||
471 | allocate_tempbuf(); | ||
472 | |||
473 | commit(); | ||
474 | |||
475 | if (tc_stat.ready) | ||
476 | rb->tagcache_commit_finalize(); | ||
477 | |||
478 | free_tempbuf(); | ||
479 | |||
480 | logdump(true); | ||
481 | gThread.user_index++; | ||
482 | logdisplay(); | ||
483 | rb->thread_wait(gThread.id); | ||
484 | rb->queue_delete(&gThread.queue); | ||
485 | |||
486 | /* Turn on backlight timeout (revert to settings) */ | ||
487 | backlight_use_settings(); | ||
488 | return PLUGIN_OK; | ||
489 | } | ||
490 | |||
491 | /****************** main thread + helper ******************/ | ||
492 | static void thread(void) | ||
493 | { | ||
494 | struct queue_event ev; | ||
495 | while (!gThread.exiting) | 893 | while (!gThread.exiting) |
496 | { | 894 | { |
497 | rb->queue_wait_w_tmo(&gThread.queue, &ev, 1); | ||
498 | switch (ev.id) | ||
499 | { | ||
500 | case SYS_USB_CONNECTED: | ||
501 | rb->usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
502 | logenabled = false; | ||
503 | break; | ||
504 | case SYS_USB_DISCONNECTED: | ||
505 | logenabled = true; | ||
506 | /*fall through*/ | ||
507 | case EV_STARTUP: | ||
508 | logf("Thread Started"); | ||
509 | break; | ||
510 | case EV_EXIT: | ||
511 | return; | ||
512 | default: | ||
513 | break; | ||
514 | } | ||
515 | logdisplay(); | 895 | logdisplay(); |
516 | 896 | ||
517 | int action = rb->get_action(CONTEXT_STD, HZ/10); | 897 | int action = rb->get_action(CONTEXT_STD, HZ/20); |
518 | 898 | ||
519 | switch( action ) | 899 | switch( action ) |
520 | { | 900 | { |
@@ -536,8 +916,15 @@ static void thread(void) | |||
536 | break; | 916 | break; |
537 | case SYS_POWEROFF: | 917 | case SYS_POWEROFF: |
538 | case ACTION_STD_CANCEL: | 918 | case ACTION_STD_CANCEL: |
539 | gThread.exiting = true; | 919 | if (tc_stat.commit_step >= 0 && !tc_stat.ready) |
540 | return; | 920 | { |
921 | if (!confirm_quit()) | ||
922 | break; | ||
923 | tc_stat.commit_delayed = true; /* Cancel the commit */ | ||
924 | } | ||
925 | rb->queue_remove_from_head(&gThread.queue, EV_EXIT); | ||
926 | rb->queue_post(&gThread.queue, EV_EXIT, 0); | ||
927 | break; | ||
541 | #ifdef HAVE_TOUCHSCREEN | 928 | #ifdef HAVE_TOUCHSCREEN |
542 | case ACTION_TOUCHSCREEN: | 929 | case ACTION_TOUCHSCREEN: |
543 | { | 930 | { |
@@ -561,8 +948,60 @@ static void thread(void) | |||
561 | default: | 948 | default: |
562 | break; | 949 | break; |
563 | } | 950 | } |
951 | yield(); | ||
952 | } | ||
953 | |||
954 | rb->thread_wait(gThread.id); | ||
955 | rb->queue_delete(&gThread.queue); | ||
956 | free_tempbuf(); | ||
957 | |||
958 | if (tc_stat.commit_delayed || !tc_stat.ready) | ||
959 | { | ||
960 | remove_files(); | ||
961 | if (gStatus.bu_exists && !prompt_backup_restore(false)) | ||
962 | rb->splash(HZ, "Restore failed!"); | ||
963 | } | ||
964 | |||
965 | if (tc_stat.ready) | ||
966 | rb->tagcache_commit_finalize(); | ||
564 | 967 | ||
968 | /* Turn on backlight timeout (revert to settings) */ | ||
969 | backlight_use_settings(); | ||
970 | return PLUGIN_OK; | ||
971 | } | ||
565 | 972 | ||
973 | /****************** main thread + helper ******************/ | ||
974 | static void thread(void) | ||
975 | { | ||
976 | struct queue_event ev; | ||
977 | while (!gThread.exiting) | ||
978 | { | ||
979 | rb->queue_wait_w_tmo(&gThread.queue, &ev, 1); | ||
980 | switch (ev.id) | ||
981 | { | ||
982 | case SYS_USB_CONNECTED: | ||
983 | rb->usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
984 | logenabled = false; | ||
985 | break; | ||
986 | case SYS_USB_DISCONNECTED: | ||
987 | logenabled = true; | ||
988 | /*fall through*/ | ||
989 | case EV_STARTUP: | ||
990 | logf("Thread Started"); | ||
991 | cpu_boost(true); | ||
992 | if (commit()) | ||
993 | tc_stat.ready = true; | ||
994 | cpu_boost(false); | ||
995 | logdump(true); | ||
996 | gThread.user_index++; | ||
997 | logdisplay(); | ||
998 | break; | ||
999 | case EV_EXIT: | ||
1000 | gThread.exiting = true; | ||
1001 | return; | ||
1002 | default: | ||
1003 | break; | ||
1004 | } | ||
566 | yield(); | 1005 | yield(); |
567 | } | 1006 | } |
568 | } | 1007 | } |