From 303a3329eb7d77ec87ab5fb1a47e56748edc95e6 Mon Sep 17 00:00:00 2001 From: Julien BLACHE Date: Thu, 31 Mar 2011 18:05:41 +0200 Subject: [PATCH] Replace AVL tree in DAAP query by a static hash using gperf --- src/.gitignore | 2 + src/DAAP2SQL.g | 6 +-- src/Makefile.am | 6 ++- src/daap_query.c | 124 ++----------------------------------------- src/daap_query.gperf | 39 ++++++++++++++ src/daap_query.h | 16 ++---- src/httpd_daap.c | 12 +---- 7 files changed, 57 insertions(+), 148 deletions(-) create mode 100644 src/daap_query.gperf diff --git a/src/.gitignore b/src/.gitignore index 2c8e1fb4..b07c4c71 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -7,3 +7,5 @@ DAAP2SQL.[ch] RSP2SQL.[ch] *.u + +daap_query_hash.c diff --git a/src/DAAP2SQL.g b/src/DAAP2SQL.g index 820887bb..a9e8a6e8 100644 --- a/src/DAAP2SQL.g +++ b/src/DAAP2SQL.g @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2010 Julien BLACHE + * Copyright (C) 2009-2011 Julien BLACHE * * 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 @@ -94,7 +94,7 @@ expr returns [ pANTLR3_STRING result, int valid ] pANTLR3_UINT8 escaped; ANTLR3_UINT8 op; int neg_op; - struct dmap_query_field_map *dqfm; + const struct dmap_query_field_map *dqfm; char *end; long long llval; @@ -162,7 +162,7 @@ expr returns [ pANTLR3_STRING result, int valid ] neg_op = 0; /* Lookup DMAP field in the query field map */ - dqfm = daap_query_field_lookup((char *)field); + dqfm = daap_query_field_lookup((char *)field, strlen((char *)field)); if (!dqfm) { DPRINTF(E_LOG, L_DAAP, "DMAP field '\%s' is not a valid field in queries\n", field); diff --git a/src/Makefile.am b/src/Makefile.am index 10a626d2..1ba8c3f7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -21,9 +21,11 @@ if COND_OSS4 OSS4SRC=laudio_oss4.c endif -GPERF_FILES = +GPERF_FILES = \ + daap_query.gperf -GPERF_PRODUCTS = +GPERF_PRODUCTS = \ + daap_query_hash.c ANTLR_GRAMMARS = \ RSP.g RSP2SQL.g \ diff --git a/src/daap_query.c b/src/daap_query.c index b3172751..7b42898e 100644 --- a/src/daap_query.c +++ b/src/daap_query.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2010 Julien BLACHE + * Copyright (C) 2009-2011 Julien BLACHE * * 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 @@ -25,8 +25,6 @@ #include #include -#include - #include "logger.h" #include "misc.h" #include "daap_query.h" @@ -36,72 +34,9 @@ #include "DAAP2SQL.h" -static struct dmap_query_field_map dmap_query_fields[] = -{ - { 0, 0, "dmap.itemname", "title" }, - { 0, 1, "dmap.itemid", "id" }, - { 0, 0, "daap.songalbum", "album" }, - { 0, 1, "daap.songalbumid", "songalbumid" }, - { 0, 0, "daap.songartist", "artist" }, - { 0, 0, "daap.songalbumartist", "album_artist" }, - { 0, 1, "daap.songbitrate", "bitrate" }, - { 0, 0, "daap.songcomment", "comment" }, - { 0, 1, "daap.songcompilation", "compilation" }, - { 0, 0, "daap.songcomposer", "composer" }, - { 0, 1, "daap.songdatakind", "data_kind" }, - { 0, 0, "daap.songdataurl", "url" }, - { 0, 1, "daap.songdateadded", "time_added" }, - { 0, 1, "daap.songdatemodified", "time_modified" }, - { 0, 0, "daap.songdescription", "description" }, - { 0, 1, "daap.songdisccount", "total_discs" }, - { 0, 1, "daap.songdiscnumber", "disc" }, - { 0, 0, "daap.songformat", "type" }, - { 0, 0, "daap.songgenre", "genre" }, - { 0, 1, "daap.songsamplerate", "samplerate" }, - { 0, 1, "daap.songsize", "file_size" }, - { 0, 1, "daap.songstoptime", "song_length" }, - { 0, 1, "daap.songtime", "song_length" }, - { 0, 1, "daap.songtrackcount", "total_tracks" }, - { 0, 1, "daap.songtracknumber", "track" }, - { 0, 1, "daap.songyear", "year" }, - { 0, 1, "com.apple.itunes.mediakind", "media_kind" }, +/* gperf static hash, daap_query.gperf */ +#include "daap_query_hash.c" - { -1, -1, NULL, NULL } -}; - -static avl_tree_t *dmap_query_fields_hash; - - -static int -dmap_query_field_map_compare(const void *aa, const void *bb) -{ - struct dmap_query_field_map *a = (struct dmap_query_field_map *)aa; - struct dmap_query_field_map *b = (struct dmap_query_field_map *)bb; - - if (a->hash < b->hash) - return -1; - - if (a->hash > b->hash) - return 1; - - return 0; -} - - -struct dmap_query_field_map * -daap_query_field_lookup(char *field) -{ - struct dmap_query_field_map dqfm; - avl_node_t *node; - - dqfm.hash = djb_hash(field, strlen(field)); - - node = avl_search(dmap_query_fields_hash, &dqfm); - if (!node) - return NULL; - - return (struct dmap_query_field_map *)node->item; -} char * daap_query_parse_sql(const char *daap_query) @@ -214,56 +149,3 @@ daap_query_parse_sql(const char *daap_query) return ret; } - -int -daap_query_init(void) -{ - avl_node_t *node; - struct dmap_query_field_map *dqfm; - int i; - - dmap_query_fields_hash = avl_alloc_tree(dmap_query_field_map_compare, NULL); - if (!dmap_query_fields_hash) - { - DPRINTF(E_FATAL, L_DAAP, "DAAP query init could not allocate AVL tree\n"); - - return -1; - } - - for (i = 0; dmap_query_fields[i].hash == 0; i++) - { - dmap_query_fields[i].hash = djb_hash(dmap_query_fields[i].dmap_field, strlen(dmap_query_fields[i].dmap_field)); - - node = avl_insert(dmap_query_fields_hash, &dmap_query_fields[i]); - if (!node) - { - if (errno != EEXIST) - DPRINTF(E_FATAL, L_DAAP, "DAAP query init failed; AVL insert error: %s\n", strerror(errno)); - else - { - node = avl_search(dmap_query_fields_hash, &dmap_query_fields[i]); - dqfm = node->item; - - DPRINTF(E_FATAL, L_DAAP, "DAAP query init failed; WARNING: duplicate hash key\n"); - DPRINTF(E_FATAL, L_DAAP, "Hash %x, string %s\n", dmap_query_fields[i].hash, dmap_query_fields[i].dmap_field); - - DPRINTF(E_FATAL, L_DAAP, "Hash %x, string %s\n", dqfm->hash, dqfm->dmap_field); - } - - goto avl_insert_fail; - } - } - - return 0; - - avl_insert_fail: - avl_free_tree(dmap_query_fields_hash); - - return -1; -} - -void -daap_query_deinit(void) -{ - avl_free_tree(dmap_query_fields_hash); -} diff --git a/src/daap_query.gperf b/src/daap_query.gperf new file mode 100644 index 00000000..3e79412e --- /dev/null +++ b/src/daap_query.gperf @@ -0,0 +1,39 @@ +%language=ANSI-C +%readonly-tables +%enum +%switch=1 +%compare-lengths +%define hash-function-name daap_query_field_hash +%define lookup-function-name daap_query_field_lookup +%define slot-name dmap_field +%struct-type +%omit-struct-type +struct dmap_query_field_map; +%% +"dmap.itemname", "title", 0 +"dmap.itemid", "id", 1 +"daap.songalbum", "album", 0 +"daap.songalbumid", "songalbumid", 1 +"daap.songartist", "artist", 0 +"daap.songalbumartist", "album_artist", 0 +"daap.songbitrate", "bitrate", 1 +"daap.songcomment", "comment", 0 +"daap.songcompilation", "compilation", 1 +"daap.songcomposer", "composer", 0 +"daap.songdatakind", "data_kind", 1 +"daap.songdataurl", "url", 0 +"daap.songdateadded", "time_added", 1 +"daap.songdatemodified", "time_modified", 1 +"daap.songdescription", "description", 0 +"daap.songdisccount", "total_discs", 1 +"daap.songdiscnumber", "disc", 1 +"daap.songformat", "type", 0 +"daap.songgenre", "genre", 0 +"daap.songsamplerate", "samplerate", 1 +"daap.songsize", "file_size", 1 +"daap.songstoptime", "song_length", 1 +"daap.songtime", "song_length", 1 +"daap.songtrackcount", "total_tracks", 1 +"daap.songtracknumber", "track", 1 +"daap.songyear", "year", 1 +"com.apple.itunes.mediakind", "media_kind", 1 diff --git a/src/daap_query.h b/src/daap_query.h index 56c058e3..d6f62368 100644 --- a/src/daap_query.h +++ b/src/daap_query.h @@ -2,29 +2,21 @@ #ifndef __DAAP_QUERY_H__ #define __DAAP_QUERY_H__ -#include - #include "logger.h" #include "misc.h" struct dmap_query_field_map { - uint32_t hash; - int as_int; char *dmap_field; char *db_col; + int as_int; }; -struct dmap_query_field_map * -daap_query_field_lookup(char *field); +/* Generated by gperf - keep in sync, don't alter */ +const struct dmap_query_field_map * +daap_query_field_lookup (register const char *str, register unsigned int len); char * daap_query_parse_sql(const char *daap_query); -int -daap_query_init(void); - -void -daap_query_deinit(void); - #endif /* !__DAAP_QUERY_H__ */ diff --git a/src/httpd_daap.c b/src/httpd_daap.c index a15f718d..abe08f0d 100644 --- a/src/httpd_daap.c +++ b/src/httpd_daap.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2010 Julien BLACHE + * Copyright (C) 2009-2011 Julien BLACHE * Copyright (C) 2010 Kai Elwert * * Adapted from mt-daapd: @@ -3174,10 +3174,6 @@ daap_init(void) next_session_id = 100; /* gotta start somewhere, right? */ update_requests = NULL; - ret = daap_query_init(); - if (ret < 0) - return ret; - for (i = 0; daap_handlers[i].handler; i++) { ret = regcomp(&daap_handlers[i].preg, daap_handlers[i].regexp, REG_EXTENDED | REG_NOSUB); @@ -3186,7 +3182,7 @@ daap_init(void) regerror(ret, &daap_handlers[i].preg, buf, sizeof(buf)); DPRINTF(E_FATAL, L_DAAP, "DAAP init failed; regexp error: %s\n", buf); - goto regexp_fail; + return -1; } } @@ -3239,8 +3235,6 @@ daap_init(void) daap_avl_alloc_fail: for (i = 0; daap_handlers[i].handler; i++) regfree(&daap_handlers[i].preg); - regexp_fail: - daap_query_deinit(); return -1; } @@ -3251,8 +3245,6 @@ daap_deinit(void) struct daap_update_request *ur; int i; - daap_query_deinit(); - for (i = 0; daap_handlers[i].handler; i++) regfree(&daap_handlers[i].preg);