summaryrefslogtreecommitdiff
path: root/apps/tagcache.c
diff options
context:
space:
mode:
authorMiika Pekkarinen <miipekk@ihme.org>2007-07-21 17:35:19 +0000
committerMiika Pekkarinen <miipekk@ihme.org>2007-07-21 17:35:19 +0000
commit9d756e2760a0926aa416b22e276c4a5b2685e84e (patch)
tree21502b59d472d57f6cdb267eb96177784beec706 /apps/tagcache.c
parent6ed7722db0f7e911684f5deb84cc4ae93d15ccac (diff)
downloadrockbox-9d756e2760a0926aa416b22e276c4a5b2685e84e.tar.gz
rockbox-9d756e2760a0926aa416b22e276c4a5b2685e84e.zip
Queue song statistical data to the tagcache system and update entirely in background. Fixes ratings disappearing or not saving in the DB at all. Fixes also UI delay when stopping playback and new statistics are committed to DB.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13955 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/tagcache.c')
-rw-r--r--apps/tagcache.c183
1 files changed, 156 insertions, 27 deletions
diff --git a/apps/tagcache.c b/apps/tagcache.c
index f832f1e543..6d738bc5fb 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -136,8 +136,26 @@ enum tagcache_queue {
136 Q_IMPORT_CHANGELOG, 136 Q_IMPORT_CHANGELOG,
137 Q_UPDATE, 137 Q_UPDATE,
138 Q_REBUILD, 138 Q_REBUILD,
139
140 /* Internal tagcache command queue. */
141 CMD_UPDATE_MASTER_HEADER,
142 CMD_UPDATE_NUMERIC,
143};
144
145struct tagcache_command_entry {
146 long command;
147 long idx_id;
148 long tag;
149 long data;
139}; 150};
140 151
152static struct tagcache_command_entry command_queue[TAGCACHE_COMMAND_QUEUE_LENGTH];
153static volatile int command_queue_widx = 0;
154static volatile int command_queue_ridx = 0;
155static struct mutex command_queue_mutex;
156/* Timestamp of the last added event, so we can wait a bit before committing the
157 * whole queue at once. */
158static long command_queue_timestamp = 0;
141 159
142/* Tag database structures. */ 160/* Tag database structures. */
143 161
@@ -2737,33 +2755,6 @@ static void free_tempbuf(void)
2737 tempbuf_size = 0; 2755 tempbuf_size = 0;
2738} 2756}
2739 2757
2740long tagcache_increase_serial(void)
2741{
2742 long old;
2743
2744 if (!tc_stat.ready)
2745 return -2;
2746
2747 while (read_lock)
2748 sleep(1);
2749
2750 old = current_tcmh.serial++;
2751 if (!update_master_header())
2752 return -1;
2753
2754 return old;
2755}
2756
2757long tagcache_get_serial(void)
2758{
2759 return current_tcmh.serial;
2760}
2761
2762long tagcache_get_commitid(void)
2763{
2764 return current_tcmh.commitid;
2765}
2766
2767static bool modify_numeric_entry(int masterfd, int idx_id, int tag, long data) 2758static bool modify_numeric_entry(int masterfd, int idx_id, int tag, long data)
2768{ 2759{
2769 struct index_entry idx; 2760 struct index_entry idx;
@@ -2783,6 +2774,7 @@ static bool modify_numeric_entry(int masterfd, int idx_id, int tag, long data)
2783 return write_index(masterfd, idx_id, &idx); 2774 return write_index(masterfd, idx_id, &idx);
2784} 2775}
2785 2776
2777#if 0
2786bool tagcache_modify_numeric_entry(struct tagcache_search *tcs, 2778bool tagcache_modify_numeric_entry(struct tagcache_search *tcs,
2787 int tag, long data) 2779 int tag, long data)
2788{ 2780{
@@ -2796,6 +2788,137 @@ bool tagcache_modify_numeric_entry(struct tagcache_search *tcs,
2796 2788
2797 return modify_numeric_entry(tcs->masterfd, tcs->idx_id, tag, data); 2789 return modify_numeric_entry(tcs->masterfd, tcs->idx_id, tag, data);
2798} 2790}
2791#endif
2792
2793#define COMMAND_QUEUE_IS_EMPTY (command_queue_ridx == command_queue_widx)
2794
2795static bool command_queue_is_full(void)
2796{
2797 int next;
2798
2799 next = command_queue_widx + 1;
2800 if (next >= TAGCACHE_COMMAND_QUEUE_LENGTH)
2801 next = 0;
2802
2803 return (next == command_queue_ridx);
2804}
2805
2806void run_command_queue(bool force)
2807{
2808 struct master_header myhdr;
2809 int masterfd;
2810
2811 if (COMMAND_QUEUE_IS_EMPTY)
2812 return;
2813
2814 if (!force && !command_queue_is_full()
2815 && current_tick - TAGCACHE_COMMAND_QUEUE_COMMIT_DELAY
2816 < command_queue_timestamp)
2817 {
2818 return;
2819 }
2820
2821 mutex_lock(&command_queue_mutex);
2822
2823 if ( (masterfd = open_master_fd(&myhdr, true)) < 0)
2824 return;
2825
2826 while (command_queue_ridx != command_queue_widx)
2827 {
2828 struct tagcache_command_entry *ce = &command_queue[command_queue_ridx];
2829
2830 switch (ce->command)
2831 {
2832 case CMD_UPDATE_MASTER_HEADER:
2833 {
2834 close(masterfd);
2835 update_master_header();
2836
2837 /* Re-open the masterfd. */
2838 if ( (masterfd = open_master_fd(&myhdr, true)) < 0)
2839 return;
2840
2841 break;
2842 }
2843 case CMD_UPDATE_NUMERIC:
2844 {
2845 modify_numeric_entry(masterfd, ce->idx_id, ce->tag, ce->data);
2846 break;
2847 }
2848 }
2849
2850 if (++command_queue_ridx >= TAGCACHE_COMMAND_QUEUE_LENGTH)
2851 command_queue_ridx = 0;
2852 }
2853
2854 close(masterfd);
2855
2856 mutex_unlock(&command_queue_mutex);
2857}
2858
2859static void queue_command(int cmd, long idx_id, int tag, long data)
2860{
2861 while (1)
2862 {
2863 int next;
2864
2865 mutex_lock(&command_queue_mutex);
2866 next = command_queue_widx + 1;
2867 if (next >= TAGCACHE_COMMAND_QUEUE_LENGTH)
2868 next = 0;
2869
2870 /* Make sure queue is not full. */
2871 if (next != command_queue_ridx)
2872 {
2873 struct tagcache_command_entry *ce = &command_queue[command_queue_widx];
2874
2875 ce->command = cmd;
2876 ce->idx_id = idx_id;
2877 ce->tag = tag;
2878 ce->data = data;
2879
2880 command_queue_widx = next;
2881 command_queue_timestamp = current_tick;
2882 mutex_unlock(&command_queue_mutex);
2883 break;
2884 }
2885
2886 /* Queue is full, try again later... */
2887 mutex_unlock(&command_queue_mutex);
2888 sleep(1);
2889 }
2890}
2891
2892long tagcache_increase_serial(void)
2893{
2894 long old;
2895
2896 if (!tc_stat.ready)
2897 return -2;
2898
2899 while (read_lock)
2900 sleep(1);
2901
2902 old = current_tcmh.serial++;
2903 queue_command(CMD_UPDATE_MASTER_HEADER, 0, 0, 0);
2904
2905 return old;
2906}
2907
2908void tagcache_update_numeric(int idx_id, int tag, long data)
2909{
2910 queue_command(CMD_UPDATE_NUMERIC, idx_id, tag, data);
2911}
2912
2913long tagcache_get_serial(void)
2914{
2915 return current_tcmh.serial;
2916}
2917
2918long tagcache_get_commitid(void)
2919{
2920 return current_tcmh.commitid;
2921}
2799 2922
2800static bool write_tag(int fd, const char *tagstr, const char *datastr) 2923static bool write_tag(int fd, const char *tagstr, const char *datastr)
2801{ 2924{
@@ -3860,6 +3983,8 @@ static void tagcache_thread(void)
3860 3983
3861 while (1) 3984 while (1)
3862 { 3985 {
3986 run_command_queue(false);
3987
3863 queue_wait_w_tmo(&tagcache_queue, &ev, HZ); 3988 queue_wait_w_tmo(&tagcache_queue, &ev, HZ);
3864 3989
3865 switch (ev.id) 3990 switch (ev.id)
@@ -3942,6 +4067,9 @@ bool tagcache_prepare_shutdown(void)
3942 4067
3943void tagcache_shutdown(void) 4068void tagcache_shutdown(void)
3944{ 4069{
4070 /* Flush the command queue. */
4071 run_command_queue(true);
4072
3945#ifdef HAVE_EEPROM_SETTINGS 4073#ifdef HAVE_EEPROM_SETTINGS
3946 if (tc_stat.ramcache) 4074 if (tc_stat.ramcache)
3947 tagcache_dumpsave(); 4075 tagcache_dumpsave();
@@ -4023,6 +4151,7 @@ void tagcache_init(void)
4023 write_lock = read_lock = 0; 4151 write_lock = read_lock = 0;
4024 4152
4025#ifndef __PCTOOL__ 4153#ifndef __PCTOOL__
4154 mutex_init(&command_queue_mutex);
4026 queue_init(&tagcache_queue, true); 4155 queue_init(&tagcache_queue, true);
4027 create_thread(tagcache_thread, tagcache_stack, 4156 create_thread(tagcache_thread, tagcache_stack,
4028 sizeof(tagcache_stack), tagcache_thread_name 4157 sizeof(tagcache_stack), tagcache_thread_name