summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiika Pekkarinen <miipekk@ihme.org>2006-04-18 18:56:56 +0000
committerMiika Pekkarinen <miipekk@ihme.org>2006-04-18 18:56:56 +0000
commitfa893c6b88d823dcdd3c746a94cfcde9765342cd (patch)
tree3aea16925a89b78f80dce844ce48d8e8fea60a22
parent2b18727a8abe08cf5f9d267d5f664bff13bd1cb2 (diff)
downloadrockbox-fa893c6b88d823dcdd3c746a94cfcde9765342cd.tar.gz
rockbox-fa893c6b88d823dcdd3c746a94cfcde9765342cd.zip
Performance optimizations for tagcache commit. Still more left to be done.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9721 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/tagcache.c295
-rw-r--r--apps/tagcache.h24
-rw-r--r--firmware/SOURCES1
-rw-r--r--firmware/common/crc32.c57
-rw-r--r--firmware/include/crc32.h25
5 files changed, 279 insertions, 123 deletions
diff --git a/apps/tagcache.c b/apps/tagcache.c
index 1c4ab6f3af..7bd0a819df 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -33,6 +33,7 @@
33#include "tagcache.h" 33#include "tagcache.h"
34#include "buffer.h" 34#include "buffer.h"
35#include "atoi.h" 35#include "atoi.h"
36#include "crc32.h"
36 37
37/* Tag Cache thread. */ 38/* Tag Cache thread. */
38static struct event_queue tagcache_queue; 39static struct event_queue tagcache_queue;
@@ -66,19 +67,12 @@ static bool tagcache_init_done = false;
66static int init_step; 67static int init_step;
67 68
68/* Queue commands. */ 69/* Queue commands. */
69#define Q_STOP_SCAN 0 70enum tagcache_queue {
70#define Q_START_SCAN 1 71 Q_STOP_SCAN = 0,
71#define Q_FORCE_UPDATE 2 72 Q_START_SCAN,
72 73 Q_FORCE_UPDATE,
73/* Tag database files. */ 74};
74#define TAGCACHE_FILE_TEMP ROCKBOX_DIR "/tagcache_tmp.tcd"
75#define TAGCACHE_FILE_MASTER ROCKBOX_DIR "/tagcache_idx.tcd"
76#define TAGCACHE_FILE_INDEX ROCKBOX_DIR "/tagcache_%d.tcd"
77
78/* Tag Cache Header version 'TCHxx' */
79#define TAGCACHE_MAGIC 0x54434802
80 75
81#define TAGCACHE_RESERVE 32768
82 76
83/* Tag database structures. */ 77/* Tag database structures. */
84 78
@@ -92,6 +86,7 @@ struct tagfile_entry {
92/* Fixed-size tag entry in master db index. */ 86/* Fixed-size tag entry in master db index. */
93struct index_entry { 87struct index_entry {
94 long tag_seek[TAG_COUNT]; 88 long tag_seek[TAG_COUNT];
89 long flag;
95}; 90};
96 91
97/* Header is the same in every file. */ 92/* Header is the same in every file. */
@@ -868,6 +863,19 @@ bool tagcache_retrieve(struct tagcache_search *tcs, int idxid,
868} 863}
869 864
870#if 0 865#if 0
866
867static bool tagcache_delete(const char *filename)
868{
869 struct index_entry *entry;
870
871 entry = find_entry_disk(filename, true);
872 if (entry == NULL)
873 {
874 logf("not found: %s", filename);
875 return false;
876 }
877}
878
871void tagcache_modify(struct tagcache_search *tcs, int type, const char *text) 879void tagcache_modify(struct tagcache_search *tcs, int type, const char *text)
872{ 880{
873 struct tagentry *entry; 881 struct tagentry *entry;
@@ -1111,7 +1119,7 @@ static bool tempbuf_insert(char *str, int id, int idx_id)
1111 return false; 1119 return false;
1112 1120
1113 index[tempbufidx].id = (struct tempbuf_id *)&tempbuf[tempbuf_pos]; 1121 index[tempbufidx].id = (struct tempbuf_id *)&tempbuf[tempbuf_pos];
1114#ifdef ROCKBOX_STRICT_ALIGN 1122#ifdef TAGCACHE_STRICT_ALIGN
1115 /* Make sure the entry is long aligned. */ 1123 /* Make sure the entry is long aligned. */
1116 if ((long)index[tempbufidx].id & 0x03) 1124 if ((long)index[tempbufidx].id & 0x03)
1117 { 1125 {
@@ -1141,41 +1149,51 @@ static bool tempbuf_unique_insert(char *str, int id)
1141 struct tempbuf_searchidx *index = (struct tempbuf_searchidx *)tempbuf; 1149 struct tempbuf_searchidx *index = (struct tempbuf_searchidx *)tempbuf;
1142 struct tempbuf_id *idp; 1150 struct tempbuf_id *idp;
1143 int i; 1151 int i;
1152 unsigned crc32;
1153 unsigned *crcbuf = (unsigned *)&tempbuf[tempbuf_size-4];
1144 1154
1145 /* Check if string already exists. */ 1155 crc32 = crc_32(str, strlen(str), 0xffffffff);
1156
1157 /* Check if the crc does not exist -> entry does not exist for sure. */
1146 for (i = 0; i < tempbufidx; i++) 1158 for (i = 0; i < tempbufidx; i++)
1147 { 1159 {
1148 if (!strcasecmp(str, index[i].str)) 1160 if (*(crcbuf--) == crc32)
1149 { 1161 {
1150 tempbuf_left -= sizeof(struct tempbuf_id); 1162 if (!strcasecmp(str, index[i].str))
1151 if (tempbuf_left - 4 < 0)
1152 return false;
1153
1154 idp = index[i].id;
1155 while (idp->next != NULL)
1156 idp = idp->next;
1157
1158 idp->next = (struct tempbuf_id *)&tempbuf[tempbuf_pos];
1159#ifdef ROCKBOX_STRICT_ALIGN
1160 /* Make sure the entry is long aligned. */
1161 if ((long)idp->next & 0x03)
1162 { 1163 {
1163 int fix = 4 - ((long)idp->next & 0x03); 1164 tempbuf_left -= sizeof(struct tempbuf_id);
1164 tempbuf_left -= fix; 1165 if (tempbuf_left - 4 < 0)
1165 tempbuf_pos += fix; 1166 return false;
1166 idp->next = (struct tempbuf_id *)(( 1167
1167 (long)idp->next & ~0x03) + 0x04); 1168 idp = index[i].id;
1168 } 1169 while (idp->next != NULL)
1170 idp = idp->next;
1171
1172 idp->next = (struct tempbuf_id *)&tempbuf[tempbuf_pos];
1173#if TAGCACHE_STRICT_ALIGN
1174 /* Make sure the entry is long aligned. */
1175 if ((long)idp->next & 0x03)
1176 {
1177 int fix = 4 - ((long)idp->next & 0x03);
1178 tempbuf_left -= fix;
1179 tempbuf_pos += fix;
1180 idp->next = (struct tempbuf_id *)
1181 (((long)idp->next & ~0x03) + 0x04);
1182 }
1169#endif 1183#endif
1170 idp = idp->next; 1184 idp = idp->next;
1171 idp->id = id; 1185 idp->id = id;
1172 idp->next = NULL; 1186 idp->next = NULL;
1173 tempbuf_pos += sizeof(struct tempbuf_id); 1187 tempbuf_pos += sizeof(struct tempbuf_id);
1174 1188
1175 return true; 1189 return true;
1190 }
1176 } 1191 }
1177 } 1192 }
1178 1193
1194 /* Insert and quit. */
1195 *crcbuf = crc32;
1196 tempbuf_left -= 4;
1179 return tempbuf_insert(str, id, -1); 1197 return tempbuf_insert(str, id, -1);
1180} 1198}
1181 1199
@@ -1200,7 +1218,7 @@ static int tempbuf_sort(int fd)
1200 struct tagfile_entry fe; 1218 struct tagfile_entry fe;
1201 int i; 1219 int i;
1202 int length; 1220 int length;
1203#ifdef ROCKBOX_STRICT_ALIGN 1221#ifdef TAGCACHE_STRICT_ALIGN
1204 int fix; 1222 int fix;
1205#endif 1223#endif
1206 1224
@@ -1213,7 +1231,7 @@ static int tempbuf_sort(int fd)
1213 fe.tag_length = length; 1231 fe.tag_length = length;
1214 fe.idx_id = index[i].idx_id; 1232 fe.idx_id = index[i].idx_id;
1215 1233
1216#ifdef ROCKBOX_STRICT_ALIGN 1234#ifdef TAGCACHE_STRICT_ALIGN
1217 /* Make sure the entry is long aligned. */ 1235 /* Make sure the entry is long aligned. */
1218 if (index[i].seek & 0x03) 1236 if (index[i].seek & 0x03)
1219 { 1237 {
@@ -1241,7 +1259,7 @@ static int tempbuf_sort(int fd)
1241 return -2; 1259 return -2;
1242 } 1260 }
1243 1261
1244#ifdef ROCKBOX_STRICT_ALIGN 1262#ifdef TAGCACHE_STRICT_ALIGN
1245 /* Write some padding. */ 1263 /* Write some padding. */
1246 if (fix) 1264 if (fix)
1247 write(fd, "XXX", fix); 1265 write(fd, "XXX", fix);
@@ -1251,15 +1269,21 @@ static int tempbuf_sort(int fd)
1251 return i; 1269 return i;
1252} 1270}
1253 1271
1254 1272inline static struct tempbuf_searchidx* tempbuf_locate(int id)
1255static struct tempbuf_searchidx* tempbuf_locate(int id)
1256{ 1273{
1257 struct tempbuf_searchidx *index = (struct tempbuf_searchidx *)tempbuf; 1274 struct tempbuf_searchidx *index = (struct tempbuf_searchidx *)tempbuf;
1258 struct tempbuf_id *idp; 1275 struct tempbuf_id *idp;
1276 static int last_id = 0;
1259 int i; 1277 int i;
1260 1278
1279 try_again:
1280
1281 if (last_id >= tempbufidx)
1282 last_id = 0;
1283
1261 /* Check if string already exists. */ 1284 /* Check if string already exists. */
1262 for (i = 0; i < tempbufidx; i++) 1285 /* FIXME: This check is extremely slow, O(n^2) */
1286 for (i = last_id; i < tempbufidx; i++)
1263 { 1287 {
1264 idp = index[i].id; 1288 idp = index[i].id;
1265 while (idp != NULL) 1289 while (idp != NULL)
@@ -1270,11 +1294,14 @@ static struct tempbuf_searchidx* tempbuf_locate(int id)
1270 } 1294 }
1271 } 1295 }
1272 1296
1297 if (last_id)
1298 goto try_again;
1299
1273 return NULL; 1300 return NULL;
1274} 1301}
1275 1302
1276 1303
1277static int tempbuf_find_location(int id) 1304inline static int tempbuf_find_location(int id)
1278{ 1305{
1279 struct tempbuf_searchidx *entry; 1306 struct tempbuf_searchidx *entry;
1280 1307
@@ -1380,12 +1407,13 @@ static bool build_numeric_index(int index_type, struct tagcache_header *h, int t
1380 1407
1381 return true; 1408 return true;
1382} 1409}
1383 1410
1384static bool build_index(int index_type, struct tagcache_header *h, int tmpfd) 1411static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
1385{ 1412{
1386 int i; 1413 int i;
1387 struct tagcache_header tch; 1414 struct tagcache_header tch;
1388 struct index_entry idx; 1415 struct index_entry idxbuf[IDX_BUF_DEPTH];
1416 int idxbuf_pos;
1389 char buf[MAX_PATH]; 1417 char buf[MAX_PATH];
1390 int fd = -1, masterfd; 1418 int fd = -1, masterfd;
1391 bool error = false; 1419 bool error = false;
@@ -1425,6 +1453,7 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
1425 */ 1453 */
1426 if (tagcache_is_sorted_tag(index_type)) 1454 if (tagcache_is_sorted_tag(index_type))
1427 { 1455 {
1456 logf("loading tags...");
1428 for (i = 0; i < tch.entry_count; i++) 1457 for (i = 0; i < tch.entry_count; i++)
1429 { 1458 {
1430 struct tagfile_entry entry; 1459 struct tagfile_entry entry;
@@ -1460,6 +1489,7 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
1460 tempbuf_insert(buf, loc + TAGFILE_MAX_ENTRIES, entry.idx_id); 1489 tempbuf_insert(buf, loc + TAGFILE_MAX_ENTRIES, entry.idx_id);
1461 yield(); 1490 yield();
1462 } 1491 }
1492 logf("done");
1463 } 1493 }
1464 else 1494 else
1465 tempbufidx = tch.entry_count; 1495 tempbufidx = tch.entry_count;
@@ -1555,6 +1585,7 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
1555 { 1585 {
1556 lseek(tmpfd, sizeof(struct tagcache_header), SEEK_SET); 1586 lseek(tmpfd, sizeof(struct tagcache_header), SEEK_SET);
1557 /* h is the header of the temporary file containing new tags. */ 1587 /* h is the header of the temporary file containing new tags. */
1588 logf("inserting new tags...");
1558 for (i = 0; i < h->entry_count; i++) 1589 for (i = 0; i < h->entry_count; i++)
1559 { 1590 {
1560 struct temp_file_entry entry; 1591 struct temp_file_entry entry;
@@ -1600,6 +1631,7 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
1600 entry.tag_length[index_type], SEEK_CUR); 1631 entry.tag_length[index_type], SEEK_CUR);
1601 yield(); 1632 yield();
1602 } 1633 }
1634 logf("done");
1603 1635
1604 /* Sort the buffer data and write it to the index file. */ 1636 /* Sort the buffer data and write it to the index file. */
1605 lseek(fd, sizeof(struct tagcache_header), SEEK_SET); 1637 lseek(fd, sizeof(struct tagcache_header), SEEK_SET);
@@ -1611,128 +1643,146 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
1611 /** 1643 /**
1612 * Now update all indexes in the master lookup file. 1644 * Now update all indexes in the master lookup file.
1613 */ 1645 */
1646 logf("updating indices...");
1614 lseek(masterfd, sizeof(struct tagcache_header), SEEK_SET); 1647 lseek(masterfd, sizeof(struct tagcache_header), SEEK_SET);
1615 for (i = 0; i < tch.entry_count; i++) 1648 for (i = 0; i < tch.entry_count; i += idxbuf_pos)
1616 { 1649 {
1650 int j;
1617 int loc = lseek(masterfd, 0, SEEK_CUR); 1651 int loc = lseek(masterfd, 0, SEEK_CUR);
1618 1652
1619 if (read(masterfd, &idx, sizeof(struct index_entry)) != 1653 idxbuf_pos = MIN(tch.entry_count - i, IDX_BUF_DEPTH);
1620 sizeof(struct index_entry)) 1654
1655 if (read(masterfd, idxbuf, sizeof(struct index_entry)*idxbuf_pos) !=
1656 (int)sizeof(struct index_entry)*idxbuf_pos)
1621 { 1657 {
1622 logf("read fail #2"); 1658 logf("read fail #2");
1623 error = true; 1659 error = true;
1624 goto error_exit ; 1660 goto error_exit ;
1625 } 1661 }
1626 idx.tag_seek[index_type] = tempbuf_find_location( 1662 lseek(masterfd, loc, SEEK_SET);
1627 idx.tag_seek[index_type]+TAGFILE_MAX_ENTRIES); 1663
1628 if (idx.tag_seek[index_type] < 0) 1664 for (j = 0; j < idxbuf_pos; j++)
1629 { 1665 {
1630 logf("update error: %d/%d", i, tch.entry_count); 1666 idxbuf[j].tag_seek[index_type] = tempbuf_find_location(
1631 error = true; 1667 idxbuf[j].tag_seek[index_type]+TAGFILE_MAX_ENTRIES);
1632 goto error_exit; 1668
1669 if (idxbuf[j].tag_seek[index_type] < 0)
1670 {
1671 logf("update error: %d/%d", i+j, tch.entry_count);
1672 error = true;
1673 goto error_exit;
1674 }
1675 yield();
1633 } 1676 }
1634 1677
1635 /* Write back the updated index. */ 1678 /* Write back the updated index. */
1636 lseek(masterfd, loc, SEEK_SET); 1679 if (write(masterfd, idxbuf, sizeof(struct index_entry)*idxbuf_pos) !=
1637 if (write(masterfd, &idx, sizeof(struct index_entry)) != 1680 (int)sizeof(struct index_entry)*idxbuf_pos)
1638 sizeof(struct index_entry))
1639 { 1681 {
1640 logf("write fail"); 1682 logf("write fail");
1641 error = true; 1683 error = true;
1642 goto error_exit; 1684 goto error_exit;
1643 } 1685 }
1644 yield();
1645 } 1686 }
1687 logf("done");
1646 } 1688 }
1647 1689
1648 /** 1690 /**
1649 * Walk through the temporary file containing the new tags. 1691 * Walk through the temporary file containing the new tags.
1650 */ 1692 */
1651 // build_normal_index(h, tmpfd, masterfd, idx); 1693 // build_normal_index(h, tmpfd, masterfd, idx);
1694 logf("updating new indices...");
1652 lseek(masterfd, masterfd_pos, SEEK_SET); 1695 lseek(masterfd, masterfd_pos, SEEK_SET);
1653 lseek(tmpfd, sizeof(struct tagcache_header), SEEK_SET); 1696 lseek(tmpfd, sizeof(struct tagcache_header), SEEK_SET);
1654 lseek(fd, 0, SEEK_END); 1697 lseek(fd, 0, SEEK_END);
1655 for (i = 0; i < h->entry_count; i++) 1698 for (i = 0; i < h->entry_count; i += idxbuf_pos)
1656 { 1699 {
1700 int j;
1701
1702 idxbuf_pos = MIN(h->entry_count - i, IDX_BUF_DEPTH);
1657 if (init) 1703 if (init)
1658 { 1704 {
1659 memset(&idx, 0, sizeof(struct index_entry)); 1705 memset(idxbuf, 0, sizeof(struct index_entry)*IDX_BUF_DEPTH);
1660 } 1706 }
1661 else 1707 else
1662 { 1708 {
1663 if (read(masterfd, &idx, sizeof(struct index_entry)) != 1709 int loc = lseek(masterfd, 0, SEEK_CUR);
1664 sizeof(struct index_entry)) 1710
1711 if (read(masterfd, idxbuf, sizeof(struct index_entry)*idxbuf_pos) !=
1712 (int)sizeof(struct index_entry)*idxbuf_pos)
1665 { 1713 {
1666 logf("read fail #2"); 1714 logf("read fail #2");
1667 error = true; 1715 error = true;
1668 break ; 1716 break ;
1669 } 1717 }
1670 lseek(masterfd, -sizeof(struct index_entry), SEEK_CUR); 1718 lseek(masterfd, loc, SEEK_SET);
1671 } 1719 }
1672 1720
1673 /* Read entry headers. */ 1721 /* Read entry headers. */
1674 if (!tagcache_is_sorted_tag(index_type)) 1722 for (j = 0; j < idxbuf_pos; j++)
1675 { 1723 {
1676 struct temp_file_entry entry; 1724 if (!tagcache_is_sorted_tag(index_type))
1677 struct tagfile_entry fe;
1678
1679 if (read(tmpfd, &entry, sizeof(struct temp_file_entry)) !=
1680 sizeof(struct temp_file_entry))
1681 {
1682 logf("read fail #1");
1683 error = true;
1684 break ;
1685 }
1686
1687 /* Read data. */
1688 if (entry.tag_length[index_type] >= (int)sizeof(buf))
1689 { 1725 {
1690 logf("too long entry!"); 1726 struct temp_file_entry entry;
1691 logf("length=%d", entry.tag_length[index_type]); 1727 struct tagfile_entry fe;
1692 logf("pos=0x%02x", lseek(tmpfd, 0, SEEK_CUR)); 1728
1693 error = true; 1729 if (read(tmpfd, &entry, sizeof(struct temp_file_entry)) !=
1694 break ; 1730 sizeof(struct temp_file_entry))
1695 } 1731 {
1732 logf("read fail #1");
1733 error = true;
1734 break ;
1735 }
1736
1737 /* Read data. */
1738 if (entry.tag_length[index_type] >= (int)sizeof(buf))
1739 {
1740 logf("too long entry!");
1741 logf("length=%d", entry.tag_length[index_type]);
1742 logf("pos=0x%02x", lseek(tmpfd, 0, SEEK_CUR));
1743 error = true;
1744 break ;
1745 }
1746
1747 lseek(tmpfd, entry.tag_offset[index_type], SEEK_CUR);
1748 if (read(tmpfd, buf, entry.tag_length[index_type]) !=
1749 entry.tag_length[index_type])
1750 {
1751 logf("read fail #3");
1752 logf("offset=0x%02x", entry.tag_offset[index_type]);
1753 logf("length=0x%02x", entry.tag_length[index_type]);
1754 error = true;
1755 break ;
1756 }
1696 1757
1697 lseek(tmpfd, entry.tag_offset[index_type], SEEK_CUR); 1758 /* Write to index file. */
1698 if (read(tmpfd, buf, entry.tag_length[index_type]) != 1759 idxbuf[j].tag_seek[index_type] = lseek(fd, 0, SEEK_CUR);
1699 entry.tag_length[index_type]) 1760 fe.tag_length = entry.tag_length[index_type];
1700 { 1761 fe.idx_id = tch.entry_count + i + j;
1701 logf("read fail #3"); 1762 write(fd, &fe, sizeof(struct tagfile_entry));
1702 logf("offset=0x%02x", entry.tag_offset[index_type]); 1763 write(fd, buf, fe.tag_length);
1703 logf("length=0x%02x", entry.tag_length[index_type]); 1764 tempbufidx++;
1704 error = true; 1765
1705 break ; 1766 /* Skip to next. */
1767 lseek(tmpfd, entry.data_length - entry.tag_offset[index_type] -
1768 entry.tag_length[index_type], SEEK_CUR);
1706 } 1769 }
1707 1770 else
1708 /* Write to index file. */
1709 idx.tag_seek[index_type] = lseek(fd, 0, SEEK_CUR);
1710 fe.tag_length = entry.tag_length[index_type];
1711 fe.idx_id = tch.entry_count + i;
1712 write(fd, &fe, sizeof(struct tagfile_entry));
1713 write(fd, buf, fe.tag_length);
1714 tempbufidx++;
1715
1716 /* Skip to next. */
1717 lseek(tmpfd, entry.data_length - entry.tag_offset[index_type] -
1718 entry.tag_length[index_type], SEEK_CUR);
1719 }
1720 else
1721 {
1722 /* Locate the correct entry from the sorted array. */
1723 idx.tag_seek[index_type] = tempbuf_find_location(i);
1724 if (idx.tag_seek[index_type] < 0)
1725 { 1771 {
1726 logf("entry not found (%d)"); 1772 /* Locate the correct entry from the sorted array. */
1727 error = true; 1773 idxbuf[j].tag_seek[index_type] = tempbuf_find_location(i + j);
1728 break ; 1774 if (idxbuf[j].tag_seek[index_type] < 0)
1775 {
1776 logf("entry not found (%d)");
1777 error = true;
1778 break ;
1779 }
1729 } 1780 }
1730 } 1781 }
1731 1782
1732
1733 /* Write index. */ 1783 /* Write index. */
1734 if (write(masterfd, &idx, sizeof(struct index_entry)) != 1784 if (write(masterfd, idxbuf, sizeof(struct index_entry)*idxbuf_pos) !=
1735 sizeof(struct index_entry)) 1785 (int)sizeof(struct index_entry)*idxbuf_pos)
1736 { 1786 {
1737 logf("tagcache: write fail #4"); 1787 logf("tagcache: write fail #4");
1738 error = true; 1788 error = true;
@@ -1741,7 +1791,8 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
1741 1791
1742 yield(); 1792 yield();
1743 } 1793 }
1744 1794 logf("done");
1795
1745 /* Finally write the uniqued tag index file. */ 1796 /* Finally write the uniqued tag index file. */
1746 if (tagcache_is_sorted_tag(index_type)) 1797 if (tagcache_is_sorted_tag(index_type))
1747 { 1798 {
diff --git a/apps/tagcache.h b/apps/tagcache.h
index 468c48c45d..1ac96b4bad 100644
--- a/apps/tagcache.h
+++ b/apps/tagcache.h
@@ -31,16 +31,38 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title,
31#define HAVE_TC_RAMCACHE 1 31#define HAVE_TC_RAMCACHE 1
32#endif 32#endif
33 33
34/* Allow a little drift to the filename ordering. */ 34/* Allow a little drift to the filename ordering (should not be too high/low). */
35#define POS_HISTORY_COUNT 4 35#define POS_HISTORY_COUNT 4
36 36
37/* How much to pre-load entries while committing to prevent seeking. */
38#define IDX_BUF_DEPTH 64
39
40/* Tag Cache Header version 'TCHxx'. Increment when changing internal structures. */
41#define TAGCACHE_MAGIC 0x54434803
42
43/* How much to allocate extra space for ramcache. */
44#define TAGCACHE_RESERVE 32768
45
37/* How many entries we can create in one tag file (for sorting). */ 46/* How many entries we can create in one tag file (for sorting). */
38#define TAGFILE_MAX_ENTRIES 20000 47#define TAGFILE_MAX_ENTRIES 20000
39 48
49/* How many entries to fetch to the seek table at once while searching. */
40#define SEEK_LIST_SIZE 50 50#define SEEK_LIST_SIZE 50
51
52/* Always strict align entries for best performance and binary compatability. */
53#define TAGCACHE_STRICT_ALIGN 1
54
41#define TAGCACHE_MAX_FILTERS 3 55#define TAGCACHE_MAX_FILTERS 3
42#define TAGCACHE_MAX_CLAUSES 10 56#define TAGCACHE_MAX_CLAUSES 10
43 57
58/* Tag database files. */
59#define TAGCACHE_FILE_TEMP ROCKBOX_DIR "/tagcache_tmp.tcd"
60#define TAGCACHE_FILE_MASTER ROCKBOX_DIR "/tagcache_idx.tcd"
61#define TAGCACHE_FILE_INDEX ROCKBOX_DIR "/tagcache_%d.tcd"
62
63/* Flags */
64#define FLAG_DELETED 0x0001
65
44enum clause { clause_none, clause_is, clause_gt, clause_gteq, clause_lt, 66enum clause { clause_none, clause_is, clause_gt, clause_gteq, clause_lt,
45 clause_lteq, clause_contains, clause_begins_with, clause_ends_with }; 67 clause_lteq, clause_contains, clause_begins_with, clause_ends_with };
46enum modifiers { clause_mod_none, clause_mod_not }; 68enum modifiers { clause_mod_none, clause_mod_not };
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 4b2e63d378..07f4ffd796 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -5,6 +5,7 @@ logf.c
5backlight.c 5backlight.c
6buffer.c 6buffer.c
7common/atoi.c 7common/atoi.c
8common/crc32.c
8common/ctype.c 9common/ctype.c
9#ifndef SIMULATOR 10#ifndef SIMULATOR
10common/dir.c 11common/dir.c
diff --git a/firmware/common/crc32.c b/firmware/common/crc32.c
new file mode 100644
index 0000000000..18ee6ac710
--- /dev/null
+++ b/firmware/common/crc32.c
@@ -0,0 +1,57 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2003 Jörg Hohensohn [IDC]Dragon
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20/* Code copied from firmware_flash plugin. */
21
22/* Tool function to calculate a CRC32 across some buffer */
23/* third argument is either 0xFFFFFFFF to start or value from last piece */
24unsigned crc_32(unsigned char* buf, unsigned len, unsigned crc32)
25{
26 /* CCITT standard polynomial 0x04C11DB7 */
27 static const unsigned crc32_lookup[16] =
28 { /* lookup table for 4 bits at a time is affordable */
29 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
30 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
31 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
32 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
33 };
34
35 unsigned char byte;
36 unsigned t;
37
38 while (len--)
39 {
40 byte = *buf++; /* get one byte of data */
41
42 /* upper nibble of our data */
43 t = crc32 >> 28; /* extract the 4 most significant bits */
44 t ^= byte >> 4; /* XOR in 4 bits of data into the extracted bits */
45 crc32 <<= 4; /* shift the CRC register left 4 bits */
46 crc32 ^= crc32_lookup[t]; /* do the table lookup and XOR the result */
47
48 /* lower nibble of our data */
49 t = crc32 >> 28; /* extract the 4 most significant bits */
50 t ^= byte & 0x0F; /* XOR in 4 bits of data into the extracted bits */
51 crc32 <<= 4; /* shift the CRC register left 4 bits */
52 crc32 ^= crc32_lookup[t]; /* do the table lookup and XOR the result */
53 }
54
55 return crc32;
56}
57
diff --git a/firmware/include/crc32.h b/firmware/include/crc32.h
new file mode 100644
index 0000000000..5e998ab1b9
--- /dev/null
+++ b/firmware/include/crc32.h
@@ -0,0 +1,25 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2003 Jörg Hohensohn [IDC]Dragon
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#ifndef _CRC32_H
20#define _CRC32_H
21
22unsigned crc_32(unsigned char* buf, unsigned len, unsigned crc32);
23
24#endif
25