示例#1
0
文件: fq_utils.c 项目: denji/fq
/*
 * return 0: keep going (to write path)
 * return -1: busted
 */
int
fq_buffered_msg_read(buffered_msg_reader *f,
                     void (*f_msg_handler)(void *, fq_msg *),
                     void *closure) {
  int rv;
  if(f->into_body < f->msg.payload_len) {
    assert(f->copy);
    /* we need to be reading a largish payload */
    while((rv = read(f->fd, f->copy->payload + f->into_body,
                     f->copy->payload_len - f->into_body)) == -1 && errno == EINTR);
    if(rv < 0 && errno == EAGAIN) return 0;
    if(rv <= 0) {
      fq_debug(FQ_DEBUG_IO, "read error: %s\n", rv < 0 ? strerror(errno) : "end-of-line");
      return -1;
    }
    fq_debug(FQ_DEBUG_MSG, "%p <-- %d bytes for payload\n", (void *)f, rv);
    f->into_body += rv;
    if(f->into_body == f->copy->payload_len) {
      f->into_body = 0;
      goto message_done;
    }
  }
  while((rv = read(f->fd, f->scratch+f->nread, sizeof(f->scratch)-f->nread)) == -1 &&
        errno == EINTR);
  fq_debug(FQ_DEBUG_IO, "%p <-- %d bytes @ %d (%d)\n", (void *)f, rv, (int)f->nread,
          (int)f->nread + (rv > 0) ? rv : 0);
  if(rv == -1 && errno == EAGAIN) return 0;
  if(rv <= 0) return -1;
  f->nread += rv;

  while(f->nread>0) {
    uint32_t body_available;
    int body_start;
    body_start = parse_message_headers(f->peermode,
                                       f->scratch+f->off, f->nread-f->off,
                                       &f->msg);
    f->into_body = 0;
    fq_debug(FQ_DEBUG_MSG, "%d = parse(+%d, %d) -> %d\n",
            body_start, f->off, (int)f->nread-f->off,
            body_start ? (int)f->msg.payload_len : 0);
    if(body_start < 0) return -1;
    if(!body_start) {
      fq_debug(FQ_DEBUG_MSG, "incomplete message header...\n");
      memmove(f->scratch, f->scratch + f->off, f->nread - f->off);
      f->nread -= f->off;
      f->off = 0;
      return 0;
    }

    /* We have a message... or the formal beginnings of one */
    f->copy = fq_msg_alloc_BLANK(f->msg.payload_len);
    memcpy(f->copy, &f->msg, sizeof(f->msg));

    f->off += body_start;
    body_available = f->nread - f->off;
    if(f->copy->payload_len < body_available) body_available = f->copy->payload_len;
    memcpy(f->copy->payload, f->scratch+f->off, body_available);
    if(body_available == f->copy->payload_len) {
      f->off += body_available;
     message_done:
      f->copy->refcnt = 1;
      fq_debug(FQ_DEBUG_MSG, "message read... injecting\n");
      f_msg_handler(closure, f->copy);
      f->copy = NULL;
      memset(&f->msg, 0, sizeof(f->msg));
    }
    else {
      f->nread = 0;
      f->off = 0;
      f->into_body = body_available;
      fq_debug(FQ_DEBUG_MSG, "incomplete message... (%d needed)\n",
             (int)f->msg.payload_len - (int)f->into_body);
      return 0;
    }
  }
  return 0;
}
示例#2
0
/*
 * return 0: keep going (to write path)
 * return -1: busted
 * 
 * Read into one of N buffers so the processing thread 
 * can do the work separate from the read
 */
int
fq_buffered_msg_read(buffered_msg_reader *f,
                     void (*f_msg_handler)(void *, fq_msg *),
                     void *closure) {
  int rv;
  static char scratch_buf[IN_READ_BUFFER_SIZE];
  while(f->into_body < f->msg->payload_len) {
    fq_assert(f->copy);
    /* we need to be reading a largish payload */
    if(f->into_body >= MAX_MESSAGE_SIZE) {
      /* read into a scratch buffer */
      size_t readsize = f->copy->payload_len - f->into_body;
      if(readsize > sizeof(scratch_buf)) readsize = sizeof(scratch_buf);
      while((rv = read(f->fd, scratch_buf, readsize)) == -1 && errno == EINTR);
    }
    else {
      while((rv = read(f->fd, f->copy->payload + f->into_body,
                       CAPPED(f->copy->payload_len) - f->into_body)) == -1 && errno == EINTR);
    }
    if(rv < 0 && errno == EAGAIN) return 0;
    if(rv <= 0) {
      fq_debug(FQ_DEBUG_IO, "read error: %s\n", rv < 0 ? strerror(errno) : "end-of-line");
      return -1;
    }
    fq_debug(FQ_DEBUG_MSG, "%p <-- %d bytes for payload\n", (void *)f, rv);
    f->into_body += rv;
    if(f->into_body == f->copy->payload_len) {
      f->into_body = 0;
      goto message_done;
    }
  }
  while((rv = read(f->fd, f->scratch+f->nread, sizeof(f->scratch)-f->nread)) == -1 &&
        errno == EINTR);
  fq_debug(FQ_DEBUG_IO, "%p <-- %d bytes @ %d (%d)\n", (void *)f, rv, (int)f->nread,
          (int)f->nread + ((rv > 0) ? rv : 0));
  if(rv == -1 && errno == EAGAIN) return 0;
  if(rv <= 0) return -1;
  f->nread += rv;

  while(f->nread>0) {
    uint32_t body_available;
    int body_start;
    body_start = parse_message_headers(f->peermode,
                                       f->scratch+f->off, f->nread-f->off,
                                       f->msg);
    f->into_body = 0;
    fq_debug(FQ_DEBUG_MSG, "%d = parse(+%d, %d) -> %d\n",
            body_start, f->off, (int)f->nread-f->off,
            body_start ? (int)f->msg->payload_len : 0);
    if(body_start < 0) return -1;
    if(!body_start) {
      fq_debug(FQ_DEBUG_MSG, "incomplete message header...\n");
      memmove(f->scratch, f->scratch + f->off, f->nread - f->off);
      f->nread -= f->off;
      f->off = 0;
      return 0;
    }

    free_message_stack *tls_free_message_stack = NULL;
    int msg_stack_idx = msg_free_stack_select(f->msg->payload_len);
    if(msg_stack_idx >= 0) {
      if(tls_free_message_handle == NULL)
        tls_free_message_handle = free_message_handle_acquire();
      if(tls_free_message_handle->stacks[msg_stack_idx] == NULL) {
        /* lazy create/init the cleanup stack */
        tls_free_message_handle->stacks[msg_stack_idx] = malloc(sizeof(free_message_stack));
        fq_init_free_message_stack(tls_free_message_handle->stacks[msg_stack_idx],
                                   FREE_MSG_LIST_SIZE/(1 << (msg_stack_idx + MSG_FREE_BASE)),
                                   (1 << (msg_stack_idx + MSG_FREE_BASE)));
      }
      tls_free_message_stack = tls_free_message_handle->stacks[msg_stack_idx];
    }

    if(tls_free_message_stack) {
      /* We have a message... or the formal beginnings of one */
      f->copy = fq_pop_free_message_stack(tls_free_message_stack);
      if (f->copy == NULL) {
        /* ran out of entries in free list */
        f->copy = fq_msg_alloc_BLANK(tls_free_message_stack->alloc_size);
        if (f->copy == NULL) {
          /* this is bad, we can't alloc */
          fq_debug(FQ_DEBUG_MSG, "unable to malloc, OOM?\n");
          return -1;
        }
      }

      /* always 1 as this msg only lives until it's copied by a worker thread */
      memcpy(f->copy, f->msg, sizeof(fq_msg));
      f->copy->refcnt = 1;
      f->copy->free_fn = fq_free_msg_fn;

    } else {
      f->copy = fq_msg_alloc_BLANK(CAPPED(f->msg->payload_len));
      if (f->copy == NULL) {
        /* this is bad, we can't alloc */
        fq_debug(FQ_DEBUG_MSG, "unable to malloc, OOM?\n");
        return -1;
      }

      memcpy(f->copy, f->msg, sizeof(fq_msg));
      f->copy->refcnt = 1;
      f->copy->free_fn = NULL;
    }

    /* assign the cleanup stack for this message */
    f->copy->cleanup_handle = tls_free_message_stack ? tls_free_message_handle : NULL;
    memset(&f->copy->cleanup_stack_entry, 0, sizeof(ck_stack_entry_t));

    f->off += body_start;
    body_available = f->nread - f->off;
    if(f->copy->payload_len < body_available) body_available = f->copy->payload_len;
    memcpy(f->copy->payload, f->scratch+f->off, CAPPED(body_available));
    if(body_available == f->copy->payload_len) {
      f->off += body_available;
     message_done:
      f->copy->refcnt = 1;
      f->copy->payload_len = CAPPED(f->copy->payload_len);
      fq_debug(FQ_DEBUG_MSG, "message read... injecting\n");
      f->copy->arrival_time = fq_gethrtime();
      f_msg_handler(closure, f->copy);
      f->copy = NULL;
      memset(f->msg, 0, sizeof(fq_msg));
      /* It is still allocated and we are the sole owner, refcnt must be 1 */
      f->msg->refcnt = 1;
    }
    else {
      f->nread = 0;
      f->off = 0;
      f->into_body = body_available;
      fq_debug(FQ_DEBUG_MSG, "incomplete message... (%d needed)\n",
             (int)f->msg->payload_len - (int)f->into_body);
      return 0;
    }
  }
  return 0;
}