These methods are called just before and just after the data serving phase respectively. They are unused in this commit, but make more sense when used from filters. --- src/connections.c | 37 +++++++++++++++++++++++++++++++++++++ src/internal.h | 2 ++ src/plugins.c | 18 ++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/src/connections.c b/src/connections.c index e225b5c..be19996 100644 --- a/src/connections.c +++ b/src/connections.c @@ -93,6 +93,8 @@ static struct connection *new_connection (int sockin, int sockout, static void free_connection (struct connection *conn); static int negotiate_handshake (struct connection *conn); static int recv_request_send_reply (struct connection *conn); +static int prepare (struct connection *conn); +static int finalize (struct connection *conn); /* Don't call these raw socket functions directly. Use conn->recv etc. */ static int raw_recv (struct connection *, void *buf, size_t len); @@ -250,6 +252,10 @@ _handle_single_connection (int sockin, int sockout) if (negotiate_handshake (conn) == -1) goto done; + /* Prepare for data serving phase. */ + if (prepare (conn) == -1) + goto done; + if (!nworkers) { /* No need for a separate thread. */ debug ("handshake complete, processing requests serially"); @@ -300,6 +306,10 @@ _handle_single_connection (int sockin, int sockout) free (workers); } + /* Finalize connection after data serving phase. */ + if (finalize (conn) == -1) + goto done; + r = get_status (conn); done: debug ("connection cleanup with final status %d", r); @@ -775,6 +785,33 @@ negotiate_handshake (struct connection *conn) return r; } +static int +prepare (struct connection *conn) +{ + int r; + + lock_request (conn); + r = backend->prepare (backend, conn); + unlock_request (conn); + + return r; +} + +static int +finalize (struct connection *conn) +{ + int r; + + lock_request (conn); + if (backend) + r = backend->finalize (backend, conn); + else + r = 0; + unlock_request (conn); + + return r; +} + static bool valid_range (struct connection *conn, uint64_t offset, uint32_t count) { diff --git a/src/internal.h b/src/internal.h index 8047b3b..dbcd89c 100644 --- a/src/internal.h +++ b/src/internal.h @@ -165,6 +165,8 @@ struct backend { void (*config_complete) (struct backend *); int (*errno_is_preserved) (struct backend *); int (*open) (struct backend *, struct connection *conn, int readonly); + int (*prepare) (struct backend *, struct connection *conn); + int (*finalize) (struct backend *, struct connection *conn); void (*close) (struct backend *, struct connection *conn); int64_t (*get_size) (struct backend *, struct connection *conn); int (*can_write) (struct backend *, struct connection *conn); diff --git a/src/plugins.c b/src/plugins.c index 137bae3..da11c2c 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -251,6 +251,22 @@ plugin_open (struct backend *b, struct connection *conn, int readonly) return 0; } +/* We don't expose .prepare and .finalize to plugins since they aren't + * necessary. Plugins can easily do the same work in .open and + * .close. + */ +static int +plugin_prepare (struct backend *b, struct connection *conn) +{ + return 0; +} + +static int +plugin_finalize (struct backend *b, struct connection *conn) +{ + return 0; +} + static void plugin_close (struct backend *b, struct connection *conn) { @@ -503,6 +519,8 @@ static struct backend plugin_functions = { .config_complete = plugin_config_complete, .errno_is_preserved = plugin_errno_is_preserved, .open = plugin_open, + .prepare = plugin_prepare, + .finalize = plugin_finalize, .close = plugin_close, .get_size = plugin_get_size, .can_write = plugin_can_write, -- 2.15.1