/*
* 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;
}
syntax highlighted by Code2HTML, v. 0.9.1