Remove libavl dependency from filescanner_itunes.c

This commit is contained in:
ejurgensen 2015-02-25 21:58:08 +01:00
parent 3a5d2d560f
commit 72d7ba1452
1 changed files with 79 additions and 54 deletions

View File

@ -43,7 +43,6 @@
# include "evhttp/evhttp.h" # include "evhttp/evhttp.h"
#endif #endif
#include "avl/avl.h"
#include "logger.h" #include "logger.h"
#include "db.h" #include "db.h"
#include "filescanner.h" #include "filescanner.h"
@ -51,11 +50,17 @@
#include "misc.h" #include "misc.h"
/* Mapping between iTunes library IDs and our DB IDs */ /* Mapping between iTunes library IDs and our DB IDs using a "hash" table of
* size ID_MAP_SIZE
*/
#define ID_MAP_SIZE 16384
struct itml_to_db_map { struct itml_to_db_map {
uint64_t itml_id; uint64_t itml_id;
uint32_t db_id; uint32_t db_id;
struct itml_to_db_map *next;
}; };
struct itml_to_db_map **id_map;
/* Mapping between iTunes library metadata keys and the offset /* Mapping between iTunes library metadata keys and the offset
* of the equivalent metadata field in struct media_file_info */ * of the equivalent metadata field in struct media_file_info */
@ -89,24 +94,65 @@ static struct metadata_map md_map[] =
{ NULL, 0, 0 } { NULL, 0, 0 }
}; };
static avl_tree_t *itml_to_db; static void
id_map_free(void)
static int
itml_to_db_compare(const void *aa, const void *bb)
{ {
struct itml_to_db_map *a = (struct itml_to_db_map *)aa; struct itml_to_db_map *map;
struct itml_to_db_map *b = (struct itml_to_db_map *)bb; int i;
if (a->itml_id < b->itml_id) for (i = 0; i < ID_MAP_SIZE; i++)
{
if (!id_map[i])
continue;
for (map = id_map[i]; id_map[i]; map = id_map[i])
{
id_map[i] = map->next;
free(map);
}
}
free(id_map);
}
/* Inserts a linked list item into "hash" position in the id_table */
static int
id_map_add(uint64_t itml_id, uint32_t db_id)
{
struct itml_to_db_map *new_map;
struct itml_to_db_map *cur_map;
int i;
new_map = malloc(sizeof(struct itml_to_db_map));
if (!new_map)
return -1; return -1;
if (a->itml_id > b->itml_id) new_map->itml_id = itml_id;
return 1; new_map->db_id = db_id;
i = itml_id % ID_MAP_SIZE;
cur_map = id_map[i];
new_map->next = cur_map;
id_map[i] = new_map;
return 0; return 0;
} }
static uint32_t
id_map_get(uint64_t itml_id)
{
struct itml_to_db_map *map;
int i;
i = itml_id % ID_MAP_SIZE;
for (map = id_map[i]; map; map = map->next)
{
if (itml_id == map->itml_id)
return map->db_id;
}
return 0;
}
/* plist helpers */ /* plist helpers */
static int static int
@ -474,8 +520,6 @@ process_tracks(plist_t tracks)
{ {
plist_t trk; plist_t trk;
plist_dict_iter iter; plist_dict_iter iter;
struct itml_to_db_map *map;
avl_node_t *mapnode;
char *str; char *str;
uint64_t trk_id; uint64_t trk_id;
uint8_t disabled; uint8_t disabled;
@ -561,28 +605,9 @@ process_tracks(plist_t tracks)
ntracks++; ntracks++;
map = (struct itml_to_db_map *)malloc(sizeof(struct itml_to_db_map)); ret = id_map_add(trk_id, mfi_id);
if (!map) if (ret < 0)
{ DPRINTF(E_LOG, L_SCAN, "Out of memory for itml -> db mapping\n");
DPRINTF(E_WARN, L_SCAN, "Out of memory for itml -> db mapping\n");
plist_dict_next_item(tracks, iter, NULL, &trk);
continue;
}
map->itml_id = trk_id;
map->db_id = mfi_id;
mapnode = avl_insert(itml_to_db, map);
if (!mapnode)
{
if (errno == EEXIST)
DPRINTF(E_WARN, L_SCAN, "Track %" PRIu64 " already in itml -> db map?!\n", trk_id);
else
DPRINTF(E_WARN, L_SCAN, "Track %" PRIu64 ": AVL insert error: %s\n", trk_id, strerror(errno));
free(map);
}
plist_dict_next_item(tracks, iter, NULL, &trk); plist_dict_next_item(tracks, iter, NULL, &trk);
} }
@ -596,10 +621,9 @@ process_tracks(plist_t tracks)
static void static void
process_pl_items(plist_t items, int pl_id) process_pl_items(plist_t items, int pl_id)
{ {
struct itml_to_db_map needle;
struct itml_to_db_map *map;
plist_t trk; plist_t trk;
avl_node_t *mapnode; uint64_t itml_id;
uint32_t db_id;
uint32_t alen; uint32_t alen;
uint32_t i; uint32_t i;
int ret; int ret;
@ -612,25 +636,23 @@ process_pl_items(plist_t items, int pl_id)
if (plist_get_node_type(trk) != PLIST_DICT) if (plist_get_node_type(trk) != PLIST_DICT)
continue; continue;
ret = get_dictval_int_from_key(trk, "Track ID", &needle.itml_id); ret = get_dictval_int_from_key(trk, "Track ID", &itml_id);
if (ret < 0) if (ret < 0)
{ {
DPRINTF(E_WARN, L_SCAN, "No Track ID found for playlist item %u\n", i); DPRINTF(E_WARN, L_SCAN, "No Track ID found for playlist item %u\n", i);
continue; continue;
} }
mapnode = avl_search(itml_to_db, &needle); db_id = id_map_get(itml_id);
if (!mapnode) if (!db_id)
{ {
DPRINTF(E_INFO, L_SCAN, "Track ID %" PRIu64 " dropped\n", needle.itml_id); DPRINTF(E_INFO, L_SCAN, "Track ID %" PRIu64 " dropped\n", itml_id);
continue; continue;
} }
map = (struct itml_to_db_map *)mapnode->item; ret = db_pl_add_item_byid(pl_id, db_id);
ret = db_pl_add_item_byid(pl_id, map->db_id);
if (ret < 0) if (ret < 0)
DPRINTF(E_WARN, L_SCAN, "Could not add ID %d to playlist\n", map->db_id); DPRINTF(E_WARN, L_SCAN, "Could not add ID %d to playlist\n", db_id);
} }
} }
@ -766,6 +788,7 @@ scan_itunes_itml(char *file)
plist_t itml; plist_t itml;
plist_t node; plist_t node;
int fd; int fd;
int size;
int ret; int ret;
DPRINTF(E_LOG, L_SCAN, "Processing iTunes library: %s\n", file); DPRINTF(E_LOG, L_SCAN, "Processing iTunes library: %s\n", file);
@ -838,21 +861,23 @@ scan_itunes_itml(char *file)
return; return;
} }
itml_to_db = avl_alloc_tree(itml_to_db_compare, free); size = ID_MAP_SIZE * sizeof(struct itml_to_db_map *);
if (!itml_to_db) id_map = malloc(size);
if (!id_map)
{ {
DPRINTF(E_FATAL, L_SCAN, "iTunes library parser could not allocate AVL tree\n"); DPRINTF(E_FATAL, L_SCAN, "iTunes library parser could not allocate ID map\n");
plist_free(itml); plist_free(itml);
return; return;
} }
memset(id_map, 0, size);
ptr = strrchr(file, '/'); ptr = strrchr(file, '/');
if (!ptr) if (!ptr)
{ {
DPRINTF(E_FATAL, L_SCAN, "Invalid filename\n"); DPRINTF(E_FATAL, L_SCAN, "Invalid filename\n");
avl_free_tree(itml_to_db); id_map_free();
plist_free(itml); plist_free(itml);
return; return;
} }
@ -864,7 +889,7 @@ scan_itunes_itml(char *file)
{ {
DPRINTF(E_LOG, L_SCAN, "No tracks loaded\n"); DPRINTF(E_LOG, L_SCAN, "No tracks loaded\n");
avl_free_tree(itml_to_db); id_map_free();
plist_free(itml); plist_free(itml);
return; return;
} }
@ -879,13 +904,13 @@ scan_itunes_itml(char *file)
{ {
DPRINTF(E_LOG, L_SCAN, "Could not find Playlists dict\n"); DPRINTF(E_LOG, L_SCAN, "Could not find Playlists dict\n");
avl_free_tree(itml_to_db); id_map_free();
plist_free(itml); plist_free(itml);
return; return;
} }
process_pls(node, file); process_pls(node, file);
avl_free_tree(itml_to_db); id_map_free();
plist_free(itml); plist_free(itml);
} }