TEST(CacheTest, InitCache) { std::cerr << "Creating strategy and order ids [" << TEST_SIZE << "]" << std::endl; for (int i=0; i<TEST_SIZE; i++) { oid_list[i] = order_id(true); sid_list[i] = strategy_id(true); } std::cerr << "Inserting oids and order info" << std::endl; for (int i=0; i<TEST_SIZE; i++) { OrderInfo_ptr info_ptr(new OrderInfo(oid_list[i], sid_list[i])); mc.add(oid_list[i], info_ptr); } std::cerr << "Cache size(): " << (mc.getCache())->size() << std::endl; ASSERT_EQ(TEST_SIZE, mc.getCache()->size()); }
/* ---------------------------------------------------------------------- */ int do_sendfile(int sd, struct rep *rep) { struct info *ip; int hdr_len = 0; /* length of the http header */ int file_bytes = 0; /* number of bytes coming from the file */ int file_fd = 0; /* file fd */ int nwritten = 0; ip = info_ptr(sd); assert(ip != NULL); assert(rep == &ip->rep); /* Calculate some things: * hdr_len - number of bytes to send using write() * file_bytes - number of file bytes to send using sendfile() * file_fd - fd to pass to sendfile() * rep->offset - offset to pass to sendfile() */ switch (ip->req.type) { case REQ_STATIC: hdr_len = (rep->end - rep->cur); /* The number of bytes coming from the file is: * The total number of bytes initially determined which includes the * header, minus the number of bytes that have been sent so far * minus the number of bytes we still have left in the header to send. */ file_bytes = rep->total_len - rep->nwritten - hdr_len; file_fd = rep->fd; break; case REQ_FASTCGI: hdr_len = 0; file_bytes = rep->total_len - hdr_len; file_fd = dyn_bufpool->track->mmap_fd; PRINT_TIME(sd, &tnow, &tprev, "rep->cur = %p dyn_bufpool->track->adjusted_addr = %p", rep->cur, dyn_bufpool->track->adjusted_addr); if (rep->offset == 0) { rep->offset = rep->cur - (char *) dyn_bufpool->track->adjusted_addr; } break; default: printf("do_sendfile(): invalid ip->req.type %d\n", ip->req.type); assert(0); break; } PRINT_TIME(sd, &tnow, &tprev, "hdr_len = %d file_bytes = %d file_fd = %d offset = %d", hdr_len, file_bytes, file_fd, rep->offset); PRINT_TIME(sd, &tnow, &tprev, "use_cache = %d", rep->use_cache); #if defined(__linux__) nwritten = sendfile_linux(ip, hdr_len, file_bytes, file_fd); #elif defined(FreeBSD) nwritten = sendfile_freebsd(ip, hdr_len, file_bytes, file_fd); #elif defined(HPUX) printf("Not tested/implemented\n"); exit(1); nwritten = sendfile_hpux(ip, hdr_len, file_bytes, file_fd); #else #error sendfile not implemented on this operating system #endif return nwritten; } /* do_sendfile */
/*----------------------------------------------------------------------*/ void send_handler(struct event_control *lecb) { extern fd_set *rdfds, *wrfds; const struct event *evt = 0; int rc = 0; int event_processed = 1; int save_errno = 0; int sd; struct info *ip; int called_explicitly = 0; int events; int evt_count; int fake_events = 0; int trace_fd = 0; static int init_done = 0; int i; int buf_index = -1; int listen_sd = -1; if (!init_done) { for (i = 0; i < EVT_BUFS_MAX; i++) { saved_tail[i] = -1; } init_done = 1; } if (options.send_loop) { should_process_sds = 1; } else { should_process_sds = 0; } consecutive = 0; send_handler_evts_done = 0; in_handler = 1; /* turn off notification while processing the event */ ecb->notify = SIG_GRP; if (lecb == NULL) { called_explicitly = 1; PRINT_TIME(NOFD, &tnow, &tprev, "---> send_handler: entered handler explicitly"); lecb = ecb; DEBG(MSG_SEND, "send_handler: lecb was NULL\n"); DEBG(MSG_SEND, "send_handler: lecb now = %p\n", lecb); DEBG(MSG_SEND, "send_handler: lecb->regs = %p\n", lecb->regs); for (i = 0; i < EVT_BUFS; i++) { DEBG(MSG_SEND, "send_handler: lecb->head[%d] = %d lecb->tail[%d] = %d\n", i, lecb->head[i], i, lecb->tail[i]); } t = bogus_regs; num_send_handler_calls++; } else { PRINT_TIME(NOFD, &tnow, &tprev, "---> send_handler: entered thru interrupt"); for (i = 0; i < EVT_BUFS; i++) { DEBG(MSG_SEND, "send_handler: lecb->head[%d] = %d lecb->tail[%d] = %d\n", i, lecb->head[i], i, lecb->tail[i]); } DEBG(MSG_SEND, "send_handler: lecb->regs = %p\n", lecb->regs); num_send_handler_interrupts++; t = lecb->regs; } /* Changed to permit calling handler explicitly */ DEBG(MSG_SEND, "send_handler: setting lecb->regs = 0xffffffff\n"); lecb->regs = (void *) 0xffffffff; save_errno = errno; if (t != bogus_regs && t != 0) { if (t->reason > 0 && t->eax < 0) { DEBG(MSG_SEND, "send_handler: syscall failure: reason = %i\n", t->reason); dump_regs(t); dump_stack(t); } send_errno = (int) t->eax; } else { send_errno = 0; } DEBG(MSG_SEND, "send_handler: send_errno = %d\n", send_errno); /* either entering a critical section or in one so we just leave handler */ if ((entering_cs || in_cs) && (!called_explicitly)) { PRINT_TIME(NOFD, &tnow, &tprev, "<--- send_handler: race detected\n"); num_sigio_races++; send_intrs_to_handle++; goto get_out; } if ((!new_connections_on || sigio_blocked) && (!called_explicitly)) { PRINT_TIME(NOFD, &tnow, &tprev, "<--- send_handler: race detected - new connections not on\n"); num_sigio_false++; send_intrs_to_handle++; goto get_out; } if (num_idle <= options.free_fd_thold) { DEBG(MSG_SEND, "WARNING! send_handler: entered num_idle = %d and " "thold = %d\n", num_idle, options.free_fd_thold); } for (i = 0; i < EVT_BUFS_MAX; i++) { saved_tail[i] = lecb->tail[i]; } consecutive = 0; while (!(bufs_empty())) { /* decide which of the event buffers to process */ buf_index = which_buf_to_process(buf_index); while ((!buf_is_empty(buf_index)) && (event_processed)) { PRINT_TIME(NOFD, &tnow, &tprev, "send_handler: at top of loop"); event_processed = 0; conns_off_if_needed(); evt_count = num_evts_array(); PRINT_TIME(NOFD, &tnow, &tprev, "send_handler: evt_count = %d", evt_count); for (i = 0; i < EVT_BUFS; i++) { PRINT_TIME(NOFD, &tnow, &tprev, "send_handler: head[%d] = %d tail[%d] = %d", i, lecb->head[i], i, lecb->tail[i]); } PRINT_TIME(NOFD, &tnow, &tprev, "send_handler: missed = %d", ecb->missed_events); #ifdef ONE_LISTENER #ifdef TBB_KINFO if (kinfo) { PRINT_TIME(NOFD, &tnow, &tprev, "send_handler: " "kinfo->qlen_young = %d kinfo->qlen = %d", kinfo->qlen_young, kinfo->qlen); PRINT_TIME(NOFD, &tnow, &tprev, "send_handler: syscall " "qlen_young = %d qlen = %d", qlen_young(server_sd), qlen(server_sd)); PRINT_TIME(NOFD, &tnow, &tprev, "send_handler: qlen_listenq = %d", qlen_listenq(server_sd)); } #endif /* TBB_KINFO */ #endif /* ONE_LISTENER */ evt = get_next_event(lecb, &buf_index); #ifdef DEBUG_ON verify_evt_array(evt, buf_index); #endif if ((MSG_MASK & MSG_TIME) || (MSG_MASK & MSG_SEND)) { print_event(evt, t); } #ifdef ARRAY_OF_BUFS num_events[buf_index]++; #else num_events++; #endif /* ARRAY_OF_BUFS */ switch (evt->type) { case EVT_SIG: /* XXX: for now - turn off notification and delivery */ /* because we are just going to print out some stats and exit */ ecb->notify = 0; ecb->queue = 0; num_evt_sig++; event_processed = 1; PRINT_TIME(NOFD, &tnow, &tprev, "send_handler: Processing EVT_SIG"); DEBG(MSG_SEND, "send_handler: Processing EVT_SIG\n"); DEBG(MSG_SEND, "send_handler: Received event: type = %d " "id = %d\n", evt->type, evt->event_id); if (t != bogus_regs) { PRINT_TIME(NOFD, &tnow, &tprev, "send_handler: eip = %p", t->eip); DEBG(MSG_SEND, "send_handler: Received event: eip = %p\n", t->eip); } if (sigs[evt->event_id] && sigs[evt->event_id] != (sighandlerfn_t) (-1)) { PRINT_TIME(NOFD, &tnow, &tprev, "send_handler: signal = %d calling handler", evt->event_id); sigs[evt->event_id] (0, evt); } else if (sigs[evt->event_id] != (sighandlerfn_t) (-1)) { DEBG(MSG_SEND, "send_handler: No handler for %i\n", evt->event_id); printf("send_handler: No handler for %i\n", evt->event_id); fflush(stdout); event_processed = 1; if (t) { dump_regs(t); } print_event(evt, t); exit(1); } else { printf("send_handler: evt->event_id = %d " "sigs[evt->event_id] = %p\n", evt->event_id, sigs[evt->event_id]); fflush(stdout); /* event_processed = 1; */ if (t) { dump_regs(t); } print_event(evt, t); exit(1); } break; case EVT_MSG: num_evt_msg++; DEBG(MSG_SEND, "send_handler: Processing message from: %i\n", evt->event_id); /* * A previous read call failed (EAGAIN) even though the event * was generated saying that the socket was ready. * So for now this is a work around where we've been * sent a message saying that we need to re-read * from the socket indicated in the msg. */ if ((int) evt->data.msg.data > 0) { sd = (int) evt->data.msg.data; ip = info_ptr(sd); assert(ip); fake_events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLREADRETRY; rc = send_do_io(sd, ip, fake_events); } event_processed = 1; break; case EVT_IPACCEPT: num_evt_ipaccept++; /* TODO: not sure this is in the right place? */ PRINT_TIME(NOFD, &tnow, &tprev, "send_handler: consecutive = %d num_idle = %d", consecutive, num_idle); sd = evt->data.ipa.fd; num_accept_calls++; PRINT_TIME(NOFD, &tnow, &tprev, "send_handler: Processing EVT_IPACCEPT sd = %d", sd); if (sd < 0) { /* In this case the sd contains the negated errno */ process_accept_errs(sd, -sd); event_processed = 1; } else { events = evt->data.io.events; if (events & POLLFIN) { /* * We are going to bypass doing a bunch of work * on a socket that has already been closed by * the client. So first we have to do a bit of * setup that subsequent code depends on (preconditions) */ ip = info_add(sd); ip->sd = sd; set_fsm_state(ip, FSM_CONNECTING); num_connections++; num_accept_successful++; num_idle--; if (num_idle == options.free_fd_thold) { PRINT_TIME(sd, &tnow, &tprev, "send_handler: ATTENTION: NUM_IDLE == %d", options.free_fd_thold); } PRINT_TIME(sd, &tnow, &tprev, "send_handler: POLL_FIN " "calling do_close"); num_close_send_early_fin++; rc = do_close(ip, REASON_SEND_POLL_FIN); event_processed = 1; } else { assert(sd <= max_fds); assert(sd > min_usable_sd); ip = info_add(sd); ip->sd = sd; set_fsm_state(ip, FSM_CONNECTING); /* Eventually we should add this to SEND */ /* listen_sd = evt->data.ipa.parent_fd; */ listen_sd = SOCK_LISTENER_USE_UNKNOWN; event_processed = send_handle_new_conn(evt, listen_sd, sd, should_process_sds); #ifdef NOT_SURE if ((options.do_multiaccept == 0 && consecutive == 1) || ((options.multiaccept_max != OPT_MULTIACCEPT_MAX_UNLIMITED) && (consecutive >= options.multiaccept_max))) { PRINT_TIME(NOFD, &tnow, &tprev, "send_handler: reached max accepts"); socket_new_conn_off(); } #endif /* if the socket is has data to be read go ahead and * read it */ if (!options.accepts_only && should_process_sds) { if (event_processed && evt->data.io.events & POLLIN) { /* TODO: this may be wrong as the event has been * processed * event_processed = * send_do_io(sd, ip, evt->data.io.events); */ rc = send_do_io(sd, ip, evt->data.io.events); } } } /* else */ } /* else */ break; case EVT_IOREADY: num_evt_ioready++; /* TODO: not sure this is in the right place? */ PRINT_TIME(NOFD, &tnow, &tprev, "send_handler: consecutive = %d num_idle = %d", consecutive, num_idle); sd = evt->data.io.fd; events = evt->data.io.events; PRINT_TIME(sd, &tnow, &tprev, "send_handler: Processing EVT_IOREADY"); if (sd < 0) { PRINT_TIME(sd, &tnow, &tprev, "send_handler: Processing EVT_IOREADY"); printf("send_handler: got negative sd on EVT_IOREADY\n"); print_event(evt, t); event_processed = 1; } else if (sock_is_listener(sd)) { if (events & POLLIN) { listen_sd = sd; ip = info_add(sd); event_processed = send_handle_new_conn(evt, listen_sd, sd, should_process_sds); /* TODO: This is just to test if it changes anything */ /* send_async_setup(sd); */ } else { PRINT_TIME(sd, &tnow, &tprev, "send_handler: listener_sd EVT_IOREADY but POLLIN " "is not set events = 0x%x", events); /* is pollhint set and nothing else */ if ((events | POLLHINT) == POLLHINT) { PRINT_TIME(sd, &tnow, &tprev, "send_handler: listener_sd no POLLIN but POLLHINT"); num_pollhint_server_consumed++; } event_processed = 1; } } else { if (!options.accepts_only && should_process_sds) { ip = info_ptr(sd); assert(ip); event_processed = send_do_io(sd, ip, events); if (!event_processed) { printf("send_handler: event not processed\n"); print_event(evt, t); exit(1); } } else { PRINT_TIME(sd, &tnow, &tprev, "send_handler: skipping events 0x%x", events); PRINT_TIME(sd, &tnow, &tprev, "send_handler: accepts_only = %d " "should_process_sds = %d", options.accepts_only, should_process_sds); event_processed = 1; } } if (!event_processed) { printf("send_handler: event not processed\n"); print_event(evt, t); exit(1); } break; case EVT_DISPATCH: num_evt_dispatch++; DEBG(MSG_SEND, "send_handler: Processing EVT_DISPATCH\n"); case EVT_SYNCH: num_evt_synch++; DEBG(MSG_SEND, "send_handler: Processing EVT_SYNCH\n"); default: num_evt_unknown++; PRINT_TIME(NOFD, &tnow, &tprev, "send_handler: doing event"); DEBG(MSG_SEND, "send_handler: lecb->head[%d] = %d " "lecb->tail[%d] = %d lecb->event_list_size[%d] = %d\n", buf_index, lecb->head[buf_index], buf_index, lecb->tail[buf_index], buf_index, lecb->event_list_size[buf_index]); DEBG(MSG_SEND, "send_handler: evt->type = %d\n", evt->type); DEBG(MSG_SEND, "send_handler: Fell down into default\n"); print_event(evt, t); exit(1); break; } /* switch */ /* NEW */ /* Did not process the event this time around */ /* so leave it in the buffer/queue to be processed later */ if (event_processed) { /* num_events++; */ send_handler_evts_done++; ++lecb->head[buf_index]; DEBG(MSG_SEND, "send_handler: event processed head for %d now = %d\n", buf_index, lecb->head[buf_index]); /* evt->type= (u32) - 1; */ send_need_to_check_events = 0; } else { DEBG(MSG_SEND, "send_handler: event not processed head for %d still = %d\n", buf_index, lecb->head[buf_index]); PRINT_TIME(NOFD, &tnow, &tprev, "send_handler: event not processed head for %d still = %d\n", buf_index, lecb->head[buf_index]); printf("send_handler: event not processed head for %d still = %d\n", buf_index, lecb->head[buf_index]); send_need_to_check_events = 1; printf("send_handler: if EVT_IPACCEPT fd = %d\n", evt->data.ipa.fd); printf("send_handler: if EVT_IOREADY fd = %d\n", evt->data.io.fd); printf("send_handler: calling exit\n"); print_event(evt, t); exit(1); } DEBG(MSG_SEND, "send_handler: send_need_to_check_events = %d\n", send_need_to_check_events); PRINT_TIME(NOFD, &tnow, &tprev, "send_handler: at bottom of loop buf_index = %d " "head = %d tail = %d", buf_index, ecb->head[buf_index], ecb->tail[buf_index]); } /* while */ } /* while */ if (consecutive > num_max_consecutive_accepts) { num_max_consecutive_accepts = consecutive; } get_out: if (consecutive > 0) { if (options.use_memcpy) { memcpy(readable, rdfds, sizeof(fd_set)); memcpy(writable, wrfds, sizeof(fd_set)); } else { *readable = *rdfds; *writable = *wrfds; } if (options.process_sds_order == OPT_PROCESS_SDS_LIFO) { q_sync(Q_ADD_TO_FRONT); } else if (options.process_sds_order == OPT_PROCESS_SDS_FIFO) { q_sync(Q_ADD_TO_REAR); } } /* Changed to allow handler to be called explicitly. */ lecb->regs = NULL; if (t != bogus_regs) { if (t->reason > 0 && t->eax < 0) { DEBG(MSG_SEND, "send_handler: Syscall failure: %i\n", t->reason); dump_regs(t); dump_stack(t); exit(1); } send_errno = (int) t->eax; } else { send_errno = 0; } /* DEBG(MSG_SEND, "send_handler: About to do restore\n"); */ DEBG(MSG_SEND, "send_handler: send_errno = %d\n", send_errno); DEBG(MSG_SEND, "send_handler: save_errno = %d\n", save_errno); DEBG(MSG_SEND, "send_handler: send_need_to_check_events = %d\n", send_need_to_check_events); PRINT_TIME(NOFD, &tnow, &tprev, "send_handler: consecutive = %d evts_done = %d", consecutive, send_handler_evts_done); /* This was used for debugging */ /* memcpy(&old_regs, t, sizeof(old_regs)); */ /* old_regs_addr = t; */ errno = save_errno; if (t != bogus_regs) { PRINT_TIME(NOFD, &tnow, &tprev, "restore_thread: eip = %p", t->eip); PRINT_TIME(NOFD, &tnow, &tprev, "restore_thread: flags = %p", t->flags); TRACE(EVT_SENDHANDLER, trace_fd = 0; rc = send_handler_evts_done;);