Stop unchanged static playlists from incrementing version number. Fix memory leak with background rescans and static playlists

This commit is contained in:
Ron Pedde 2004-12-03 06:43:20 +00:00
parent 8d9587e4fc
commit 7823fae9d5
4 changed files with 158 additions and 10 deletions

View File

@ -78,7 +78,9 @@ typedef struct tag_playlist {
unsigned int id; unsigned int id;
int songs; int songs;
int is_smart; int is_smart;
int found;
char *name; char *name;
int file_time;
struct tag_playlistentry *nodes; struct tag_playlistentry *nodes;
struct tag_playlist *next; struct tag_playlist *next;
} DB_PLAYLIST; } DB_PLAYLIST;
@ -157,6 +159,8 @@ static int db_unlock(void);
static void db_gdbmlock(void); static void db_gdbmlock(void);
static int db_gdbmunlock(void); static int db_gdbmunlock(void);
static DB_PLAYLIST *db_playlist_find(int playlistid);
int db_start_initial_update(void); int db_start_initial_update(void);
int db_end_initial_update(void); int db_end_initial_update(void);
int db_is_empty(void); int db_is_empty(void);
@ -166,7 +170,8 @@ int db_deinit(void);
int db_version(void); int db_version(void);
int db_add(MP3FILE *mp3file); int db_add(MP3FILE *mp3file);
int db_delete(int id); int db_delete(int id);
int db_add_playlist(unsigned int playlistid, char *name, int is_smart); int db_delete_playlist(unsigned int playlistid);
int db_add_playlist(unsigned int playlistid, char *name, int file_time, int is_smart);
int db_add_playlist_song(unsigned int playlistid, unsigned int itemid); int db_add_playlist_song(unsigned int playlistid, unsigned int itemid);
int db_unpackrecord(datum *pdatum, MP3FILE *pmp3); int db_unpackrecord(datum *pdatum, MP3FILE *pmp3);
int db_scanning(void); int db_scanning(void);
@ -413,6 +418,7 @@ int db_version(void) {
int db_start_initial_update(void) { int db_start_initial_update(void) {
datum tmp_key,tmp_nextkey; datum tmp_key,tmp_nextkey;
int err; int err;
DB_PLAYLIST *current;
/* we need a write lock on the db -- stop enums from happening */ /* we need a write lock on the db -- stop enums from happening */
db_writelock(); db_writelock();
@ -448,6 +454,14 @@ int db_start_initial_update(void) {
tmp_key=tmp_nextkey; tmp_key=tmp_nextkey;
} }
/* walk through the playlists and mark them as not found */
current=db_playlists.next;
while(current) {
current->found=0;
current=current->next;
}
db_update_mode=1; db_update_mode=1;
db_unlock(); db_unlock();
@ -461,6 +475,8 @@ int db_start_initial_update(void) {
*/ */
int db_end_initial_update(void) { int db_end_initial_update(void) {
const void *val; const void *val;
DB_PLAYLIST *current,*last;
DB_PLAYLISTENTRY *pple;
DPRINTF(E_DBG,L_DB|L_SCAN,"Initial update over. Removing stale items\n"); DPRINTF(E_DBG,L_DB|L_SCAN,"Initial update over. Removing stale items\n");
for(val=rblookup(RB_LUFIRST,NULL,db_removed); val != NULL; for(val=rblookup(RB_LUFIRST,NULL,db_removed); val != NULL;
@ -479,6 +495,36 @@ int db_end_initial_update(void) {
gdbm_reorganize(db_songs); gdbm_reorganize(db_songs);
gdbm_sync(db_songs); gdbm_sync(db_songs);
DPRINTF(E_DBG,L_DB,"Reorganize done\n"); DPRINTF(E_DBG,L_DB,"Reorganize done\n");
DPRINTF(E_DBG,L_DB|L_PL,"Finding deleted static playlists\n");
current=db_playlists.next;
last=&db_playlists;
while(current) {
if((!current->found)&&(!current->is_smart)) {
DPRINTF(E_DBG,L_DB|L_PL,"Deleting playlist %s\n",current->name);
last->next=current->next;
if(current->nodes)
db_playlist_count--;
db_version_no++;
while(current->nodes) {
pple=current->nodes;
current->nodes=pple->next;
free(pple);
}
if(current->name)
free(current->name);
free(current);
current=last;
}
current=current->next;
}
db_update_mode=0; db_update_mode=0;
db_gdbmunlock(); db_gdbmunlock();
db_unlock(); db_unlock();
@ -498,15 +544,107 @@ int db_is_empty(void) {
} }
/**
* Get the pointer to a specific playlist. MUST HAVE A
* READLOCK TO CALL THIS!
*
* @param playlistid playlist to find
* @returns DB_PLAYLIST of playlist, or null otherwise.
*/
DB_PLAYLIST *db_playlist_find(int playlistid) {
DB_PLAYLIST *current;
current=db_playlists.next;
while(current && (current->id != playlistid))
current=current->next;
if(!current) {
return NULL;
}
return current;
}
/**
* delete a given playlist
*
* @param playlistid playlist to delete
*/
int db_delete_playlist(unsigned int playlistid) {
DB_PLAYLIST *plist;
DB_PLAYLISTENTRY *pple;
DB_PLAYLIST *last, *current;
DPRINTF(E_DBG,L_PL,"Deleting playlist %d\n",playlistid);
db_writelock();
current=db_playlists.next;
last=&db_playlists;
while(current && (current->id != playlistid)) {
last=current;
current=current->next;
}
if(!current) {
db_unlock();
return -1;
}
last->next=current->next;
if(current->nodes)
db_playlist_count--;
db_version_no++;
db_unlock();
while(current->nodes) {
pple=current->nodes;
current->nodes=pple->next;
free(pple);
}
if(current->name)
free(current->name);
free(current);
return 0;
}
/**
* find the last modified time of a specific playlist
*
* @param playlistid playlist to check (inode)
* @returns file_time of playlist, or 0 if no playlist
*/
int db_playlist_last_modified(int playlistid) {
DB_PLAYLIST *plist;
int file_time;
db_readlock();
plist=db_playlist_find(playlistid);
if(!plist) {
db_unlock();
return 0;
}
file_time=plist->file_time;
/* mark as found, so deleted playlists can go away */
plist->found=1;
db_unlock();
return file_time;
}
/* /*
* db_add_playlist * db_add_playlist
* *
* Add a new playlist * Add a new playlist
*
* FIXME: this assume we are in db_update mode... if this is called at random,
* then we have to get a write lock.
*/ */
int db_add_playlist(unsigned int playlistid, char *name, int is_smart) { int db_add_playlist(unsigned int playlistid, char *name, int file_time, int is_smart) {
int err; int err;
DB_PLAYLIST *pnew; DB_PLAYLIST *pnew;
@ -518,6 +656,8 @@ int db_add_playlist(unsigned int playlistid, char *name, int is_smart) {
pnew->id=playlistid; pnew->id=playlistid;
pnew->nodes=NULL; pnew->nodes=NULL;
pnew->songs=0; pnew->songs=0;
pnew->found=1;
pnew->file_time=file_time;
pnew->is_smart=is_smart; pnew->is_smart=is_smart;
if(!pnew->name) { if(!pnew->name) {
@ -1259,7 +1399,7 @@ MP3FILE *db_find(int id) { /* FIXME: Not reentrant */
MEMNOTIFY(content.dptr); MEMNOTIFY(content.dptr);
if(!content.dptr) { if(!content.dptr) {
DPRINTF(E_WARN,L_DB,"Could not find id %d\n",id); DPRINTF(E_DBG,L_DB,"Could not find id %d\n",id);
db_unlock(); db_unlock();
return NULL; return NULL;
} }

View File

@ -35,8 +35,9 @@ extern int db_deinit(void);
extern int db_version(void); extern int db_version(void);
extern int db_add(MP3FILE *mp3file); extern int db_add(MP3FILE *mp3file);
extern int db_delete(int id); extern int db_delete(int id);
extern int db_add_playlist(unsigned int playlistid, char *name, int is_smart); extern int db_add_playlist(unsigned int playlistid, char *name, int file_time, int is_smart);
extern int db_add_playlist_song(unsigned int playlistid, unsigned int itemid); extern int db_add_playlist_song(unsigned int playlistid, unsigned int itemid);
extern int db_delete_playlist(unsigned int playlistid);
extern ENUMHANDLE db_enum_begin(void); extern ENUMHANDLE db_enum_begin(void);
extern MP3FILE *db_enum(ENUMHANDLE *handle); extern MP3FILE *db_enum(ENUMHANDLE *handle);
@ -58,7 +59,7 @@ extern int db_playlist_items_enum(ENUMHANDLE *current);
extern int db_playlist_items_enum_end(ENUMHANDLE handle); extern int db_playlist_items_enum_end(ENUMHANDLE handle);
extern char *db_get_playlist_name(int playlistid); extern char *db_get_playlist_name(int playlistid);
extern int db_playlist_last_modified(int playlistid);
extern int db_scanning(void); extern int db_scanning(void);
/* For persistant databases only */ /* For persistant databases only */

View File

@ -460,13 +460,20 @@ void scan_static_playlist(char *path, struct dirent *pde, struct stat *psb) {
struct stat sb; struct stat sb;
DPRINTF(E_WARN,L_SCAN|L_PL,"Processing static playlist: %s\n",pde->d_name); DPRINTF(E_WARN,L_SCAN|L_PL,"Processing static playlist: %s\n",pde->d_name);
/* see if we should update it */
if(db_playlist_last_modified(psb->st_ino) == psb->st_mtime)
return;
db_delete_playlist(psb->st_ino);
strcpy(m3u_path,pde->d_name); strcpy(m3u_path,pde->d_name);
snprintf(playlist_path,sizeof(playlist_path),"%s/%s",path,pde->d_name); snprintf(playlist_path,sizeof(playlist_path),"%s/%s",path,pde->d_name);
m3u_path[strlen(pde->d_name) - 4] = '\0'; m3u_path[strlen(pde->d_name) - 4] = '\0';
playlistid=psb->st_ino; playlistid=psb->st_ino;
fd=open(playlist_path,O_RDONLY); fd=open(playlist_path,O_RDONLY);
if(fd != -1) { if(fd != -1) {
db_add_playlist(playlistid,m3u_path,0); db_add_playlist(playlistid,m3u_path,psb->st_mtime,0);
DPRINTF(E_INF,L_SCAN|L_PL,"Added playlist as id %d\n",playlistid); DPRINTF(E_INF,L_SCAN|L_PL,"Added playlist as id %d\n",playlistid);
memset(linebuffer,0x00,sizeof(linebuffer)); memset(linebuffer,0x00,sizeof(linebuffer));

View File

@ -230,7 +230,7 @@ void pl_register(void) {
pcurrent=pl_smart.next; pcurrent=pl_smart.next;
while(pcurrent) { while(pcurrent) {
DPRINTF(E_INF,L_PL,"Adding smart playlist %s as %d\n",pcurrent->name,pcurrent->id) DPRINTF(E_INF,L_PL,"Adding smart playlist %s as %d\n",pcurrent->name,pcurrent->id)
db_add_playlist(pcurrent->id, pcurrent->name,1); db_add_playlist(pcurrent->id, pcurrent->name,0,1);
pcurrent=pcurrent->next; pcurrent=pcurrent->next;
} }
} }