/* * 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; }