summaryrefslogtreecommitdiffstats
path: root/xlators/protocol/server/src/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/protocol/server/src/server.c')
-rw-r--r--xlators/protocol/server/src/server.c96
1 files changed, 82 insertions, 14 deletions
diff --git a/xlators/protocol/server/src/server.c b/xlators/protocol/server/src/server.c
index b0697bb7b9d..b45b77baae0 100644
--- a/xlators/protocol/server/src/server.c
+++ b/xlators/protocol/server/src/server.c
@@ -36,6 +36,26 @@
#include "authenticate.h"
#include "rpcsvc.h"
+void
+grace_time_handler (void *data)
+{
+ server_connection_t *conn = NULL;
+ xlator_t *this = NULL;
+
+ conn = data;
+ this = conn->this;
+
+ GF_VALIDATE_OR_GOTO (THIS->name, conn, out);
+ GF_VALIDATE_OR_GOTO (THIS->name, this, out);
+
+ gf_log (this->name, GF_LOG_INFO, "grace timer expired");
+
+ server_cancel_conn_timer (this, conn);
+ server_connection_put (this, conn);
+out:
+ return;
+}
+
struct iobuf *
gfs_serialize_reply (rpcsvc_request_t *req, void *arg, struct iovec *outmsg,
xdrproc_t xdrproc)
@@ -554,11 +574,10 @@ int
server_rpc_notify (rpcsvc_t *rpc, void *xl, rpcsvc_event_t event,
void *data)
{
- xlator_t *this = NULL;
- rpc_transport_t *xprt = NULL;
- server_connection_t *conn = NULL;
- server_conf_t *conf = NULL;
-
+ xlator_t *this = NULL;
+ rpc_transport_t *xprt = NULL;
+ server_connection_t *conn = NULL;
+ server_conf_t *conf = NULL;
if (!xl || !data) {
gf_log_callingfn ("server", GF_LOG_WARNING,
@@ -589,20 +608,37 @@ server_rpc_notify (rpcsvc_t *rpc, void *xl, rpcsvc_event_t event,
}
case RPCSVC_EVENT_DISCONNECT:
conn = get_server_conn_state (this, xprt);
- if (conn)
- server_connection_cleanup (this, conn);
-
- gf_log (this->name, GF_LOG_INFO,
- "disconnected connection from %s",
- xprt->peerinfo.identifier);
+ if (!conn)
+ break;
+ put_server_conn_state (this, xprt);
+ gf_log (this->name, GF_LOG_INFO, "disconnecting connection"
+ "from %s", xprt->peerinfo.identifier);
list_del (&xprt->list);
+ pthread_mutex_lock (&conn->lock);
+ {
+ if (conn->timer)
+ goto unlock;
+
+ gf_log (this->name, GF_LOG_INFO, "starting a grace "
+ "timer for %s", xprt->name);
+
+ conn->timer = gf_timer_call_after (this->ctx,
+ conf->grace_tv,
+ grace_time_handler,
+ conn);
+ }
+ unlock:
+ pthread_mutex_unlock (&conn->lock);
+
break;
case RPCSVC_EVENT_TRANSPORT_DESTROY:
- conn = get_server_conn_state (this, xprt);
- if (conn)
- server_connection_put (this, conn);
+ /*- conn obj has been disassociated from xprt on first
+ * disconnect.
+ * conn cleanup and destruction is handed over to
+ * grace_time_handler or the subsequent handler that 'owns'
+ * the conn. Nothing left to be done here. */
break;
default:
break;
@@ -668,6 +704,30 @@ _copy_auth_opt (dict_t *unused,
int
+server_init_grace_timer (xlator_t *this, dict_t *options,
+ server_conf_t *conf)
+{
+ int32_t ret = -1;
+ int32_t grace_timeout = -1;
+
+ GF_VALIDATE_OR_GOTO ("server", this, out);
+ GF_VALIDATE_OR_GOTO (this->name, options, out);
+ GF_VALIDATE_OR_GOTO (this->name, conf, out);
+
+ ret = dict_get_int32 (options, "grace-timeout", &grace_timeout);
+ if (!ret)
+ conf->grace_tv.tv_sec = grace_timeout;
+ else
+ conf->grace_tv.tv_sec = 10;
+
+ conf->grace_tv.tv_usec = 0;
+
+ ret = 0;
+out:
+ return ret;
+}
+
+int
reconfigure (xlator_t *this, dict_t *options)
{
@@ -761,6 +821,7 @@ reconfigure (xlator_t *this, dict_t *options)
"Reconfigure not found for transport" );
}
}
+ ret = server_init_grace_timer (this, options, conf);
out:
gf_log ("", GF_LOG_DEBUG, "returning %d", ret);
@@ -797,6 +858,10 @@ init (xlator_t *this)
INIT_LIST_HEAD (&conf->xprt_list);
pthread_mutex_init (&conf->mutex, NULL);
+ ret = server_init_grace_timer (this, this->options, conf);
+ if (ret)
+ goto out;
+
ret = server_build_config (this, conf);
if (ret)
goto out;
@@ -1032,5 +1097,8 @@ struct volume_options options[] = {
.type = GF_OPTION_TYPE_PATH,
.default_value = "/tmp"
},
+ {.key = {"grace-timeout"},
+ .type = GF_OPTION_TYPE_INT,
+ },
{ .key = {NULL} },
};