From edbc12015d8bea459e18927b9ce27ba6026c0834 Mon Sep 17 00:00:00 2001 From: Adam Sutton Date: Mon, 28 May 2012 15:41:56 +0100 Subject: [PATCH] Add global object hash similar to that used by andoma in original code. Although mine includes ALL objects, its currently only used for broadcast lookup as generally the others will probably be quicker (episodes?) to go via the normal URI based maps. --- src/epg.c | 45 +++++++++++++++++++++++++++------------------ src/epg.h | 22 ++++++++++++++++------ 2 files changed, 43 insertions(+), 24 deletions(-) diff --git a/src/epg.c b/src/epg.c index 6fb320a8..2b3c8470 100644 --- a/src/epg.c +++ b/src/epg.c @@ -45,12 +45,16 @@ #include "htsmsg_binary.h" #include "epggrab.h" +/* Broadcast hashing */ +#define EPG_HASH_WIDTH 1024 +#define EPG_HASH_MASK (EPG_HASH_WIDTH - 1) + /* Element lists */ -struct epg_object_tree epg_brands; -struct epg_object_tree epg_seasons; -struct epg_object_tree epg_episodes; -struct epg_object_tree epg_channels; -struct epg_object_tree epg_broadcasts; +epg_object_list_t epg_objects[EPG_HASH_WIDTH]; +epg_object_tree_t epg_brands; +epg_object_tree_t epg_seasons; +epg_object_tree_t epg_episodes; +epg_object_tree_t epg_channels; /* Unmapped */ LIST_HEAD(epg_channel_unmapped_list, epg_channel); @@ -59,10 +63,9 @@ struct epg_channel_unmapped_list epg_channel_unmapped; struct channel_unmapped_list channel_unmapped; /* Unreferenced */ -LIST_HEAD(epg_object_unref_list, epg_object); -struct epg_object_unref_list epg_object_unref; +epg_object_list_t epg_object_unref; -/* Global counters */ +/* Global counter */ static uint64_t _epg_object_idx = 0; /* ************************************************************************** @@ -332,6 +335,7 @@ static epg_object_t *_epg_object_find if (!eo->putref) eo->putref = _epg_object_putref; _epg_object_idx++; LIST_INSERT_HEAD(&epg_object_unref, eo, ulink); + LIST_INSERT_HEAD(&epg_objects[eo->id & EPG_HASH_WIDTH], eo, hlink); } } @@ -359,11 +363,20 @@ static epg_object_t *_epg_object_find_by_uri return eo; } -static epg_object_t *_epg_object_find_by_id +static epg_object_t *_epg_object_find_by_id2 ( uint64_t id ) +{ + epg_object_t *eo; + LIST_FOREACH(eo, &epg_objects[id & EPG_HASH_WIDTH], hlink) { + if (eo->id == id) return eo; + } + return NULL; +} + +static epg_object_t *_epg_object_find_by_id ( uint64_t id, epg_object_tree_t *tree ) { epg_object_t *eo; - if (!tree) return NULL; + if (!tree) return _epg_object_find_by_id2(id); RB_FOREACH(eo, tree, glink) { if ( eo->id == id ) return eo; } @@ -755,13 +768,12 @@ int epg_episode_set_number ( epg_episode_t *episode, uint16_t number ) int epg_episode_set_part ( epg_episode_t *episode, uint16_t part, uint16_t count ) { int save = 0; - // TODO: could treat part/count independently - if ( !episode || !part || !count ) return 0; + if ( !episode || !part ) return 0; if ( episode->part_number != part ) { episode->part_number = part; save |= 1; } - if ( episode->part_count != count ) { + if ( count && episode->part_count != count ) { episode->part_count = count; save |= 1; } @@ -925,14 +937,11 @@ epg_broadcast_t* epg_broadcast_find_by_time // TODO: allow optional channel parameter? epg_broadcast_t *epg_broadcast_find_by_id ( uint64_t id, epg_channel_t *ec ) { - epg_object_t *eo = NULL, *eoc; + epg_object_t *eo = NULL; if ( ec ) { eo = _epg_object_find_by_id(id, &((epg_channel_t*)ec)->schedule); } else { - RB_FOREACH(eoc, &epg_channels, glink) { - eo = _epg_object_find_by_id(id, &((epg_channel_t*)eoc)->schedule); - if (eo) break; - } + eo = _epg_object_find_by_id2(id); } return (epg_broadcast_t*)eo; } diff --git a/src/epg.h b/src/epg.h index 0137852d..87e208c3 100644 --- a/src/epg.h +++ b/src/epg.h @@ -32,6 +32,7 @@ /* * Map types */ +LIST_HEAD(epg_object_list, epg_object); RB_HEAD(epg_object_tree, epg_object); RB_HEAD(epg_brand_tree, epg_brand); RB_HEAD(epg_season_tree, epg_season); @@ -48,6 +49,7 @@ typedef struct epg_season epg_season_t; typedef struct epg_episode epg_episode_t; typedef struct epg_broadcast epg_broadcast_t; typedef struct epg_channel epg_channel_t; +typedef struct epg_object_list epg_object_list_t; typedef struct epg_object_tree epg_object_tree_t; typedef struct epg_brand_tree epg_brand_tree_t; typedef struct epg_season_tree epg_season_tree_t; @@ -62,7 +64,8 @@ typedef struct epg_broadcast_tree epg_broadcast_tree_t; /* Object */ typedef struct epg_object { - RB_ENTRY(epg_object) glink; ///< Global list link + RB_ENTRY(epg_object) glink; ///< Global (URI) list link + LIST_ENTRY(epg_object) hlink; ///< Global (ID) hash link LIST_ENTRY(epg_object) ulink; ///< Global unref'd link char *uri; ///< Unique ID (from grabber) @@ -150,8 +153,6 @@ epg_season_t *epg_season_deserialize ( htsmsg_t *m, int create, int *save ); /* ************************************************************************ * Episode - * - * TODO: ee_genre needs to be a list * ***********************************************************************/ /* Object */ @@ -192,6 +193,8 @@ int epg_episode_set_description ( epg_episode_t *e, const char *description ) __attribute__((warn_unused_result)); int epg_episode_set_number ( epg_episode_t *e, uint16_t number ) __attribute__((warn_unused_result)); +int epg_episode_set_onscreen ( epg_episode_t *e, const char *onscreen ) + __attribute__((warn_unused_result)); int epg_episode_set_part ( epg_episode_t *e, uint16_t number, uint16_t count ) __attribute__((warn_unused_result)); @@ -199,6 +202,10 @@ int epg_episode_set_brand ( epg_episode_t *e, epg_brand_t *b ) __attribute__((warn_unused_result)); int epg_episode_set_season ( epg_episode_t *e, epg_season_t *s ) __attribute__((warn_unused_result)); +int epg_episode_set_genre ( epg_episode_t *e, uint8_t g ) + __attribute__((warn_unused_result)); +int epg_episode_set_genre_str ( epg_episode_t *e, const char *s ) + __attribute__((warn_unused_result)); /* EpNum format helper */ // output string will be: @@ -248,9 +255,9 @@ typedef struct epg_broadcast uint8_t is_new; ///< New series / file premiere uint8_t is_repeat; ///< Repeat screening - RB_ENTRY(epg_broadcast) elink; ///< Episode link - epg_episode_t *episode; ///< Episode shown - epg_channel_t *channel; ///< Channel being broadcast on + RB_ENTRY(epg_broadcast) elink; ///< Episode link + epg_episode_t *episode; ///< Episode shown + epg_channel_t *channel; ///< Channel being broadcast on } epg_broadcast_t; @@ -281,6 +288,7 @@ typedef struct epg_channel epg_object_t _; ///< Parent object char *name; ///< Channel name + char *icon; ///< Channel icon char **sname; ///< DVB svc names (to map) int **sid; ///< DVB svc ids (to map) @@ -302,6 +310,8 @@ epg_channel_t *epg_channel_find_by_id ( uint64_t id ); /* Mutators */ int epg_channel_set_name ( epg_channel_t *c, const char *n ) __attribute__((warn_unused_result)); +int epg_channel_set_icon ( epg_channel_t *c, const char *i ) + __attribute__((warn_unused_result)); int epg_channel_set_channel ( epg_channel_t *c, channel_t *ch ); /* Accessors */