$Log$
+ Revision 621.15 2004/06/16 03:13:02 ajc
+ * Scheduler fix ... added the rescan pipe back in
+
Revision 621.14 2004/06/15 20:42:42 ajc
* Store the body of any large (>1K) message in a separate database. This
will allow fast headers-only retrieval later.
Fri Jul 10 1998 Art Cancro <ajc@uncensored.citadel.org>
* Initial CVS import
+
lprintf(CTDL_CRIT, "Cannot open temp file: %s\n", strerror(errno));
return;
}
- msg = CtdlFetchMessage(msgnum);
+ msg = CtdlFetchMessage(msgnum, 1);
}
/* Now figure out what the client wants, and get it */
/* Otherwise, load the message into memory.
*/
else if (!strcasecmp(itemlist[i], "BODYSTRUCTURE")) {
- if (msg == NULL) msg = CtdlFetchMessage(IMAP->msgids[seq-1]);
+ if (msg == NULL) msg = CtdlFetchMessage(IMAP->msgids[seq-1], 1);
imap_fetch_bodystructure(IMAP->msgids[seq-1],
itemlist[i], msg);
}
else if (!strcasecmp(itemlist[i], "ENVELOPE")) {
- if (msg == NULL) msg = CtdlFetchMessage(IMAP->msgids[seq-1]);
+ if (msg == NULL) msg = CtdlFetchMessage(IMAP->msgids[seq-1], 1);
imap_fetch_envelope(IMAP->msgids[seq-1], msg);
}
else if (!strcasecmp(itemlist[i], "INTERNALDATE")) {
- if (msg == NULL) msg = CtdlFetchMessage(IMAP->msgids[seq-1]);
+ if (msg == NULL) msg = CtdlFetchMessage(IMAP->msgids[seq-1], 1);
imap_fetch_internaldate(msg);
}
if (IMAP->num_msgs > 0)
for (i = 0; i < IMAP->num_msgs; ++i)
if (IMAP->flags[i] && IMAP_SELECTED) {
- msg = CtdlFetchMessage(IMAP->msgids[i]);
+ msg = CtdlFetchMessage(IMAP->msgids[i], 1);
if (msg != NULL) {
if (imap_do_search_msg(i+1, msg, num_items,
itemlist, is_uid)) {
if (num_msgs > 0) {
if (compare != NULL) {
for (a = 0; a < num_msgs; ++a) {
- msg = CtdlFetchMessage(msglist[a]);
+ msg = CtdlFetchMessage(msglist[a], 1);
if (msg != NULL) {
if (CtdlMsgCmp(msg, compare)) {
msglist[a] = 0L;
* NOTE: Caller is responsible for freeing the returned CtdlMessage struct
* using the CtdlMessageFree() function.
*/
-struct CtdlMessage *CtdlFetchMessage(long msgnum)
+struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body)
{
struct cdbdata *dmsgtext;
struct cdbdata *dbigmsg;
*/
/*
- * Fetch the message from disk.
+ * Fetch the message from disk. If we're in sooper-fast headers
+ * only mode, request that we don't even bother loading the body
+ * into memory.
*/
- TheMessage = CtdlFetchMessage(msg_num);
+ if (headers_only == HEADERS_FAST) {
+ TheMessage = CtdlFetchMessage(msg_num, 0);
+ }
+ else {
+ TheMessage = CtdlFetchMessage(msg_num, 1);
+ }
if (TheMessage == NULL) {
if (do_proto) cprintf("%d Can't locate msg %ld on disk\n",
}
msgnum = extract_long(cmdbuf, 0);
- msg = CtdlFetchMessage(msgnum);
+ msg = CtdlFetchMessage(msgnum, 1);
if (msg == NULL) {
cprintf("%d Message %ld not found.\n",
ERROR + MESSAGE_NOT_FOUND, msgnum);
if ( (flags & SM_VERIFY_GOODNESS)
|| (flags & SM_DO_REPL_CHECK)
) {
- msg = CtdlFetchMessage(msgid);
+ msg = CtdlFetchMessage(msgid, 1);
if (msg == NULL) return(ERROR + ILLEGAL_VALUE);
}
time_t timestamp = (-1L);
lprintf(CTDL_DEBUG, "check_repl() found message %ld\n", msgnum);
- msg = CtdlFetchMessage(msgnum);
+ msg = CtdlFetchMessage(msgnum, 1);
if (msg == NULL) return;
if (msg->cm_fields['T'] != NULL) {
timestamp = atol(msg->cm_fields['T']);
conf = NULL;
}
else {
- msg = CtdlFetchMessage(msgnum);
+ msg = CtdlFetchMessage(msgnum, 1);
if (msg != NULL) {
conf = strdup(msg->cm_fields['M']);
CtdlFreeMessage(msg);
int CtdlDeleteMessages(char *, long, char *);
void CtdlWriteObject(char *, char *, char *, struct ctdluser *,
int, int, unsigned int);
-struct CtdlMessage *CtdlFetchMessage(long msgnum);
+struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body);
void CtdlFreeMessage(struct CtdlMessage *msg);
void serialize_message(struct ser_ret *, struct CtdlMessage *);
int is_valid_message(struct CtdlMessage *);
return;
}
- msg = CtdlFetchMessage(msgnum);
+ msg = CtdlFetchMessage(msgnum, 1);
if (msg == NULL) {
cprintf("%d Message %ld not found.\n",
ERROR + ILLEGAL_VALUE,
* us the ability to load the event into memory so we can diddle the
* attendees.
*/
- msg = CtdlFetchMessage(msgnum_being_replaced);
+ msg = CtdlFetchMessage(msgnum_being_replaced, 1);
if (msg == NULL) {
return(2); /* internal error */
}
return;
}
- msg = CtdlFetchMessage(msgnum);
+ msg = CtdlFetchMessage(msgnum, 1);
if (msg == NULL) {
cprintf("%d Message %ld not found.\n",
ERROR + ILLEGAL_VALUE,
strcpy(conflict_event_uid, "");
strcpy(conflict_event_summary, "");
- msg = CtdlFetchMessage(msgnum);
+ msg = CtdlFetchMessage(msgnum, 1);
if (msg == NULL) return;
memset(&ird, 0, sizeof ird);
strcpy(ird.desired_partnum, "_HUNT_");
struct CtdlMessage *msg;
struct ical_respond_data ird;
- msg = CtdlFetchMessage(msgnum);
+ msg = CtdlFetchMessage(msgnum, 1);
if (msg == NULL) {
cprintf("%d Message %ld not found.\n",
ERROR + ILLEGAL_VALUE,
cal = (icalcomponent *)data;
- msg = CtdlFetchMessage(msgnum);
+ msg = CtdlFetchMessage(msgnum, 1);
if (msg == NULL) return;
memset(&ird, 0, sizeof ird);
strcpy(ird.desired_partnum, "_HUNT_");
for (a=0; a<num_msgs; ++a) {
delnum = msglist[a];
- msg = CtdlFetchMessage(delnum);
+ msg = CtdlFetchMessage(delnum, 0); /* dont need body */
if (msg != NULL) {
xtime = atol(msg->cm_fields['T']);
CtdlFreeMessage(msg);
void inetcfg_init_backend(long msgnum, void *userdata) {
struct CtdlMessage *msg;
- msg = CtdlFetchMessage(msgnum);
+ msg = CtdlFetchMessage(msgnum, 1);
if (msg != NULL) {
inetcfg_setTo(msg);
CtdlFreeMessage(msg);
void spamstrings_init_backend(long msgnum, void *userdata) {
struct CtdlMessage *msg;
- msg = CtdlFetchMessage(msgnum);
+ msg = CtdlFetchMessage(msgnum, 1);
if (msg != NULL) {
spamstrings_setTo(msg);
CtdlFreeMessage(msg);
*/
if (sc->ignet_push_shares != NULL) {
- msg = CtdlFetchMessage(msgnum);
+ msg = CtdlFetchMessage(msgnum, 1);
if (msg != NULL) {
size_t newpath_len;
lprintf(CTDL_DEBUG, "smtp_do_procmsg(%ld)\n", msgnum);
- msg = CtdlFetchMessage(msgnum);
+ msg = CtdlFetchMessage(msgnum, 1);
if (msg == NULL) {
lprintf(CTDL_ERR, "SMTP: tried %ld but no such message!\n", msgnum);
return;
char buf[SIZ];
char tempfile[SIZ];
- msg = CtdlFetchMessage(msgnum);
+ msg = CtdlFetchMessage(msgnum, 1);
if (msg == NULL) return; /* fail silently */
cprintf("message\n");
void vcard_add_to_directory(long msgnum, void *data) {
struct CtdlMessage *msg;
- msg = CtdlFetchMessage(msgnum);
+ msg = CtdlFetchMessage(msgnum, 1);
if (msg != NULL) {
vcard_extract_internet_addresses(msg, vcard_directory_add_user);
}
if (VC->msgnum < 0L) return vcard_new();
- msg = CtdlFetchMessage(VC->msgnum);
+ msg = CtdlFetchMessage(VC->msgnum, 1);
if (msg == NULL) return vcard_new();
v = vcard_load(msg->cm_fields['M']);
return;
}
- msg = CtdlFetchMessage(msgnum);
+ msg = CtdlFetchMessage(msgnum, 1);
if (msg == NULL) return;
ptr = msg->cm_fields['M'];
time_t last_purge = 0; /* Last dead session purge */
static int num_threads = 0; /* Current number of threads */
int num_sessions = 0; /* Current number of sessions */
+static int rescan[2]; /* The rescan pipe */
pthread_t initial_thread; /* tid for main() thread */
* socket breaks.
*/
signal(SIGPIPE, SIG_IGN);
+
+ /*
+ * Set up the rescan pipe. When a session goes idle, it writes a
+ * single byte to this pipe to wake up the thread calling select(),
+ * which tells it to rescan the list of session sockets.
+ */
+ if (pipe(rescan) != 0) {
+ lprintf(CTDL_EMERG, "Cannot create rescan pipe: %s\n",
+ strerror(errno));
+ abort();
+ }
}
do_select: force_purge = 0;
bind_me = NULL; /* Which session shall we handle? */
- /* Initialize the fdset. */
+ /* Initialize the fdset. Start with the rescan pipe. */
FD_ZERO(&readfds);
- highest = 0;
+ FD_SET(rescan[0], &readfds);
+ highest = rescan[0] + 1;
begin_critical_section(S_SESSION_TABLE);
for (ptr = ContextList; ptr != NULL; ptr = ptr->next) {
serviceptr->h_greeting_function();
become_session(NULL);
con->state = CON_IDLE;
+
+ /* Wake up the currently blocking select() by
+ * writing a dummy byte to the rescan pipe.
+ */
+ write(rescan[1], &i, 1);
goto do_select;
}
}
break;
}
+ /* If the rescan pipe went active, read a dummy byte from it */
+ if (FD_ISSET(rescan[0], &readfds)) {
+ read(rescan[0], &i, 1);
+ goto do_select;
+ }
+
/* It must be a client socket. Find a context that has data
* waiting on its socket *and* is in the CON_IDLE state. Any
* active sockets other than our chosen one are marked as
force_purge = CC->kill_me;
become_session(NULL);
bind_me->state = CON_IDLE;
+
+ /* Wake up the currently blocking select() by writing
+ * a dummy byte to the rescan pipe.
+ */
+ write(rescan[1], &i, 1);
}
dead_session_purge(force_purge);