summaryrefslogtreecommitdiff
path: root/src/providers/ldap
diff options
context:
space:
mode:
authorJan Zeleny <jzeleny@redhat.com>2012-06-20 13:42:06 -0400
committerJakub Hrozek <jhrozek@redhat.com>2012-08-01 16:19:41 +0200
commit10922e0293f3ebf056708acacce35e93fe07747e (patch)
treecefb07a15c1166acbc3c16911cd2bfc551aae975 /src/providers/ldap
parentbbd33e46aa6194c1086939f7cf8538c067186455 (diff)
downloadsssd-10922e0293f3ebf056708acacce35e93fe07747e.tar.gz
sssd-10922e0293f3ebf056708acacce35e93fe07747e.tar.bz2
sssd-10922e0293f3ebf056708acacce35e93fe07747e.zip
Primary server support: support for "disconnecting" connections in LDAP
This patch adds support for marking existing connections as being disconnected. Each such connection can't be used for new queries and a new one has to be created instead if necessary. This will ensure that pending operations will end gracefully during reconnection. Also all new queries to the server we are reconnecting to will use another (probably newly created) connection.
Diffstat (limited to 'src/providers/ldap')
-rw-r--r--src/providers/ldap/sdap_id_op.c41
1 files changed, 37 insertions, 4 deletions
diff --git a/src/providers/ldap/sdap_id_op.c b/src/providers/ldap/sdap_id_op.c
index d4f6fe34..3036d0cc 100644
--- a/src/providers/ldap/sdap_id_op.c
+++ b/src/providers/ldap/sdap_id_op.c
@@ -72,9 +72,14 @@ struct sdap_id_conn_data {
int notify_lock;
/* list of operations using connect */
struct sdap_id_op *ops;
+ /* A flag which is signalizing that this
+ * connection will be disconnected and should
+ * not be used any more */
+ bool disconnecting;
};
static void sdap_id_conn_cache_be_offline_cb(void *pvt);
+static void sdap_id_conn_cache_fo_reconnect_cb(void *pvt);
static void sdap_id_release_conn_data(struct sdap_id_conn_data *conn_data);
static int sdap_id_conn_data_destroy(struct sdap_id_conn_data *conn_data);
@@ -118,6 +123,14 @@ int sdap_id_conn_cache_create(TALLOC_CTX *memctx,
goto fail;
}
+ ret = be_add_reconnect_cb(conn_cache, id_ctx->be,
+ sdap_id_conn_cache_fo_reconnect_cb, conn_cache,
+ NULL);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("be_add_reconnect_cb failed.\n"));
+ goto fail;
+ }
+
*conn_cache_out = conn_cache;
return EOK;
@@ -139,6 +152,18 @@ static void sdap_id_conn_cache_be_offline_cb(void *pvt)
}
}
+/* Callback for attempt to reconnect to primary server */
+static void sdap_id_conn_cache_fo_reconnect_cb(void *pvt)
+{
+ struct sdap_id_conn_cache *conn_cache = talloc_get_type(pvt, struct sdap_id_conn_cache);
+ struct sdap_id_conn_data *cached_connection = conn_cache->cached_connection;
+
+ /* Release any cached connection on going offline */
+ if (cached_connection != NULL) {
+ cached_connection->disconnecting = true;
+ }
+}
+
/* Release sdap_id_conn_data and destroy it if no longer needed */
static void sdap_id_release_conn_data(struct sdap_id_conn_data *conn_data)
{
@@ -194,7 +219,8 @@ static bool sdap_can_reuse_connection(struct sdap_id_conn_data *conn_data)
{
int timeout;
- if (!conn_data || !conn_data->sh || !conn_data->sh->connected) {
+ if (!conn_data || !conn_data->sh ||
+ !conn_data->sh->connected || conn_data->disconnecting) {
return false;
}
@@ -721,6 +747,7 @@ int sdap_id_op_connect_recv(struct tevent_req *req, int *dp_error)
int sdap_id_op_done(struct sdap_id_op *op, int retval, int *dp_err_out)
{
bool communication_error;
+ struct sdap_id_conn_data *current_conn = op->conn_data;
switch (retval) {
case EIO:
case ETIMEDOUT:
@@ -733,8 +760,8 @@ int sdap_id_op_done(struct sdap_id_op *op, int retval, int *dp_err_out)
break;
}
- if (communication_error && op->conn_data != 0
- && op->conn_data == op->conn_cache->cached_connection) {
+ if (communication_error && current_conn != 0
+ && current_conn == op->conn_cache->cached_connection) {
/* do not reuse failed connection */
op->conn_cache->cached_connection = NULL;
@@ -774,9 +801,15 @@ int sdap_id_op_done(struct sdap_id_op *op, int retval, int *dp_err_out)
op->reconnect_retry_count = 0;
}
- if (op->conn_data) {
+ if (current_conn) {
DEBUG(9, ("releasing operation connection\n"));
sdap_id_op_hook_conn_data(op, NULL);
+
+ if (current_conn->ops == NULL || current_conn->disconnecting) {
+ DEBUG(SSSDBG_TRACE_FUNC, ("Connection is marked for "
+ "disconnection, executing ...\n"));
+ sdap_id_release_conn_data(current_conn);
+ }
}
*dp_err_out = dp_err;