/* * Copyright (c) 2003-2005 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 2006 Claus Assmann * * 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: aqrdq.h,v 1.19 2006/11/13 02:10:17 ca Exp $ */ #ifndef SM_AQRDQ_H #define SM_AQRDQ_H 1 #include "sm/generic.h" #include "sm/magic.h" #include "sm/types.h" #include "sm/time.h" #include "sm/pthread.h" #include "sm/net.h" #include "sm/bhtable.h" #include "sm/ringhd.h" #include "sm/queue.h" #include "sm/actdb.h" #include "sm/aqrdqstr.h" #include "sm/log.h" #ifndef AQRDQ_CHECK # define AQRDQ_CHECK 1 #endif /* ** Active Queue Recipient Destination Queue ** These entries are accessed via a hash table from AQ (aq_ctx->aq_rdq_ht). ** They store information about (rcpt) entries in AQ that are ** being sent/destined to the same destination (only IPv4 address currently). ** ** XXX Note: DA idx is NOT used. It must be part of the key for lookups! */ struct aqrdq_ctx_S { #if AQRDQ_CHECK sm_magic_T sm_magic; #endif /* this probably needs individual locking! pthread_mutex_t aqrdq_mutex; */ uint aqrdq_da; /* DA index */ ipv4_T aqrdq_srv_ipv4; /* XXX HACK! */ uint32_t aqrdq_flags; uint aqrdq_entries; #if 0 // uint aqrdq_entries_max; #endif aq_rcpts_T aqrdq_rcpts; /* ** This is used to ** - keep a "cache" of aqrdq_ctx_P, compare ** occ_entry_P and libdadb/occh.c: occ_entry_new/free ** XXX not yet implemented. ** - link "used" entries together, then the scheduler ** can "walk" through the list. ** Use a double-linked list go get fancier operations, e.g., ** "rotate" the queue, so the head points to the "next" ctx ** that should be scheduled (rotation would introduce some kind ** of fairness). */ TAILQ_ENTRY(aqrdq_ctx_S) aqrdq_link; }; /* AQRDQ ctx flags */ #define AQRDQ_FL_NONE 0x0000 /* guess */ #define AQRDQ_FL_USED 0x0001 /* in use */ #define AQRDQ_FL_OCEXC 0x0002 /* number of open sessions exceeded */ /* not checked anywhere (yet) */ /* TA is waiting, inform scheduler when a transaction is done */ /* #define AQRDQ_FL_TA_WAIT 0x0004 * not yet used */ #define AQRDQ_SET_FLAG(aqrdq_ctx, fl) (aqrdq_ctx)->aqrdq_flags |= (fl) #define AQRDQ_CLR_FLAG(aqrdq_ctx, fl) (aqrdq_ctx)->aqrdq_flags &= ~(fl) #define AQRDQ_IS_FLAG(aqrdq_ctx, fl) (((aqrdq_ctx)->aqrdq_flags & (fl)) != 0) #if 0 /* Operations on aq_rcpt lists */ //#define AQR_RDQ_INIT(hd) SM_RINGHD_INIT(hd) //#define AQR_RDQ_APP(hd, aq_rcpt) SM_RINGHD_APPEND((hd), (aq_rcpt), aqr_dest_link) //#define AQR_RDQ_DELENTRY(hd, aq_rcpt) SM_RINGHD_DELENTRY((hd), AQR_DEST2R(aq_rcpt)) #endif /* 0 */ /* Operations on aq_rcpt lists (in AQ RDQ) */ #define AQ_RDQ_INIT(aqrdq) TAILQ_INIT(&(aqrdq)) #define AQ_RDQ_EMPTY(aqrdq) TAILQ_EMPTY(&(aqrdq)) #define AQ_RDQ_FIRST(aqrdq) TAILQ_FIRST(&(aqrdq)) #define AQ_RDQ_END(aqrdq) TAILQ_END(&(aqrdq)) #define AQ_RDQ_LAST(aqrdq) TAILQ_LAST(&(aqrdq), aq_rcpts_S) #define AQ_RDQ_NEXT(aq_rcpt) TAILQ_NEXT(aq_rcpt, aqr_dest_link) #define AQ_RDQ_INSERT_TAIL(aqrdq, aq_rcpt) TAILQ_INSERT_TAIL(&(aqrdq), aq_rcpt, aqr_dest_link) #define AQ_RDQ_INSERT_HEAD(aqrdq, aq_rcpt) TAILQ_INSERT_HEAD(&(aqrdq), aq_rcpt, aqr_dest_link) #define AQ_RDQ_REMOVE(aqrdq, aq_rcpt) TAILQ_REMOVE(&(aqrdq), aq_rcpt, aqr_dest_link) /* Operations on aqrdq_ctx lists (in AQ) */ #define AQ_RDQS_INIT(aqrdqs) TAILQ_INIT(&(aqrdqs)) #define AQ_RDQS_FIRST(aqrdqs) TAILQ_FIRST(&(aqrdqs)) #define AQ_RDQS_END(aqrdqs) TAILQ_END(&(aqrdqs)) #define AQ_RDQS_NEXT(aqrdq_ctx) TAILQ_NEXT(aqrdq_ctx, aqrdq_link) #define AQ_RDQS_INSERT_TAIL(aqrdqs, aqrdq_ctx) TAILQ_INSERT_TAIL(&(aqrdqs), aqrdq_ctx, aqrdq_link) #define AQ_RDQS_INSERT_HEAD(aqrdqs, aqrdq_ctx) TAILQ_INSERT_HEAD(&(aqrdqs), aqrdq_ctx, aqrdq_link) #define AQ_RDQS_REMOVE(aqrdqs, aqrdq_ctx) TAILQ_REMOVE(&(aqrdqs), aqrdq_ctx, aqrdq_link) #if AQRDQ_CHECK # define SM_IS_AQRDQE(aqrdq_ctx) SM_REQUIRE_ISA((aqrdq_ctx), SM_AQRDQ_MAGIC) #else # define SM_IS_AQRDQE(aqrdq_ctx) SM_REQUIRE((aqrdq_ctx) != NULL) #endif sm_ret_T aq_rdq_add(aq_ctx_P _aq_ctx, aq_rcpt_P _aq_rcpt, uint32_t *_paqrdq_flags, thr_lock_T _locktype); sm_ret_T aq_rdq_rm(aq_ctx_P _aq_ctx, aq_rcpt_P _aq_rcpt, thr_lock_T _locktype, sm_log_ctx_P _lctx); sm_ret_T aq_rdq_find(aq_ctx_P _aq_ctx, ipv4_T _ipv4, aqrdq_ctx_P *_paqrdq_ctx, thr_lock_T _locktype); #endif /* SM_AQRDQ_H */