/* * 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: adbupd.c,v 1.26 2006/12/11 01:22:06 ca Exp $") #include "sm/types.h" #include "sm/assert.h" #include "sm/magic.h" #include "sm/str.h" #include "sm/time.h" #include "sm/mta.h" #include "sm/memops.h" #include "sm/qmgr.h" #include "sm/actdb-int.h" #include "sm/qmgr-int.h" #include "adb.h" /* ** AQ_RSND_CTX_FREE -- Free aq_rsnd_ctx ** ** Parameters: ** aq_rsnd_ctx -- aq recipient send RCB to SMTPC context ** ** Returns: ** SM_SUCCESS ** ** Last code review: 2005-04-14 20:31:18 ** Last code change: */ sm_ret_T aq_rsnd_ctx_free(aq_rsnd_ctx_P aq_rsnd_ctx) { if (aq_rsnd_ctx != NULL) sm_free_size(aq_rsnd_ctx, sizeof(*aq_rsnd_ctx)); return SM_SUCCESS; } /* ** AQ_RSND_CTX_NEW -- Create new aq_rsnd_ctx ** ** Parameters: ** aq_ctx -- AQ context ** aq_rcpt -- AQ rcpt ** paq_rsnd_ctx -- (ptr to) rcpt send RCB to SMTPC context (output) ** ** Returns: ** usual sm_error code; ENOMEM ** ** Last code review: 2005-04-14 20:31:00 ** Last code change: */ sm_ret_T aq_rsnd_ctx_new(aq_ctx_P aq_ctx, aq_rcpt_P aq_rcpt, aq_rsnd_ctx_P *paq_rsnd_ctx) { aq_rsnd_ctx_P aq_rsnd_ctx; SM_IS_AQ(aq_ctx); SM_REQUIRE(paq_rsnd_ctx != NULL); aq_rsnd_ctx = (aq_rsnd_ctx_P)sm_zalloc(sizeof(*aq_rsnd_ctx)); if (aq_rsnd_ctx == NULL) return sm_error_temp(SM_EM_AQ, ENOMEM); aq_rsnd_ctx->aqrsc_aq_ctx = aq_ctx; aq_rsnd_ctx->aqrsc_rcpt = aq_rcpt; *paq_rsnd_ctx = aq_rsnd_ctx; return SM_SUCCESS; } /* ** AQ_RCPTSENT2DA -- change status flags for recipients sent to a DA. ** This is a callback that is invoked after an RCB has been sent. ** See qm_to_sc() for a discussion. ** ** Parameters: ** ctx -- aq recipient send RCB to SMTPC context ** ** Returns: ** usual sm_error code ** ** Locking: locks entire aq_ctx. ** ** Last code review: 2005-04-15 20:13:50 ** Last code change: */ sm_ret_T aq_rcptsent2da(void *ctx) { int r; sm_ret_T ret; time_T tm; aq_ctx_P aq_ctx; thr_lock_T locktype; aq_rcpt_P aq_rcpt, aq_rcpt_nxt; aq_rsnd_ctx_P aq_rsnd_ctx; qmgr_ctx_P qmgr_ctx; SM_REQUIRE(ctx != NULL); aq_rsnd_ctx = (aq_rsnd_ctx_P)ctx; aq_ctx = aq_rsnd_ctx->aqrsc_aq_ctx; aq_rcpt = aq_rsnd_ctx->aqrsc_rcpt; qmgr_ctx = aq_ctx->aq_qmgr_ctx; SM_IS_AQ(aq_ctx); SM_IS_AQ_RCPT(aq_rcpt); SM_IS_QMGR_CTX(qmgr_ctx); locktype = THR_LOCK_UNLOCK; if (thr_lock_it(locktype)) { r = pthread_mutex_lock(&aq_ctx->aq_mutex); SM_LOCK_OK(r); if (r != 0) return sm_error_perm(SM_EM_AQ, r); } ret = SM_SUCCESS; tm = evthr_time(qmgr_ctx->qmgr_ev_ctx); /* go through the list of entries in the DA transaction */ aq_rcpt_nxt = aq_rcpt; do { #if QMGR_DEBUG > 1 QM_LEV_DPRINTF(3, (QM_DEBFP, "sev=DBG, func=aq_rcptsent2da, aq_rcpt=%p, aq_rcpt_nxt=%p\n", aq_rcpt, aq_rcpt_nxt)); aq_rcpt_print(aq_rcpt); #endif /* QMGR_DEBUG > 1 */ ret = aq_waitq_add(aq_ctx, aq_rcpt_nxt, tm, AQWQ_DA, false); /* AQR_SET_FLAG(aq_rcpt_nxt, AQR_FL_WAIT4UPD); */ QM_LEV_DPRINTF(3, (QM_DEBFP, "sev=DBG, func=aq_rcptsent2da, aq_rcpt_nxt=%p, aq_waitq_add=%x\n", aq_rcpt_nxt, ret)); aq_rcpt_nxt = AQR_DA_SUCC(aq_rcpt_nxt); } while (aq_rcpt_nxt != aq_rcpt); tm = aq_waitq_first_tmo(aq_ctx, AQWQ_DA, false); if (tm > 0) ret = qmgr_set_aq_cleanup(aq_ctx->aq_qmgr_ctx->qmgr_cleanup_ctx, tm, true); else QM_LEV_DPRINTF(3, (QM_DEBFP, "sev=DBG, func=aq_rcptsent2da, expt=%7ld\n", (long) tm)); if ((!sm_is_err(ret) && thr_unl_no_err(locktype)) || (sm_is_err(ret) && thr_unl_if_err(locktype))) { r = pthread_mutex_unlock(&aq_ctx->aq_mutex); SM_ASSERT(r == 0); if (r != 0 && sm_is_success(ret)) ret = sm_error_perm(SM_EM_AQ, r); } aq_rsnd_ctx_free(aq_rsnd_ctx); return ret; }