/* ----------------------------------------------------------------------------
 * Raima Database Manager
 *
 * Copyright (c) 2001-2008 Birdstep Technology Inc.,  All rights reserved.
 *
 * Use of this software, whether in source code format, or in executable,
 * binary object code form, is governed by the Birdstep LICENSE which
 * is fully described in the LICENSE.TXT file, included within this
 * distribution of files.
 * ----------------------------------------------------------------------------
 */
#if !defined(__DBXTRN_H)
#define __DBXTRN_H

#include "base.h"
#include "dbtype.h"

#ifdef __cplusplus
extern "C" {
#endif

/* Database Dictionary Tables */

#define LOCK_STACK_SIZE    10

struct TASK_S;

typedef void (EXTERNAL_FCN *ERRORPROCA)(int32_t, char *);
typedef void (EXTERNAL_FCN *ERRORPROC2A)(int32_t, const char *, void *, struct TASK_S *);
#if !defined(RDM_NO_UNICODE)
typedef void (EXTERNAL_FCN *ERRORPROCW)(int32_t, wchar_t *);
typedef void (EXTERNAL_FCN *ERRORPROC2W)(int32_t, const wchar_t *, void *, struct TASK_S *);
#endif

/* used to verify sanity of task pointer */
#define TASK_MAGIC1  0x7d24a90f
#define TASK_MAGIC2  0xb85ecd62
#define DB_MAGIC     0xa4f73bc9
#define CURSOR_MAGIC 0x1157aa09

typedef struct db_crypt_map 
{
    const char          *name;   /* the database name */
    ENC                  enc;    /* the encryption context associated with this db */
    struct db_crypt_map *next;   /* the next map in the list */
} DB_CRYPT_MAP;

/* database table entry declaration */
typedef struct DB_ENTRY_S
{
    uint32_t            magic;
    DB_ADDR             curr_rec;

    /* Dictionary */
    SCHEMA_ENTRY       *dbd;

    /* size and offsets for this db */
    uint16_t            dba_size;          /* database address size (in bytes) */
    uint16_t            faddr_size;        /* faddr size (in bytes) */
    uint16_t            vaddr_size;        /* vaddr size (in bytes) */
    uint16_t            mem_ptr_size;      /* mem_ptr size (in bytes) */
    uint16_t            mp_owner;          /* owner offset for mem_ptr */
    uint16_t            mp_prev;           /* prev offset for mem_ptr */
    uint16_t            mp_next;           /* next offset for mem_ptr */
    uint16_t            set_ptr_size;      /* set_ptr size (in bytes) */
    uint16_t            sp_members;        /* members offset for set_ptr */
    uint16_t            sp_first;          /* first offset for set_ptr */
    uint16_t            sp_last;           /* last offset for set_ptr */
    uint16_t            rec_hdr_size;      /* record header size (in bytes) */
    uint32_t            max_files;         /* max files allowed in this db */
    uint64_t            max_pages;         /* max pages per file in this db */
    uint64_t            max_vardataslots;  /* max slots in a vardata file for this db */
    uint64_t            max_records;       /* max records per file in this db */

    /* scope: size_ft */
    size_t              lp_size;      /* size of lock_pkt allocation */
    size_t              fp_size;      /* size of free_pkt allocation */
    TFS_LM_FREE        *free_pkt;

    /* scope: size_st */
    DB_ADDR            *curr_own;
    DB_ADDR            *curr_mem;

    /* scope: size_fd */
    uint32_t            keyl_cnt;
    uint32_t            no_of_keys;
    uint32_t            no_of_hashs;

    /* scope: no_of_blobs */
    BLOB_INFO          *blob_info;  /* [WLW] formerly indexed by blob_offset */
    uint16_t            no_of_blobs;

    /* Keys */
    uint16_t            key_size;     /* Must be as big as any compound
                                      key field, or key file slot. */
    KEY_INFO           *key_info;
    KEY_INFO           *curkey;
    HASH_INFO          *hash_info;
    HASH_INFO          *curhash;
    char               *key_buff1;         /* Buffers for expanding com- */
    char               *key_buff2;         /* pound keys to full length. */

    B_BT                btSetKey;            /* key list for d_makenew */
    DB_ADDR             sysdba;              /* database address of system record */
    int16_t             db_ver;              /* version of dbd file */
    char                endian;              /* endianess of dbd file */
    char                dba_type;            /* dba type of dbd file */
    char                string_format;       /* string format of dbd file */
    uint16_t            db_flags;            /* e.g. INMEMORY */
    DB_READ_ONLY_OPTS   db_read_only;      /* is this database read-only */
    DB_BOOLEAN          rot;                 /* do we have a ROT open on this database */
    struct TASK_S      *task;

    const RECORD_ENTRY *rn_rt;   /* Last record type supplied to recfrst/recset */
    DB_ADDR             rn_dba;     /* Last db addr computed by recfrst/recset/recnext */

    /* misc. informatino */
    int32_t             use_locale_sort;

    /* union information */
    uint16_t            no_of_unions;
    DB_INSTANCE        *db_inst;

    /* encryption context */
    char               *enc_buff;  /* buffer for page encryption */
    
    /* cursor information */
    struct DB_CURSOR_S *cursors;
} DB_ENTRY;

typedef DB_ENTRY       *RDM_DB;
typedef const DB_ENTRY *RDM_DB_C;

typedef struct TASK_S
{
    int32_t              db_status;
    RT_CONN_INFO        *tfs_conns;
    char                *dbuserid;
    uint32_t             magic1;
    PSP_MEMTAG           tag;

    /* Open databases */
    int32_t              curr_db;
    int32_t              set_db;
    uint16_t             no_of_dbs;
    DB_ENTRY           **db_table;     /* scope: no_of_dbs */
    RDM_OPEN_MODE        mode;         /* open mode flags */
    uint32_t             initsize;

    /* Logging data */
    LOG_FILE_CTX        *lfh;
    uint32_t             log_curr_file;

    int32_t              errnum;       /* primary error code */
    int32_t              err_ex;       /* secondary error code */
    int32_t              errno_c;      /* O/S error code */
    const char          *errfile;
    int32_t              errline;
    void                *err_userdata;
    void  (EXTERNAL_FCN *error_func)(void);
    int16_t              which_err_func;
    char*                iniFile;
    int32_t              dbopen;
    int16_t              inmemory;
    DB_ULONG             dboptflag;    /* which Dboptions have been explicitly set */
    DB_ULONG             dboptions;
    uint16_t             old_no_of_dbs;

    /* Locking */
    uint32_t             readlocksecs;
    uint32_t             writelocksecs;
    uint32_t             dbwait_time;
    uint32_t             db_timeout;
    int32_t              db_lockmgr;
    uint32_t             drrefresh;

    /* Replication */
    /*void                *repTask; */
    DB_BOOLEAN           bReadOnly;
    DB_BOOLEAN           bRepClient;

    /* Transactions */
    int16_t              tr_precommitted;
    TRANS_TYPE           tr_type;
    TRMARK              *trmark;
    TRMARK              *excl_mark;

    /* Memory pools */
    PSP_POOL             trmark_pool;
    PSP_POOL             usedkeypage_pool;

    /* Miscellaneous */
    char                *vdata_buff1;  /* Buffers for expanding varchar */
    char                *vdata_buff2;  /* fields to full length strings */
    uint16_t             vdata_size;   /* Must be as big as any varchar
                                          field in any open database. */
    DB_BOOLEAN           session_active;
    int32_t              cnt_open_files;    /* count of currently open files */
    TFS_LIB_TYPE         tfs_type;
    char                *default_tfs_hostname;
    uint16_t             default_tfs_port;
    DB_CRYPT_MAP        *dbCryptMap;

#ifdef DBSTAT
    GEN_STATS            gen_stats;
#endif /* DBSTAT */

#if !defined(RDM_NO_HA)
    int32_t              ha_enabled;
#endif /* ! RDM_NO_HA */

    DB_ULONG             db_trace;
    int16_t              db_indent;
    DB_ULONG             db_debug;
    uint32_t             magic2;
    DB_BOOLEAN           rep_slave;
} TASK, DB_TASK;

typedef TASK       *RDM_TASK;
typedef const TASK *RDM_TASK_C;

typedef struct {
    uint32_t updtime;
    F_ADDR   next;
    F_ADDR   prev;
    uint32_t seq;
    uint32_t size;
    char    *data;
} BLOB_HDR;

typedef struct {
    uint32_t updtime;
    F_ADDR4  next;
    F_ADDR4  prev;
    uint32_t seq;
    uint32_t size;
    char    *data;
} BLOB_HDR4;

/** Internal Structure for a generic RDM cursor 
 *
 *   This structure contains the elements required for a generic RDM cursor.
 */
typedef struct DB_CURSOR_S
{
    uint32_t            magic;        /**< Sanity check value */
    RDM_CURSOR_TYPE     type;         /**< The type of cursor */
    RDM_CURSOR_POSITION position;     /**< The type of cursor */
    DB_ENTRY           *db;           /**< RDM db structure */
    PSP_MEMTAG          tag;

    DB_ADDR             curr_dba;     /**< record position for the cursor */
    DB_ADDR             next_dba;     /**< next record position for the cursor (used for set cursors only) */
    const RECORD_ENTRY *rt;           /**< cursor record entry */
    
    CURSOR_POSITION_FCN first;          /**< function pointer for moving the cursor to the first record in the collection */
    CURSOR_POSITION_FCN last;           /**< function pointer for moving the cursor to the last record in the collection */
    CURSOR_POSITION_FCN next;           /**< function pointer for moving the cursor to the next record in the collection */
    CURSOR_POSITION_FCN previous;       /**< function pointer for moving the cursor to the previous record in the collection */
    CURSOR_FIND_BY_DBA_FCN findByDBA;   /**< function pointer for moving the cursor to a specific DBA */
    CURSOR_FIND_BY_KEY_FCN findByKey;   /**< function pointer for moving the cursor to a specific value */
    CURSOR_FIND_BY_RECORD_FCN findByRecord;   /**< function pointer for moving the cursor to a specific value */
    CURSOR_COMPARE_FCN  compare;        /**< function pointer for comparing cursor position */
    CURSOR_COUNT_FCN    count;          /**< function pointer for getting the count of records in a cursor */
    CURSOR_DISCONNECT_FCN disconnect;   /**< function pointer for disconnecting a set cursor */
    CURSOR_GET_RECORD_TYPE_FCN getRecordType; /**< function pointer for getting the cursor's record type */
    CURSOR_CHECK_LOCKING_FCN checkLocking;  /**< function pointer for checking that the required locks are in place */
    
    /* Needed for set cursors */
    const SET_ENTRY *st;         /**< cursor set type */
    DB_ADDR          curr_owner; /**< cursor owner record DBA */
    
    /* Needed for key cursors */
    const FIELD_ENTRY  *key_fd;       /**< cursor key/hash field entry */

    /* Needed for key range cursors */
    char       *range_start_value;
    uint16_t    range_start_num_flds;
    uint16_t    range_start_str_len;
    char       *range_end_value;
    uint16_t    range_end_num_flds;
    uint16_t    range_end_str_len;
    
    BLOB_INFO          *bi;           /**< blob field information */
    KEY_INFO           *ki;           /**< cursor key information */
    HASH_INFO          *hi;           /**< cursor hash information */

    uint32_t            rec_length;    /**< the size of user data for the record */
    uint32_t            buffer_length; /**< the size of record buffer */
    char               *rec_buffer;    /**< buffer for reading/writing records and fields */
    char               *key_buffer;    /**< buffer for storing key value */
    
    struct DB_CURSOR_S  *next_cursor;          /**< pointer to next cursor related to the same db */
    struct DB_CURSOR_S  *prev_cursor;          /**< pointer to previous cursor related to the same db */
} DB_CURSOR;

typedef DB_CURSOR       *RDM_CURSOR;
typedef const DB_CURSOR *RDM_CURSOR_C;

#ifdef __cplusplus
}
#endif

#endif  /* __DBXTRN_H */

