/*
* Copyright (c) 2004, 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: dadbclose.c,v 1.13 2007/05/28 17:15:37 ca Exp $")
#include "sm/types.h"
#include "sm/assert.h"
#include "sm/magic.h"
#include "sm/str.h"
#include "sm/mta.h"
#include "sm/memops.h"
#include "sm/qmgr.h"
#include "sm/qmgr-int.h"
#include "sm/dadb.h"
#include "sm/da.h"
#include "dadb.h"
#include "occ.h"
/*
** DADB_ENTRY_FREE -- free a DADB entry
**
** Parameters:
** dadb_entry -- DADB entry
**
** Returns:
** none
**
** Last code review: 2005-03-16 06:13:26
** Last code change: 2007-05-28 14:56:52
*/
void
dadb_entry_free(dadb_entry_P dadb_entry)
{
if (dadb_entry == NULL)
return;
SM_IS_DADBE(dadb_entry);
#if DADBE_MUTEX
(void) pthread_mutex_destroy(&dadb_entry->dadbe_mutex);
#endif
#if DADB_CHECK
dadb_entry->sm_magic = SM_MAGIC_NULL;
#endif
#if MTA_USE_TLS
SM_STR_FREE(dadb_entry->dadbe_se_conf);
SM_STR_FREE(dadb_entry->dadbe_lhs);
SM_STR_FREE(dadb_entry->dadbe_tag);
#endif
sm_free_size(dadb_entry, sizeof(*dadb_entry));
return;
}
/*
** DADB_CLOSE -- close a DADB; including all open sessions
**
** Parameters:
** qmgr_ctx -- QMGR context (only qmgr_conf is needed)
** dadb_ctx -- DADB context
** locktype -- kind of locking
**
** Returns:
** usual sm_error code
**
** Locking: locks dadb_ctx if requested but only to set dadb_state.
** may lock edbc_ctx, aq_ctx, dadb_ctx in subroutines.
**
** Last code review: 2005-03-16 17:04:41; see comments below
** Last code change: 2006-02-18 22:03:53
*/
sm_ret_T
dadb_close(qmgr_ctx_P qmgr_ctx, dadb_ctx_P dadb_ctx, thr_lock_T locktype)
{
uint i;
sm_ret_T ret;
int r;
bool done;
dadb_entry_P dadb_entry;
aq_ta_P aq_ta;
if (dadb_ctx == NULL)
return SM_SUCCESS;
SM_IS_DADB(dadb_ctx);
ret = SM_SUCCESS;
if (thr_lock_it(locktype))
{
r = pthread_mutex_lock(&dadb_ctx->dadb_mutex);
SM_LOCK_OK(r);
if (r != 0)
return sm_error_perm(SM_EM_DA, r);
}
done = !DADB_IS_OK(dadb_ctx);
if (!done)
dadb_ctx->dadb_state = DADB_ST_STOP;
/*
** Note: this should "wait" for any ongoing modifications to dadb.
** This could be achieved using a condition variable and a counter
** (for the number of ongoing dadb_entry modifications).
** A dadb_entry modification may be "in progress" but due to
** scheduling it may be done after this function "free"d dadb_entry.
*/
if (thr_unl_always(locktype))
{
r = pthread_mutex_unlock(&dadb_ctx->dadb_mutex);
SM_ASSERT(r == 0);
if (r != 0)
ret = sm_error_perm(SM_EM_DA, r);
}
if (done)
return ret;
/*
** Notes:
** This loop checks dadb_ctx->dadb_entries != NULL to avoid an if
** around the entire loop (which requires further indentation).
** This isn't really optimal (checking the variable on each iteration)
** but shouldn't have any noticeable impact.
**
** The return value (ret) of the last function call inside the loop
** is used as return value of this function; moreover, some return
** values are simply ignored. This isn't optimal but this is just
** some cleanup code hence any errors can be ignored.
*/
for (i = 0;
dadb_ctx->dadb_entries != NULL && i < dadb_ctx->dadb_entries_max;
i++)
{
dadb_entry = (dadb_ctx->dadb_entries)[i];
#if DADB_ENTRIES_DEBUG
sm_io_fprintf(smioerr,
"i=%3d, dadb_entry=%p, flags=%#x, da_se_id=%s, da_ta_id=%s\n"
, i, dadb_entry
, dadb_entry != NULL ? dadb_entry->dadbe_flags : 0xff
, dadb_entry != NULL ? dadb_entry->dadbe_da_se_id : "-"
, dadb_entry != NULL ? dadb_entry->dadbe_da_ta_id : "-"
);
#endif
if (dadb_entry == NULL)
continue;
#if DADBE_MUTEX
r = pthread_mutex_lock(&dadb_entry->dadbe_mutex);
SM_LOCK_OK(r);
#endif
if (!DADBE_IS_FREE(dadb_entry)) {
if (dadb_entry->dadbe_rcpt != NULL &&
(aq_ta = dadb_entry->dadbe_rcpt->aqr_ss_ta) != NULL) {
SM_ASSERT(SESSTA_EQ(dadb_entry->dadbe_ss_ta_id,
aq_ta->aqt_ss_ta_id));
}
else
ret = aq_ta_find(qmgr_ctx->qmgr_aq,
dadb_entry->dadbe_ss_ta_id, true, &aq_ta);
if (sm_is_success(ret)) {
/* session must be closed */
DADBE_SET_FLAG(dadb_entry, DADBE_FL_SE_CL);
/* Update transaction status */
ret = qda_update_ta_stat(qmgr_ctx,
dadb_entry->dadbe_da_ta_id,
SMTPC_DA_ST, DA_TERMINATED,
dadb_ctx, dadb_entry,
aq_ta, NULL, NULL, THR_LOCK_UNLOCK);
/* fixme: complain on error? */
}
else {
ret = dadb_sess_close_entry(qmgr_ctx, dadb_ctx,
dadb_entry, true, NULL, THR_LOCK_UNLOCK);
}
}
#if DADBE_MUTEX
r = pthread_mutex_unlock(&dadb_entry->dadbe_mutex);
SM_ASSERT(r == 0);
#endif
dadb_entry_free(dadb_entry);
(dadb_ctx->dadb_entries)[i] = NULL;
}
FREE_DADB_ENTRIES(dadb_ctx);
return ret;
}
syntax highlighted by Code2HTML, v. 0.9.1