/* * Copyright (c) 2003-2005 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. */ #include "sm/generic.h" SM_RCSID("@(#)$Id: aqrdqh.c,v 1.14 2006/11/13 02:10:21 ca Exp $") #include "sm/types.h" #include "sm/assert.h" #include "sm/magic.h" #include "sm/aqrdq.h" #include "sm/actdb-int.h" #include "aqrdq.h" /* make this dependent on the size of AQ? */ #define AQ_RDQ_FREE_LIMIT 8 /* ** AQ_RDQ_NEW -- get/allocate new rdq entry ** ** Parameters: ** aq_ctx -- AQ context ** da_idx -- DA index ** ipv4 -- IPv4 address of server ** paqrdq_ctx -- (pointer to) AQ RDQ entry (output) ** ** Returns: ** usual sm_error code; ENOMEM ** ** Locking: aq_ctx must be locked by caller. ** ** Side Effects: none on error ** ** Last code review: 2005-03-25 00:53:25 ** Last code change: 2006-11-11 18:26:01 */ sm_ret_T aq_rdq_new(aq_ctx_P aq_ctx, uint da_idx, ipv4_T ipv4, aqrdq_ctx_P *paqrdq_ctx) { sm_ret_T ret; aqrdq_ctx_P aqrdq_ctx; bht_entry_P entry; SM_REQUIRE(paqrdq_ctx != NULL); if (aq_ctx->aq_rdq_free > 0) { aqrdq_ctx = AQ_RDQS_FIRST(aq_ctx->aq_rdqs_free); SM_IS_AQRDQE(aqrdq_ctx); AQ_RDQS_REMOVE(aq_ctx->aq_rdqs_free, aqrdq_ctx); --aq_ctx->aq_rdq_free; } else { aqrdq_ctx = (aqrdq_ctx_P) sm_zalloc(sizeof(*aqrdq_ctx)); if (aqrdq_ctx == NULL) return sm_error_temp(SM_EM_AQ, ENOMEM); } AQ_RDQ_INIT(aqrdq_ctx->aqrdq_rcpts); aqrdq_ctx->aqrdq_da = da_idx; aqrdq_ctx->aqrdq_srv_ipv4 = ipv4; ret = bht_add(aq_ctx->aq_rdq_ht, (void *) &aqrdq_ctx->aqrdq_srv_ipv4, sizeof(aqrdq_ctx->aqrdq_srv_ipv4), aqrdq_ctx, &entry); if (sm_is_err(ret)) goto error; AQ_RDQS_INSERT_TAIL(aq_ctx->aq_rdqs, aqrdq_ctx); ++aq_ctx->aq_rdq_used; if (aq_ctx->aq_rdq_used > aq_ctx->aq_rdq_used_max) aq_ctx->aq_rdq_used_max = aq_ctx->aq_rdq_used; #if AQRDQ_CHECK aqrdq_ctx->sm_magic = SM_AQRDQ_MAGIC; #endif *paqrdq_ctx = aqrdq_ctx; return SM_SUCCESS; error: if (aqrdq_ctx != NULL) sm_free_size(aqrdq_ctx, sizeof(*aqrdq_ctx)); return ret; } /* ** AQ_RDQ_FREE -- free rdq entry (may append to "free-list") ** ** Parameters: ** aq_ctx -- AQ context ** aqrdq_ctx -- AQ RDQ entry ** ** Returns: ** SM_SUCCESS ** ** Locking: aq_ctx must be locked by caller. ** ** Last code review: 2005-04-04 22:37:46 ** Last code change: */ sm_ret_T aq_rdq_free(aq_ctx_P aq_ctx, aqrdq_ctx_P aqrdq_ctx) { if (aqrdq_ctx == NULL) return SM_SUCCESS; SM_IS_AQ(aq_ctx); AQ_RDQS_REMOVE(aq_ctx->aq_rdqs, aqrdq_ctx); SM_ASSERT(aq_ctx->aq_rdq_used > 0); --aq_ctx->aq_rdq_used; if (aq_ctx->aq_rdq_free < AQ_RDQ_FREE_LIMIT) { ++aq_ctx->aq_rdq_free; /* ** Clean out all data; maybe only a part? ** Counters should be down to zero, lists should be empty ** (however, the list operation may leave references ** to the wrong list in the entries). ** What else? */ sm_memzero(aqrdq_ctx, sizeof(*aqrdq_ctx)); AQ_RDQS_INSERT_HEAD(aq_ctx->aq_rdqs_free, aqrdq_ctx); #if AQRDQ_CHECK aqrdq_ctx->sm_magic = SM_AQRDQ_MAGIC; #endif } else { #if AQRDQ_CHECK aqrdq_ctx->sm_magic = SM_MAGIC_NULL; #endif sm_free_size(aqrdq_ctx, sizeof(*aqrdq_ctx)); } return SM_SUCCESS; } /* ** AQ_RDQ_HT_FREE -- free rdq entry (wrapper for bht destroy callback) ** ** Parameters: ** value -- AQ RDQ entry ** key -- unused ** ctx -- AQ context ** ** Returns: ** usual sm_error code ** ** Locking: aq_ctx must be locked by caller. ** ** Last code review: 2005-04-04 22:38:24 ** Last code change: */ void aq_rdq_ht_free(void *value, void *key, void *ctx) { (void) aq_rdq_free((aq_ctx_P) ctx, (aqrdq_ctx_P) value); return; }