今回はKVSからのレスポンスをウェブアプリケーションに書き出す部分。「その5」で見たna_client_callbackの残り半分を読んでいく。
static void na_client_callback(EV_P_ struct ev_io *w, int revents)
{
int cfd, tsfd, size;
na_client_t *client;
na_env_t *env;
cfd = w->fd;
client = (na_client_t *)w->data;
env = client->env;
tsfd = client->tsfd;
pthread_rwlock_rdlock(&env->lock_refused);
if ((client->is_refused_active != env->is_refused_active) || env->is_refused_accept) {
pthread_rwlock_unlock(&env->lock_refused);
NA_EVENT_FAIL(NA_ERROR_INVALID_CONNPOOL, EV_A, w, client, env);
return; // request fail
}
pthread_rwlock_unlock(&env->lock_refused);
if (env->loop_max > 0 && client->loop_cnt++ > env->loop_max) {
NA_EVENT_FAIL(NA_ERROR_OUTOF_LOOP, EV_A, w, client, env);
return; // request fail
}
if (revents & EV_READ) {
..
} else if (revents & EV_WRITE) {
ここまではいつもどおり。
size = write(cfd,
client->srbuf + client->cwbufsize,
client->srbufsize - client->cwbufsize);
if (size < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
return; // not ready yet
}
if (errno == EPIPE) {
NA_EVENT_FAIL(NA_ERROR_BROKEN_PIPE, EV_A, w, client, env);
} else {
NA_EVENT_FAIL(NA_ERROR_FAILED_WRITE, EV_A, w, client, env);
}
return; // request fail
}
client->cwbufsize += size;
ここも特におかしいところはない。
- srbuf: レスポンスバッファーの先頭を指すポインター
- srbufsize: レスポンスバッファーのうち実際に使われているバイト数
- cwbufsize: レスポンスバッファーのうち書き出しが終わったバイト数
if (client->cwbufsize < client->srbufsize) {
na_event_switch(EV_A_ w, &client->c_watcher, cfd, EV_WRITE);
return;
} else {
client->crbufsize = 0;
client->cwbufsize = 0;
client->srbufsize = 0;
client->swbufsize = 0;
client->request_bufsize = env->request_bufsize;
client->response_bufsize = env->response_bufsize;
client->event_state = NA_EVENT_STATE_CLIENT_READ;
client->req_cnt = 0;
client->res_cnt = 0;
na_event_switch(EV_A_ w, &client->c_watcher, cfd, EV_READ);
return;
}
}
}
最後に書き出し完了していたらclientを初期化して、na_event_switchでまたREADフェーズに入っている。動的に確保したバッファーも解放したりはしてない。
ここまででneoagentの挙動は理解できた。コネクションプールとかクライアントプールっていったい何なの?とかソケットの扱いとか色々あるけど、とりあえず1人読書会はここまでにしておく。