--- a/memcache/connection.c Thu Aug 28 01:42:28 2008 +0300
+++ b/memcache/connection.c Thu Aug 28 03:12:11 2008 +0300
@@ -19,9 +19,10 @@
static void _memcache_conn_ev_read (evutil_socket_t fd, short event, void *arg);
static void memcache_conn_error (struct memcache_conn *conn);
-static void memcache_conn_req_error (struct memcache_conn *conn);
static void memcache_conn_req_done (struct memcache_conn *conn);
+void memcache_conn_close (struct memcache_conn *conn);
+
struct memcache_conn *memcache_conn_open (struct memcache_server *server) {
struct memcache_conn *conn = NULL;
@@ -83,31 +84,30 @@
assert(conn->fd > 0 && conn->is_connected);
assert(conn->req == NULL);
- // store the req
- conn->req = req;
-
// write the request header into our bufferevent's output buffer
if (memcache_cmd_format_header(bufferevent_get_output(conn->bev), req->cmd_type, &req->key, &req->obj)) {
- // just fail the request
- memcache_conn_req_error(conn);
-
ERROR("failed to init the cmd");
}
+ // store the req
+ conn->req = req;
+
// tell our bufferevent to send it
- if (bufferevent_enable(conn->bev, EV_WRITE)) {
- // fail the entire connection
- memcache_conn_error(conn);
-
+ if (bufferevent_enable(conn->bev, EV_WRITE))
PERROR("bufferevent_enable");
- }
// tell the req that it is underway
memcache_req_send(req);
+
+ // success
+ return;
error:
+ if (conn->req)
+ memcache_conn_error(conn);
- return;
+ else
+ memcache_req_error(req);
}
/*
@@ -122,6 +122,20 @@
}
/*
+ * Write out the final \r\n to terminate the request data
+ */
+void memcache_conn_finish_req_data (struct memcache_conn *conn) {
+ if (bufferevent_write(conn->bev, "\r\n", 2))
+ PERROR("bufferevent_write");
+
+ // ok
+ return;
+
+error:
+ memcache_conn_error(conn);
+}
+
+/*
* Start reading a reply from the connection
*/
void memcache_conn_handle_reply (struct memcache_conn *conn) {
@@ -139,7 +153,7 @@
return;
error:
- memcache_conn_req_error(conn);
+ memcache_conn_error(conn);
}
/*
@@ -210,7 +224,7 @@
return;
error:
- memcache_conn_req_error(conn);
+ memcache_conn_error(conn);
}
/*
@@ -258,7 +272,8 @@
assert(evbuffer_get_length(bufferevent_get_output(bev)) == 0);
// does this request have some data to be included in the request?
- if (conn->req->buf.data > 0) {
+ // if the data has already been sent (we handle the final \r\n as well), then skip this.
+ if (conn->req->have_buf && conn->req->buf.offset == 0) {
// we need to send the request data next
memcache_conn_send_req_data(conn);
@@ -322,7 +337,7 @@
// free the header data read from the buf
free(header_data);
- memcache_conn_req_error(conn);
+ memcache_conn_error(conn);
}
@@ -365,8 +380,8 @@
PERROR("event_add");
} else {
- // done! We can handle the reply now
- memcache_conn_handle_reply(conn);
+ // done! Send the terminating \r\n next
+ memcache_conn_finish_req_data(conn);
}
// success
@@ -428,35 +443,30 @@
memcache_conn_error(conn);
}
+// XXX: need to flush/disable buffers/events on errors
+
/*
* The entire connection failed
*/
static void memcache_conn_error (struct memcache_conn *conn) {
// fail the request, if we have one
- if (conn->req)
- memcache_conn_req_error(conn);
+ if (conn->req) {
+ // error out the req
+ memcache_req_error(conn->req);
+ assert(conn->req->conn == NULL);
+
+ // we are now available again
+ conn->req = NULL;
+ }
+
+ // close the connection
+ memcache_conn_close(conn);
// tell the server we failed
memcache_server_conn_dead(conn->server, conn);
}
/*
- * Request failed somehow
- */
-static void memcache_conn_req_error (struct memcache_conn *conn) {
- // ensure that we do currently have a req
- assert(conn->req);
-
- // error out the req
- memcache_req_error(conn->req);
- assert(conn->req->conn == NULL);
-
- // we are now available again
- conn->req = NULL;
-
-}
-
-/*
* Detach the request
*/
static void memcache_conn_req_done (struct memcache_conn *conn) {
@@ -469,15 +479,11 @@
// we are now available again
conn->req = NULL;
+
+ memcache_server_conn_ready(conn->server, conn);
}
-void memcache_conn_free (struct memcache_conn *conn) {
- // ensure we don't have a req bound to us
- assert(conn->req == NULL);
-
- // ensure that the connection is not considered to be connected anymore
- assert(!conn->is_connected);
-
+void memcache_conn_close (struct memcache_conn *conn) {
// close the fd if needed
if (conn->fd > 0) {
if (close(conn->fd))
@@ -492,9 +498,23 @@
assert(event_pending(&conn->ev_write, EV_WRITE|EV_TIMEOUT, NULL) == 0);
// free the bufferevent
- if (conn->bev)
+ if (conn->bev) {
bufferevent_free(conn->bev);
+ conn->bev = NULL;
+ }
+
+ // not connected anymore
+ conn->is_connected = 0;
+}
+
+void memcache_conn_free (struct memcache_conn *conn) {
+ // ensure we don't have a req bound to us
+ assert(conn->req == NULL);
+
+ // ensure that the connection is not considered to be connected anymore
+ assert(!conn->is_connected);
+
// free it
free(conn);
}