/*
* Copyright (c) 2002-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: edbr.c,v 1.19 2006/05/02 17:13:38 ca Exp $")
#include "sm/error.h"
#include "sm/memops.h"
#include "sm/assert.h"
#include "sm/reccom.h"
#include "sm/rcb.h"
#include "sm/qmgr-int.h"
#include "sm/actdb-int.h"
#include "edb-int.h"
#include "sm/edb.h"
#include "sm/pthread.h"
/*
** EDB_RD_OPEN -- open a read cursor
**
** Parameters:
** edb_ctx -- EDB context
** pedb_cursor -- pointer to EDB cursor (output)
**
** Returns:
** usual sm_error code
*/
sm_ret_T
edb_rd_open(edb_ctx_P edb_ctx, edb_cursor_P *pedb_cursor)
{
int r;
SM_ASSERT(edb_ctx != NULL);
SM_ASSERT(pedb_cursor != NULL);
r = edb_ctx->edb_bdb->cursor(edb_ctx->edb_bdb, NULL, pedb_cursor, 0);
if (r != 0)
return sm_error_perm(SM_EM_EDB, r);
return SM_SUCCESS;
}
/*
** EDB_RD_CLOSE -- close read cursor
**
** Parameters:
** edb_ctx -- EDB context
** edb_cursor -- EDB cursor
**
** Returns:
** usual sm_error code
*/
sm_ret_T
edb_rd_close(edb_ctx_P edb_ctx, edb_cursor_P edb_cursor)
{
int r;
SM_ASSERT(edb_ctx != NULL);
SM_ASSERT(edb_cursor != NULL);
r = edb_cursor->c_close(edb_cursor);
if (r != 0)
return sm_error_perm(SM_EM_EDB, r);
return SM_SUCCESS;
}
/*
** EDB_RD_NEXT -- read next entry
**
** Parameters:
** edb_ctx -- EDB context
** edb_cursor -- EDB cursor
** edb_req -- request: contains key to read, rcb to fill (I/O)
**
** Returns:
** usual sm_error code
*/
sm_ret_T
edb_rd_next(edb_ctx_P edb_ctx, edb_cursor_P edb_cursor, edb_req_P edb_req)
{
sm_rcb_P rcb;
sm_ret_T ret;
int r;
size_t l;
DBT db_key, db_data;
SM_ASSERT(edb_ctx != NULL);
SM_ASSERT(edb_req != NULL);
r = pthread_mutex_lock(&edb_ctx->edb_mutex);
SM_LOCK_OK(r);
if (r != 0)
{
/* LOG? */
return sm_error_perm(SM_EM_EDB, r);
}
/* XXX This should be a transaction... check BDB doc */
ret = SM_SUCCESS;
rcb = edb_req->edb_req_rcb;
sm_memzero(&db_key, sizeof(db_key));
sm_memzero(&db_data, sizeof(db_data));
db_key.flags = DB_DBT_USERMEM;
db_key.data = edb_req->edb_req_id;
db_key.ulen = sizeof(edb_req->edb_req_id); /* SMTP_ID_SIZE */
db_data.flags = DB_DBT_USERMEM;
db_data.data = sm_rcb_data(rcb);
db_data.ulen = sm_rcb_getsize(rcb);
ret = SM_SUCCESS;
r = edb_cursor->c_get(edb_cursor, &db_key, &db_data, DB_NEXT);
l = db_data.size;
if (r == DB_BUFFER_SMALL && l < EDB_RC_MAXSZ && sm_rcb_getsize(rcb) < l)
{
l = (l + 1023) & ~1023; /* round to 1024; see BDB docs */
if (!sm_is_err(sm_rcb_resize_data(rcb, l)))
{
db_data.data = sm_rcb_data(rcb);
db_data.ulen = sm_rcb_getsize(rcb);
r = edb_cursor->c_get(edb_cursor, &db_key, &db_data,
DB_NEXT);
l = db_data.size;
}
}
if (r != 0)
ret = sm_error_perm(SM_EM_EDB, r);
/* How to handle DB_NOTFOUND? */
else if (l < sm_rcb_getmax(rcb))
sm_rcb_setlen(edb_req->edb_req_rcb, db_data.size);
/* fall through for unlocking */
r = pthread_mutex_unlock(&edb_ctx->edb_mutex);
SM_ASSERT(r == 0);
if (r != 0 && sm_is_success(ret))
ret = sm_error_perm(SM_EM_EDB, r);
/* cleanup? */
return ret;
}
/*
** EDB_GET_TYPE -- extract type from edb_req
**
** Parameters:
** edb_req -- request: contains key to read, rcb to fill (I/O)
**
** Returns:
** >0: type
** <0: usual sm_error code
*/
sm_ret_T
edb_get_type(edb_req_P edb_req)
{
sm_rcb_P rcb;
sm_ret_T ret;
uint32_t v, l, rt, tl;
SM_ASSERT(edb_req != NULL);
rcb = edb_req->edb_req_rcb;
ret = sm_rcb_open_dec(rcb);
/* Total length of record */
ret = sm_rcb_getuint32(rcb, &tl);
if (sm_is_err(ret))
goto error;
if (tl > EDB_RC_MAXSZ || tl > sm_rcb_getlen(rcb))
goto err0;
/* transaction status */
ret = sm_rcb_get3uint32(rcb, &l, &rt, &v);
if (sm_is_err(ret))
goto error;
if (l != 4 || (rt != RT_EDB_TA_ST && rt != RT_EDBR_ST
&& rt != RT_EDB_VERSION))
goto err0;
(void) sm_rcb_close_dec(rcb);
if (sm_is_err(ret))
goto error;
return (rt == RT_EDB_TA_ST) ? EDB_REQ_TA
: ((rt == RT_EDBR_ST) ? EDB_REQ_RCPT : EDB_REQ_VRS);
err0:
ret = sm_error_perm(SM_EM_EDB, SM_E_PR_ERR);
error:
(void) sm_rcb_close_decn(rcb);
/* cleanup? */
return ret;
}
syntax highlighted by Code2HTML, v. 0.9.1