DJWLindenaar balanced tree and master process patch

git-svn-id: https://svn.musicpd.org/mpd/trunk@3669 09075e82-0dd4-0310-85a5-a0d7c8717e4f
This commit is contained in:
Qball Cow 2005-11-16 14:43:04 +00:00
parent 402c8cd707
commit 32e5f4ca2b
13 changed files with 291 additions and 118 deletions

View File

@ -84,6 +84,10 @@ AC_CHECK_LIB(nsl,gethostbyname,MPD_LIBS="$MPD_LIBS -lnsl",)
AC_CHECK_LIB(m,exp,MPD_LIBS="$MPD_LIBS -lm",) AC_CHECK_LIB(m,exp,MPD_LIBS="$MPD_LIBS -lm",)
PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.0, [MPD_LIBS="$MPD_LIBS $GLIB_LIBS" MPD_CFLAGS="$MPD_CFLAGS $GLIB_CFLAGS"],[echo "Unable to find glib-2.0 of version 2.0 or above"])
dnl doesn't work for systems that don't have CODESET like OpenBSD dnl doesn't work for systems that don't have CODESET like OpenBSD
dnl AC_CHECK_HEADER(langinfo.h,[enable_langinfo=yes;AC_DEFINE(HAVE_LANGINFO,1,[Define if nl_langinfo.h is present])],enable_langinfo=no) dnl AC_CHECK_HEADER(langinfo.h,[enable_langinfo=yes;AC_DEFINE(HAVE_LANGINFO,1,[Define if nl_langinfo.h is present])],enable_langinfo=no)
AM_LANGINFO_CODESET AM_LANGINFO_CODESET

View File

@ -399,7 +399,7 @@ int decoderInit(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) {
pc->error = PLAYER_ERROR_SYSTEM; pc->error = PLAYER_ERROR_SYSTEM;
return -1; return -1;
} }
DEBUG("decoder PID: %d\n", decode_pid);
getPlayerData()->playerControl.decode_pid = decode_pid; getPlayerData()->playerControl.decode_pid = decode_pid;
unblockSignals(); unblockSignals();

View File

@ -178,7 +178,7 @@ int updateInit(FILE * fp, List * pathList) {
if(directory_updatePid==0) { if(directory_updatePid==0) {
/* child */ /* child */
int dbUpdated = 0; int dbUpdated = 0;
clearPlayerPid(); //clearPlayerPid();
unblockSignals(); unblockSignals();
@ -784,6 +784,7 @@ int addToDirectory(Directory * directory, char * shortname, char * name) {
void closeMp3Directory() { void closeMp3Directory() {
freeDirectory(mp3rootDirectory); freeDirectory(mp3rootDirectory);
destroyTagTracker();
} }
Directory * findSubDirectory(Directory * directory,char * name) { Directory * findSubDirectory(Directory * directory,char * name) {

View File

@ -213,7 +213,10 @@ void closeAllListenSockets() {
DEBUG("closing listen socket %i\n", i); DEBUG("closing listen socket %i\n", i);
while(close(listenSockets[i]) < 0 && errno==EINTR); while(close(listenSockets[i]) < 0 && errno==EINTR);
} }
freeAllListenSockets();
}
void freeAllListenSockets() {
numberOfListenSockets = 0; numberOfListenSockets = 0;
free(listenSockets); free(listenSockets);
listenSockets = NULL; listenSockets = NULL;

View File

@ -33,6 +33,7 @@ void getConnections(fd_set * fds);
int isAListenSocket(int sock); int isAListenSocket(int sock);
void closeAllListenSockets(); void closeAllListenSockets();
void freeAllListenSockets();
/* fdmax should be initialized to something */ /* fdmax should be initialized to something */
void addListenSocketsToFdSet(fd_set * fds, int * fdmax); void addListenSocketsToFdSet(fd_set * fds, int * fdmax);

View File

@ -54,6 +54,9 @@
#define SYSTEM_CONFIG_FILE_LOCATION "/etc/mpd.conf" #define SYSTEM_CONFIG_FILE_LOCATION "/etc/mpd.conf"
#define USER_CONFIG_FILE_LOCATION "/.mpdconf" #define USER_CONFIG_FILE_LOCATION "/.mpdconf"
volatile int masterPid = 0;
volatile int mainPid = 0;
typedef struct _Options { typedef struct _Options {
int kill; int kill;
int daemon; int daemon;
@ -288,6 +291,45 @@ void openDB(Options * options, char * argv0) {
} }
} }
void startMainProcess() {
int pid;
fflush(0);
pid = fork();
if(pid>0) {
initInputStream();
initReplayGainState();
/* qball crappy code */
readAudioDevicesState();
/* free stuff we don't need */
freeAllListenSockets();
mainPid = pid;
masterInitSigHandlers();
while (masterHandlePendingSignals()!=COMMAND_RETURN_KILL)
waitOnSignals();
/* we're killed */
playerKill();
finishAudioConfig();
finishAudioDriver();
/* qball crappy code */
saveAudioDevicesState();
finishPaths();
kill(mainPid, SIGTERM);
exit(EXIT_SUCCESS);
} else if(pid<0) {
ERROR("problems fork'ing main process!\n");
exit(EXIT_FAILURE);
}
DEBUG("main process started!\n");
}
void daemonize(Options * options) { void daemonize(Options * options) {
FILE * fp; FILE * fp;
ConfigParam * pidFileParam = parseConfigFilePath(CONF_PID_FILE, 1); ConfigParam * pidFileParam = parseConfigFilePath(CONF_PID_FILE, 1);
@ -338,6 +380,7 @@ void daemonize(Options * options) {
DEBUG("writing pid file\n"); DEBUG("writing pid file\n");
fprintf(fp, "%lu\n", (unsigned long)getpid()); fprintf(fp, "%lu\n", (unsigned long)getpid());
fclose(fp); fclose(fp);
masterPid = getpid();
} }
void setupLogOutput(Options * options, FILE * out, FILE * err) { void setupLogOutput(Options * options, FILE * out, FILE * err) {
@ -451,6 +494,7 @@ int main(int argc, char * argv[]) {
parseOptions(argc, argv, &options); parseOptions(argc, argv, &options);
if(options.kill) killFromPidFile(argv[0], options.kill); if(options.kill) killFromPidFile(argv[0], options.kill);
initStats(); initStats();
initTagConfig(); initTagConfig();
@ -459,31 +503,39 @@ int main(int argc, char * argv[]) {
if(options.createDB <= 0 && !options.updateDB) listenOnPort(); if(options.createDB <= 0 && !options.updateDB) listenOnPort();
changeToUser(); changeToUser();
openLogFiles(&options, &out, &err); openLogFiles(&options, &out, &err);
initPlayerData();
daemonize(&options);
initInputPlugins();
initPaths(); initPaths();
initAudioConfig();
initAudioDriver();
startMainProcess();
/* This is the main process which has
* been forked from the master process.
*/
initPermissions(); initPermissions();
initReplayGainState();
initPlaylist(); initPlaylist();
initInputPlugins();
openDB(&options, argv[0]); openDB(&options, argv[0]);
initCommands(); initCommands();
initPlayerData();
initAudioConfig();
initAudioDriver();
initVolume(); initVolume();
initInterfaces(); initInterfaces();
initInputStream();
printMemorySavedByTagTracker(); printMemorySavedByTagTracker();
printSavedMemoryFromFilenames(); printSavedMemoryFromFilenames();
/*printSavedMemoryFromDirectoryNames();*/ /*printSavedMemoryFromDirectoryNames();*/
daemonize(&options);
setupLogOutput(&options, out, err); setupLogOutput(&options, out, err);
@ -491,8 +543,6 @@ int main(int argc, char * argv[]) {
initSigHandlers(); initSigHandlers();
readPlaylistState(); readPlaylistState();
/* qball crappy code */
readAudioDevicesState();
while(COMMAND_RETURN_KILL!=doIOForInterfaces()) { while(COMMAND_RETURN_KILL!=doIOForInterfaces()) {
if(COMMAND_RETURN_KILL==handlePendingSignals()) break; if(COMMAND_RETURN_KILL==handlePendingSignals()) break;
@ -502,12 +552,8 @@ int main(int argc, char * argv[]) {
} }
savePlaylistState(); savePlaylistState();
/* qball crappy code */
saveAudioDevicesState();
playerKill();
freeAllInterfaces(); freeAllInterfaces();
closeAllListenSockets(); closeAllListenSockets();
closeMp3Directory(); closeMp3Directory();

View File

@ -43,11 +43,7 @@
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
volatile int player_pid = 0; extern int masterPid;
void clearPlayerPid() {
player_pid = 0;
}
static void resetPlayerMetadata() { static void resetPlayerMetadata() {
PlayerControl * pc = &(getPlayerData()->playerControl); PlayerControl * pc = &(getPlayerData()->playerControl);
@ -60,7 +56,7 @@ static void resetPlayerMetadata() {
void resetPlayer() { void resetPlayer() {
int pid; int pid;
clearPlayerPid(); setPlayerPid(0);
getPlayerData()->playerControl.stop = 0; getPlayerData()->playerControl.stop = 0;
getPlayerData()->playerControl.play = 0; getPlayerData()->playerControl.play = 0;
getPlayerData()->playerControl.pause = 0; getPlayerData()->playerControl.pause = 0;
@ -77,7 +73,7 @@ void resetPlayer() {
} }
void player_sigChldHandler(int pid, int status) { void player_sigChldHandler(int pid, int status) {
if(player_pid==pid) { if(getPlayerPid()==pid) {
DEBUG("SIGCHLD caused by player process\n"); DEBUG("SIGCHLD caused by player process\n");
if(WIFSIGNALED(status) && WTERMSIG(status)!=SIGTERM && if(WIFSIGNALED(status) && WTERMSIG(status)!=SIGTERM &&
WTERMSIG(status)!=SIGINT) WTERMSIG(status)!=SIGINT)
@ -87,7 +83,7 @@ void player_sigChldHandler(int pid, int status) {
} }
resetPlayer(); resetPlayer();
} }
else if(pid==getPlayerData()->playerControl.decode_pid && player_pid<=0) else if(pid==getPlayerData()->playerControl.decode_pid && getPlayerPid()<=0)
{ {
if(WIFSIGNALED(status) && WTERMSIG(status)!=SIGTERM) { if(WIFSIGNALED(status) && WTERMSIG(status)!=SIGTERM) {
ERROR("(caught by master parent) " ERROR("(caught by master parent) "
@ -100,24 +96,31 @@ void player_sigChldHandler(int pid, int status) {
} }
int playerInit() { int playerInit() {
kill(masterPid, SIGUSR2);
while (getPlayerPid()==0) my_usleep(10000); //we need to wait for the signal to take effect
return 0;
}
int playerInitReal() {
int player_pid;
blockSignals(); blockSignals();
player_pid = fork(); player_pid = fork();
if(player_pid==0) { if(player_pid==0) {
PlayerControl * pc = &(getPlayerData()->playerControl); PlayerControl * pc = &(getPlayerData()->playerControl);
clearUpdatePid(); //clearUpdatePid();
unblockSignals(); unblockSignals();
setSigHandlersForDecoder(); setSigHandlersForDecoder();
closeAllListenSockets(); //closeAllListenSockets();
freeAllInterfaces(); //freeAllInterfaces();
closeMp3Directory(); //closeMp3Directory();
finishPlaylist(); //finishPlaylist();
finishPermissions(); //finishPermissions();
finishCommands(); //finishCommands();
finishVolume(); //finishVolume();
while(1) { while(1) {
if(pc->play) decode(); if(pc->play) decode();
@ -148,10 +151,13 @@ int playerInit() {
else if(player_pid<0) { else if(player_pid<0) {
unblockSignals(); unblockSignals();
ERROR("player Problems fork()'ing\n"); ERROR("player Problems fork()'ing\n");
setPlayerPid(0);
player_pid = 0; player_pid = 0;
return -1; return -1;
} }
else
setPlayerPid(player_pid);
unblockSignals(); unblockSignals();
return 0; return 0;
@ -183,13 +189,13 @@ int playerPlay(FILE * fp, Song * song) {
pc->utf8url[MAXPATHLEN] = '\0'; pc->utf8url[MAXPATHLEN] = '\0';
pc->play = 1; pc->play = 1;
if(player_pid==0 && playerInit()<0) { if(getPlayerPid()==0 && playerInit()<0) {
pc->play = 0; pc->play = 0;
return -1; return -1;
} }
resetPlayerMetadata(); resetPlayerMetadata();
while(player_pid>0 && pc->play) my_usleep(1000); while(getPlayerPid()>0 && pc->play) my_usleep(1000);
return 0; return 0;
} }
@ -197,9 +203,9 @@ int playerPlay(FILE * fp, Song * song) {
int playerStop(FILE * fp) { int playerStop(FILE * fp) {
PlayerControl * pc = &(getPlayerData()->playerControl); PlayerControl * pc = &(getPlayerData()->playerControl);
if(player_pid>0 && pc->state!=PLAYER_STATE_STOP) { if(getPlayerPid()>0 && pc->state!=PLAYER_STATE_STOP) {
pc->stop = 1; pc->stop = 1;
while(player_pid>0 && pc->stop) my_usleep(1000); while(getPlayerPid()>0 && pc->stop) my_usleep(1000);
} }
pc->queueState = PLAYER_QUEUE_BLANK; pc->queueState = PLAYER_QUEUE_BLANK;
@ -216,16 +222,16 @@ void playerKill() {
playerCloseAudio(stderr); playerCloseAudio(stderr);
if(player_pid>0 && pc->closeAudio) sleep(1);*/ if(player_pid>0 && pc->closeAudio) sleep(1);*/
pid = player_pid; pid = getPlayerPid();
if(pid>0) kill(pid,SIGTERM); if(pid>0) kill(pid,SIGTERM);
} }
int playerPause(FILE * fp) { int playerPause(FILE * fp) {
PlayerControl * pc = &(getPlayerData()->playerControl); PlayerControl * pc = &(getPlayerData()->playerControl);
if(player_pid>0 && pc->state!=PLAYER_STATE_STOP) { if(getPlayerPid()>0 && pc->state!=PLAYER_STATE_STOP) {
pc->pause = 1; pc->pause = 1;
while(player_pid>0 && pc->pause) my_usleep(1000); while(getPlayerPid()>0 && pc->pause) my_usleep(1000);
} }
return 0; return 0;
@ -234,7 +240,7 @@ int playerPause(FILE * fp) {
int playerSetPause(FILE * fp, int pause) { int playerSetPause(FILE * fp, int pause) {
PlayerControl * pc = &(getPlayerData()->playerControl); PlayerControl * pc = &(getPlayerData()->playerControl);
if(player_pid<=0) return 0; if(getPlayerPid()<=0) return 0;
switch(pc->state) { switch(pc->state) {
case PLAYER_STATE_PLAY: case PLAYER_STATE_PLAY:
@ -314,7 +320,7 @@ char * getPlayerErrorStr() {
void playerCloseAudio() { void playerCloseAudio() {
PlayerControl * pc = &(getPlayerData()->playerControl); PlayerControl * pc = &(getPlayerData()->playerControl);
if(player_pid>0) { if(getPlayerPid()>0) {
if(playerStop(stderr)<0) return; if(playerStop(stderr)<0) return;
pc->closeAudio = 1; pc->closeAudio = 1;
} }
@ -354,20 +360,20 @@ void setQueueState(int queueState) {
void playerQueueLock() { void playerQueueLock() {
PlayerControl * pc = &(getPlayerData()->playerControl); PlayerControl * pc = &(getPlayerData()->playerControl);
if(player_pid>0 && pc->queueLockState==PLAYER_QUEUE_UNLOCKED) if(getPlayerPid()>0 && pc->queueLockState==PLAYER_QUEUE_UNLOCKED)
{ {
pc->lockQueue = 1; pc->lockQueue = 1;
while(player_pid>0 && pc->lockQueue) my_usleep(1000); while(getPlayerPid()>0 && pc->lockQueue) my_usleep(1000);
} }
} }
void playerQueueUnlock() { void playerQueueUnlock() {
PlayerControl * pc = &(getPlayerData()->playerControl); PlayerControl * pc = &(getPlayerData()->playerControl);
if(player_pid>0 && pc->queueLockState==PLAYER_QUEUE_LOCKED) if(getPlayerPid()>0 && pc->queueLockState==PLAYER_QUEUE_LOCKED)
{ {
pc->unlockQueue = 1; pc->unlockQueue = 1;
while(player_pid>0 && pc->unlockQueue) my_usleep(1000); while(getPlayerPid()>0 && pc->unlockQueue) my_usleep(1000);
} }
} }
@ -394,7 +400,7 @@ int playerSeek(FILE * fp, Song * song, float time) {
resetPlayerMetadata(); resetPlayerMetadata();
pc->seekWhere = time; pc->seekWhere = time;
pc->seek = 1; pc->seek = 1;
while(player_pid>0 && pc->seek) my_usleep(1000); while(getPlayerPid()>0 && pc->seek) my_usleep(1000);
} }
return 0; return 0;

View File

@ -34,6 +34,7 @@ int buffered_chunks;
#define DEFAULT_BUFFER_BEFORE_PLAY 0 #define DEFAULT_BUFFER_BEFORE_PLAY 0
PlayerData * playerData_pd; PlayerData * playerData_pd;
int * player_pid;
void initPlayerData() { void initPlayerData() {
float perc = DEFAULT_BUFFER_BEFORE_PLAY; float perc = DEFAULT_BUFFER_BEFORE_PLAY;
@ -102,6 +103,22 @@ void initPlayerData() {
ERROR("problems shmctl'ing\n"); ERROR("problems shmctl'ing\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/* maybe the following should be put in the same shm block as the previous
* or maybe even made a part of the playerData struct
*/
allocationSize = sizeof(int);
if((shmid = shmget(IPC_PRIVATE,allocationSize,IPC_CREAT|0600))<0) {
ERROR("problems shmget'ing\n");
exit(EXIT_FAILURE);
}
if((player_pid = shmat(shmid,NULL,0))<0) {
ERROR("problems shmat'ing\n");
exit(EXIT_FAILURE);
}
if (shmctl(shmid, IPC_RMID, 0)<0) {
ERROR("problems shmctl'ing\n");
exit(EXIT_FAILURE);
}
buffer = &(playerData_pd->buffer); buffer = &(playerData_pd->buffer);
@ -147,6 +164,15 @@ PlayerData * getPlayerData() {
return playerData_pd; return playerData_pd;
} }
int getPlayerPid() {
return *player_pid;
}
void setPlayerPid(int pid) {
*player_pid = pid;
}
void freePlayerData() { void freePlayerData() {
shmdt(playerData_pd); shmdt(playerData_pd);
shmdt(player_pid);
} }

View File

@ -43,6 +43,8 @@ typedef struct _PlayerData {
void initPlayerData(); void initPlayerData();
PlayerData * getPlayerData(); PlayerData * getPlayerData();
int getPlayerPid();
void setPlayerPid(int pid);
void freePlayerData(); void freePlayerData();

View File

@ -19,6 +19,7 @@
#include "sig_handlers.h" #include "sig_handlers.h"
#include "player.h" #include "player.h"
#include "playerData.h"
#include "playlist.h" #include "playlist.h"
#include "directory.h" #include "directory.h"
#include "command.h" #include "command.h"
@ -33,10 +34,30 @@
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <errno.h> #include <errno.h>
#include <unistd.h>
extern volatile int masterPid;
extern volatile int mainPid;
int masterHandlePendingSignals() {
if(signal_is_pending(SIGINT) || signal_is_pending(SIGTERM)) {
DEBUG("master process got SIGINT or SIGTERM, exiting\n");
return COMMAND_RETURN_KILL;
}
if(signal_is_pending(SIGHUP)) {
signal_clear(SIGHUP);
/* Forward it to the main process, which will update the DB */
kill(mainPid, SIGHUP);
}
return 0;
}
int handlePendingSignals() { int handlePendingSignals() {
if(signal_is_pending(SIGINT) || signal_is_pending(SIGTERM)) { if(signal_is_pending(SIGINT) || signal_is_pending(SIGTERM)) {
DEBUG("got SIGINT or SIGTERM, exiting\n"); DEBUG("main process got SIGINT or SIGTERM, exiting\n");
return COMMAND_RETURN_KILL; return COMMAND_RETURN_KILL;
} }
@ -57,17 +78,55 @@ int handlePendingSignals() {
void chldSigHandler(int signal) { void chldSigHandler(int signal) {
int status; int status;
int pid; int pid;
DEBUG("got SIGCHLD\n"); DEBUG("main process got SIGCHLD\n");
while(0 != (pid = wait3(&status,WNOHANG,NULL))) { while(0 != (pid = wait3(&status,WNOHANG,NULL))) {
if(pid<0) { if(pid<0) {
if(errno==EINTR) continue; if(errno==EINTR) continue;
else break; else break;
} }
player_sigChldHandler(pid,status);
directory_sigChldHandler(pid,status); directory_sigChldHandler(pid,status);
} }
} }
void masterChldSigHandler(int signal) {
int status;
int pid;
DEBUG("master process got SIGCHLD\n");
while(0 != (pid = wait3(&status,WNOHANG,NULL))) {
if(pid<0) {
if(errno==EINTR) continue;
else break;
}
DEBUG("PID: %d\n",pid);
if (pid == mainPid) kill(getpid(), SIGTERM);
player_sigChldHandler(pid,status);
}
}
int playerInitReal();
void masterSigUsr2Handler(int signal) {
DEBUG("Master process got SIGUSR2 starting a new player process\n");
if (getPlayerPid() <= 0)
playerInitReal();
}
void masterInitSigHandlers() {
struct sigaction sa;
sa.sa_flags = 0;
sa.sa_handler = SIG_IGN;
while(sigaction(SIGPIPE,&sa,NULL)<0 && errno==EINTR);
sa.sa_handler = masterChldSigHandler;
while(sigaction(SIGCHLD,&sa,NULL)<0 && errno==EINTR);
sa.sa_handler = masterSigUsr2Handler;
while(sigaction(SIGUSR2,&sa,NULL)<0 && errno==EINTR);
signal_handle(SIGUSR1);
signal_handle(SIGINT);
signal_handle(SIGTERM);
signal_handle(SIGHUP);
}
void initSigHandlers() { void initSigHandlers() {
struct sigaction sa; struct sigaction sa;
@ -114,17 +173,32 @@ void ignoreSignals() {
while(sigaction(SIGPIPE,&sa,NULL)<0 && errno==EINTR); while(sigaction(SIGPIPE,&sa,NULL)<0 && errno==EINTR);
while(sigaction(SIGCHLD,&sa,NULL)<0 && errno==EINTR); while(sigaction(SIGCHLD,&sa,NULL)<0 && errno==EINTR);
while(sigaction(SIGUSR1,&sa,NULL)<0 && errno==EINTR); while(sigaction(SIGUSR1,&sa,NULL)<0 && errno==EINTR);
while(sigaction(SIGUSR2,&sa,NULL)<0 && errno==EINTR);
while(sigaction(SIGINT,&sa,NULL)<0 && errno==EINTR); while(sigaction(SIGINT,&sa,NULL)<0 && errno==EINTR);
while(sigaction(SIGTERM,&sa,NULL)<0 && errno==EINTR); while(sigaction(SIGTERM,&sa,NULL)<0 && errno==EINTR);
while(sigaction(SIGHUP,&sa,NULL)<0 && errno==EINTR); while(sigaction(SIGHUP,&sa,NULL)<0 && errno==EINTR);
} }
void waitOnSignals() {
sigset_t sset;
sigfillset(&sset);
sigdelset(&sset,SIGCHLD);
sigdelset(&sset,SIGUSR1);
sigdelset(&sset,SIGUSR2);
sigdelset(&sset,SIGHUP);
sigdelset(&sset,SIGINT);
sigdelset(&sset,SIGTERM);
sigsuspend(&sset);
}
void blockSignals() { void blockSignals() {
sigset_t sset; sigset_t sset;
sigemptyset(&sset); sigemptyset(&sset);
sigaddset(&sset,SIGCHLD); sigaddset(&sset,SIGCHLD);
sigaddset(&sset,SIGUSR1); sigaddset(&sset,SIGUSR1);
sigaddset(&sset,SIGUSR2);
sigaddset(&sset,SIGHUP); sigaddset(&sset,SIGHUP);
sigaddset(&sset,SIGINT); sigaddset(&sset,SIGINT);
sigaddset(&sset,SIGTERM); sigaddset(&sset,SIGTERM);
@ -137,6 +211,7 @@ void unblockSignals() {
sigemptyset(&sset); sigemptyset(&sset);
sigaddset(&sset,SIGCHLD); sigaddset(&sset,SIGCHLD);
sigaddset(&sset,SIGUSR1); sigaddset(&sset,SIGUSR1);
sigaddset(&sset,SIGUSR2);
sigaddset(&sset,SIGHUP); sigaddset(&sset,SIGHUP);
sigaddset(&sset,SIGINT); sigaddset(&sset,SIGINT);
sigaddset(&sset,SIGTERM); sigaddset(&sset,SIGTERM);

View File

@ -22,8 +22,10 @@
#include "../config.h" #include "../config.h"
int handlePendingSignals(); int handlePendingSignals();
int masterHandlePendingSignals();
void initSigHandlers(); void initSigHandlers();
void masterInitSigHandlers();
void finishSigHandlers(); void finishSigHandlers();
@ -31,6 +33,8 @@ void setSigHandlersForDecoder();
void ignoreSignals(); void ignoreSignals();
void waitOnSignals();
void blockSignals(); void blockSignals();
void unblockSignals(); void unblockSignals();

View File

@ -1,11 +1,12 @@
#include "tagTracker.h" #include "tagTracker.h"
#include "list.h"
#include "log.h" #include "log.h"
#include <glib/gtree.h>
#include <assert.h> #include <assert.h>
#include <stdlib.h>
static List * tagLists[TAG_NUM_OF_ITEM_TYPES] = static GTree * tagLists[TAG_NUM_OF_ITEM_TYPES] =
{ {
NULL, NULL,
NULL, NULL,
@ -21,89 +22,96 @@ typedef struct tagTrackerItem {
mpd_sint8 visited; mpd_sint8 visited;
} TagTrackerItem; } TagTrackerItem;
int keyCompare(const void *a, const void *b, void *data) {
return strcmp(a,b);
}
char * getTagItemString(int type, char * string) { char * getTagItemString(int type, char * string) {
ListNode * node; TagTrackerItem * item;
int pos; TagTrackerItem ** itemPointer = &item;
char *key;
char **keyPointer = &key;
/*if(type == TAG_ITEM_TITLE) return strdup(string);*/ /*if(type == TAG_ITEM_TITLE) return strdup(string);*/
if(tagLists[type] == NULL) { if(tagLists[type] == NULL) {
tagLists[type] = makeList(free, 1); tagLists[type] = g_tree_new_full(keyCompare, NULL, free, free);
sortList(tagLists[type]);
} }
if(findNodeInList(tagLists[type], string, &node, &pos)) { if((TagTrackerItem *)g_tree_lookup_extended(tagLists[type], string, (void**)keyPointer, (void**)itemPointer )) {
((TagTrackerItem *)node->data)->count++; item->count++;
} }
else { else {
TagTrackerItem * item = malloc(sizeof(TagTrackerItem)); item = malloc(sizeof(TagTrackerItem));
item->count = 1; item->count = 1;
item->visited = 0; item->visited = 0;
node = insertInListBeforeNode(tagLists[type], node, pos, key = strdup(string);
string, item); g_tree_insert(tagLists[type], key, item);
} }
return node->key; return key;
} }
void removeTagItemString(int type, char * string) { void removeTagItemString(int type, char * string) {
ListNode * node; TagTrackerItem *item;
int pos;
assert(string); assert(string);
assert(tagLists[type]); assert(tagLists[type]);
if(tagLists[type] == NULL) return; if(tagLists[type] == NULL) return;
/*if(!node) { if((item = g_tree_lookup(tagLists[type], string))) {
free(string);
return;
}*/
if(findNodeInList(tagLists[type], string, &node, &pos)) {
TagTrackerItem * item = node->data;
item->count--; item->count--;
if(item->count <= 0) deleteNodeFromList(tagLists[type], node); if(item->count <= 0) g_tree_remove(tagLists[type], string);
} }
if(tagLists[type]->numberOfNodes == 0) { /* why would this be done??? free it when mpd quits...
if(tagLists[type]->numberOfNodes == 0) {
freeList(tagLists[type]); freeList(tagLists[type]);
tagLists[type] = NULL; tagLists[type] = NULL;
} }
*/
}
void destroyTagTracker() {
int type;
for (type=0; type < TAG_NUM_OF_ITEM_TYPES; type ++)
if (tagLists[type])
g_tree_destroy(tagLists[type]);
} }
int getNumberOfTagItems(int type) { int getNumberOfTagItems(int type) {
if(tagLists[type] == NULL) return 0; if(tagLists[type] == NULL) return 0;
return tagLists[type]->numberOfNodes; return g_tree_nnodes(tagLists[type]);
} }
int calcSavedMemory(char *key, TagTrackerItem* value, int* sum) {
*sum -= sizeof(int) + 4*sizeof(void*); //sizeof(_GTreeNode)
*sum -= sizeof(TagTrackerItem);
*sum += (strlen(key)+1)*value->count;
return FALSE;
}
void printMemorySavedByTagTracker() { void printMemorySavedByTagTracker() {
int i; int i;
ListNode * node;
size_t sum = 0; size_t sum = 0;
for(i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) { for(i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) {
if(!tagLists[i]) continue; if(!tagLists[i]) continue;
sum -= sizeof(List); sum -= 5*sizeof(void*);//sizeof(_GTree)
g_tree_foreach(tagLists[i], (GTraverseFunc)calcSavedMemory, &sum);
node = tagLists[i]->firstNode;
while(node != NULL) {
sum -= sizeof(ListNode);
sum -= sizeof(TagTrackerItem);
sum -= sizeof(node->key);
sum += (strlen(node->key)+1)*(*((int *)node->data));
node = node->nextNode;
}
} }
DEBUG("saved memory from tags: %li\n", (long)sum); DEBUG("saved memory from tags: %li\n", (long)sum);
} }
void sortTagTrackerInfo() { void sortTagTrackerInfo() {
/* implicit sorting
int i; int i;
for(i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) { for(i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) {
@ -112,56 +120,52 @@ void sortTagTrackerInfo() {
DEBUG("sorting %s info\n", mpdTagItemKeys[i]); DEBUG("sorting %s info\n", mpdTagItemKeys[i]);
sortList(tagLists[i]); sortList(tagLists[i]);
} }*/
} }
int resetVisitedFlag(char *key, TagTrackerItem *value, void *data) {
value->visited = 0;
return FALSE;
}
void resetVisitedFlagsInTagTracker(int type) { void resetVisitedFlagsInTagTracker(int type) {
ListNode * node;
if(!tagLists[type]) return; if(!tagLists[type]) return;
node = tagLists[type]->firstNode; g_tree_foreach(tagLists[type], (GTraverseFunc)resetVisitedFlag, NULL);
while(node) {
((TagTrackerItem *)node->data)->visited = 0;
node = node->nextNode;
}
} }
int wasVisitedInTagTracker(int type, char * str) { int wasVisitedInTagTracker(int type, char * str) {
void * item; TagTrackerItem * item;
if(!tagLists[type]) return 0; if(!tagLists[type]) return 0;
if(!findInList(tagLists[type], str, &item)) return 0; if(!(item = g_tree_lookup(tagLists[type], str))) return 0;
return ((TagTrackerItem *)item)->visited; return item->visited;
} }
void visitInTagTracker(int type, char * str) { void visitInTagTracker(int type, char * str) {
void * item;
if(!tagLists[type]) return;
if(!findInList(tagLists[type], str, &item)) return;
((TagTrackerItem *)item)->visited = 1;
}
void printVisitedInTagTracker(FILE * fp, int type) {
ListNode * node;
TagTrackerItem * item; TagTrackerItem * item;
if(!tagLists[type]) return; if(!tagLists[type]) return;
node = tagLists[type]->firstNode; if(!(item = g_tree_lookup(tagLists[type], str))) return;
while(node) { item->visited = 1;
item = node->data; }
if(item->visited) {
myfprintf(fp, "%s: %s\n", mpdTagItemKeys[type], struct _PrintVisitedUserdata {
node->key); FILE *fp;
} char *type;
node = node->nextNode; };
}
int printVisitedFlag(char *key, TagTrackerItem* value, struct _PrintVisitedUserdata *data) {
if(value->visited) myfprintf(data->fp, "%s: %s\n", data->type, key);
return FALSE;
}
void printVisitedInTagTracker(FILE * fp, int type) {
struct _PrintVisitedUserdata data = {fp, mpdTagItemKeys[type]};
if(!tagLists[type]) return;
g_tree_foreach( tagLists[type], (GTraverseFunc)printVisitedFlag, (void*)&data);
} }

View File

@ -6,6 +6,7 @@
char * getTagItemString(int type, char * string); char * getTagItemString(int type, char * string);
void removeTagItemString(int type, char * string); void removeTagItemString(int type, char * string);
void destroyTagTracker();
int getNumberOfTagItems(int type); int getNumberOfTagItems(int type);