/*
* 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: t-edbi-0.c,v 1.10 2007/06/18 04:42:31 ca Exp $")
#include "sm/assert.h"
#include "sm/magic.h"
#include "sm/error.h"
#include "sm/memops.h"
#include "sm/test.h"
#include "sm/edb.h"
#include "sm/edbcnf.h"
#include "sm/actdb-int.h"
#define QMGR_DEBUG_DEFINE 1
#include "sm/qmgrdbg.h"
#include "edb-int.h"
/*
** Write some DEFEDB entries and read them back to check whether it worked.
** Interactive to perform some other operations.
** This is mostly a program to play around and see what happens, it
** does not run as a test program.
*/
#define RCPT_MAX_LEN 256
/* Options for test; use bitmap? */
#define OPT_NO_DEL 1
#define OPT_INTER 0
static sm_ret_T
cmp_aq_rcpt(aq_rcpt_P aq_rcpt, aq_rcpt_P aq_rcpt_rd)
{
SM_TEST(sm_memeq(aq_rcpt->aqr_ss_ta_id,
aq_rcpt_rd->aqr_ss_ta_id, SMTP_STID_SIZE));
SM_TEST(sm_memeq(sm_str_data(aq_rcpt->aqr_pa),
sm_str_data(aq_rcpt_rd->aqr_pa),
sm_str_getlen(aq_rcpt->aqr_pa)));
if (aq_rcpt->aqr_msg != NULL && aq_rcpt_rd->aqr_msg != NULL)
{
SM_TEST(sm_memeq(sm_str_data(aq_rcpt->aqr_msg),
sm_str_data(aq_rcpt_rd->aqr_msg),
sm_str_getlen(aq_rcpt->aqr_msg)));
}
SM_TEST(aq_rcpt->aqr_addrs[0].aqra_ipv4 ==
aq_rcpt_rd->aqr_addrs[0].aqra_ipv4);
SM_TEST(aq_rcpt->aqr_da_idx == aq_rcpt_rd->aqr_da_idx);
SM_TEST(aq_rcpt->aqr_st_time == aq_rcpt_rd->aqr_st_time);
SM_TEST(aq_rcpt->aqr_idx == aq_rcpt_rd->aqr_idx);
SM_TEST(aq_rcpt->aqr_status == aq_rcpt_rd->aqr_status);
SM_TEST(aq_rcpt->aqr_tries == aq_rcpt_rd->aqr_tries);
SM_TEST(aq_rcpt->aqr_next_try == aq_rcpt_rd->aqr_next_try);
SM_TEST(aq_rcpt->aqr_last_try == aq_rcpt_rd->aqr_last_try);
return SM_SUCCESS;
}
static sm_ret_T
chg_rcpt(aq_rcpt_P aq_rcpt, int ta, int pid, int index)
{
sessta_id_T ta_id;
sm_str_P str;
sm_ret_T ret;
char buf[RCPT_MAX_LEN];
/* lots of stuff just to get a valid aq_rcpt entry... */
ret = SM_SUCCESS;
sm_snprintf(ta_id, sizeof(ta_id), SMTPS_STID_FORMAT,
(ulonglong_T) ta, pid);
SESSTA_COPY(aq_rcpt->aqr_ss_ta_id, ta_id);
sm_snprintf(buf, sizeof(buf), "<a-%d@b.c>", index);
str = sm_str_scpy0(NULL, buf, RCPT_MAX_LEN);
if (aq_rcpt->aqr_pa != NULL)
sm_str_free(aq_rcpt->aqr_pa);
aq_rcpt->aqr_pa = str;
sm_snprintf(buf, sizeof(buf), "451 Just some text %d", index);
str = sm_str_scpy0(NULL, buf, RCPT_MAX_LEN);
if (aq_rcpt->aqr_msg != NULL)
sm_str_free(aq_rcpt->aqr_msg);
aq_rcpt->aqr_msg = str;
/* would require htonl, but not really needed here */
aq_rcpt->aqr_addrs[0].aqra_ipv4 = 0x7f000001;
aq_rcpt->aqr_addrs[0].aqra_expt = 0x7fffffff;
aq_rcpt->aqr_addrs[0].aqra_pref = 1;
aq_rcpt->aqr_addr_max = 1;
aq_rcpt->aqr_da_idx = 0;
aq_rcpt->aqr_st_time = 123456;
aq_rcpt->aqr_idx = index;
aq_rcpt->aqr_status = AQR_ST_NEW;
aq_rcpt->aqr_tries = 3;
aq_rcpt->aqr_last_try = 123567;
aq_rcpt->aqr_next_try = 123789;
return ret;
}
static sm_ret_T
chg_req_rcpt(edb_req_P edb_req, int ta, int pid, int index)
{
sessta_id_T ta_id;
sm_ret_T ret;
ret = SM_SUCCESS;
sm_snprintf(ta_id, sizeof(ta_id), SMTPS_STID_FORMAT,
(ulonglong_T) ta, pid);
sm_snprintf(edb_req->edb_req_id, sizeof(edb_req->edb_req_id),
SMTP_RCPTID_FORMAT, ta_id, index);
edb_req->edb_req_type = EDB_REQ_RCPT;
return ret;
}
static aq_rcpt_P
new_rcpt(void)
{
aq_rcpt_P aq_rcpt;
aq_rcpt = (aq_rcpt_P) sm_zalloc(sizeof(*aq_rcpt));
SM_TEST(aq_rcpt != NULL);
if (aq_rcpt == NULL)
return NULL;
aq_rcpt->aqr_addrs = (aq_raddr_P) sm_malloc(sizeof(*(aq_rcpt->aqr_addrs)));
if (aq_rcpt->aqr_addrs == NULL)
return NULL;
#if AQ_RCPT_CHECK
aq_rcpt->sm_magic = SM_AQ_RCPT_MAGIC;
#endif /* AQ_TA_CHECK */
return aq_rcpt;
}
static sm_ret_T
chg_req_ta(edb_req_P edb_req, int ta, int pid)
{
sm_ret_T ret;
ret = SM_SUCCESS;
sm_snprintf(edb_req->edb_req_id, sizeof(edb_req->edb_req_id),
SMTPS_STID_FORMAT, (ulonglong_T) ta, pid);
edb_req->edb_req_type = EDB_REQ_TA;
return ret;
}
static sm_ret_T
cmp_aq_ta(aq_ta_P aq_ta, aq_ta_P aq_ta_rd)
{
SM_TEST(sm_memeq(sm_str_data(aq_ta->aqt_mail->aqm_pa),
sm_str_data(aq_ta_rd->aqt_mail->aqm_pa),
sm_str_getlen(aq_ta->aqt_mail->aqm_pa)));
#if 0
SM_TEST(aq_rcpt->aqr_status == aq_rcpt_rd->aqr_status);
#endif /* 0 */
return SM_SUCCESS;
}
static sm_ret_T
chg_ta(aq_ta_P aq_ta, int ta, int pid, int index)
{
sessta_id_T ta_id;
sm_str_P str;
sm_ret_T ret;
char mail_pa[RCPT_MAX_LEN];
/* lots of stuff just to get a valid aq_ta entry... */
ret = SM_SUCCESS;
sm_snprintf(ta_id, sizeof(ta_id), SMTPS_STID_FORMAT,
(ulonglong_T) ta, pid);
SESSTA_COPY(aq_ta->aqt_ss_ta_id, ta_id);
sm_snprintf(mail_pa, sizeof(mail_pa), "<x-%d@y.z>", index);
str = sm_str_scpy0(NULL, mail_pa, RCPT_MAX_LEN);
aq_ta->aqt_mail->aqm_pa = str;
aq_ta->aqt_st_time = 123457;
aq_ta->aqt_rcpts_tot = 4; /* total number recipients */
aq_ta->aqt_rcpts_left = 4; /* rcpts still to deliver */
aq_ta->aqt_rcpts_temp = 1;
aq_ta->aqt_rcpts_perm = 0;
aq_ta->aqt_rcpts_ar = 4;
aq_ta->aqt_state = 400;
aq_ta->aqt_cdb_id = sm_cstr_scpyn((const uchar *) ta_id, SMTP_STID_SIZE);
SM_TEST(aq_ta->aqt_cdb_id != NULL);
return ret;
}
static aq_ta_P
new_ta(void)
{
aq_ta_P aq_ta;
aq_ta = (aq_ta_P) sm_zalloc(sizeof(*aq_ta));
SM_TEST(aq_ta != NULL);
if (aq_ta == NULL)
return NULL;
aq_ta->aqt_mail = (aq_mail_P) sm_malloc(sizeof(*(aq_ta->aqt_mail)));
SM_TEST(aq_ta->aqt_mail != NULL);
if (aq_ta->aqt_mail == NULL)
return NULL;
#if AQ_TA_CHECK
aq_ta->sm_magic = SM_AQ_TA_MAGIC;
#endif /* AQ_TA_CHECK */
return aq_ta;
}
static void
free_rcpt(aq_rcpt_P aq_rcpt)
{
if (aq_rcpt == NULL)
return;
if (aq_rcpt->aqr_pa != NULL)
SM_STR_FREE(aq_rcpt->aqr_pa);
sm_free(aq_rcpt);
}
static void
free_ta(aq_ta_P aq_ta)
{
if (aq_ta == NULL)
return;
if (aq_ta->aqt_mail != NULL)
{
SM_STR_FREE(aq_ta->aqt_mail->aqm_pa);
SM_FREE(aq_ta->aqt_mail);
}
SM_CSTR_FREE(aq_ta->aqt_cdb_id);
sm_free(aq_ta);
}
static void
edbi0(int opts)
{
sm_ret_T ret;
edb_ctx_P edb_ctx;
aq_ctx_P aq_ctx;
aq_ctx_T aq_ctx_s;
aq_rcpt_P aq_rcpt;
aq_rcpt_P aq_rcpt_rd;
aq_ta_P aq_ta;
aq_ta_P aq_ta_rd;
smtp_status_T rcpt_st;
edb_req_P edb_req;
int i;
edb_ctx = NULL;
aq_ctx = &aq_ctx_s;
edb_req = NULL;
aq_ta = NULL;
aq_ta_rd = NULL;
aq_rcpt = NULL;
aq_rcpt_rd = NULL;
ret = edb_open(NULL, NULL, NULL, &edb_ctx);
SM_TEST(ret == SM_SUCCESS);
if (sm_is_err(ret))
return;
ret = aq_open(NULL, &aq_ctx, 256, 0);
SM_TEST(ret == SM_SUCCESS);
if (sm_is_err(ret))
goto error;
aq_rcpt = new_rcpt();
SM_TEST(aq_rcpt != NULL);
if (aq_rcpt == NULL)
goto error;
aq_rcpt_rd = new_rcpt();
SM_TEST(aq_rcpt_rd != NULL);
if (aq_rcpt_rd == NULL)
goto error;
aq_ta = new_ta();
SM_TEST(aq_ta != NULL);
if (aq_ta == NULL)
goto error;
aq_ta_rd = new_ta();
SM_TEST(aq_ta_rd != NULL);
if (aq_ta_rd == NULL)
goto error;
/* no entries */
ret = edb_wr_status(edb_ctx, NULL);
SM_TEST(ret == SM_SUCCESS);
ret = chg_ta(aq_ta, 0, 1, 0);
SM_TEST(ret == SM_SUCCESS);
ret = edb_ta_app(edb_ctx, aq_ta, NULL, 450);
SM_TEST(ret == SM_SUCCESS);
ret = edb_wr_status(edb_ctx, NULL);
SM_TEST(ret == SM_SUCCESS);
if (sm_is_err(ret))
goto error;
ret = chg_rcpt(aq_rcpt, 0, 1, 0);
SM_TEST(ret == SM_SUCCESS);
rcpt_st = 451;
ret = edb_rcpt_app(edb_ctx, aq_rcpt, NULL, rcpt_st);
SM_TEST(ret == SM_SUCCESS);
ret = edb_wr_status(edb_ctx, NULL);
SM_TEST(ret == SM_SUCCESS);
if (sm_is_err(ret))
goto error;
/* add some recipient data */
for (i = 0; i < 4; i++)
{
ret = chg_rcpt(aq_rcpt, i, 1, 2);
SM_TEST(ret == SM_SUCCESS);
rcpt_st = 452 + i;
ret = edb_rcpt_app(edb_ctx, aq_rcpt, NULL, rcpt_st);
SM_TEST(ret == SM_SUCCESS);
}
/* write it out */
ret = edb_wr_status(edb_ctx, NULL);
SM_TEST(ret == SM_SUCCESS);
if (sm_is_err(ret))
goto error;
ret = edb_req_new(edb_ctx, EDB_RQF_NONE, &edb_req, false);
SM_TEST(ret == SM_SUCCESS);
if (sm_is_err(ret))
goto error;
/* read ta data back and compare */
ret = chg_req_ta(edb_req, 0, 1);
SM_TEST(ret == SM_SUCCESS);
ret = chg_ta(aq_ta, 0, 1, 0);
SM_TEST(ret == SM_SUCCESS);
ret = edb_rd_req(edb_ctx, edb_req);
SM_TEST(ret == SM_SUCCESS);
ret = edb_ta_dec(edb_req, aq_ta_rd);
SM_TEST(ret == SM_SUCCESS);
aq_ta->aqt_state = 400;
ret = cmp_aq_ta(aq_ta, aq_ta_rd);
SM_TEST(ret == SM_SUCCESS);
/* read rcpt data back and compare */
ret = chg_req_rcpt(edb_req, 0, 1, 0);
SM_TEST(ret == SM_SUCCESS);
ret = chg_rcpt(aq_rcpt, 0, 1, 0);
SM_TEST(ret == SM_SUCCESS);
ret = edb_rd_req(edb_ctx, edb_req);
SM_TEST(ret == SM_SUCCESS);
ret = edb_rcpt_dec(edb_req, aq_rcpt_rd);
SM_TEST(ret == SM_SUCCESS);
aq_rcpt->aqr_status = 451;
ret = cmp_aq_rcpt(aq_rcpt, aq_rcpt_rd);
SM_TEST(ret == SM_SUCCESS);
/* read rcpt data back and compare */
for (i = 0; i < 4; i++)
{
ret = chg_rcpt(aq_rcpt, i, 1, 2);
SM_TEST(ret == SM_SUCCESS);
aq_rcpt->aqr_status = 452 + i;
ret = chg_req_rcpt(edb_req, i, 1, 2);
SM_TEST(ret == SM_SUCCESS);
ret = edb_rd_req(edb_ctx, edb_req);
SM_TEST(ret == SM_SUCCESS);
ret = edb_rcpt_dec(edb_req, aq_rcpt_rd);
SM_TEST(ret == SM_SUCCESS);
ret = cmp_aq_rcpt(aq_rcpt, aq_rcpt_rd);
SM_TEST(ret == SM_SUCCESS);
SM_STR_FREE(aq_rcpt->aqr_pa);
}
if (opts == OPT_NO_DEL)
goto done;
if (opts == OPT_INTER)
{
bool stop;
int c;
stop = false;
while ((c = getchar()) != EOF && !stop)
{
switch (c)
{
case 'c':
ret = edb_ctx->edb_bdbenv->txn_checkpoint(
edb_ctx->edb_bdbenv,
/*
kbyte
If the kbyte parameter is non-zero, a checkpoint will be done
if more than kbyte kilobytes of log data have been written
since the last checkpoint.
min
If the min parameter is non-zero, a checkpoint will be done if
more than min minutes have passed since the last checkpoint.
*/
/* u_int32_t kbyte, u_int32_t min */
0, 0, 0);
if (ret != 0)
edb_ctx->edb_bdbenv->err(
edb_ctx->edb_bdbenv, ret,
"checkpoint");
break;
case 's':
stop = true;
break;
default:
break;
}
}
}
/* Delete rcpts: directly */
for (i = 0; i < 2; i++)
{
ret = chg_rcpt(aq_rcpt, i, 1, 2);
SM_TEST(ret == SM_SUCCESS);
ret = chg_req_rcpt(edb_req, i, 1, 2);
SM_TEST(ret == SM_SUCCESS);
ret = edb_rcpt_rm(edb_ctx, edb_req->edb_req_id);
SM_TEST(ret == SM_SUCCESS);
}
/* Delete rcpts: add requests */
for (i = 2; i < 4; i++)
{
ret = chg_rcpt(aq_rcpt, i, 1, 2);
SM_TEST(ret == SM_SUCCESS);
ret = chg_req_rcpt(edb_req, i, 1, 2);
SM_TEST(ret == SM_SUCCESS);
ret = edb_rcpt_rm_req(edb_ctx, edb_req->edb_req_id, NULL);
SM_TEST(ret == SM_SUCCESS);
}
/* Delete rcpts: commit requests */
ret = edb_wr_status(edb_ctx, NULL);
SM_TEST(ret == SM_SUCCESS);
done:
free_rcpt(aq_rcpt);
free_rcpt(aq_rcpt_rd);
free_ta(aq_ta);
free_ta(aq_ta_rd);
ret = edb_req_rel(edb_ctx, edb_req, 0, THR_NO_LOCK);
SM_TEST(ret == SM_SUCCESS);
ret = aq_close(aq_ctx);
SM_TEST(ret == SM_SUCCESS);
ret = edb_close(edb_ctx);
SM_TEST(ret == SM_SUCCESS);
return;
error:
/* always close db */
ret = edb_close(edb_ctx);
SM_TEST(ret == SM_SUCCESS);
return;
}
int
main(int argc, char *argv[])
{
int opts, c;
opts = 0;
while ((c = getopt(argc, argv, "d")) != -1)
{
switch (c)
{
case 'd':
opts = OPT_NO_DEL;
break;
default:
/*
usage(argv[0]);
*/
return 1;
}
}
sm_test_begin(argc, argv, "test edb 0");
/* Ignore result, directory may already exist */
(void) mkdir(EDB_HOME, 0700);
edbi0(opts);
return sm_test_end();
}
syntax highlighted by Code2HTML, v. 0.9.1