Esempio n. 1
0
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());
}
Esempio n. 2
0
/* ---------------------------------------------------------------------- */
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;);