buffer_status_t buffer_write(struct buffer *b, int fd, const void *p, size_t size) { ssize_t nbytes; #if 0 /* Should we attempt to drain any previously buffered data? This could help reduce latency in pushing out the data if we are stuck in a long-running thread that is preventing the main select loop from calling the flush thread... */ if (b->head && (buffer_flush_available(b, fd) == BUFFER_ERROR)) return BUFFER_ERROR; #endif if (b->head) /* Buffer is not empty, so do not attempt to write the new data. */ nbytes = 0; else if ((nbytes = write(fd, p, size)) < 0) { if (ERRNO_IO_RETRY(errno)) nbytes = 0; else { zlog_warn("%s: write error on fd %d: %s", __func__, fd, safe_strerror(errno)); return BUFFER_ERROR; } } /* Add any remaining data to the buffer. */ { size_t written = nbytes; if (written < size) buffer_put(b, ((const char *)p)+written, size-written); } return b->head ? BUFFER_PENDING : BUFFER_EMPTY; }
static int svz_tunnel_flush_data(struct thread * thread) { struct tclient * tclient = THREAD_ARG(thread); tclient->t_write = NULL; if(tclient->sock < 0) return -1; switch (buffer_flush_available(tclient->wb, tclient->sock)) { case BUFFER_ERROR: zlog_warn("%s: buffer_flush_available failed on zclient fd %d, closing", __func__, tclient->sock); return svz_tunnel_failed(tclient); break; case BUFFER_PENDING: tclient->t_write = thread_add_write(master, svz_tunnel_flush_data, tclient, tclient->sock); break; case BUFFER_EMPTY: break; } return 0; }
static int zserv_flush_data(struct thread *thread) { struct zserv *client = THREAD_ARG(thread); client->t_write = NULL; if (client->t_suicide) { zebra_client_close(client); return -1; } switch (buffer_flush_available(client->wb, client->sock)) { case BUFFER_ERROR: zlog_warn("%s: buffer_flush_available failed on zserv client fd %d, " "closing", __func__, client->sock); zebra_client_close(client); break; case BUFFER_PENDING: client->t_write = thread_add_write(zebrad.master, zserv_flush_data, client, client->sock); break; case BUFFER_EMPTY: break; } return 0; }
buffer_status_t buffer_write(struct buffer *b, int fd, const void *p, size_t size) { ssize_t nbytes; char* tmpstr = "happy every day\n";/**add by gjd: used for debug**/ #if 0 /* Should we attempt to drain any previously buffered data? This could help reduce latency in pushing out the data if we are stuck in a long-running thread that is preventing the main select loop from calling the flush thread... */ if (b->head && (buffer_flush_available(b, fd) == BUFFER_ERROR)) return BUFFER_ERROR; #endif if (b->head) /* Buffer is not empty, so do not attempt to write the new data. */ nbytes = 0; // else if ((nbytes = write(fd, tmpstr, strlen(tmpstr))) < 0)/**add by gjd: used for debug**/ else if ((nbytes = write(fd, p, size)) < 0) { if (ERRNO_IO_RETRY(errno)) nbytes = 0; else { zlog_warn("%s: write error on fd %d: %s", __func__, fd, safe_strerror(errno)); return BUFFER_ERROR; } } #ifdef BUFFER_DEBUG/**add by gjd: used for debug**/ { int i; for(i=0;i<nbytes;i=i+1) { zlog_debug("**** %x \n",*((char *)p + i)); // zlog_debug("**** %x \n",*(tmpstr+i));/**add by gjd: used for debug**/ } } #endif /* Add any remaining data to the buffer. */ { #ifdef BUFFER_DEBUG zlog_debug("%s : line %d , nbytes = %d \n",__func__,__LINE__,nbytes); #endif size_t written = nbytes; if (written < size) buffer_put(b, ((const char *)p)+written, size-written); } return b->head ? BUFFER_PENDING : BUFFER_EMPTY; }
/* Keep flushing data to the fd until the buffer is empty or an error is encountered or the operation would block. */ buffer_status_t buffer_flush_all (struct buffer *b, int fd) { buffer_status_t ret; struct buffer_data *head; size_t head_sp; if (!b->head) return BUFFER_EMPTY; head_sp = (head = b->head)->sp; /* Flush all data. */ while ((ret = buffer_flush_available(b, fd)) == BUFFER_PENDING) { if ((b->head == head) && (head_sp == head->sp) && (errno != EINTR)) /* No data was flushed, so kernel buffer must be full. */ return ret; head_sp = (head = b->head)->sp; } return ret; }