diff options
author | Max Kellermann <max@duempel.org> | 2008-09-08 11:47:57 +0200 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2008-09-08 11:47:57 +0200 |
commit | f0e64ceb48c485baf32528bba44875885d384354 (patch) | |
tree | c9869f5a5dd25a7eb88791ca6aa95f7c0e77168c | |
parent | 2b8040b42524dad68ea85c45a4be25909a03eb5c (diff) | |
download | mpd-f0e64ceb48c485baf32528bba44875885d384354.tar.gz mpd-f0e64ceb48c485baf32528bba44875885d384354.tar.xz mpd-f0e64ceb48c485baf32528bba44875885d384354.zip |
use strset.h instead of tagTracker.h
With a large music database, the linear string collection in
tagTracker.c becomes very slow. We implemented that in a
quick'n'dirty fashion when we removed tree.c, and now we rewrite it
using the fast hashed string set.
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/dbUtils.c | 23 | ||||
-rw-r--r-- | src/stats.c | 44 | ||||
-rw-r--r-- | src/tag.c | 1 | ||||
-rw-r--r-- | src/tagTracker.c | 117 | ||||
-rw-r--r-- | src/tagTracker.h | 34 |
6 files changed, 58 insertions, 163 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 5a5439bfc..076802015 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -90,7 +90,6 @@ mpd_headers = \ tag_id3.h \ tag_print.h \ tag_save.h \ - tagTracker.h \ utf8.h \ strset.h \ utils.h \ @@ -158,7 +157,6 @@ mpd_SOURCES = \ tag_id3.c \ tag_print.c \ tag_save.c \ - tagTracker.c \ strset.c \ utils.c \ volume.c \ diff --git a/src/dbUtils.c b/src/dbUtils.c index 9eb6aa46b..d204d7e1e 100644 --- a/src/dbUtils.c +++ b/src/dbUtils.c @@ -25,7 +25,7 @@ #include "song.h" #include "song_print.h" #include "tag.h" -#include "tagTracker.h" +#include "strset.h" #include "log.h" #include "storedPlaylist.h" @@ -278,7 +278,8 @@ static void freeListCommandItem(ListCommandItem * item) free(item); } -static void visitTag(struct client *client, Song * song, enum tag_type tagType) +static void visitTag(struct client *client, struct strset *set, + Song * song, enum tag_type tagType) { int i; struct tag *tag = song->tag; @@ -293,7 +294,7 @@ static void visitTag(struct client *client, Song * song, enum tag_type tagType) for (i = 0; i < tag->numOfItems; i++) { if (tag->items[i]->type == tagType) { - visitInTagTracker(tagType, tag->items[i]->value); + strset_add(set, tag->items[i]->value); } } } @@ -301,6 +302,7 @@ static void visitTag(struct client *client, Song * song, enum tag_type tagType) struct list_tags_data { struct client *client; ListCommandItem *item; + struct strset *set; }; static int listUniqueTagsInDirectory(Song * song, void *_data) @@ -310,7 +312,7 @@ static int listUniqueTagsInDirectory(Song * song, void *_data) if (tagItemsFoundAndMatches(song, item->numConditionals, item->conditionals)) { - visitTag(data->client, song, item->tagType); + visitTag(data->client, data->set, song, item->tagType); } return 0; @@ -328,14 +330,23 @@ int listAllUniqueTags(struct client *client, int type, int numConditionals, }; if (type >= 0 && type <= TAG_NUM_OF_ITEM_TYPES) { - resetVisitedFlagsInTagTracker(type); + data.set = strset_new(); } ret = traverseAllIn(NULL, listUniqueTagsInDirectory, NULL, &data); if (type >= 0 && type <= TAG_NUM_OF_ITEM_TYPES) { - printVisitedInTagTracker(client, type); + const char *value; + + strset_rewind(data.set); + + while ((value = strset_next(data.set)) != NULL) + client_printf(client, "%s: %s\n", + mpdTagItemKeys[type], + value); + + strset_free(data.set); } freeListCommandItem(item); diff --git a/src/stats.c b/src/stats.c index 280450f14..ee0854e16 100644 --- a/src/stats.c +++ b/src/stats.c @@ -1,5 +1,6 @@ /* the Music Player Daemon (MPD) * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) + * Copyright (C) 2008 Max Kellermann <max@duempel.org> * This project's homepage is: http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,7 +23,7 @@ #include "tag.h" #include "client.h" #include "player_control.h" -#include "tagTracker.h" +#include "strset.h" #include "os_compat.h" Stats stats; @@ -33,11 +34,48 @@ void initStats(void) stats.numberOfSongs = 0; } +struct visit_data { + enum tag_type type; + struct strset *set; +}; + +static int visit_tag_items(Song *song, void *_data) +{ + const struct visit_data *data = _data; + unsigned i; + + if (song->tag == NULL) + return 0; + + for (i = 0; i < (unsigned)song->tag->numOfItems; ++i) { + const struct tag_item *item = song->tag->items[i]; + if (item->type == data->type) + strset_add(data->set, item->value); + } + + return 0; +} + +static unsigned int getNumberOfTagItems(int type) +{ + struct visit_data data = { + .type = type, + .set = strset_new(), + }; + unsigned int ret; + + traverseAllIn(NULL, visit_tag_items, NULL, &data); + + ret = strset_size(data.set); + strset_free(data.set); + return ret; +} + int printStats(struct client *client) { client_printf(client, - "artists: %i\n" - "albums: %i\n" + "artists: %u\n" + "albums: %u\n" "songs: %i\n" "uptime: %li\n" "playtime: %li\n" @@ -23,7 +23,6 @@ #include "utf8.h" #include "log.h" #include "conf.h" -#include "tagTracker.h" #include "song.h" /** diff --git a/src/tagTracker.c b/src/tagTracker.c deleted file mode 100644 index bc9a43bc7..000000000 --- a/src/tagTracker.c +++ /dev/null @@ -1,117 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "tagTracker.h" - -#include "tag.h" -#include "utils.h" -#include "client.h" -#include "directory.h" - -struct visited { - struct visited *next; - - /** - * this is the original pointer passed to visitInTagTracker(), - * i.e. the caller must not invalidate it until he calls - * resetVisitedFlagsInTagTracker(). - */ - const char *value; -} mpd_packed; - -static struct visited *visited_heads[TAG_NUM_OF_ITEM_TYPES]; -static unsigned num_visited[TAG_NUM_OF_ITEM_TYPES]; - -static int visit_tag_items(Song *song, void *data) -{ - enum tag_type type = (enum tag_type)(size_t)data; - unsigned i; - - if (song->tag == NULL) - return 0; - - for (i = 0; i < (unsigned)song->tag->numOfItems; ++i) { - const struct tag_item *item = song->tag->items[i]; - if (item->type == type) - visitInTagTracker(type, item->value); - } - - return 0; -} - -int getNumberOfTagItems(int type) -{ - int ret; - - resetVisitedFlagsInTagTracker(type); - - traverseAllIn(NULL, visit_tag_items, NULL, (void*)(size_t)type); - - ret = (int)num_visited[type]; - resetVisitedFlagsInTagTracker(type); - return ret; -} - -void resetVisitedFlagsInTagTracker(int type) -{ - while (visited_heads[type] != NULL) { - struct visited *v = visited_heads[type]; - visited_heads[type] = v->next; - free(v); - } - - num_visited[type] = 0; -} - -static struct visited * -find_visit(int type, const char *p) -{ - struct visited *v; - - for (v = visited_heads[type]; v != NULL; v = v->next) - if (strcmp(v->value, p) == 0) - return v; - - return NULL; -} - -void visitInTagTracker(int type, const char *str) -{ - struct visited *v = find_visit(type, str); - size_t length; - - if (v != NULL) - return; - - length = strlen(str); - v = xmalloc(sizeof(*v)); - v->value = str; - v->next = visited_heads[type]; - visited_heads[type] = v; - ++num_visited[type]; -} - -void printVisitedInTagTracker(struct client *client, int type) -{ - struct visited *v; - - for (v = visited_heads[type]; v != NULL; v = v->next) - client_printf(client, "%s: %s\n", - mpdTagItemKeys[type], - v->value); -} diff --git a/src/tagTracker.h b/src/tagTracker.h deleted file mode 100644 index f3c778329..000000000 --- a/src/tagTracker.h +++ /dev/null @@ -1,34 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TAG_TRACKER_H -#define TAG_TRACKER_H - -struct client; - -int getNumberOfTagItems(int type); - -void printMemorySavedByTagTracker(void); - -void resetVisitedFlagsInTagTracker(int type); - -void visitInTagTracker(int type, const char *str); - -void printVisitedInTagTracker(struct client *client, int type); - -#endif |