static int handle_reply (rr_dev dev, const char *reply, size_t nbytes, size_t term_bytes) { if (dev->opt_log_cb) dev->opt_log_cb (dev, RR_LOG_RECV, reply, nbytes + term_bytes, dev->opt_log_cl); switch(dev->proto) { case RR_PROTO_FIVED: return fived_handle_reply (dev, reply, nbytes); case RR_PROTO_TONOKIP: return tonokip_handle_reply (dev, reply, nbytes); case RR_PROTO_SIMPLE: if (!strncasecmp ("ok", reply, 2) && dev->reply_cb) { rr_dev_handle_ok (dev); dev->reply_cb (dev, RR_OK, 0.0, NULL, dev->reply_cl); } else if (dev->error_cb) dev->error_cb (dev, RR_E_UNKNOWN_REPLY, reply, nbytes, dev->error_cl); return 0; default: return RR_E_UNSUPPORTED_PROTO; } return 0; }
/* print to the log */ void rr_dev_log (rr_dev dev, int debug_level, const char *format, ...) { int len; va_list args; char buffer[4096]; if (debug_level > dev->debug_output) return; va_start (args, format); len = vsnprintf (buffer, 4095, format, args); access (buffer, 0); if (dev->opt_log_cb) dev->opt_log_cb (dev, RR_LOG_MSG, buffer, len, dev->opt_log_cl); va_end (args); }
int rr_dev_handle_writable (rr_dev dev) { ssize_t result; if (dev->sendbuf_fill == 0) { if (dev->init_send_count <= 0 && !dev->send_next) { rr_dev_log (dev, RR_DEBUG_MEDIUM, "writeable - init count is %d, no send_next queue %d resend %d\n", dev->init_send_count, dev->dev_cmdqueue_size, dev->sendsize[RR_PRIO_RESEND]); /* wait until there is space in the device buffer and/or an ok */ dev->wait_wr_cb (dev, 0, dev->wait_wr_cl); return 0; } /* Last block is gone; prepare to send a new block */ int prio; blocknode *node = NULL; for (prio = RR_PRIO_COUNT - 1; prio >= 0; --prio) { if (dev->paused[prio]) continue; node = dev->sendhead[prio]; if (node) { /* We have a block to send! Get it ready. */ dev->bytes_sent = 0; result = fmtblock (dev, node); if (result < 0) { /* FIXME: This will confuse code expecting errno to be set */ return result; } if (result == 0) rr_dev_log (dev, RR_DEBUG_ALWAYS, "unusual error - nothing in block to write\n"); dev->send_next = 0; dev->sendbuf_fill = result; dev->sending_prio = prio; break; } } if (!node) { /* No data to write */ dev->wait_wr_cb (dev, 0, dev->wait_wr_cl); return 0; } } /* Perform write */ do { result = write (dev->fd, dev->sendbuf + dev->bytes_sent, dev->sendbuf_fill - dev->bytes_sent); } while (result < 0 && errno == EINTR); if (result < 0) return result; if (dev->opt_log_cb) dev->opt_log_cb (dev, RR_LOG_SEND, dev->sendbuf + dev->bytes_sent, dev->sendbuf_fill - dev->bytes_sent, dev->opt_log_cl); dev->bytes_sent += result; if (dev->bytes_sent == dev->sendbuf_fill) { /* We've sent the complete block. */ blocknode *node = rr_dev_pop_from_queue (dev, dev->sending_prio); if (node->line < 0) { node->line = dev->lineno; ++(dev->lineno); } /* Update sent cache */ assert (node->block != NULL); rr_dev_prepend_to_queue (dev, RR_PRIO_SENTCACHE, node); if (dev->sendsize[RR_PRIO_SENTCACHE] > (dev->sentcachesize * 3 / 2)) shrink_sentcache (dev); /* Indicate that we're ready for the next. */ dev->sendbuf_fill = 0; } return result; }