static void empty_queue (rr_dev dev, int prio) { while (dev->sendhead[prio]) { blocknode *node = rr_dev_pop_from_queue (dev, prio); blocknode_free (node); } assert (dev->sendhead[prio] == NULL); assert (dev->sendtail[prio] == NULL); dev->sendsize[prio] = 0; }
void empty_buffers(rr_dev device) { unsigned i; for(i = 0; i < RR_PRIO_COUNT; ++i) { blocknode *j = device->sendhead[i]; while(j != NULL) { blocknode *next = j->next; free(j); j = next; } device->sendhead[i] = NULL; } for(i = 0; i < device->sentcachesize; ++i) { if(device->sentcache[i]) { blocknode_free(device->sentcache[i]); device->sentcache[i] = NULL; } } }
/* free extra elements at the end of the sentcache */ static void shrink_sentcache (rr_dev dev) { int i; blocknode *next, *l = dev->sendhead[RR_PRIO_SENTCACHE]; for (i = 0; i < dev->sentcachesize; i++) l = l ? l->next : NULL; if (!l) return; dev->sendtail[RR_PRIO_SENTCACHE] = l; next = l->next; l->next = NULL; for (l = next; l; l = next) { next = l->next; blocknode_free (l); dev->sendsize[RR_PRIO_SENTCACHE]--; } }
int rr_handle_writable(rr_dev device) { ssize_t result; if(device->sendbuf_fill == 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) { node = device->sendhead[prio]; if(node) { /* We have a block to send! Get it ready. */ device->bytes_sent = 0; result = fmtblock(device, node); if(result < 0) { /* FIXME: This will confuse code expecting errno to be set */ return result; } device->sendbuf_fill = result; device->sending_prio = prio; break; } } if(!node) { /* No data to write */ device->want_writable(device, device->ww_data, 0); return 0; } } /* Perform write */ do { result = write(device->fd, device->sendbuf + device->bytes_sent, device->sendbuf_fill - device->bytes_sent); } while(result < 0 && errno == EINTR); if(result < 0) { return result; } device->bytes_sent += result; if(device->bytes_sent == device->sendbuf_fill) { /* We've sent the complete block. */ blocknode *node = device->sendhead[device->sending_prio]; if(device->onsend) { device->onsend(device, device->onsend_data, node->cbdata, device->sendbuf, device->sendbuf_fill); } device->sendhead[device->sending_prio] = node->next; node->line = device->lineno; ++(device->lineno); /* Update sent cache */ if(device->sentcache[device->sentcachesize - 1]) { blocknode_free(device->sentcache[device->sentcachesize - 1]); } ssize_t i; for(i = device->sentcachesize - 1; i > 0 ; --i) { device->sentcache[i] = device->sentcache[i-1]; } device->sentcache[0] = node; /* Indicate that we're ready for the next. */ device->sendbuf_fill = 0; } return result; }