#include "snprintf.h"
#endif
-#ifdef DEBUG_MEMORY_LEAKS
-struct TheHeap *heap = NULL;
-#endif
-
pthread_mutex_t Critters[MAX_SEMAPHORES]; /* Things needing locking */
pthread_key_t MyConKey; /* TSD key for MyContext() */
* Note: the variable "buf" below needs to be large enough to handle any
* log data sent through this function. BE CAREFUL!
*/
-void lprintf(int loglevel, const char *format, ...) {
+void lprintf(enum LogLevel loglevel, const char *format, ...) {
va_list arg_ptr;
char buf[SIZ];
snprintf(buf, 6, "[%3d]", CC->cs_pid);
buf[5] = ' ';
}
- syslog(LOG_NOTICE, buf);
+ syslog(loglevel, buf);
}
}
else if (loglevel <= verbosity) {
* %03ld to %06ld and remove " / 1000" after tv.tv_usec.
*/
if (CC && CC->cs_pid) {
+#if 0
+ /* Millisecond display */
fprintf(stderr,
"%04d/%02d/%02d %2d:%02d:%02d.%03ld [%3d] %s",
tim->tm_year + 1900, tim->tm_mon + 1,
tim->tm_mday, tim->tm_hour, tim->tm_min,
tim->tm_sec, (long)tv.tv_usec / 1000,
CC->cs_pid, buf);
+#endif
+ /* Microsecond display */
+ fprintf(stderr,
+ "%04d/%02d/%02d %2d:%02d:%02d.%06ld [%3d] %s",
+ tim->tm_year + 1900, tim->tm_mon + 1,
+ tim->tm_mday, tim->tm_hour, tim->tm_min,
+ tim->tm_sec, (long)tv.tv_usec,
+ CC->cs_pid, buf);
} else {
+#if 0
+ /* Millisecond display */
fprintf(stderr,
"%04d/%02d/%02d %2d:%02d:%02d.%03ld %s",
tim->tm_year + 1900, tim->tm_mon + 1,
tim->tm_mday, tim->tm_hour, tim->tm_min,
tim->tm_sec, (long)tv.tv_usec / 1000, buf);
+#endif
+ /* Microsecond display */
+ fprintf(stderr,
+ "%04d/%02d/%02d %2d:%02d:%02d.%06ld %s",
+ tim->tm_year + 1900, tim->tm_mon + 1,
+ tim->tm_mday, tim->tm_hour, tim->tm_min,
+ tim->tm_sec, (long)tv.tv_usec, buf);
}
fflush(stderr);
}
-#ifdef DEBUG_MEMORY_LEAKS
-void *tracked_malloc(size_t tsize, char *tfile, int tline) {
- void *ptr;
- struct TheHeap *hptr;
-
- ptr = malloc(tsize);
- if (ptr == NULL) {
- lprintf(3, "DANGER! mallok(%d) at %s:%d failed!\n",
- tsize, tfile, tline);
- return(NULL);
- }
-
- hptr = (struct TheHeap *) malloc(sizeof(struct TheHeap));
- strcpy(hptr->h_file, tfile);
- hptr->h_line = tline;
- hptr->next = heap;
- hptr->h_ptr = ptr;
- heap = hptr;
- return ptr;
-}
-
-char *tracked_strdup(const char *orig, char *tfile, int tline) {
- char *s;
-
- s = tracked_malloc( (strlen(orig)+1), tfile, tline);
- if (s == NULL) return NULL;
-
- strcpy(s, orig);
- return s;
-}
-
-void tracked_free(void *ptr) {
- struct TheHeap *hptr, *freeme;
-
- if (heap->h_ptr == ptr) {
- hptr = heap->next;
- free(heap);
- heap = hptr;
- }
- else {
- for (hptr=heap; hptr->next!=NULL; hptr=hptr->next) {
- if (hptr->next->h_ptr == ptr) {
- freeme = hptr->next;
- hptr->next = hptr->next->next;
- free(freeme);
- }
- }
- }
-
- free(ptr);
-}
-
-void *tracked_realloc(void *ptr, size_t size) {
- void *newptr;
- struct TheHeap *hptr;
-
- newptr = realloc(ptr, size);
-
- for (hptr=heap; hptr!=NULL; hptr=hptr->next) {
- if (hptr->h_ptr == ptr) hptr->h_ptr = newptr;
- }
-
- return newptr;
-}
-
-
-void dump_tracked() {
- struct TheHeap *hptr;
-
- cprintf("%d Here's what's allocated...\n", LISTING_FOLLOWS);
- for (hptr=heap; hptr!=NULL; hptr=hptr->next) {
- cprintf("%20s %5d\n",
- hptr->h_file, hptr->h_line);
- }
-#ifdef __GNUC__
- malloc_stats();
-#endif
-
- cprintf("000\n");
-}
-#endif
-
-
/*
* We used to use master_cleanup() as a signal handler to shut down the server.
* however, master_cleanup() and the functions it calls do some things that
* session to which the calling thread is currently bound.
*/
if (pthread_key_create(&MyConKey, NULL) != 0) {
- lprintf(1, "Can't create TSD key!! %s\n", strerror(errno));
+ lprintf(CTDL_CRIT, "Can't create TSD key!! %s\n", strerror(errno));
}
/*
*/
void begin_critical_section(int which_one)
{
- /* lprintf(9, "begin_critical_section(%d)\n", which_one); */
+ /* lprintf(CTDL_DEBUG, "begin_critical_section(%d)\n", which_one); */
/* ensure nobody ever tries to do a critical section within a
transaction; this could lead to deadlock. */
cdb_check_handles();
*/
void end_critical_section(int which_one)
{
- /* lprintf(9, "end_critical_section(%d)\n", which_one); */
+ /* lprintf(CTDL_DEBUG, "end_critical_section(%d)\n", which_one); */
pthread_mutex_unlock(&Critters[which_one]);
}
s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s < 0) {
- lprintf(1, "citserver: Can't create a socket: %s\n",
+ lprintf(CTDL_EMERG, "citserver: Can't create a socket: %s\n",
strerror(errno));
return(-1);
}
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
- lprintf(1, "citserver: Can't bind: %s\n",
+ lprintf(CTDL_EMERG, "citserver: Can't bind: %s\n",
strerror(errno));
close(s);
return(-1);
}
if (listen(s, actual_queue_len) < 0) {
- lprintf(1, "citserver: Can't listen: %s\n", strerror(errno));
+ lprintf(CTDL_EMERG, "citserver: Can't listen: %s\n", strerror(errno));
close(s);
return(-1);
}
i = unlink(sockpath);
if (i != 0) if (errno != ENOENT) {
- lprintf(1, "citserver: can't unlink %s: %s\n",
+ lprintf(CTDL_EMERG, "citserver: can't unlink %s: %s\n",
sockpath, strerror(errno));
return(-1);
}
s = socket(AF_UNIX, SOCK_STREAM, 0);
if (s < 0) {
- lprintf(1, "citserver: Can't create a socket: %s\n",
+ lprintf(CTDL_EMERG, "citserver: Can't create a socket: %s\n",
strerror(errno));
return(-1);
}
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
- lprintf(1, "citserver: Can't bind: %s\n",
+ lprintf(CTDL_EMERG, "citserver: Can't bind: %s\n",
strerror(errno));
return(-1);
}
if (listen(s, actual_queue_len) < 0) {
- lprintf(1, "citserver: Can't listen: %s\n", strerror(errno));
+ lprintf(CTDL_EMERG, "citserver: Can't listen: %s\n", strerror(errno));
return(-1);
}
struct CitContext *CreateNewContext(void) {
struct CitContext *me, *ptr;
- me = (struct CitContext *) mallok(sizeof(struct CitContext));
+ me = (struct CitContext *) malloc(sizeof(struct CitContext));
if (me == NULL) {
- lprintf(1, "citserver: can't allocate memory!!\n");
+ lprintf(CTDL_ALERT, "citserver: can't allocate memory!!\n");
return NULL;
}
memset(me, 0, sizeof(struct CitContext));
if (CC->buffering == 0) {
CC->buffering = 1;
CC->buffer_len = 0;
- CC->output_buffer = mallok(SIZ);
+ CC->output_buffer = malloc(SIZ);
}
}
if (CC->buffering == 1) {
CC->buffering = 0;
client_write(CC->output_buffer, CC->buffer_len);
- phree(CC->output_buffer);
+ free(CC->output_buffer);
CC->output_buffer = NULL;
CC->buffer_len = 0;
}
if (CC->buffering) {
old_buffer_len = CC->buffer_len;
CC->buffer_len += nbytes;
- CC->output_buffer = reallok(CC->output_buffer, CC->buffer_len);
+ CC->output_buffer = realloc(CC->output_buffer, CC->buffer_len);
memcpy(&CC->output_buffer[old_buffer_len], buf, nbytes);
return;
}
retval = write(sock, &buf[bytes_written],
nbytes - bytes_written);
if (retval < 1) {
- lprintf(2, "client_write() failed: %s\n",
+ lprintf(CTDL_ERR, "client_write() failed: %s\n",
strerror(errno));
if (sock == CC->client_socket) CC->kill_me = 1;
return;
rlen = read(CC->client_socket, &buf[len], bytes-len);
if (rlen<1) {
- lprintf(2, "client_read() failed: %s\n",
+ lprintf(CTDL_ERR, "client_read() failed: %s\n",
strerror(errno));
CC->kill_me = 1;
return(-1);
serviceptr = serviceptr->next ) {
if (serviceptr->tcp_port > 0)
- lprintf(3, "Closing listener on port %d\n",
+ lprintf(CTDL_INFO, "Closing listener on port %d\n",
serviceptr->tcp_port);
if (serviceptr->sockpath != NULL)
- lprintf(3, "Closing listener on '%s'\n",
+ lprintf(CTDL_INFO, "Closing listener on '%s'\n",
serviceptr->sockpath);
close(serviceptr->msock);
struct worker_node *n;
pthread_attr_t attr;
- n = mallok(sizeof(struct worker_node));
+ n = malloc(sizeof(struct worker_node));
if (n == NULL) {
- lprintf(1, "can't allocate worker_node, exiting\n");
+ lprintf(CTDL_EMERG, "can't allocate worker_node, exiting\n");
time_to_die = -1;
return;
}
if ((ret = pthread_attr_init(&attr))) {
- lprintf(1, "pthread_attr_init: %s\n", strerror(ret));
+ lprintf(CTDL_EMERG, "pthread_attr_init: %s\n", strerror(ret));
time_to_die = -1;
return;
}
/* we seem to need something bigger than FreeBSD's default 64k stack */
if ((ret = pthread_attr_setstacksize(&attr, 128 * 1024))) {
- lprintf(1, "pthread_attr_setstacksize: %s\n", strerror(ret));
+ lprintf(CTDL_EMERG, "pthread_attr_setstacksize: %s\n", strerror(ret));
time_to_die = -1;
return;
}
if ((ret = pthread_create(&n->tid, &attr, worker_thread, NULL) != 0))
{
- lprintf(1, "Can't create worker thread: %s\n",
+ lprintf(CTDL_ALERT, "Can't create worker thread: %s\n",
strerror(ret));
}
* section, so we have to do it like this.
*/
if (rem != NULL) {
- lprintf(9, "Purging session %d\n", rem->cs_pid);
+ lprintf(CTDL_DEBUG, "Purging session %d\n", rem->cs_pid);
RemoveContext(rem);
}
if ((*node)->tid == self) {
tmp = *node;
*node = (*node)->next;
- phree(tmp);
+ free(tmp);
break;
}
struct ServiceFunctionHook *serviceptr;
int m;
- lprintf(9, "Initializing master fdset\n");
+ lprintf(CTDL_DEBUG, "Initializing master fdset\n");
FD_ZERO(&masterfds);
masterhighest = 0;
- lprintf(9, "Will listen on rescan pipe %d\n", rescan[0]);
+ lprintf(CTDL_DEBUG, "Will listen on rescan pipe %d\n", rescan[0]);
FD_SET(rescan[0], &masterfds);
if (rescan[0] > masterhighest) masterhighest = rescan[0];
for (serviceptr = ServiceHookTable; serviceptr != NULL;
serviceptr = serviceptr->next ) {
m = serviceptr->msock;
- lprintf(9, "Will listen on master socket %d\n", m);
+ lprintf(CTDL_DEBUG, "Will listen on master socket %d\n", m);
FD_SET(m, &masterfds);
if (m > masterhighest) {
masterhighest = m;
}
}
- lprintf(9, "masterhighest = %d\n", masterhighest);
+ lprintf(CTDL_DEBUG, "masterhighest = %d\n", masterhighest);
}
int i;
char junk;
int highest;
+ /* This is synchronized below; it helps implement round robin mode */
+ static struct CitContext* next_session = NULL;
struct CitContext *ptr;
struct CitContext *bind_me = NULL;
fd_set readfds;
*/
if (retval < 0) {
if (errno != EINTR) {
- lprintf(9, "Exiting (%s)\n", strerror(errno));
+ lprintf(CTDL_EMERG, "Exiting (%s)\n", strerror(errno));
time_to_die = 1;
} else if (!time_to_die)
goto do_select;
if (FD_ISSET(serviceptr->msock, &readfds)) {
ssock = accept(serviceptr->msock, NULL, 0);
if (ssock < 0) {
- lprintf(2, "citserver: accept(): %s\n",
+ lprintf(CTDL_CRIT,
+ "citserver: accept(): %s\n",
strerror(errno));
}
else {
- lprintf(7, "citserver: "
+ lprintf(CTDL_NOTICE,
"New client socket %d\n",
ssock);
else {
bind_me = NULL;
begin_critical_section(S_SESSION_TABLE);
- for (ptr = ContextList;
+ /*
+ * We start where we left off. If we get to the end
+ * we'll start from the beginning again, then give up
+ * if we still don't find anything. This ensures
+ * that all contexts get a more-or-less equal chance
+ * to run. And yes, I did add a goto to the code. -IO
+ */
+find_session: if (next_session == NULL)
+ next_session = ContextList;
+ for (ptr = next_session;
( (ptr != NULL) && (bind_me == NULL) );
ptr = ptr->next) {
if ( (FD_ISSET(ptr->client_socket, &readfds))
* letting anyone else touch the context list.
*/
bind_me->state = CON_EXECUTING;
+ next_session = bind_me->next;
+ } else if (next_session == ContextList) {
+ next_session = NULL;
+ }
+ if (bind_me == NULL && next_session != NULL) {
+ next_session = NULL;
+ goto find_session;
}
end_critical_section(S_SESSION_TABLE);