summaryrefslogtreecommitdiff
path: root/apps/tagcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/tagcache.c')
-rw-r--r--apps/tagcache.c144
1 files changed, 102 insertions, 42 deletions
diff --git a/apps/tagcache.c b/apps/tagcache.c
index 753675f906..5ab77264f6 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -222,6 +222,8 @@ struct statefile_header {
222 222
223/* Pointer to allocated ramcache_header */ 223/* Pointer to allocated ramcache_header */
224static struct ramcache_header *ramcache_hdr; 224static struct ramcache_header *ramcache_hdr;
225/* lock entity to temporarily prevent ramcache_hdr from moving */
226static int move_lock;
225#endif 227#endif
226 228
227/** 229/**
@@ -1035,6 +1037,8 @@ static bool check_clauses(struct tagcache_search *tcs,
1035 { 1037 {
1036 tfe = (struct tagfile_entry *) 1038 tfe = (struct tagfile_entry *)
1037 &ramcache_hdr->tags[clause->tag][seek]; 1039 &ramcache_hdr->tags[clause->tag][seek];
1040 /* str points to movable data, but no locking required here,
1041 * as no yield() is following */
1038 str = tfe->tag_data; 1042 str = tfe->tag_data;
1039 } 1043 }
1040 } 1044 }
@@ -1149,9 +1153,11 @@ static bool build_lookup_list(struct tagcache_search *tcs)
1149# endif 1153# endif
1150 ) 1154 )
1151 { 1155 {
1156 move_lock++; /* lock because below makes a pointer to movable data */
1152 for (i = tcs->seek_pos; i < current_tcmh.tch.entry_count; i++) 1157 for (i = tcs->seek_pos; i < current_tcmh.tch.entry_count; i++)
1153 { 1158 {
1154 struct tagcache_seeklist_entry *seeklist; 1159 struct tagcache_seeklist_entry *seeklist;
1160 /* idx points to movable data, don't yield or reload */
1155 struct index_entry *idx = &ramcache_hdr->indices[i]; 1161 struct index_entry *idx = &ramcache_hdr->indices[i];
1156 if (tcs->seek_list_count == SEEK_LIST_SIZE) 1162 if (tcs->seek_list_count == SEEK_LIST_SIZE)
1157 break ; 1163 break ;
@@ -1175,8 +1181,7 @@ static bool build_lookup_list(struct tagcache_search *tcs)
1175 /* Check for conditions. */ 1181 /* Check for conditions. */
1176 if (!check_clauses(tcs, idx, tcs->clause, tcs->clause_count)) 1182 if (!check_clauses(tcs, idx, tcs->clause, tcs->clause_count))
1177 continue; 1183 continue;
1178 1184 /* Add to the seek list if not already in uniq buffer (doesn't yield)*/
1179 /* Add to the seek list if not already in uniq buffer. */
1180 if (!add_uniqbuf(tcs, idx->tag_seek[tcs->type])) 1185 if (!add_uniqbuf(tcs, idx->tag_seek[tcs->type]))
1181 continue; 1186 continue;
1182 1187
@@ -1187,6 +1192,7 @@ static bool build_lookup_list(struct tagcache_search *tcs)
1187 seeklist->idx_id = i; 1192 seeklist->idx_id = i;
1188 tcs->seek_list_count++; 1193 tcs->seek_list_count++;
1189 } 1194 }
1195 move_lock--;
1190 1196
1191 tcs->seek_pos = i; 1197 tcs->seek_pos = i;
1192 1198
@@ -1538,10 +1544,11 @@ static bool get_next(struct tagcache_search *tcs)
1538 struct tagfile_entry *ep; 1544 struct tagfile_entry *ep;
1539 1545
1540 ep = (struct tagfile_entry *)&ramcache_hdr->tags[tcs->type][tcs->position]; 1546 ep = (struct tagfile_entry *)&ramcache_hdr->tags[tcs->type][tcs->position];
1541 tcs->result = ep->tag_data; 1547 /* don't return ep->tag_data directly as it may move */
1542 tcs->result_len = strlen(tcs->result) + 1; 1548 tcs->result_len = strlcpy(buf, ep->tag_data, sizeof(buf)) + 1;
1549 tcs->result = buf;
1543 tcs->idx_id = ep->idx_id; 1550 tcs->idx_id = ep->idx_id;
1544 tcs->ramresult = true; 1551 tcs->ramresult = false; /* was true before we copied to buf too */
1545 1552
1546 /* Increase position for the next run. This may get overwritten. */ 1553 /* Increase position for the next run. This may get overwritten. */
1547 tcs->position += sizeof(struct tagfile_entry) + ep->tag_length; 1554 tcs->position += sizeof(struct tagfile_entry) + ep->tag_length;
@@ -1703,15 +1710,34 @@ bool tagcache_fill_tags(struct mp3entry *id3, const char *filename)
1703 entry = &ramcache_hdr->indices[idx_id]; 1710 entry = &ramcache_hdr->indices[idx_id];
1704 1711
1705 memset(id3, 0, sizeof(struct mp3entry)); 1712 memset(id3, 0, sizeof(struct mp3entry));
1706 1713 char* buf = id3->id3v2buf;
1707 id3->title = get_tag_string(entry, tag_title); 1714 ssize_t remaining = sizeof(id3->id3v2buf);
1708 id3->artist = get_tag_string(entry, tag_artist); 1715
1709 id3->album = get_tag_string(entry, tag_album); 1716 /* this macro sets id3 strings by copying to the id3v2buf */
1710 id3->genre_string = get_tag_string(entry, tag_genre); 1717#define SET(x, y) do \
1711 id3->composer = get_tag_string(entry, tag_composer); 1718 { \
1712 id3->comment = get_tag_string(entry, tag_comment); 1719 if (remaining > 0) \
1713 id3->albumartist = get_tag_string(entry, tag_albumartist); 1720 { \
1714 id3->grouping = get_tag_string(entry, tag_grouping); 1721 x = NULL; /* initialize with null if tag doesn't exist */ \
1722 char* src = get_tag_string(entry, y); \
1723 if (src) \
1724 { \
1725 x = buf; \
1726 size_t len = strlcpy(buf, src, remaining) +1; \
1727 buf += len; remaining -= len; \
1728 } \
1729 } \
1730 } while(0)
1731
1732
1733 SET(id3->title, tag_title);
1734 SET(id3->artist, tag_artist);
1735 SET(id3->album, tag_album);
1736 SET(id3->genre_string, tag_genre);
1737 SET(id3->composer, tag_composer);
1738 SET(id3->comment, tag_comment);
1739 SET(id3->albumartist, tag_albumartist);
1740 SET(id3->grouping, tag_grouping);
1715 1741
1716 id3->length = get_tag_numeric(entry, tag_length, idx_id); 1742 id3->length = get_tag_numeric(entry, tag_length, idx_id);
1717 id3->playcount = get_tag_numeric(entry, tag_playcount, idx_id); 1743 id3->playcount = get_tag_numeric(entry, tag_playcount, idx_id);
@@ -2903,6 +2929,9 @@ static bool commit(void)
2903#ifdef HAVE_DIRCACHE 2929#ifdef HAVE_DIRCACHE
2904 bool dircache_buffer_stolen = false; 2930 bool dircache_buffer_stolen = false;
2905#endif 2931#endif
2932#ifdef HAVE_TC_RAMCACHE
2933 bool ramcache_buffer_stolen = false;
2934#endif
2906 bool local_allocation = false; 2935 bool local_allocation = false;
2907 2936
2908 logf("committing tagcache"); 2937 logf("committing tagcache");
@@ -2976,6 +3005,8 @@ static bool commit(void)
2976 tempbuf = (char *)(ramcache_hdr + 1); 3005 tempbuf = (char *)(ramcache_hdr + 1);
2977 tempbuf_size = tc_stat.ramcache_allocated - sizeof(struct ramcache_header) - 128; 3006 tempbuf_size = tc_stat.ramcache_allocated - sizeof(struct ramcache_header) - 128;
2978 tempbuf_size &= ~0x03; 3007 tempbuf_size &= ~0x03;
3008 move_lock++;
3009 ramcache_buffer_stolen = true;
2979 } 3010 }
2980#endif 3011#endif
2981 3012
@@ -3072,6 +3103,8 @@ static bool commit(void)
3072#endif 3103#endif
3073 3104
3074#ifdef HAVE_TC_RAMCACHE 3105#ifdef HAVE_TC_RAMCACHE
3106 if (ramcache_buffer_stolen)
3107 move_lock--;
3075 /* Reload tagcache. */ 3108 /* Reload tagcache. */
3076 if (tc_stat.ramcache_allocated > 0) 3109 if (tc_stat.ramcache_allocated > 0)
3077 tagcache_start_scan(); 3110 tagcache_start_scan();
@@ -3689,9 +3722,11 @@ static bool delete_entry(long idx_id)
3689 { 3722 {
3690 struct tagfile_entry *tfe; 3723 struct tagfile_entry *tfe;
3691 int32_t *seek = &ramcache_hdr->indices[idx_id].tag_seek[tag]; 3724 int32_t *seek = &ramcache_hdr->indices[idx_id].tag_seek[tag];
3692 3725
3693 tfe = (struct tagfile_entry *)&ramcache_hdr->tags[tag][*seek]; 3726 tfe = (struct tagfile_entry *)&ramcache_hdr->tags[tag][*seek];
3727 move_lock++; /* protect tfe and seek if crc_32() yield()s */
3694 *seek = crc_32(tfe->tag_data, strlen(tfe->tag_data), 0xffffffff); 3728 *seek = crc_32(tfe->tag_data, strlen(tfe->tag_data), 0xffffffff);
3729 move_lock--;
3695 myidx.tag_seek[tag] = *seek; 3730 myidx.tag_seek[tag] = *seek;
3696 } 3731 }
3697 else 3732 else
@@ -3813,6 +3848,30 @@ static bool check_event_queue(void)
3813#endif 3848#endif
3814 3849
3815#ifdef HAVE_TC_RAMCACHE 3850#ifdef HAVE_TC_RAMCACHE
3851
3852static void fix_ramcache(void* old_addr, void* new_addr)
3853{
3854 ptrdiff_t offpos = new_addr - old_addr;
3855 for (int i = 0; i < TAG_COUNT; i++)
3856 ramcache_hdr->tags[i] += offpos;
3857}
3858
3859static int move_cb(int handle, void* current, void* new)
3860{
3861 (void)handle;
3862 if (move_lock > 0)
3863 return BUFLIB_CB_CANNOT_MOVE;
3864
3865 fix_ramcache(current, new);
3866 ramcache_hdr = new;
3867 return BUFLIB_CB_OK;
3868}
3869
3870static struct buflib_callbacks ops = {
3871 .move_callback = move_cb,
3872 .shrink_callback = NULL,
3873};
3874
3816static bool allocate_tagcache(void) 3875static bool allocate_tagcache(void)
3817{ 3876{
3818 struct master_header tcmh; 3877 struct master_header tcmh;
@@ -3833,7 +3892,7 @@ static bool allocate_tagcache(void)
3833 */ 3892 */
3834 tc_stat.ramcache_allocated = tcmh.tch.datasize + 256 + TAGCACHE_RESERVE + 3893 tc_stat.ramcache_allocated = tcmh.tch.datasize + 256 + TAGCACHE_RESERVE +
3835 sizeof(struct ramcache_header) + TAG_COUNT*sizeof(void *); 3894 sizeof(struct ramcache_header) + TAG_COUNT*sizeof(void *);
3836 int handle = core_alloc("tc ramcache", tc_stat.ramcache_allocated); 3895 int handle = core_alloc_ex("tc ramcache", tc_stat.ramcache_allocated, &ops);
3837 ramcache_hdr = core_get_data(handle); 3896 ramcache_hdr = core_get_data(handle);
3838 memset(ramcache_hdr, 0, sizeof(struct ramcache_header)); 3897 memset(ramcache_hdr, 0, sizeof(struct ramcache_header));
3839 memcpy(&current_tcmh, &tcmh, sizeof current_tcmh); 3898 memcpy(&current_tcmh, &tcmh, sizeof current_tcmh);
@@ -3871,12 +3930,13 @@ static bool tagcache_dumpload(void)
3871 3930
3872 3931
3873 /* Lets allocate real memory and load it */ 3932 /* Lets allocate real memory and load it */
3874 handle = core_alloc("tc ramcache", shdr.tc_stat.ramcache_allocated); 3933 handle = core_alloc_ex("tc ramcache", shdr.tc_stat.ramcache_allocated, &ops);
3875 ramcache_hdr = core_get_data(handle); 3934 ramcache_hdr = core_get_data(handle);
3935 moev_lock++;
3876 rc = read(fd, ramcache_hdr, shdr.tc_stat.ramcache_allocated); 3936 rc = read(fd, ramcache_hdr, shdr.tc_stat.ramcache_allocated);
3937 move_lock--;
3877 close(fd); 3938 close(fd);
3878 3939
3879 offpos = (long)ramcache_hdr - (long)shdr.hdr;
3880 if (rc != shdr.tc_stat.ramcache_allocated) 3940 if (rc != shdr.tc_stat.ramcache_allocated)
3881 { 3941 {
3882 logf("read failure!"); 3942 logf("read failure!");
@@ -3887,8 +3947,7 @@ static bool tagcache_dumpload(void)
3887 memcpy(&tc_stat, &shdr.tc_stat, sizeof(struct tagcache_stat)); 3947 memcpy(&tc_stat, &shdr.tc_stat, sizeof(struct tagcache_stat));
3888 3948
3889 /* Now fix the pointers */ 3949 /* Now fix the pointers */
3890 for (i = 0; i < TAG_COUNT; i++) 3950 fix_ramcache(shdr.hdr, ramcache_hdr);
3891 ramcache_hdr->tags[i] += offpos;
3892 3951
3893 /* Load the tagcache master header (should match the actual DB file header). */ 3952 /* Load the tagcache master header (should match the actual DB file header). */
3894 memcpy(&current_tcmh, &shdr.mh, sizeof current_tcmh); 3953 memcpy(&current_tcmh, &shdr.mh, sizeof current_tcmh);
@@ -3919,7 +3978,9 @@ static bool tagcache_dumpsave(void)
3919 write(fd, &shdr, sizeof shdr); 3978 write(fd, &shdr, sizeof shdr);
3920 3979
3921 /* And dump the data too */ 3980 /* And dump the data too */
3981 move_lock++;
3922 write(fd, ramcache_hdr, tc_stat.ramcache_allocated); 3982 write(fd, ramcache_hdr, tc_stat.ramcache_allocated);
3983 move_lock--;
3923 close(fd); 3984 close(fd);
3924 3985
3925 return true; 3986 return true;
@@ -3962,7 +4023,8 @@ static bool load_tagcache(void)
3962 4023
3963 /* Master header copy should already match, this can be redundant to do. */ 4024 /* Master header copy should already match, this can be redundant to do. */
3964 memcpy(&current_tcmh, &tcmh, sizeof current_tcmh); 4025 memcpy(&current_tcmh, &tcmh, sizeof current_tcmh);
3965 4026
4027 move_lock++; /* lock for the reset of the scan, simpler to handle */
3966 idx = ramcache_hdr->indices; 4028 idx = ramcache_hdr->indices;
3967 4029
3968 /* Load the master index table. */ 4030 /* Load the master index table. */
@@ -3972,8 +4034,7 @@ static bool load_tagcache(void)
3972 if (bytesleft < 0) 4034 if (bytesleft < 0)
3973 { 4035 {
3974 logf("too big tagcache."); 4036 logf("too big tagcache.");
3975 close(fd); 4037 goto failure;
3976 return false;
3977 } 4038 }
3978 4039
3979 /* DEBUG: After tagcache commit and dircache rebuild, hdr-sturcture 4040 /* DEBUG: After tagcache commit and dircache rebuild, hdr-sturcture
@@ -3982,8 +4043,7 @@ static bool load_tagcache(void)
3982 if (rc != sizeof(struct index_entry)) 4043 if (rc != sizeof(struct index_entry))
3983 { 4044 {
3984 logf("read error #10"); 4045 logf("read error #10");
3985 close(fd); 4046 goto failure;
3986 return false;
3987 } 4047 }
3988 4048
3989 idx++; 4049 idx++;
@@ -4010,7 +4070,7 @@ static bool load_tagcache(void)
4010 p += sizeof(struct tagcache_header); 4070 p += sizeof(struct tagcache_header);
4011 4071
4012 if ( (fd = open_tag_fd(tch, tag, false)) < 0) 4072 if ( (fd = open_tag_fd(tch, tag, false)) < 0)
4013 return false; 4073 goto failure_nofd;
4014 4074
4015 for (ramcache_hdr->entry_count[tag] = 0; 4075 for (ramcache_hdr->entry_count[tag] = 0;
4016 ramcache_hdr->entry_count[tag] < tch->entry_count; 4076 ramcache_hdr->entry_count[tag] < tch->entry_count;
@@ -4022,7 +4082,7 @@ static bool load_tagcache(void)
4022 { 4082 {
4023 /* Abort if we got a critical event in queue */ 4083 /* Abort if we got a critical event in queue */
4024 if (check_event_queue()) 4084 if (check_event_queue())
4025 return false; 4085 goto failure;
4026 } 4086 }
4027 4087
4028 fe = (struct tagfile_entry *)p; 4088 fe = (struct tagfile_entry *)p;
@@ -4032,8 +4092,7 @@ static bool load_tagcache(void)
4032 { 4092 {
4033 /* End of lookup table. */ 4093 /* End of lookup table. */
4034 logf("read error #11"); 4094 logf("read error #11");
4035 close(fd); 4095 goto failure;
4036 return false;
4037 } 4096 }
4038 4097
4039 /* We have a special handling for the filename tags. */ 4098 /* We have a special handling for the filename tags. */
@@ -4051,16 +4110,14 @@ static bool load_tagcache(void)
4051 buf[10] = '\0'; 4110 buf[10] = '\0';
4052 logf("TAG:%s", buf); 4111 logf("TAG:%s", buf);
4053 logf("too long filename"); 4112 logf("too long filename");
4054 close(fd); 4113 goto failure;
4055 return false;
4056 } 4114 }
4057 4115
4058 rc = read(fd, buf, fe->tag_length); 4116 rc = read(fd, buf, fe->tag_length);
4059 if (rc != fe->tag_length) 4117 if (rc != fe->tag_length)
4060 { 4118 {
4061 logf("read error #12"); 4119 logf("read error #12");
4062 close(fd); 4120 goto failure;
4063 return false;
4064 } 4121 }
4065 4122
4066 /* Check if the entry has already been removed */ 4123 /* Check if the entry has already been removed */
@@ -4071,15 +4128,13 @@ static bool load_tagcache(void)
4071 if (idx->flag & FLAG_DIRCACHE) 4128 if (idx->flag & FLAG_DIRCACHE)
4072 { 4129 {
4073 logf("internal error!"); 4130 logf("internal error!");
4074 close(fd); 4131 goto failure;
4075 return false;
4076 } 4132 }
4077 4133
4078 if (idx->tag_seek[tag] != pos) 4134 if (idx->tag_seek[tag] != pos)
4079 { 4135 {
4080 logf("corrupt data structures!"); 4136 logf("corrupt data structures!");
4081 close(fd); 4137 goto failure;
4082 return false;
4083 } 4138 }
4084 4139
4085# ifdef HAVE_DIRCACHE 4140# ifdef HAVE_DIRCACHE
@@ -4126,8 +4181,7 @@ static bool load_tagcache(void)
4126 logf("too big tagcache #2"); 4181 logf("too big tagcache #2");
4127 logf("tl: %ld", fe->tag_length); 4182 logf("tl: %ld", fe->tag_length);
4128 logf("bl: %ld", bytesleft); 4183 logf("bl: %ld", bytesleft);
4129 close(fd); 4184 goto failure;
4130 return false;
4131 } 4185 }
4132 4186
4133 p = fe->tag_data; 4187 p = fe->tag_data;
@@ -4141,8 +4195,7 @@ static bool load_tagcache(void)
4141 logf("len=0x%04lx", fe->tag_length); // 0x4000 4195 logf("len=0x%04lx", fe->tag_length); // 0x4000
4142 logf("pos=0x%04lx", lseek(fd, 0, SEEK_CUR)); // 0x433 4196 logf("pos=0x%04lx", lseek(fd, 0, SEEK_CUR)); // 0x433
4143 logf("tag=0x%02x", tag); // 0x00 4197 logf("tag=0x%02x", tag); // 0x00
4144 close(fd); 4198 goto failure;
4145 return false;
4146 } 4199 }
4147 } 4200 }
4148 close(fd); 4201 close(fd);
@@ -4151,7 +4204,14 @@ static bool load_tagcache(void)
4151 tc_stat.ramcache_used = tc_stat.ramcache_allocated - bytesleft; 4204 tc_stat.ramcache_used = tc_stat.ramcache_allocated - bytesleft;
4152 logf("tagcache loaded into ram!"); 4205 logf("tagcache loaded into ram!");
4153 4206
4207 move_lock--;
4154 return true; 4208 return true;
4209
4210failure:
4211 close(fd);
4212failure_nofd:
4213 move_lock--;
4214 return false;
4155} 4215}
4156#endif /* HAVE_TC_RAMCACHE */ 4216#endif /* HAVE_TC_RAMCACHE */
4157 4217