void bufferevent_read_pressure_cb(struct evbuffer *buf, size_t old, size_t now, void *arg) { struct bufferevent *bufev = arg; if (bufev->wm_read.high == 0 || now < bufev->wm_read.high) { evbuffer_setcb(buf, NULL, NULL); if (bufev->enabled & EV_READ) bufferevent_add(&bufev->ev_read, bufev->timeout_read); } }
static void bufferevent_readcb(int fd, short event, void *arg) { struct bufferevent *bufev = arg; int res = 0; short what = OPAL_EVBUFFER_READ; size_t len; if (event == OPAL_EV_TIMEOUT) { what |= OPAL_EVBUFFER_TIMEOUT; goto error; } res = evbuffer_read(bufev->input, fd, -1); if (res == -1) { if (errno == EAGAIN || errno == EINTR) goto reschedule; /* error case */ what |= OPAL_EVBUFFER_ERROR; } else if (res == 0) { /* eof case */ what |= OPAL_EVBUFFER_EOF; } if (res <= 0) goto error; bufferevent_add(&bufev->ev_read, bufev->timeout_read); /* See if this callbacks meets the water marks */ len = OPAL_EVBUFFER_LENGTH(bufev->input); if (bufev->wm_read.low != 0 && len < bufev->wm_read.low) return; if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) { struct evbuffer *buf = bufev->input; opal_event_del(&bufev->ev_read); /* Now schedule a callback for us */ evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev); return; } /* Invoke the user callback - must always be called last */ (*bufev->readcb)(bufev, bufev->cbarg); return; reschedule: bufferevent_add(&bufev->ev_read, bufev->timeout_read); return; error: (*bufev->errorcb)(bufev, what, bufev->cbarg); }
void bufferevent_read_pressure_cb(struct evbuffer *buf, size_t old, size_t now, void *arg) { struct bufferevent *bufev = arg; /* * If we are below the watermark then reschedule reading if it's * still enabled. */ if (bufev->wm_read.high == 0 || now < bufev->wm_read.high) { evbuffer_setcb(buf, NULL, NULL); if (bufev->enabled & EV_READ) bufferevent_add(&bufev->ev_read, bufev->timeout_read); } }
static void buffertls_readcb(int fd, short event, void *arg) { struct buffertls *buftls = arg; struct bufferevent *bufev = buftls->bt_bufev; struct tls *ctx = buftls->bt_ctx; int res = 0; short what = EVBUFFER_READ; size_t len; int howmuch = -1; if (event == EV_TIMEOUT) { what |= EVBUFFER_TIMEOUT; goto error; } /* * If we have a high watermark configured then we don't want to * read more data than would make us reach the watermark. */ if (bufev->wm_read.high != 0) { howmuch = bufev->wm_read.high - EVBUFFER_LENGTH(bufev->input); /* we might have lowered the watermark, stop reading */ if (howmuch <= 0) { struct evbuffer *buf = bufev->input; event_del(&bufev->ev_read); evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev); return; } } res = evtls_read(bufev->input, fd, howmuch, ctx); switch (res) { case TLS_WANT_POLLIN: bufferevent_add(&bufev->ev_read, bufev->timeout_read); return; case TLS_WANT_POLLOUT: event_del(&bufev->ev_write); event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_readcb, buftls); bufferevent_add(&bufev->ev_write, bufev->timeout_write); return; case -1: what |= EVBUFFER_ERROR; break; case 0: what |= EVBUFFER_EOF; break; } if (res <= 0) goto error; event_del(&bufev->ev_write); event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_writecb, buftls); if (bufev->enabled & EV_READ) bufferevent_add(&bufev->ev_read, bufev->timeout_read); if (EVBUFFER_LENGTH(bufev->output) != 0 && bufev->enabled & EV_WRITE) bufferevent_add(&bufev->ev_write, bufev->timeout_write); /* See if this callbacks meets the water marks */ len = EVBUFFER_LENGTH(bufev->input); if (bufev->wm_read.low != 0 && len < bufev->wm_read.low) return; if (bufev->wm_read.high != 0 && len >= bufev->wm_read.high) { struct evbuffer *buf = bufev->input; event_del(&bufev->ev_read); /* Now schedule a callback for us when the buffer changes */ evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev); } /* Invoke the user callback - must always be called last */ if (bufev->readcb != NULL) (*bufev->readcb)(bufev, bufev->cbarg); return; error: (*bufev->errorcb)(bufev, what, bufev->cbarg); }
static void bufferevent_readcb(int fd, short event, void *arg) { struct bufferevent *bufev = arg; int res = 0; short what = EVBUFFER_READ; size_t len; int howmuch = -1; if (event == EV_TIMEOUT) { what |= EVBUFFER_TIMEOUT; goto error; } /* * If we have a high watermark configured then we don't want to * read more data than would make us reach the watermark. */ if (bufev->wm_read.high != 0) { howmuch = bufev->wm_read.high - EVBUFFER_LENGTH(bufev->input); /* we might have lowered the watermark, stop reading */ if (howmuch <= 0) { struct evbuffer *buf = bufev->input; event_del(&bufev->ev_read); evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev); return; } } res = evbuffer_read(bufev->input, fd, howmuch); if (res == -1) { if (errno == EAGAIN || errno == EINTR) goto reschedule; /* error case */ what |= EVBUFFER_ERROR; } else if (res == 0) { /* eof case */ what |= EVBUFFER_EOF; } if (res <= 0) goto error; bufferevent_add(&bufev->ev_read, bufev->timeout_read); /* See if this callbacks meets the water marks */ len = EVBUFFER_LENGTH(bufev->input); if (bufev->wm_read.low != 0 && len < bufev->wm_read.low) return; if (bufev->wm_read.high != 0 && len >= bufev->wm_read.high) { struct evbuffer *buf = bufev->input; event_del(&bufev->ev_read); /* Now schedule a callback for us when the buffer changes */ evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev); } /* Invoke the user callback - must always be called last */ if (bufev->readcb != NULL) (*bufev->readcb)(bufev, bufev->cbarg); return; reschedule: bufferevent_add(&bufev->ev_read, bufev->timeout_read); return; error: (*bufev->errorcb)(bufev, what, bufev->cbarg); }
static void bufferevent_readcb(int fd, short event, void *arg) { struct bufferevent *bufev = arg; int res = 0; short what = EVBUFFER_READ; size_t len; int howmuch = -1; if (event == EV_TIMEOUT) { what |= EVBUFFER_TIMEOUT; goto error; } if (bufev->wm_read.high != 0) { howmuch = bufev->wm_read.high - EVBUFFER_LENGTH(bufev->input); if (howmuch <= 0) { struct evbuffer *buf = bufev->input; event_del(&bufev->ev_read); evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev); return; } } res = evbuffer_read(bufev->input, fd, howmuch); if (res == -1) { if (errno == EAGAIN || errno == EINTR) goto reschedule; what |= EVBUFFER_ERROR; } else if (res == 0) { what |= EVBUFFER_EOF; } if (res <= 0) goto error; bufferevent_add(&bufev->ev_read, bufev->timeout_read); len = EVBUFFER_LENGTH(bufev->input); if (bufev->wm_read.low != 0 && len < bufev->wm_read.low) return; if (bufev->wm_read.high != 0 && len >= bufev->wm_read.high) { struct evbuffer *buf = bufev->input; event_del(&bufev->ev_read); evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev); } if (bufev->readcb != NULL) (*bufev->readcb)(bufev, bufev->cbarg); return; reschedule: bufferevent_add(&bufev->ev_read, bufev->timeout_read); return; error: (*bufev->errorcb)(bufev, what, bufev->cbarg); }
/* * zark: 当epoll层的读事件到来, 会从活跃队列中回调该函数, * 开始从socket中读取数据. */ static void bufferevent_readcb(int fd, short event, void *arg) { struct bufferevent *bufev = arg; int res = 0; short what = EVBUFFER_READ; size_t len; int howmuch = -1; //! zark: bufferevent是对I/O操作的封装, 所以不监听超时事件. if (event == EV_TIMEOUT) { what |= EVBUFFER_TIMEOUT; goto error; } /* * If we have a high watermark configured then we don't want to * read more data than would make us reach the watermark. * * zark: 这里有必要普及一下libevent关于输入输出时的水位概念. * 读取低水位 - 读取操作使得输入缓冲区的数据量在此级别或者更高时, * 读取回调将被调用.默认值为0, 所以每个读取操作都会 * 导致读取回调被调用. * 读取高水位 - 输入缓冲区中的数据量达到此级别后,bufferevent将停 * 止读取,直到输入缓冲区中足够量的数据被抽取,使得数 * 据量低于此级别.默认值是无限, 所以永远不会因为输入 * 缓冲区的大小而停止读取. * 写入低水位 - 写入操作使得输出缓冲区的数据量达到或者低于此级别时, * 写入回调将被调用.默认值是0, 所以只有输出缓冲区空的 * 时候才会调用写入回调. * 写入高水位 - bufferevent没有直接使用这个水位. 它在bufferevent用 * 作另外一个bufferevent的底层传输端口时有特殊意义.请 * 看后面关于过滤型bufferevent的介绍. */ //! zark: 读取高水位到达, 停止读取. if (bufev->wm_read.high != 0) { howmuch = bufev->wm_read.high - EVBUFFER_LENGTH(bufev->input); /* we might have lowered the watermark, stop reading */ if (howmuch <= 0) { struct evbuffer *buf = bufev->input; event_del(&bufev->ev_read); //! 删除当前读事件. /* * zark: 设置一个新的读事件, 该读事件的callback函 * 数(即bufferevent_read_pressure_cb)会检测 * 当输入冲区大小小于高水位时, 会再次添加正 * 常的读取event. */ evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev); return; } } /* * zark: 开始从fd读取数据到我们的输入缓冲区中. */ res = evbuffer_read(bufev->input, fd, howmuch); if (res == -1) { if (errno == EAGAIN || errno == EINTR) goto reschedule; /* error case */ what |= EVBUFFER_ERROR; } else if (res == 0) { /* eof case */ what |= EVBUFFER_EOF; } if (res <= 0) goto error; /* * zark: 因为bufferevent当初添加事件的时候没有使用 * persist来修饰event, 所以需要重新添加. */ bufferevent_add(&bufev->ev_read, bufev->timeout_read); /* See if this callbacks meets the water marks */ len = EVBUFFER_LENGTH(bufev->input); /* * zark: 读取低水位线没有达到, 所以不能调用callback, 直接return~ */ if (bufev->wm_read.low != 0 && len < bufev->wm_read.low) return; /* * zark: 读取高水位到达, 停止读取. */ if (bufev->wm_read.high != 0 && len >= bufev->wm_read.high) { struct evbuffer *buf = bufev->input; event_del(&bufev->ev_read); /* Now schedule a callback for us when the buffer changes */ evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev); } /* Invoke the user callback - must always be called last */ /* * zark: 哈哈, 一顿乱七八糟的check下来, 终于到了调用我们 * 真正注册的读取回调函数拉~ 散花~ */ if (bufev->readcb != NULL) (*bufev->readcb)(bufev, bufev->cbarg); return; reschedule: bufferevent_add(&bufev->ev_read, bufev->timeout_read); return; /* * zark: 调用我们注册的错误处理回调函数. */ error: (*bufev->errorcb)(bufev, what, bufev->cbarg); }