e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * CDDL HEADER START
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * The contents of this file are subject to the terms of the
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Common Development and Distribution License (the "License").
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * You may not use this file except in compliance with the License.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * or http://www.opensolaris.org/os/licensing.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * See the License for the specific language governing permissions
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * and limitations under the License.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * When distributing Covered Code, include this CDDL HEADER in each
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * If applicable, add the following below this CDDL HEADER, with the
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * fields enclosed by brackets "[]" replaced with your own identifying
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * information: Portions Copyright [yyyy] [name of copyright owner]
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * CDDL HEADER END
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Use is subject to license terms.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#ifndef _NS_CONNMGMT_H
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#define _NS_CONNMGMT_H
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#pragma ident "%Z%%M% %I% %E% SMI"
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#ifdef __cplusplus
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethextern "C" {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#endif
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include <thread.h>
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include "ns_sldap.h"
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include "ns_internal.h"
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#include "ns_cache_door.h"
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstruct ns_conn_user; /* connection user, forward definition */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstruct ns_conn_mt; /* multi-threaded (MT) connection, forward definition */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstruct ns_conn_mgmt; /* connection management, forward definition */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#define NS_CONN_MT_USER_NO_MAX -1
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#define NS_CONN_MT_USER_MAX NS_CONN_MT_USER_NO_MAX
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#define NS_LIST_TRY_MAX 3
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Structure for handling the waiter of a pending multi-threaded (MT) connection
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethtypedef struct ns_conn_waiter {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth cond_t waitcv;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth uint8_t signaled;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth struct ns_conn_user *key;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth struct ns_conn_waiter *next, *prev;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth} ns_conn_waiter_t;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * type of a connection user
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethtypedef enum {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_USER_SEARCH = 1,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_USER_WRITE = 2,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_USER_AUTH = 3,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_USER_GETENT = 4
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth} ns_conn_user_type_t;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * state of a connection user
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethtypedef enum {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_USER_UNINITED = 0,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_USER_ALLOCATED = 1,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_USER_FINDING = 2, /* looking for an MT connection */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_USER_WAITING = 3, /* waiting for an MT connection */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_USER_WOKEUP = 4,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_USER_CONNECT_ERROR = 5,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_USER_CONNECTED = 6,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_USER_DISCONNECTED = 7,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_USER_FREED = 8
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth} ns_conn_user_state_t;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * A connection user represents a request processed by libsldap. It
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * usually is a thread using the same connection from start to end.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Different connection users of the same type can share the same
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * connection opened for that type. But search and getent users can
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * share the same connection opened for either search or getent. AUTH
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * connection are not shareable.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * A getent user may have a longer lifespan and live outside of libsldap.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * This is because the associated search cookie is passed back to the caller
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * via the firstEntry call and used in the subsequent nextEntry or endEntry
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * calls. Even though the firstEntry and the nextEntry/endEntry calls may
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * be running in a different thread, the connection being used will be the
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * same. It is the one assigend during the firstEntry call.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethstruct ns_conn_user {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_user_type_t type; /* search, write, auth, getent, ... */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_user_state_t state;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth thread_t tid; /* id of the thread starts the request */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth struct ns_conn_user *next; /* next conn_user in the linked list */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth struct ns_conn_mt *conn_mt; /* the MT connection being used */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth struct ns_conn_mgmt *conn_mgmt; /* ref counted conn management */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth void *userinfo; /* private data of the request */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_ldap_return_code ns_rc; /* error return code */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_ldap_error_t *ns_error; /* error info */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t referral; /* using a referred server ? */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t retry; /* retry the request on certain error? */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t keep_conn; /* keep the conn for reuse ? */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t use_mt_conn; /* using/used an MT connection ? */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t bad_mt_conn; /* MT connection is not usable ? */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth};
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * state of an MT connection
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethtypedef enum {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_MT_UNINITED = 0,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_MT_CONNECTING = 1,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_MT_CONNECT_ERROR = 2,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_MT_CONNECTED = 3,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_MT_CLOSING = 4
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth} ns_conn_mt_state_t;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * An ns_conn_mt (or MT connection) represents an ldap connection
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * that can be shared among multiple threads. It also represents
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * the set of connection users using the ldap connection. It contains
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * a pointer to the Connection structure that has the physical info
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * of the connection (server name, address, ldap handle, etc). It
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * also contains a linked list of all the conn_user using the ldap
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * connection. The connection users can wait on an MT connection
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * to become available or be told to abort and clean up when one of
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * the connection user detects an error and knows that the connection
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * is no longer usable. The error info is then saved in the structure
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * for other users to consume.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * An MT connection is meant to be shared concurrently and persistent.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Even when there's no current user, it will be kept by the connection
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * management, waiting for the next user. It will be closed when
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * a connection error is detected, when a better server should be
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * used, when the Native LDAP configuration change, or when the libsldap
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * is being unloaded.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethtypedef struct ns_conn_mt {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth mutex_t lock;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mt_state_t state;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth pid_t pid; /* process creates the connection */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth thread_t tid; /* thread creates the connection */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth struct ns_conn_mt *next; /* next conn_mt in the linked list */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_user_t *cu_head; /* head of conn_user linked list */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_user_t *cu_tail; /* tail of conn_user linked list */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth struct ns_conn_mgmt *conn_mgmt; /* ref counted conn management */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_waiter_t waiter; /* first of the connection waiters */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth uint_t cu_cnt; /* number of the using conn_user */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int32_t cu_max; /* max. allowed number of conn_user */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth uint_t waiter_cnt; /* number of waiters */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_user_type_t opened_for; /* type of conn_user opened for */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth Connection *conn; /* name, IP address, ldap handle, etc */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth time_t create_time; /* time when connection created */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth time_t access_time; /* time when last used */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_ldap_return_code ns_rc; /* saved error code */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_ldap_error_t *ns_error; /* saved error info */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t close_when_nouser; /* close connection when */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth /* last user is done ? */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t detached; /* no longer in connection pool? */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t referral; /* using a referred server ? */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth} ns_conn_mt_t;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * state of a connection management
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * (a connection pool sharing the same native LDAP configuration)
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethtypedef enum {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_MGMT_UNINITED = 0,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_MGMT_INACTIVE = 1, /* conn sharing not yet requested */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_MGMT_ACTIVE = 2, /* connection sharing required/requested */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_CONN_MGMT_DETACHED = 3 /* on the way down, no new user allowed */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth} ns_conn_mgmt_state_t;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * An ns_conn_mgmt (or connection management) represents the set of MT
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * connections using the same native LDAP configuration. It is a connection
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * pool that can adjust the MT connection status and usage based on the
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * change notifications it receives from the ldap_cachemgr daemon, OR When
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * the change is detected at config refresh time. When a server status
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * change (up or down) notification is received or detected, it will
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * close the MT connections using the server. Or mark them as to-be-closed
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * and close them when all users are done using them. When a config change
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * notice is received, it will detach itself and allow a new ns_conn_mgmt be
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * created for the new configuration. The old config would still be used
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * by the detached ns_conn_mgmt. Both will be destroyed when all existing
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * conn_user are done. Any conn_user and MT connection created after the
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * configuration switch will use the new configuration.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Note that there's always just one current ns_conn_mgmt. Its usage is
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * reference counted. Any new conn_user or MT connection referencing
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * the ns_conn_mgmt adds 1 to the count, any release of the ns_conn_mgmt
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * decrement the count by 1. The ns_conn_mgmt can not be freed until
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * the reference count becomes zero.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * Each ns_conn_mgmt references a native LDAP configuration. The config
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * component of this library always maintains a global configuration. It is
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * referred to as the current global config. The current ns_conn_mgmt
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * uses that global config. When an ns_conn_mgmt is detached, or not
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * longer active/current, the config it uses is no longer the current global
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * one, which is referred as the per connection management config. When
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * the ns_conn_mgmt is freed, the config will also be destroyed.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethtypedef struct ns_conn_mgmt {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth mutex_t lock;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mgmt_state_t state;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth pid_t pid; /* process creates the conn_mgmt */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth thread_t procchg_tid; /* id of the change monitor thread */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mt_t *cm_head; /* head of the conn_mt linked list */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_conn_mt_t *cm_tail; /* tail of the conn_mt linked list */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth mutex_t cfg_lock; /* lock serializes access to config */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ldap_get_chg_cookie_t cfg_cookie; /* used to detect if config changes */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_config_t *config; /* the native LDAP config being used */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth char **pservers; /* preferred servers defined in config */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth uint_t cm_cnt; /* number of MT connection in the pool */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth uint_t ref_cnt; /* number of reference by conn_MT/conn_user */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t is_nscd; /* running in a nscd ? */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t is_peruser_nscd; /* running in a per-user nscd ? */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t ldap_mt; /* libldap supports multi-threaded client ? */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t do_mt_conn; /* need and able to do MT conn ? */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t shutting_down; /* on the way down ? */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t cfg_reloaded; /* config is not current ? */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t procchg_started; /* change monitor thread started ? */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t procchg_door_call; /* in door call and waiting ? */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t pservers_loaded; /* pservers array is set ? */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth} ns_conn_mgmt_t;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * For a connection management and the conn_mt connections it manages, it is
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * very helpful to know exactly when the Native LDAP configuration changes
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * and when the status of the configured servers change. If the config
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * changes, new connection management will be created. If servers go up
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * or down, conn_mt connections being used need to be dropped or switched.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * For processes other than the main nscd, the changes has to be detected
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * in a less efficient way by libsldap. For the main nscd (not including
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * peruser nscd), the connection management which has active conn_mt
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * connections can rely on the ldap_cachemgr daemon to report if there's any
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * change in servers' status or if the native LDAP configuration has changed.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth *
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * The mechanism for reporting of the changes is a door call sent from
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * libsldap to ldap_cachemgr. The call will not be returned until changes
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * detected by ldap_cachemgr. When the change info is passed back to
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * libsldap, the change monitor thread will wake up from the door call
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * and process the notification. For servers went from up to down, the
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * associated MT connections will be closed, and then all conn_users'
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * state will be marked as closing. When a conn_user notices it, the
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * operations represented by that conn_user will be ended with error
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * info. When a more preferred server is up, MT connections using
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * less preferred servers will be marked as closed-when-all-user-done,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * so that new connection will be opened and using the preferred server.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * A configuration change causes the current connection management and
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * the configuration it uses to become detached but continually being
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * used by the old MT connections. Any new MT connection opened will
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * be put in a new connection management and uses the new configuration
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * immediately.
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethtypedef enum {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_SERVER_UP = 1,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth NS_SERVER_DOWN = 2
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth} ns_server_status_t;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethtypedef struct ns_server_status_change {
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int num_server;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth boolean_t config_changed;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_server_status_t *changes; /* array of status change */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth char **servers; /* array of server */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth} ns_server_status_change_t;
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth/*
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth * connection management functions
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth */
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethns_conn_mgmt_t *__s_api_conn_mgmt_init();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethint __s_api_setup_mt_ld(LDAP *ld);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethint __s_api_check_mtckey();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethvoid __s_api_use_prev_conn_mgmt(int, ns_config_t *);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethns_conn_user_t *__s_api_conn_user_init(int, void *, boolean_t);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethvoid __s_api_conn_mt_return(ns_conn_user_t *);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethvoid __s_api_conn_user_free(ns_conn_user_t *);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethint __s_api_conn_mt_add(Connection *con, ns_conn_user_t *, ns_ldap_error_t **);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethint __s_api_conn_mt_get(const char *, const int, const ns_cred_t *,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth Connection **, ns_ldap_error_t **, ns_conn_user_t *);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethvoid __s_api_conn_mt_remove(ns_conn_user_t *, int, ns_ldap_error_t **);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethint __s_api_check_libldap_MT_conn_support(ns_conn_user_t *, LDAP *ld,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth ns_ldap_error_t **);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethvoid __s_api_conn_mt_close(ns_conn_user_t *, int, ns_ldap_error_t **);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethvoid __s_api_reinit_conn_mgmt_new_config(ns_config_t *);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethint __s_api_setup_retry_search(ns_conn_user_t **, ns_conn_user_type_t, int *,
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth int *, ns_ldap_error_t **);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethint __s_api_setup_getnext(ns_conn_user_t *, int *, ns_ldap_error_t **);
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57ethvoid __s_api_shutdown_conn_mgmt();
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#ifdef __cplusplus
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth}
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#endif
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth
e1dd0a2f3a26050d1f183c1cafae42c4e3a0b57eth#endif /* _NS_CONNMGMT_H */