/* * 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. * * $Id: edb.h,v 1.53 2007/06/18 04:42:30 ca Exp $ */ #ifndef SM_EDB_H #define SM_EDB_H 1 #include "sm/generic.h" #include "sm/types.h" #include "sm/magic.h" #include "sm/str.h" #include "sm/time.h" #include "sm/mta.h" #include "sm/io.h" #include "sm/log.h" #include "sm/rcb.h" #include "sm/bdb.h" #include "sm/pthread.h" #include "sm/actdb.h" #include "sm/queue.h" #include "sm/edbdef.h" #include "sm/edbcnf.h" #ifndef SM_REQL_FLE #define SM_REQL_FLE 0 #endif /* Abstraction layer for deferred envelope database (disk only) */ #if 0 XXX Use same data as AQ? /* from db.func.tex: */ #endif /* 0 */ /* ** Default and maximum size for an RCB which is used to hold ta/rcpt ** information for transferring AQ data to/from EDB. ** Note: if the default size is rather large, then a lot of space is ** wasted. If it is too small, then it could happen that an ** encoding/decoding fails because it runs out of memory. ** XXX need to gather some statistics (and count some bytes...) ** The last entry is the "minimum" size for a rcpt RCB: about 96 bytes ** default data and up to 256 bytes of address rounded to the next ** multiple of 2. */ #define EDB_RC_SZ (8 * 1024) #define EDB_RC_MAXSZ (64 * 1024) #define EDB_RC_SMALLSZ 512 typedef struct edb_ctx_S edb_ctx_T, *edb_ctx_P; typedef struct edb_req_S edb_req_T, *edb_req_P; #if 0 typedef struct edb_ta_S edb_ta_T, *edb_ta_P; typedef struct edb_rcpt_S edb_rcpt_T, *edb_rcpt_P; #endif /* 0 */ /* Berkeley DB cursor */ typedef DBC edb_cursor_T, *edb_cursor_P; /* Use enum? */ #define EDB_REQ_TA 0x01 #define EDB_REQ_RCPT 0x02 #define EDB_REQ_VRS 0x04 #define EDB_REQ_TA_DEL 0x11 #define EDB_REQ_RCPT_DEL 0x12 /* request flags */ #define EDB_RQF_NONE 0x00u #define EDB_RQF_SMALL 0x01u /* get a "small" rcb */ #define EDB_RQF_ALLOC 0x02u /* alloc rcb even if there are some in list */ #define EDB_RQF_FREE 0x04u /* free rcb instead of putting it into a list */ #if SM_REQL_FLE #define EDB_RQF_EMERG 0x08u /* get an "emergency" rcb */ #endif /* ** struct to store "requests", i.e., a list of changes for DEFEDB. ** These changes will be committed in a single transaction. ** An RCB stores the data for the DB entry, req_id is the key, ** its content depends on the request type: it's either a ** - transaction ID or a ** - recipient ID */ struct edb_req_S { uint edb_req_type; smtp_id_T edb_req_id; sm_rcb_P edb_req_rcb; SIMPLEQ_ENTRY(edb_req_S) edb_req_link; }; #define EDBREQL_INIT(edb_req_hd) SIMPLEQ_INIT(edb_req_hd) #define EDBREQL_FIRST(edb_req_hd) SIMPLEQ_FIRST(edb_req_hd) #define EDBREQL_END(edb_req_hd) SIMPLEQ_END(edb_req_hd) #define EDBREQL_EMPTY(edb_req_hd) SIMPLEQ_EMPTY(edb_req_hd) #define EDBREQL_NEXT(edb_req) SIMPLEQ_NEXT(edb_req, edb_req_link) #define EDBREQL_PRE(edb_req_hd, edb_req) SIMPLEQ_INSERT_HEAD(edb_req_hd, edb_req, edb_req_link) #define EDBREQL_APP(edb_req_hd, edb_req) SIMPLEQ_INSERT_TAIL(edb_req_hd, edb_req, edb_req_link) #define EDBREQL_REMOVE(edb_req_hd) SIMPLEQ_REMOVE_HEAD(edb_req_hd, edb_req_link) #define SM_IS_EDBREQL(edb_req_hd) SM_ASSERT((edb_req_hd) != NULL) typedef SIMPLEQ_HEAD(, edb_req_S) edb_req_hd_T, *edb_req_hd_P; #if 0 /* ** No extra data structures for EDB rcpts/tas, the data is transferred ** using AQ structures to avoid extra copying. */ /* ** XXX need: ** delivery agent ** host(list) for connection (pre-MX?) */ // struct edb_rcpt_S // { // sessta_id_T edbr_ss_ta_id; /* ta id in SMTPS */ // sm_str_P edbr_pa; /* printable addr */ // smtp_status_T edbr_status; /* status */ // uint edbr_flags; /* flags */ // rcpt_idx_T edbr_idx; /* rcpt idx */ // uint edbr_tries; /* deliver attemts */ // uint32_t edbr_srv_ipv4; /* XXX HACK! */ // time_T edbr_st_time; /* start time (rcvd) */ // time_T edbr_last_try; // time_T edbr_next_try; // // /* XXX parameters? */ // }; // // // /* transaction context */ // struct edb_ta_S // { // sessta_id_T edbta_ta_id; /* ta id in SMTPS */ // sm_str_P edbta_mail_pa; /* printable addr */ // uint edbta_rcpts_tot; /* total number recipients */ // uint edbta_rcpts_left; /* rcpts still to deliver */ // uint edbta_state; // size_t edbta_msg_size; /* KB */ // cdb_id_P edbta_cdb_id; // // /* XXX other times? */ // time_T edbta_st_time; /* start time (received) */ // }; #endif /* 0 */ sm_ret_T edb_open(edb_cnf_P _edb_cnf, const char *_base_path, sm_log_ctx_P _lctx, edb_ctx_P *_edb); sm_ret_T edb_close(edb_ctx_P _edb); sm_ret_T edb_rcpt_app(edb_ctx_P _edb_ctx, aq_rcpt_P _aq_rcpt, edb_req_hd_P _edb_req_hd, int _status); sm_ret_T edb_ta_app(edb_ctx_P _edb_ctx, aq_ta_P _aq_ta, edb_req_hd_P _edb_req_hd, int _status); sm_ret_T edb_wr_status(edb_ctx_P _edb_ctx, edb_req_hd_P _edb_req_hd); sm_ret_T edb_rd_req(edb_ctx_P _edb_ctx, edb_req_P _edb_req); sm_ret_T edb_req_new(edb_ctx_P _edb_ctx, uint32_t _flags, edb_req_P *_pedb_req, bool _lockit); sm_ret_T edb_req_rel(edb_ctx_P _edb_ctx, edb_req_P _edb_req, uint32_t _flags, thr_lock_T _locktype); sm_ret_T edb_rcpt_dec(edb_req_P _edb_req, aq_rcpt_P _aq_rcpt); sm_ret_T edb_ta_dec(edb_req_P _edb_req, aq_ta_P _aq_ta); sm_ret_T edb_rd_open(edb_ctx_P _edb_ctx, edb_cursor_P *_pedb_cursor); sm_ret_T edb_rd_close(edb_ctx_P _edb_ctx, edb_cursor_P _edb_cursor); sm_ret_T edb_rd_next(edb_ctx_P _edb_ctx, edb_cursor_P _edb_cursor, edb_req_P _edb_req); sm_ret_T edb_get_type(edb_req_P _edb_req); sm_ret_T edb_ta_rm(edb_ctx_P _edb_ctx, sessta_id_T _ta_id); sm_ret_T edb_rcpt_rm(edb_ctx_P _edb_ctx, rcpt_id_T _rcpt_id); sm_ret_T edb_ta_rm_req(edb_ctx_P _edb_ctx, sessta_id_T _ta_id, edb_req_hd_P _edb_req_hd); sm_ret_T edb_rcpt_rm_req(edb_ctx_P _edb_ctx, rcpt_id_T _rcpt_id, edb_req_hd_P _edb_req_hd); sm_ret_T edb_req_free(edb_req_P _edb_req); sm_ret_T edb_reql_free(edb_ctx_P _edb_ctx, edb_req_hd_P _edb_reql); sm_ret_T edb_reql_init(edb_ctx_P _edb_ctx, edb_req_hd_P _edb_reql, thr_lock_T _locktype); sm_ret_T edb_chkpt(edb_ctx_P _edb_ctx); sm_ret_T edb_status(edb_ctx_P _edb_ctx, sm_file_T *_fp); #endif /* SM_EDB_H */