/*
 * Copyright (c) 2003-2006 Sendmail, Inc. and its suppliers.
 *      All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 *
 *	$Id: occ.h,v 1.31 2006/02/17 18:45:11 ca Exp $
 */

#ifndef SM_OCC_H
#define SM_OCC_H 1

#include "sm/generic.h"
#include "sm/magic.h"
#include "sm/types.h"
#include "sm/time.h"
#include "sm/net.h"	/* IPv4 type */
#include "sm/pthread.h"
#include "sm/queue.h"
#include "sm/qmgr.h"
#include "sm/occstr.h"
#include "sm/io.h"

#if DA_OCC_RSC
# include "sm/rsc.h"
# define OCC_HT_P rsc_P
#else
# include "sm/bhtable.h"
# define OCC_HT_P bht_P
#endif

#ifndef OCC_CHECK
# define OCC_CHECK	1
#endif

typedef struct occ_entry_S	occ_entry_T, *occ_entry_P;
typedef SIMPLEQ_HEAD(, occ_entry_S)	occ_entry_hd_T, *occ_entry_hd_P;

/* Outgoing (open) Connection Cache context */
struct occ_ctx_S
{
#if OCC_CHECK
	sm_magic_T	 sm_magic;
#endif
	pthread_mutex_t	 occx_mutex;

	/* strings to perform lookups */
	sm_str_P	 occx_lhs;
	sm_str_P	 occx_tag;
	sm_str_P	 occx_rhs;
	occ_entry_hd_T	 occx_fl_hd;	/* list of free OCC entries */
	OCC_HT_P	 occx_ht;	/* connection cache */
};

/* Outgoing (open) Connection Cache entry */
struct occ_entry_S
{
#if OCC_CHECK
	sm_magic_T	 sm_magic;
#endif
/*	individual locking required?
	pthread_mutex_t	 occe_mutex;
*/
	ipv4_T		 occe_srv_ipv4;	/* XXX HACK! */

	uint		 occe_flags;

	/* concurrency control: initial, current, maximum */
	uint		 occe_init_conc;
	uint		 occe_cur_conc;
	uint		 occe_max_conc;

	uint		 occe_open_se;	/* # of open sessions */
	uint		 occe_open_ta;	/* # of open transaction */
#if 0
	time_T		 occe_last_conn; /* time of last connect */
#endif
	time_T		 occe_last_upd;	/* time of last update */
	uint		 occe_timeout;	/* expire entry after this timeout */
	SIMPLEQ_ENTRY(occ_entry_S)	 occ_fl;	/* next free entry */
};

/* OCC entry flags; see also DA entry flags */
#define OCCE_FL_NONE		0x0000	/* guess */
#define OCCE_FL_USED		0x0001	/* in use */

/* inform scheduler when a session is done */
#define OCCE_FL_SE_WAIT		0x0002

/* inform scheduler when a transaction is done */
#define OCCE_FL_TA_WAIT		0x0004

#define OCCE_FL_LOGEXC		0x0008	/* "limit exceeded" has been logged */

#define OCCE_FL_BLW_LIM		0x0010	/* occe_open_se < occe_cur_conc */

#define OCCE_SET_FLAG(occ_entry, fl)	(occ_entry)->occe_flags |= (fl)
#define OCCE_CLR_FLAG(occ_entry, fl)	(occ_entry)->occe_flags &= ~(fl)
#define OCCE_IS_FLAG(occ_entry, fl)	(((occ_entry)->occe_flags & (fl)) != 0)

#define OCCFL_INIT(occ_fl_hd)	SIMPLEQ_INIT(occ_fl_hd)
#define OCCFL_FIRST(occ_fl_hd)	SIMPLEQ_FIRST(occ_fl_hd)
#define OCCFL_END(occ_fl_hd)	SIMPLEQ_END(occ_fl_hd)
#define OCCFL_EMPTY(occ_fl_hd)	SIMPLEQ_EMPTY(occ_fl_hd)
#define OCCFL_NEXT(occ_entry)	SIMPLEQ_NEXT(occ_entry, occ_fl)
#define OCCFL_PRE(occ_fl_hd, occ_entry) SIMPLEQ_INSERT_HEAD(occ_fl_hd, occ_entry, occ_fl)
#define OCCFL_APP(occ_fl_hd, occ_entry) SIMPLEQ_INSERT_TAIL(occ_fl_hd, occ_entry, occ_fl)
#define OCCFL_REMOVE(occ_fl_hd) SIMPLEQ_REMOVE_HEAD(occ_fl_hd, occ_fl)

sm_ret_T occ_entry_find(OCC_HT_P occ_ht, ipv4_T ipv4, occ_entry_P *pocc_entry, pthread_mutex_t *occ_mutex, thr_lock_T locktype);

sm_ret_T occ_print(occ_ctx_P _occ_ctx, sm_file_T *_fp, thr_lock_T _locktype);

#endif /* SM_OCC_H */


syntax highlighted by Code2HTML, v. 0.9.1