/* ----------------------------------------------------------------------------
 * 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(__DBTYPE_H)
#define __DBTYPE_H

#include "dbtype_legacy.h"
#include "transport.h"
#include "base.h"

/* If INTERNAL_H is defined, then this file is being included only for the
    struct definitions needed to use d_internals().  Therefore, much of the
    stuff in here is not needed and may even cause conflicts with other
    software packages.
    If this file is needed for all the other stuff as well as the struct
    definitions and "internal.h" is also needed, then this file must be
    #include-d BEFORE "internal.h" is #include-d.
*/

#include "tfs_lm.h"     /* must be before dbxtrn.h */

/* ---------------------------------------------------------------------------
    Configure the runtime
*/

#ifdef DBSTAT
#include "dbstat.h"     /* must be before dbxtrn.h */
#endif

/* ------------------------------------------------------------------------ */

#define MAX_ALLOC   ((uint32_t) USHRT_MAX)  /* max allocation size */
#define MAX_TABLE   ((uint32_t) INT_MAX)    /* max table entries */

/* Data definitions used for the B-tree algorithms */
#define ROOT_ADDR    ((F_ADDR)  1)            /* node number of root */
#define NULL_NODE    ((F_ADDR) -1)            /* null node pointer */

#if !defined(INTERNAL_H)

#define NOPGHOLD  0
#define PGHOLD_R  1
#define PGHOLD_W  2

#define KEYFIND   0
#define KEYNEXT   1
#define KEYPREV   2
#define KEYFRST   3
#define KEYLAST   4

/* last key status value */
typedef enum {
    KEYINSTEOF,
    KEYINSTINIT,
    KEYINSTFOUND,
    KEYINSTNOTFOUND
} KEY_INST_STATUS;

typedef enum {
    KEYINIT,
    KEYFOUND,
    KEYNOTFOUND,
    KEYREPOS
} KEY_STATUS;

/* last key status value */
typedef enum {
    DB_READ_WRITE    =  0,
    DB_READ_ONLY     =  1,
    DB_RO_BEFORE_ROT =  2
} DB_READ_ONLY_OPTS;

/* mode values for setting options */
#define OPT_OFF 0
#define OPT_ON  1
#define OPT_DEF 2

/* Constants used by d_open and d_iopen */
#define FIRST_OPEN 0
#define INCR_OPEN  1

#endif /* INTERNAL_H */

/* Masks for different files that can be in-memory */
#define IN_MEM_DBD      0x01
#define IN_MEM_LOG      0x04

/* dictionary attribute flags */
#define SORTFLD         0x0001   /* field is a set sort field */
#define STRUCTFLD       0x0002   /* field is sub-field of struct */
#define ONLYKEY         0x0008   /* this key field is the only one in its key file */
#define COMKEYED        0x0010   /* (record contains) or (field included in) compound key */

#define RDM_STATIC      0x0002   /* file/record is static */
#define RDM_TRANSLATE   0x0004   /* record contains varchar fields or other fields that need translation */
#define RDM_CIRCULAR    0x0008   /* file/record is circular */

#define NEEDS_COMMIT    0x0001
#define TEMPORARY       0x0020   /* file is temporary (no lockmgr & or logging) */
#define VARCOMPACT      0x0040   /* file is a compact vardata file (no pointers back to records) */
#define INMEMORY        0x0080   /* file is in-memory */
#define READ_FLAG       0x0100   /* file is in-memory, read */
#define INMEMREAD       (INMEMORY|READ_FLAG)
#define PERSIST_FLAG    0x0200   /* file is in-memory, persistent */
#define INMEMPERSIST    (INMEMORY|READ_FLAG|PERSIST_FLAG)
#define INMEM_FLAGS     (INMEMORY|READ_FLAG|PERSIST_FLAG)

#define DBD_MEM_PATH    0x0400   /* database dictionary was supplied as in-memory structure */
#define DBD_UNICODE     0x0800   /* database dictionary is in unicode format */
#define DBD_DBA8        0x1000   /* database uses dba8 */
#define DBD_BIGENDIAN   0x2000   /* database dictionary is big endian */
#define DBD_UTF32       0x4000   /* database uses 32-bit widechar */

#if !defined(INTERNAL_H)

#ifndef TRUE
#define FALSE  0
#define TRUE   1
#endif

#define DBUSER_ALIVE_BYTE  1
#define DBUSER_COMMIT_BYTE 2

/* Number of elements in a vector */
#define arraysize(v) (sizeof(v)/sizeof(*(v)))

#define AD_DBD_VER_LEN 8 
#define INT_SIZE      sizeof(int32_t)
#define SHORT_SIZE    sizeof(int16_t)
#define LONG_SIZE     sizeof(int32_t)
#define CHAR_SIZE     sizeof(char)
#define DB_ADDR_SIZE  sizeof(DB_ADDR)
#define DB_ADDR4_SIZE sizeof(DB_ADDR4)
#define DB_ADDR8_SIZE sizeof(DB_ADDR8)
#define PGHDRSIZE     4
#define FLOAT_SIZE    sizeof(float)
#define DOUBLE_SIZE   sizeof(double)

#endif /* INTERNAL_H */

#define DBA_NONE      NONE_DBA
#define DBA4_NONE     ((DB_ADDR4) -1)
#define DBA8_NONE     ((DB_ADDR8) -1)
#define DCH_NONE      ((F_ADDR) -1)

#define FILEMASK8     0xFFFFUL
#define FILESHIFT8    48
#define FILEMASK4     0xFFU
#define FILESHIFT4    24

#define RECHDRSIZE    (sizeof(int16_t) + DB_ADDR_SIZE)
#define RECHDRSIZE4   (sizeof(int16_t) + DB_ADDR4_SIZE)
#define RECHDRSIZE8   (sizeof(int16_t) + DB_ADDR8_SIZE)
#define ADDRMASK      db->max_records
#define ADDRMASK4     MAXRECORDS4
#define ADDRMASK8     MAXRECORDS8
#define OPTKEYNDX     0x003F
#define OPTKEY_LIMIT  63
#define OPTKEYSHIFT   10
#define OPTKEYMASK    0xFC00
#define RLBMASK       0x4000
#define DELMASK       0x8000

#define OPTKEYINDEX(flags) ((int16_t) ((((flags) & OPTKEYMASK) >> OPTKEYSHIFT) & OPTKEYNDX) - 1)

typedef enum {TR_UNKNOWN, TR_CHANGE, TR_INIT} TRANS_TYPE;

typedef struct PGZERO_REP_S
{
    DB_ULONG    pz_trans_num;      /* current transaction number */
    REP_DB_TYPE pz_db_type;        /* is this database a master or slave */
}  PGZERO_REP;

#define PGZERO_REP_SIZE sizeof(PGZERO_REP)

/* replication information structure definition */
typedef struct
{
    REP_DB_TYPE      rep_type;               /* replication type of the db */
    TX_FILE          rep_log;                /* the replog file handle   */
    uint16_t         rec_bm_size;            /* total number of records */
    uint16_t         key_bm_size;            /* total number of keys */
    uint16_t         set_bm_size;            /* total number of sets */
    uint32_t         has_schema;
    uint8_t         *key_writelock_bm;       /* key read lock bitmap */
    uint8_t         *rec_writelock_bm;       /* record read lock bitmap */
    uint8_t         *set_writelock_bm;       /* key read lock bitmap */
    char            *precommit_replog_name;  /* temporary replication log file name */
    PSP_FILE_OFFSET  data_offset;            /* offset to the data (after header and schema information) */
    PSP_FILE_OFFSET  rep_log_offset;         /* current offset in rep file */
}  REPLICATION_INFO;

/* Runtime TFS connection definition */
typedef struct _rt_conn_info
{
    TX_USER               userID;
    uint32_t              num_dbs;
    //uint32_t              modified;
    UUID_VAL              uuid;
    struct _rt_conn_info *next;
    struct _rt_conn_info *prev;
} RT_CONN_INFO;

/* set pointer structure definition */
typedef struct _set_ptr4
{
    F_ADDR4  total;     /* total number of members in set */
    DB_ADDR4 first;     /* database address of first member in set */
    DB_ADDR4 last;      /* database address of last member in set */
}  SET_PTR4;

/* set pointer structure definition */
typedef struct
{
    F_ADDR8  total;     /* total number of members in set */
    DB_ADDR8 first;     /* database address of first member in set */
    DB_ADDR8 last;      /* database address of last member in set */
}  SET_PTR8;

/* uno set pointer structure definition */
typedef struct _set_ptr
{
    F_ADDR   total;    /* total number of members in set */
    DB_ADDR  first;    /* database address of first member in set */
    DB_ADDR  last;     /* database address of last member in set */
}  SET_PTR;

/* member pointer structure definition */
typedef struct _mem_ptr4
{
    DB_ADDR4 owner;     /* database address of owner record */
    DB_ADDR4 prev;      /* database address of previous member in set */
    DB_ADDR4 next;      /* database address of next member in set */
}  MEM_PTR4;

/* member pointer structure definition */
typedef struct _mem_ptr8
{
    DB_ADDR8 owner;     /* database address of owner record */
    DB_ADDR8 prev;      /* database address of previous member in set */
    DB_ADDR8 next;      /* database address of next member in set */
}  MEM_PTR8;

/* uno member pointer structure definition */
typedef struct _mem_ptr
{
    DB_ADDR owner;     /* database address of owner record */
    DB_ADDR prev;      /* database address of previous member in set */
    DB_ADDR next;      /* database address of next member in set */
}  MEM_PTR;

/* For replication utility functions */
typedef void *        REP_HANDLE;

/* For RDMHTTP utility functions */
typedef void *        RHS_HANDLE;

/* For d_tfs functions */
typedef void *        TFS_HANDLE;

/* define old tfs lib types for backward compatibility */
#define TFS_LIB_TYPE            TFS_TYPE
#define TFS_LIB_TYPE_TFS        TFS_TYPE_TFS
#define TFS_LIB_TYPE_RPC        TFS_TYPE_RPC
#define TFS_LIB_TYPE_STANDALONE TFS_TYPE_STANDALONE

typedef struct {
    uint32_t           count;
    const char *const *users;
} TFS_USER_LIST;

typedef struct {
    uint32_t              count;
    const wchar_t *const *users;
} TFS_USER_LISTW;

typedef int32_t (EXTERNAL_FCN TFS_XAPI_FCN)(RHS_HANDLE, TX_CONN, const char *, const char *, const char *);

typedef struct tfs_functionmap {
    const char         *name;           /* part of a URL, will not be wchar */
    TFS_XAPI_FCN       *fcn;
} TFS_XAPI_FCNMAP;

typedef struct _tfs_xapi_params {
    const TFS_XAPI_FCNMAP  *xapifcnmap;  /* fcn map for http functions */
    uint16_t                fcnmapsize;  /* number of entries in xapifcnmap */
    const char             *subdocroot;  /* dir under httpdocs for html files */
} TFS_XAPI_PARAMS;

typedef struct _tfs_params {
    uint16_t            port;        /* server listen port */
    uint32_t            rd_only;     /* Use read-only device */
    uint32_t            no_disk;     /* diskless system - True|False */
    uint32_t            max_content_len;  /* maximum content length value for the http server initialization */
    uint32_t            max_buffer_size;  /* maximum buffer length value for the http server initialization */
    uint16_t            verbose;     /* verbose - True|False */
    uint16_t            no_page_ref; /* skip page referencing? */
    const char         *logfile;
    const char         *stdout_file;
    const char         *name;
    TX_CONN_TYPE        transportBitmap;
} TFS_PARAMS;

#if !defined(RDM_NO_UNICODE)
typedef struct _tfs_xapi_paramsw {
    const TFS_XAPI_FCNMAP  *xapifcnmap;  /* fcn map for http functions */
    uint16_t                fcnmapsize;  /* number of entries in xapifcnmap */
    const wchar_t          *subdocroot;  /* dir under httpdocs for html files */
} TFS_XAPI_PARAMSW;

typedef struct _tfs_paramsw {
    uint16_t            port;        /* server listen port */
    uint32_t            rd_only;     /* Use read-only device */
    uint32_t            no_disk;     /* diskless system - True|False */
    uint16_t            verbose;     /* verbose - True|False */
    uint16_t            no_page_ref; /* skip page referencing? */
    const wchar_t      *logfile;
    const wchar_t      *stdout_file;
    const wchar_t      *name;
    TX_CONN_TYPE        transportBitmap;
} TFS_PARAMSW;
#endif

#define LITERAL_NULL_DBA        { 0, 0, 0 }
#define LITERAL_NONE_DBA        { (uint16_t) -1, (FILE_NO) -1, (F_ADDR8) -1 }

static const DB_ADDR NULL_DBA = LITERAL_NULL_DBA;
static const DB_ADDR NONE_DBA = LITERAL_NONE_DBA;

#define DBA_ISNULL(d)       ((d).dba_file == 0 && (d).dba_offset == 0)
#define DBA_ISNONE(d)       ((d).dba_uno == -1 && (d).dba_file == -1 && (d).dba_offset == -1)
#define DBA_EQUAL(d1, d2)       ((d1).dba_uno == (d2).dba_uno && (d1).dba_file == (d2).dba_file && (d1).dba_offset == (d2).dba_offset)

/* max size of set pointer */
/* member count + prior + next */
#define SETP4SIZE  (sizeof(SET_PTR4))
#define SETP8SIZE  (sizeof(SET_PTR8))
#define SP4_MEMBERS (offsetof(SET_PTR4, total))  /* Offset to total members in set ptr */
#define SP8_MEMBERS (offsetof(SET_PTR8, total))  /* Offset to total members in set ptr */
#define SP4_FIRST   (offsetof(SET_PTR4, first))  /* Offset to first member ptr in set ptr */
#define SP8_FIRST   (offsetof(SET_PTR8, first))  /* Offset to first member ptr in set ptr */
#define SP4_LAST    (offsetof(SET_PTR4, last))   /* Offset to last member ptr in set ptr */
#define SP8_LAST    (offsetof(SET_PTR8, last))   /* Offset to last member ptr in set ptr */

#define MEMP4SIZE   (sizeof(MEM_PTR4))           /* Size of member pointer = 3*DB_ADDR_SIZE */
#define MEMP8SIZE   (sizeof(MEM_PTR8))           /* Size of member pointer = 3*DB_ADDR_SIZE */
#define MP4_OWNER   (offsetof(MEM_PTR4, owner))  /* Offset to owner ptr in member ptr */
#define MP8_OWNER  (offsetof(MEM_PTR8, owner))  /* Offset to owner ptr in member ptr */
#define MP4_PREV   (offsetof(MEM_PTR4, prev))   /* Offset to previous member ptr in member ptr */
#define MP8_PREV   (offsetof(MEM_PTR8, prev))   /* Offset to previous member ptr in member ptr */
#define MP4_NEXT   (offsetof(MEM_PTR4, next))   /* Offset to next member ptr in member ptr */
#define MP8_NEXT   (offsetof(MEM_PTR8, next))   /* Offset to next member ptr in member ptr */

/* LMC transport name length in TAF file */
#define LMCTYPELEN      12

#define NAMELEN         32       /* max record/set/field name + null */
#define MAXKEYLEN       256      /* if changed, qdefns.h needs updating */

#if defined(NOT_USED)
#define MAXKEYSIZE      MAXKEYLEN
#endif

#if !defined(INTERNAL_H)

#define DEFIXPAGES      5        /* default number of index cache pages */
#define DEFDBPAGES      100      /* default number of database cache pages */
#define MINIXPAGES      3        /* minimum number of index cache pages */
#define MINDBPAGES      5        /* minimum number of database cache pages */
#define LENVDBID        48
#define DEFDRREFRESH    1000     /* default # of msecs for a dirty-read refresh */

/* Default value for ft_maxpages, i.e.
   default maximum number of pages for in-memory files.
*/
#if 0
#define DEFAULT_MAX_PAGES     2048
#else
#define DEFAULT_MAX_PAGES        0
#endif

#define DEFAULT_HASH_SIZE 1000000

#endif /* INTERNAL_H */

/* record/set lock descriptor */
typedef struct lock_descr
{
    char       fl_type;       /* 'r'ead, 'w'rite, e'x'clusive, 'f'ree */
    char       fl_prev;       /* previous lock type */
    FILE_NO   *fl_list;       /* array of files used by record/set */
    uint32_t   fl_cnt;        /* Number of elements in fl_list */
    DB_BOOLEAN fl_kept;       /* Is lock kept after transaction? */
} LOCK_DESCR;

#define MAXDIMS         3

#define RDM_DATA_FILE    'd'
#define RDM_KEY_FILE     'k'
#define RDM_HASH_FILE    'h'
#define RDM_VARDATA_FILE 'v'
#define RDM_BLOB_FILE    'b'

typedef struct PG0_S
{
    F_ADDR   dchain;                /* delete chain pointer */
    F_ADDR   next;                  /* next page or record slot */
    DB_ULONG timestamp;             /* file's timestamp value */
    F_ADDR   circnext;              /* circ tables only: next record slot */
    uint32_t bdate;                 /* date/time of last backup */
    char     vdb_id[LENVDBID];      /* RDM id mark */
} PG0;

struct pgver;

typedef struct TRMARK_S {
    PSP_FILE_OFFSET  replog_pos;    /* curr pos in replog file for rollback */
    struct TRMARK_S *trnext;
    char             trid[EXPANDABLE];
} TRMARK;

struct RECORD_ENTRY_S;

typedef struct
{
    char     ad_ft_name[FILEPATHLEN];/* name of file */
    uint64_t ad_ft_hashsize;         /* initial size of the hash array */
    F_ADDR8  ad_ft_maxpages;         /* maximum number of pages in a file */
    F_ADDR8  ad_ft_maxslots;         /* maximum number of slots in a file */
    uint16_t ad_ft_slots;            /* record slots per page */
    uint16_t ad_ft_slsize;           /* size of record slots in bytes */
    uint16_t ad_ft_pgsize;           /* size of page */
    uint16_t ad_ft_flags;            /* e.g. STATIC */
    uint16_t ad_ft_ptroffset;        /* for vardata files: offset from start
                                        of slot to delete chain pointer, if
                                        slot is deleted */
    char     ad_ft_type;             /* 'd'ata, 'k'ey, 'v'ardata, 'b'lob, or 'h'ash */
    char     ad_ft_unused[5];        /* padding so this structure aligns correctly */
} AD_FILE_ENTRY;

typedef struct FILE_INSTANCE_S
{
    FILE_NO    fi_fref;            /* lock manager file reference */
    int32_t    fi_applocks;        /* number of read locks or -1 for write lock */
#if defined(RDM_HAS_XLOCKS)
    int32_t    fi_excllocks;       /* number of exclusive locks */
#endif
    int32_t    fi_keptlocks;       /* number of kept locks */
    TX_FILE    fi_txfh;            /* TX file handle */
    DB_BOOLEAN fi_open;            /* TRUE if file is open, FALSE if it is closed */
    uint32_t   fi_lmtimestamp;     /* file timestamp from lock mgr */
    uint32_t   fi_cachetimestamp;  /* previous file timestamp from lock mgr */
    uint64_t   fi_cachetimestamp_time; /* time the fi_cachetimestamp was last updated */
} FILE_INSTANCE;

typedef struct FILE_ENTRY_S
{
    uint64_t       ft_hashsize;        /* initial size of the hash array */
    uint64_t       ft_buckets;         /* number of buckets in a hash file */
    F_ADDR         ft_maxpages;        /* maximum number of pages in a file */
    F_ADDR         ft_maxslots;        /* maximum number of slots in a file */
    FILE_INSTANCE *ft_inst;            /* Information about a particular file instance */
    FILE_NO        ft_ndx;             /* index in file table of this entry */
    uint16_t       ft_slots;           /* record slots per page */
    uint16_t       ft_slsize;          /* size of record slots in bytes */
    uint16_t       ft_pgsize;          /* size of page */
    uint16_t       ft_flags;           /* e.g. STATIC */
    uint16_t       ft_ptroffset;       /* for vardata files: offset from start
                                          of slot to delete chain pointer, if
                                          slot is deleted */
    uint16_t       ft_count;           /* count of the number of items in this file */
    char           ft_name[FILEPATHLEN];/* name of file */
    char           ft_type;            /* 'd'=data, 'k'=key, 'o'=overflow, 'v'=vardata */
} FILE_ENTRY;

typedef struct AD_FIELD_ENTRY_S
{
    char     ad_fd_key;           /* see the #defines just above */
    uint16_t ad_fd_type;          /* see the #defines just above */
    uint16_t ad_fd_len;           /* length of field in bytes */
    uint8_t  ad_fd_prec;          /* precision for decimal type */
    uint8_t  ad_fd_scale;         /* scale for decimal type */
    uint16_t ad_fd_dim[MAXDIMS];  /* size of each array dimension */
    uint16_t ad_fd_keyfile;       /* task->file_table entry for key file */
    uint16_t ad_fd_keyno;         /* key prefix number */
    uint16_t ad_fd_ptr;           /* offset to field in record or 1st compound key field in task->key_table */
    uint16_t ad_fd_rec;           /* record table entry of record containing field */
    uint16_t ad_fd_flags;         /* see the #defines at the top of the file */
    uint16_t ad_fd_extfile;       /* file_table entry for vardata file */
    uint16_t ad_fd_varmax;        /* maximum size in bytes of varchar data
                                     excluding null terminator, which is not stored */
    uint16_t ad_fd_nvptrs;        /* number of pointers to slots in vardata file */
    uint16_t ad_fd_len_ex;        /* length of field in bytes, in external structures passed into runtime
                                     library, i.e. with varchar fields expanded to full size. (same as
                                     fd_len except for varchar fields) */
    uint16_t ad_fd_ptr_ex;        /* offset to field in bytes, in external structures passed into runtime lib
                                     (same as fd_ptr except for fields in records which contain varchars) */
    uint16_t ad_fd_keylen;        /* length of key value stored in B-tree, same as fd_len except for
                                     partial keys - only applies to strings and binary char arrays */
} AD_FIELD_ENTRY;

/* Forward declaration to avoid compiler warnings on the following line */
struct DB_ENTRY_S;

typedef int32_t (*FLDCMP_FCN)(const struct FIELD_ENTRY_S *, const FIELD_DATA *,
        const FIELD_DATA *, const struct DB_ENTRY_S *);

/* =========================================================================
   Type handling defintions
*/
typedef struct FIELD_ENTRY_S
{
    const char *fd_name;          /* field name */
    RDM_TYPE    fd_type;          /* field type */
    char        fd_key;           /* key type */
    uint8_t     fd_prec;          /* field precision for decimal type */
    uint8_t     fd_scale;         /* field scale for decimal type */
    uint16_t    fd_len;           /* length of field in bytes */
    uint16_t    fd_dim[MAXDIMS];  /* size of each array dimension */
    uint16_t    fd_keyfile;       /* task->file_table entry for key file */
    uint16_t    fd_keyno;         /* key prefix number */
    uint16_t    fd_ptr;           /* offset to field in record or 1st compound key field in task->key_table */
    uint16_t    fd_rec;           /* record table entry of record containing field */
    uint16_t    fd_flags;         /* see the #defines at the top of the file */
    uint16_t    fd_extfile;       /* file_table entry for vardata/blob file */
    uint16_t    fd_varmax;        /* maximum size in bytes of varchar data
                                     excluding null terminator, which is not stored */
    uint16_t    fd_nvptrs;        /* number of pointers to slots in vardata file */
    uint16_t    fd_len_ex;        /* length of field in bytes, in external structures passed into runtime
                                     library, i.e. with varchar fields expanded to full size. (same as
                                     fd_len except for varchar fields) */
    uint16_t    fd_ptr_ex;        /* offset to field in bytes, in external structures passed into runtime lib
                                     (same as fd_ptr except for fields in records which contain varchars) */
    uint16_t    fd_keylen;        /* length of key value stored in B-tree, same as fd_len except for
                                     partial keys - only applies to strings and binary char arrays */
    uint16_t    fd_num_struct_flds;
    uint16_t    fd_num_key_flds;
    uint16_t    fd_entries;
    uint16_t    fd_strdim;
    uint32_t    fd_rec_keyno;    /* offset into record key/hash/blob field table (rt_keys/blobs/hashes) */
    uint16_t    fd_use_locale;
    uint32_t    fd_ndx;           /* index in file table of this entry */
    const RDM_TYPE_INFO         *fd_tinfo;
    const FILE_ENTRY            *fd_keyft;
    const FILE_ENTRY            *fd_extft;
    const struct RECORD_ENTRY_S *fd_rt; /* fields record entry */
    const struct KEY_ENTRY_S   **fd_key_flds;
#if defined(RDM_LOCAL_LOCALE)
    psp_locale_t                 fd_locale;
#endif
} FIELD_ENTRY;

#define fd_rec_hashno fd_rec_keyno   /* We are reusing the fd_rec_keyno field for hashes */
#define fd_rec_blobno fd_rec_keyno   /* We are reusing the fd_rec_keyno field for blobs */
#define fd_blobno     fd_keyno       /* We are reusing the fd_keyno field for blobs */
#define fd_hashno     fd_keyno       /* We are reusing the fd_keyno field for blobs */
#define fd_blobfile   fd_extfile
#define fd_blobft     fd_extft
#define fd_hashft     fd_keyft

#define fd_varfile  fd_extfile
#define fd_varft    fd_extft

#define FIRST      'f'
#define LAST       'l'
#define NEXT       'n'

#define ASCENDING  'a'
#define DESCENDING 'd'
#define NOORDER    'n'

typedef struct AA_SET_ENTRY_S
{
    int16_t  aa_st_order;      /* 'f'=first, 'l'=last, 'a'=ascending,
                               'd'=descending, 'n'=no order */
    uint16_t aa_st_own_rt;     /* record table entry of owner */
    uint16_t aa_st_own_ptr;    /* offset to set pointers in record */
    uint16_t aa_st_members;    /* index of first member record in member table */
    uint16_t aa_st_memtot;     /* total number of members of set */
    uint16_t aa_st_flags;      /* unused (formerly indicated timestamps */
} AA_SET_ENTRY;

typedef struct SET_ENTRY_S
{
    const char             *st_name;    /* set name */
    int16_t                 st_order;   /* 'f'=first, 'l'=last, 'a'=ascending,
                                           'd'=descending, 'n'=no order */
    uint16_t                st_own_rt;  /* record table entry of owner */
    uint16_t                st_own_ptr; /* offset to set pointers in record */
    uint16_t                st_members; /* index of first member record in member table */
    uint16_t                st_memtot;  /* total number of members of set */
    uint16_t                st_flags;   /* unused (formerly indicated timestamps */
    uint16_t                st_ndx;     /* index into set table for this entry */
    struct RECORD_ENTRY_S  *st_rt;      /* record table entry for set owner */
    struct MEMBER_ENTRY_S **st_mt;      /* array of member table entries for this set */
} SET_ENTRY;

typedef struct AA_MEMBER_ENTRY_S
{
    uint16_t aa_mt_record;     /* record table entry for this member */
    uint16_t aa_mt_mem_ptr;    /* offset to member ptrs in record */
    uint16_t aa_mt_sort_fld;   /* sort table entry of first sort field */
    uint16_t aa_mt_totsf;      /* total number of sort fields */
} AA_MEMBER_ENTRY;

typedef struct MEMBER_ENTRY_S
{
    uint16_t                mt_record;    /* record table entry for this member */
    uint16_t                mt_mem_ptr;   /* offset to member ptrs in record */
    uint16_t                mt_sort_fld;  /* sort table entry of first sort field */
    uint16_t                mt_totsf;     /* total number of sort fields */
    uint32_t                mt_ndx;       /* index in member table of this entry */
    SET_ENTRY              *mt_st;        /* set entry of set containing this member */
    struct RECORD_ENTRY_S  *mt_rt;        /* record table entry for this member */
    struct SORT_ENTRY_S   **mt_sort_flds; /* array of field entries for sorting */
} MEMBER_ENTRY;

typedef struct AD_SORT_ENTRY_S
{
    uint32_t ad_se_fld;     /* field table entry of sort field */
    uint16_t ad_se_set;     /* set table entry of sorted set */
}  AD_SORT_ENTRY;

typedef struct SORT_ENTRY_S
{
    uint32_t            se_fld;  /* field table entry of sort field */
    uint16_t            se_set;  /* set table entry of sorted set */
    uint32_t            se_ndx;  /* index in sort table of this entry */
    const MEMBER_ENTRY *se_mt;   /* member entry */
    const FIELD_ENTRY  *se_fd;   /* field entry */
}  SORT_ENTRY;

typedef struct AD_RECORD_ENTRY_S
{
    uint16_t ad_rt_file;    /* file table entry of file containing record */
    uint16_t ad_rt_len;     /* total length of record */
    uint16_t ad_rt_data;    /* offset to start of data in record */
    uint32_t ad_rt_fields;  /* first field def in task->field_table */
    uint16_t ad_rt_fdtot;   /* total number of fields in record */
    uint16_t ad_rt_flags;
    uint16_t ad_rt_len_ex;  /* length of record in external format, i.e.
                               with all varchar fields expanded to full
                               size - same as aa_rt_len except in records
                               with varchar fields. */
} AD_RECORD_ENTRY;

typedef struct CRYPT_ENTRY_S
{
    ENC_TYPE ct_enc_type;               /* encryption algorithm for the database */
    uint8_t  ct_data_pw[CRYPTPWLEN];    /* encryption passcode for the file_pw */
    uint8_t  ct_file_pw[CRYPTPWLEN];    /* encryption passcode for the db files */
}  CRYPT_ENTRY;

typedef struct AD_CRYPT_ENTRY_S
{
    uint16_t ad_ct_enc_type;               /* encryption algorithm for the database */
    uint8_t  ad_ct_data_pw[CRYPTPWLEN];    /* encryption password for the file_pw */
    uint8_t  ad_ct_file_pw[CRYPTPWLEN];    /* encryption password for the db files */
}  AD_CRYPT_ENTRY;

struct SCHEMA_ENTRY_S;

typedef struct RECORD_ENTRY_S
{
    const char                  *rt_name;      /* record name */
    uint16_t                     rt_file;      /* file table entry of file containing record */
    uint16_t                     rt_len;       /* total length of record */
    uint16_t                     rt_data;      /* offset to start of data in record */
    uint32_t                     rt_fields;    /* first field def in task->field_table */
    uint16_t                     rt_fdtot;     /* total number of fields in record */
    uint16_t                     rt_flags;
    uint16_t                     rt_len_ex;    /* length of record in external format, i.e.
                                                  with all varchar fields expanded to full
                                                  size - same as rt_len except in records
                                                  with varchar fields. */
    uint16_t                     rt_totndx;    /* index into the record counts in the file */
    uint32_t                     rt_keytot;    /* total number of keys in record */
    uint32_t                     rt_hashtot;   /* total number of hashes in record */
    uint32_t                     rt_noowns;    /* number of sets record is an owner of */
    uint32_t                     rt_nomems;    /* number of sets record is a member of */
    uint32_t                     rt_noblobs;   /* number of blobs in the record */
    uint32_t                     rt_novarchar; /* number of varchar fields in the record */
    uint16_t                     rt_ndx;       /* index into record table for this record */
    const FILE_ENTRY            *rt_ft;        /* owning file */
    const SET_ENTRY            **rt_ownsets;   /* list of sets this record is an owner of */
    const MEMBER_ENTRY         **rt_memsets;   /* list of sets this record is a member of */
    const FIELD_ENTRY          **rt_blobs;     /* list of blob fields in this record */
    const FIELD_ENTRY          **rt_varchar;   /* list of varchar fields in this record */
    const FIELD_ENTRY          **rt_flds;      /* array of fields in this record */
    const FIELD_ENTRY          **rt_keys;      /* array of keys in this record */
    const FIELD_ENTRY          **rt_hashs;     /* array of hashs in this record */
    const struct SCHEMA_ENTRY_S *rt_dbd;
} RECORD_ENTRY;

/* kinds of keys */
#define DB_INDEX_NONE      'n'
#define DB_INDEX_DUPLICATE 'd'
#define DB_INDEX_UNIQUE    'u'
#define DB_INDEX_HASH      'h'

#define IS_UNIQUE_KEY_INDEX(fd)    ((fd)->fd_key == DB_INDEX_UNIQUE)
#define IS_DUPLICATE_KEY_INDEX(fd) ((fd)->fd_key == DB_INDEX_DUPLICATE)

#define IS_KEY_INDEX(fd)        (IS_UNIQUE_KEY_INDEX(fd) || IS_DUPLICATE_KEY_INDEX(fd))
#define IS_HASH_INDEX(fd)       ((fd)->fd_key == DB_INDEX_HASH)
#define IS_NOT_INDEX(fd)        ((fd)->fd_key == DB_INDEX_NONE)

typedef struct AD_KEY_ENTRY_S
{
    uint16_t ad_kt_key;        /* compound key field number */
    uint32_t ad_kt_field;      /* field number of included field */
    uint16_t ad_kt_ptr;        /* offset to start of field data in key,
                                  as stored in database, which may contain
                                  partial strings */
    uint16_t ad_kt_len;        /* length of field data in key, as stored
                                  in database - different from original
                                  field length for varchar and partial
                                  strings */
    uint16_t ad_kt_ptr_ex;     /* offset to start of field data in
                                  external structure passed in from
                                  application, which contains full
                                  strings only */
    uint16_t ad_kt_len_ex;     /* length of field data in external structure
                                  passed in from application - must be same
                                  as fd_len_ex in field definition */
    int16_t  ad_kt_sort;       /* 'a' = ascending, 'd' = descending */
} AD_KEY_ENTRY;

typedef struct KEY_ENTRY_S
{
    uint32_t           kt_key;    /* compound key field number */
    uint32_t           kt_field;  /* field number of included field */
    uint16_t           kt_ptr;    /* offset to start of field data in key,
                                     as stored in database, which may contain
                                     partial strings */
    uint16_t           kt_len;    /* length of field data in key, as stored
                                     in database - different from original
                                     field length for varchar and partial
                                     strings */
    uint16_t           kt_ptr_ex; /* offset to start of field data in
                                     external structure passed in from
                                     application, which contains full
                                     strings only */
    uint16_t           kt_len_ex; /* length of field data in external structure
                                     passed in from application - must be same
                                     as fd_len_ex in field definition */
    int16_t            kt_sort;   /* 'a' = ascending, 'd' = descending */
    const FIELD_ENTRY *kt_fd;     /* pointer to the included field; */
} KEY_ENTRY;

#define PGZERO_TOTAL_COUNT(ft) (((ft)->ft_type == RDM_DATA_FILE) ? (ft)->ft_count : 0)

typedef struct PGZERO8_S
{
    F_ADDR8  pz_dchain;                 /* delete chain pointer */
    F_ADDR8  pz_next;                   /* next available slot number */
    DB_ULONG pz_unused;                 /* obsolete */
    DB_ULONG pz_unused2;                /* padding for obsolete value */
    F_ADDR8  pz_circnext;               /* circ tables only: next slot */
    uint8_t  pz_dbkey[CRYPTPWLEN];      /* encryption passcode for the databases */
    uint8_t  pz_filekey[CRYPTPWLEN];    /* encryption passcode for the database files */
    F_ADDR8  pz_totals[EXPANDABLE];     /* record totals */
} PGZERO8;

/* size of the struct as stored in the files (dba8) */
#define PGZERO8SZ(ft) (offsetof(PGZERO8, pz_totals) + PGZERO_TOTAL_COUNT(ft) * sizeof(F_ADDR8))

/* page zero table entry */
typedef struct PGZERO4_S
{
    F_ADDR4  pz_dchain;                 /* delete chain pointer */
    F_ADDR4  pz_next;                   /* next available slot number */
    DB_ULONG pz_unused;                 /* placeholder for file's timestamp value */
    F_ADDR4  pz_circnext;               /* circ tables only: next slot */
    uint8_t  pz_dbkey[CRYPTPWLEN];      /* encryption passcode for the databases */
    uint8_t  pz_filekey[CRYPTPWLEN];    /* encryption passcode for the database files */
    F_ADDR4  pz_totals[EXPANDABLE];     /* record totals */
}  PGZERO4;

/* size of the struct as stored in the files (dba4) */
#define PGZERO4SZ(ft) (offsetof(PGZERO4, pz_totals) + PGZERO_TOTAL_COUNT(ft) * sizeof(F_ADDR4))

/* page zero table entry */
typedef struct PGZERO_S
{
    DB_BOOLEAN pz_initialized; /* TRUE if the file has just been initialized */
    F_ADDR     pz_dchain;
    F_ADDR     pz_next;
    F_ADDR     pz_circnext;
    uint8_t    pz_dbkey[CRYPTPWLEN];      /* encryption passcode for the databases */
    uint8_t    pz_filekey[CRYPTPWLEN];    /* encryption passcode for the database files */
    F_ADDR    *pz_totals;
}  PGZERO;

typedef const void *PGHNDL;

/* node key search path stack entry: one per level per key field */
typedef struct NODE_PATH_S
{
    F_ADDR   node;  /* node (page) number  */
    uint16_t slot;  /* slot number of key */
} NODE_PATH;

typedef struct {
    FIELD_DATA data;
    DB_ADDR    dba;
} KEY_POSITION;

/* index key information: one entry per key field */
typedef struct KEY_INFO_S
{
    KEY_POSITION            *pos;        /* current position in the index */
    KEY_POSITION             userpos;    /* user data */
    uint32_t                 keysize;    /* maximum size of the key (curr_pos.val
                                            will be allocated to this size */
    uint16_t                 max_lvls;   /* maximum possible levels for key */
    int32_t                  keydir;     /* key direction (via d_keydir) */
    int32_t                  reposdir;   /* key direction (via d_keydir) */
    KEY_STATUS               lstat;      /* status of the key */
    const FIELD_ENTRY       *fd;
    const FILE_ENTRY        *ft;
    struct DB_ENTRY_S       *db;
    struct KEY_INST_INFO_S  *key_inst_info;
} KEY_INFO;

/* index file node structure */
typedef struct
{
    uint32_t last_chgd;         /* date/time of last change of this node */
    uint16_t used_slots;        /* current # of used slots in node */
    char     slots[EXPANDABLE]; /* start of slot area */
} KEY_NODE;

typedef struct _USED_KEY_PAGES
{
    struct _USED_KEY_PAGES *next;
    KEY_NODE               *node;
    PGHNDL                  pg;
    F_ADDR                  addr;
    int32_t                 hold;
    int32_t                 modified;
    FILE_NO                 fno;
} USED_KEY_PAGES;

typedef struct KEY_INST_INFO_S
{
    KEY_POSITION                pos;
    NODE_PATH                  *node_path;
    KEY_INST_STATUS             lstat;      /* status of the key instance */
    uint16_t                    value_used; /* has this union value been used in key fcns */
    uint16_t                    level;      /* current level # in node path */
    int32_t                     lastdir;    /* last direction travelled */
    USED_KEY_PAGES             *used;
    KEY_INFO                   *ki;
    const struct DB_INSTANCE_S *dbi;
} KEY_INST_INFO;

typedef struct HASH_INFO_S
{
    uint32_t                 hashsize;
    char                    *data;
    const FIELD_ENTRY       *fd;
    const FILE_ENTRY        *ft;
    struct HASH_INST_INFO_S *hash_inst_info;
} HASH_INFO;

typedef struct HASH_INST_INFO_S
{
    F_ADDR                      root;
    F_ADDR                      curr;
    uint16_t                    slotno;
    char                       *normalized;
    HASH_INFO                  *hi;
    const struct DB_INSTANCE_S *dbi;
} HASH_INST_INFO;

#define HASH_VALUE      uint64_t
#define HASH_VALUE_HALF uint32_t

typedef struct KEY_RESULTS_S
{
    DB_ADDR    *curr_rec;
    KEY_INFO  **curkey;
    HASH_INFO **curhash;
} KEY_RESULTS;

/* key slot structure */
#if defined(NOT_USED)
typedef struct key_slot
{
    F_ADDR   child;            /* child node pointer */
    uint16_t keyno;            /* key number */
    char     data[MAXKEYSIZE]; /* start of key data */
} KEY_SLOT;
#endif

typedef struct key_slot_ptr
{
    F_ADDR      child;         /* child node pointer */
    uint16_t    keyno;         /* key number */
    const char *data;          /* start of key data */
} KEY_SLOT_PTR;

/* blob information; one entry per blob field */
typedef struct
{
    DB_ADDR            dba;
    BLOB_ID            bid;
    F_ADDR             pgno;
    BLOBSIZE_T         pos;
    BLOBSIZE_T         size;
    FILE_NO            bfile;
    uint16_t           slsize;
    const FIELD_ENTRY *fd;
} BLOB_INFO;

struct TASK_S;
struct DB_ENTRY_S;

typedef struct SCHEMA_ENTRY_S {
    uint16_t      dba8;
    uint32_t      page_size;
    FILE_NO       size_ft;
    uint16_t      size_rt;
    uint16_t      size_st;
    uint16_t      size_mt;
    uint16_t      size_srt;
    uint32_t      size_fd;
    uint16_t      size_kt;
    uint16_t      size_ct;
    uint32_t      offset_ct;
    FILE_ENTRY   *file_table;
    RECORD_ENTRY *record_table;
    FIELD_ENTRY  *field_table;
    KEY_ENTRY    *key_table;
    SET_ENTRY    *set_table;
    MEMBER_ENTRY *member_table;
    SORT_ENTRY   *sort_table;
    CRYPT_ENTRY  *crypt_table;
} SCHEMA_ENTRY;

/* database instance entry declaration */
typedef struct DB_INSTANCE_S
{
    uint16_t           uno;
    TX_DB              dbID;
    PGZERO            *pgzero;
    RT_CONN_INFO      *tfs_conn;
    int16_t            lm_session_active; /* have we called tx_lmDbOpen */
    FILE_NO           *file_index;
    uint16_t           size_fi;
    REPLICATION_INFO   ri;                /* replication information */
    BVCACHE            cache;
    PSP_POOL           idPool;
    PSP_POOL           pageEntryPool;
    uint16_t           modified;          /* has this database instance been modified */
    const ENC         *enc_in;            /* encryption context for reading pages */
    const ENC         *enc_out;           /* encryption context for writing pages */
#ifdef DBSTAT
    FILE_STATS        *file_stats;
#endif
    char              *db_name;           /* name of this database */

    TFS_LM_LOCK       *lock_pkt;

    /* scope: keyl_cnt */
    LOCK_DESCR        *key_locks;

    /* scope: size_rt */
    LOCK_DESCR        *rec_locks;

    /* scope: size_st */
    LOCK_DESCR        *set_locks;
    
    /* Dictionary */
    SCHEMA_ENTRY       dbd;

    /* Replication master information */
    B_REP_DB          *repdb;
    B_SCHEMA_VER       schema_version;
    uint64_t           dbIniTimestamp;
    uint64_t           tfsIniTimestamp;

    /* Replication slave information */
    B_REP_DB          *slave_repdb;
    B_SCHEMA_VER       slave_schema_version;

    /* Dictionary */
    struct DB_ENTRY_S *db;
} DB_INSTANCE;

typedef struct DICT_SIZE_S
{
    uint32_t Page_size;
    uint32_t Size_ft;
    uint32_t Size_rt;
    uint32_t Size_fd;
    uint32_t Size_st;
    uint32_t Size_mt;
    uint32_t Size_srt;
    uint32_t Size_kt;
    uint32_t Size_ct;
} DICT_SIZE;

typedef struct AD_DICT_SIZE_S
{
    uint32_t ad_Page_size;
    uint32_t ad_Size_ft;
    uint32_t ad_Size_rt;
    uint32_t ad_Size_fd;
    uint32_t ad_Size_st;
    uint32_t ad_Size_mt;
    uint32_t ad_Size_srt;
    uint32_t ad_Size_kt;
    uint32_t ad_Size_ct;
    uint32_t ad_padding;
} AD_DICT_SIZE;

/* Forward declaration to avoid compiler warnings */
struct DB_CURSOR_S;

/** Enumeration for RDM cursor positions 
 *
 *   The enumeration identifies the current position for an RDM cursor.  A cursor can be positioned
 *   at a record, between records, before all records, or after all records
 */
typedef enum RDM_CURSOR_POSITION_E
{
    CURSOR_AT_RECORD = 1,    /**< enum value for a cursor positioned at a valid record */
    CURSOR_BETWEEN_RECORDS,  /**< enum value for a cursor positioned between records */
    CURSOR_BETWEEN_KEYS,     /**< enum value for a cursor positioned between key values */
    CURSOR_BEFORE_FIRST,     /**< enum value for a cursor positioned  before all records */
    CURSOR_AFTER_LAST,       /**< enum value for a cursor positioned after all records */
    CURSOR_DELETED,          /**< enum value for a cursor whose current record has been deleted */
    CURSOR_KEY_CHANGED,      /**< enum value for a cursor whose key value has been changed */
    CURSOR_UNLINKED,         /**< enum value for a cursor whose curent record has been unlinked */
    CURSOR_RELINKED,         /**< enum value for a cursor whose curent record has been relinked */
    CURSOR_LOST_POSITION,    /**< enum value for a set cursor that has it's position lost */
    CURSOR_RECORD_GONE,      /**< enum value for a single cursor that has had it's record deleted */
    CURSOR_SET_GONE          /**< enum value for a set cursor that has had it's owner deleted */
} RDM_CURSOR_POSITION;

/** Enumeration for RDM cursor comparisons 
 *
 *   The enumeration allows for position comparisons between two cursors.  A cursor can either be
 *   positioned before, after, or equal to the position of another cursor.  How positioning is 
 *   determined is based on the type of cursor being compared.
 */
typedef enum RDM_CURSOR_COMPARE_E
{
    CURSOR_BEFORE = -1,   /**< enum value for a cursor positioned before another cursor */
    CURSOR_EQUAL = 0,     /**< enum value for a cursor positioned equal to another cursor */
    CURSOR_AFTER = 1      /**< enum value for a cursor positioned after another cursor */
} RDM_CURSOR_COMPARE;

/** Enumeration for cursor types 
 *
 *   The enumeration specifies the type of a cursor
 */
typedef enum RDM_CURSOR_TYPE_E
{
    CURSOR_TYPE_BEFORE_FIRST = 1,   /**< enum value for a BeforeFirst special cursor */
    CURSOR_TYPE_AFTER_LAST,         /**< enum value for a AfterLast special cursor */
    CURSOR_TYPE_REC_SCAN,           /**< enum value for a record scan cursor */
    CURSOR_TYPE_KEY_SCAN,           /**< enum value for a record scan cursor */
    CURSOR_TYPE_SET_SCAN,           /**< enum value for a key scan cursor */
    CURSOR_TYPE_SINGLETON,          /**< enum value for a singleton cursor */
    CURSOR_TYPE_ALLOCATED           /**< enum value for a cursor that has only been allocated */
} RDM_CURSOR_TYPE;

/** Function pointer for cursor navigation functions */
typedef int32_t (INTERNAL_FCN *CURSOR_POSITION_FCN)(struct DB_CURSOR_S *);

/** Function pointer for cursor comparison functions */
typedef int32_t (INTERNAL_FCN *CURSOR_COMPARE_FCN)(const struct DB_CURSOR_S *, const struct DB_CURSOR_S *, RDM_CURSOR_COMPARE *);

/** Function pointer for cursor count functions */
typedef int32_t (INTERNAL_FCN *CURSOR_COUNT_FCN)(const struct DB_CURSOR_S *, uint64_t *);

/** Function pointer for finding a record by dba */
typedef int32_t (INTERNAL_FCN *CURSOR_FIND_BY_DBA_FCN)(struct DB_CURSOR_S *, const DB_ADDR *);

/** Function pointer for finding a record by cursor */
typedef int32_t (INTERNAL_FCN *CURSOR_FIND_BY_RECORD_FCN)(struct DB_CURSOR_S *, const struct DB_CURSOR_S *);

typedef int32_t (INTERNAL_FCN *CURSOR_FIND_BY_KEY_FCN)(struct DB_CURSOR_S *, const FIELD_ENTRY *, const void *, uint16_t, uint16_t);

/** Function pointer for adding a record */
typedef int32_t (INTERNAL_FCN *CURSOR_CREATE_RECORD_FCN)(struct DB_CURSOR_S *, const RECORD_ENTRY *, const void *, uint32_t);

/** Function pointer for getting the record type */
typedef int32_t (INTERNAL_FCN *CURSOR_GET_RECORD_TYPE_FCN)(const struct DB_CURSOR_S *, int32_t *);

/** Function pointer for disconnection a record */
typedef int32_t (INTERNAL_FCN *CURSOR_DISCONNECT_FCN)(struct DB_CURSOR_S *, const SET_ENTRY *);

/** Function pointer for validating locks */
typedef int32_t (INTERNAL_FCN *CURSOR_CHECK_LOCKING_FCN)(const struct DB_CURSOR_S *);

#if !defined(INTERNAL_H)

#define DB_CLOSE  close
#define DB_READ   read
#define DB_WRITE  write
#define DB_LSEEK  lseek


#define DB_TELL(fd)   DB_LSEEK(fd, 0, PSP_SEEK_CUR)

/* File stream functions used in dbedit */
#define DB_FTELL ftell

#endif /* INTERNAL_H */

struct sk
{
    char    *sk_val;
    uint32_t sk_fld;
};

/* file rename table entry declarations */
typedef struct ren_entry
{
    char   *file_name;
    char   *ren_db_name;
    FILE_NO file_no;
} REN_ENTRY;

typedef struct {
    union {
        FILE_ENTRY                 *p;
        AB_FILE_ENTRY              *ab;
        AA_FILE_ENTRY_DBA4         *aaa4;
        AA_FILE_ENTRY_DBA8         *aaa8;
        V300_FILE_ENTRY            *v300;
        V301_FILE_ENTRY            *v301;
        V500_FILE_ENTRY            *v500;
        V600_FILE_ENTRY            *v600;
#if !defined(RDM_NO_UNICODE)
        AA_FILE_ENTRY_UNICODE_DBA4 *aau4;
        AA_FILE_ENTRY_UNICODE_DBA8 *aau8;
        U500_FILE_ENTRY            *u500;
        U600_FILE_ENTRY            *u600;
#endif
    } fptr;
    union {
        RECORD_ENTRY      *p;
        V300_RECORD_ENTRY *v300;
        V600_RECORD_ENTRY *v600;
        AA_RECORD_ENTRY   *aa;
        AD_RECORD_ENTRY   *ad;
    } rptr;
    union {
        FIELD_ENTRY      *p;
        V300_FIELD_ENTRY *v300;
        V600_FIELD_ENTRY *v600;
        AA_FIELD_ENTRY   *aa;
        AD_FIELD_ENTRY   *ad;
    } fdptr;
    union {
        KEY_ENTRY      *p;
        V300_KEY_ENTRY *v300;
        V600_KEY_ENTRY *v600;
        AA_KEY_ENTRY   *aa;
    } kptr;
} TABLE_PTRS;

#if !defined(INTERNAL_H)

typedef struct
{
    char  *strbuf;
    size_t buflen;
    size_t strlen;
} DB_STRING;

#ifdef DB_TRACE

#define API_ENTER(fn)   {if (task->db_trace & TRACE_API) api_enter(fn, task);}
#define API_RETURN(c)   return((task->db_trace & TRACE_API) ? api_exit(task) : 0, (c))
#define API_EXIT()      {if (task->db_trace & TRACE_API) api_exit(task);}

#else  /* DB_TRACE */

#define API_ENTER(fn)   UNREF_PARM(fn)
#define API_RETURN(c)   return(c)
#define API_EXIT()      /**/

#endif /* DB_TRACE */

#define DBA_FILE(d) ((d).dba_file)
#define DBA_SLOT(d) ((F_ADDR) ((d).dba_offset))
#define DBA_UNO(d)  ((d).dba_uno)

#if !defined(RELEASE)
    /* This removes some uninitialized memory problems for valgrind */
#define INITIALIZE_DBA(db_addr) memset(&(db_addr), 0, sizeof(DB_ADDR));
#else
#define INITIALIZE_DBA(db_addr)
#endif

#define ENCODE_DBA(uno, file, slot, db_addr) \
    INITIALIZE_DBA(db_addr) \
    (db_addr).dba_uno = (uno); \
    (db_addr).dba_file = (file); \
    (db_addr).dba_offset = (slot);

#define ENCODE_DBA4(file, slot, dba) \
    (*(dba) = (((F_ADDR4) (file) & FILEMASK4) << FILESHIFT4) | \
            ((F_ADDR4) (slot) & ADDRMASK4))

#define ENCODE_DBA8(file, slot, dba) \
    (*(dba) = (((F_ADDR8) (file) & FILEMASK8) << FILESHIFT8) | \
            ((F_ADDR8) (slot) & ADDRMASK8))

#define DB_ADDR_FILE(d) ((d).dba_file)
#define DB_ADDR_FILE4(dba) ((FILE_NO) (((F_ADDR) (dba) >> FILESHIFT4) & FILEMASK4))
#define DB_ADDR_FILE8(dba) ((FILE_NO) (FILEMASK8 & (dba >> FILESHIFT8)))

#define DB_ADDR_SLOT(d) ((F_ADDR) ((d).dba_offset))
#define DB_ADDR_SLOT4(dba) ((F_ADDR4) (dba) & ADDRMASK4)
#define DB_ADDR_SLOT8(dba) ((F_ADDR8) (dba) & ADDRMASK8)

#define DB_ADDR_UNO(d)  ((d).dba_uno)

#define DECODE_DBA(dba, file, slot) {\
    *(file) = DBA_FILE(dba);\
    *(slot) = DBA_SLOT(dba);\
}

#define DECODE_DBA_UNO(dba, uno, file, slot) {\
    *(uno) =  DBA_UNO(dba);\
    *(file) = DBA_FILE(dba);\
    *(slot) = DBA_SLOT(dba);\
}

#define DECODE_DBA4(dba, file, slot) {\
    *(file) = DB_ADDR_FILE4(dba);\
    *(slot) = DB_ADDR_SLOT4(dba);\
}

#define DECODE_DBA8(dba, file, slot) {\
    *(file) = DB_ADDR_FILE8(dba);\
    *(slot) = DB_ADDR_SLOT8(dba);\
}

#define DB_ADDR_EQ(d1, d2)      ((DBA_UNO(d1) == DBA_UNO(d2)) && (DB_ADDR_SLOT(d1) == DB_ADDR_SLOT(d2)) && (DB_ADDR_FILE(d1) == DB_ADDR_FILE(d2)))


#endif /* INTERNAL_H */

#define DB_TIMEOUT     10     /* lock request wait 10 seconds in queue */

#define NET_TIMEOUT    3      /* how long to wait for connection */

#ifndef MSGVER
#define MSGVER  0x500
#endif

/***************************************************************************
  RDM open mode definitions
*/
#define RDM_OPM_SHARED    0x0000
#define RDM_OPM_EXCLUSIVE 0x0001
#define RDM_OPM_READONLY  0x0002

#define RDM_OPM_MODE_MASK 0x0003
#define RDM_OPM_STRICT    0x0020
#define RDM_OPM_REPCLI    0x0040
#define RDM_OPM_TRANSOFF  0x0080

#define GET_OPEN_MODE(mode)     ((uint32_t) (mode) & RDM_OPM_MODE_MASK)
#define IS_SHARED(mode)         (GET_OPEN_MODE(mode) == RDM_OPM_SHARED)
#define IS_EXCLUSIVE(mode)      (GET_OPEN_MODE(mode) == RDM_OPM_EXCLUSIVE)
#define IS_READONLY(mode)       (GET_OPEN_MODE(mode) == RDM_OPM_READONLY)

#define IS_NOTRANS(mode)        ((uint32_t) (mode) & RDM_OPM_TRANSOFF)
#define IS_REPCLI(mode)         ((uint32_t) (mode) & RDM_OPM_REPCLI)
#define IS_STRICT(mode)         ((uint32_t) (mode) & RDM_OPM_STRICT)

#define IS_SHARED_TASK(task)    IS_SHARED((task)->mode)
#define IS_EXCLUSIVE_TASK(task) IS_EXCLUSIVE((task)->mode)
#define IS_READONLY_TASK(task)  IS_READONLY((task)->mode)

#define IS_NOTRANS_TASK(task)   IS_NOTRANS((task)->mode)
#define IS_REPCLI_TASK(task)    IS_REPCLI((task)->mode)
#define IS_STRICT_TASK(task)    IS_STRICT((task)->mode)

/** Enumeration for RDM database open modes
 *
 *   This enumeration specifies the open mode for RDM databases
 */
typedef enum RDM_OPEN_MODE_E
{
    RDM_OPEN_SHARED             = RDM_OPM_SHARED,             /**< Open database is shared mode */
    RDM_OPEN_EXCLUSIVE          = RDM_OPM_EXCLUSIVE,  /**< Open database in exclusive mode */
    RDM_OPEN_READONLY           = RDM_OPM_READONLY,           /**< Open database in read-only mode */
    RDM_OPEN_REP_CLIENT         = (RDM_OPM_SHARED | RDM_OPM_REPCLI), /**< Open database as a replication client */
    RDM_OPEN_EXCLUSIVE_TRANSOFF = (RDM_OPM_EXCLUSIVE | RDM_OPM_TRANSOFF), /**< Open database in exclusive mode with no transactions */
    RDM_OPEN_SHARED_STRICT      = (RDM_OPM_SHARED | RDM_OPM_STRICT), /**< Open database in shared mode, requiring locks */
    RDM_OPEN_READONLY_STRICT    = (RDM_OPM_READONLY | RDM_OPM_STRICT) /**< Open database in readonly mode, requiring locks */
} RDM_OPEN_MODE;

typedef enum RDM_CURSOR_FCNS_E
{
    D_CREATERECORD = 0,
    D_CURSORALLOC,
    D_GETRECORDS,
    D_GETRECORDSATDBA,
    D_GETRECORDSBYKEY,
    D_GETRECORDSBYKEYATVALUE,
    D_GETSYSTEMRECORD,
    DC_ADDMEMBER,
    DC_AFTERLAST,
    DC_BEFOREFIRST,
    DC_CHECKPOSITION,
    DC_CLONE,
    DC_COMPAREPOSITION,
    DC_CONNECT,
    DC_CURSORFREE,
    DC_DELETE,
    DC_DISCONNECT,
    DC_DISCONNECTANDDELETE,
    DC_FINDBYDBA,
    DC_FINDBYKEY,
    DC_FINDBYRECORD,
    DC_FIRST,
    DC_GETAFTERLAST,
    DC_GETBEFOREFIRST,
    DC_GETBLOB,
    DC_GETBLOBSIZE,
    DC_GETCOUNT,
    DC_GETDB,
    DC_GETDBA,
    DC_GETDBN,
    DC_GETFIELD,
    DC_GETFIELDS,
    DC_GETMEMBERCOUNT,
    DC_GETMEMBERS,
    DC_GETOWNER,
    DC_GETOWNERDBA,
    DC_GETRECORDSATRECORD,
    DC_GETRECORDSBYKEYATRECORD,
    DC_GETRECTYPE,
    DC_GETSELF,
    DC_GETSIBLINGS,
    DC_GETSIBLINGSATRECORD,
    DC_GETTASK,
    DC_HASOWNER,
    DC_ISAFTERLAST,
    DC_ISBEFOREFIRST,
    DC_KEYADD,
    DC_KEYEXIST,
    DC_KEYREMOVE,
    DC_LAST,
    DC_NEXT,
    DC_PREV,
    DC_RECONNECT,
    DC_REMOVEMEMBER,
    DC_SETBLOB,
    DC_SETBLOBSIZE,
    DC_SETFIELD,
    DC_SETFIELDS,
    DH_CREATERECORD,
    DH_CURSORALLOC,
    DH_GETRECORDS,
    DH_GETRECORDSATDBA,
    DH_GETRECORDSBYKEY,
    DH_GETRECORDSBYKEYATVALUE,
    DH_GETSYSTEMRECORD
} RDM_CURSOR_FCN;

/* Status structure for d_fillnewArray() */
typedef struct
{
    int32_t rc;
    DB_ADDR dba;
} RDM_RAWSTAT;

#define S_SUCCEEDED(rc)     ((rc) == S_OKAY || (rc) == S_OKAY_WITH_INFO)

#if !defined(TX_DEFAULT_LOGFILE_TRANS)
#define TX_DEFAULT_LOGFILE_TRANS  1000       /* Keep 1,000 transaction per log */
#endif

#if !defined(TX_DEFAULT_LOGFILE_SIZE)
#define TX_DEFAULT_LOGFILE_SIZE   10485760   /* Max log size of 10 MB */
#endif

#if !defined(TX_DEFAULT_LOGFILES)
#define TX_DEFAULT_LOGFILES       1          /* Clean up old log files when we have more than 50 on disk */
#endif

#if !defined(TX_DEFAULT_LOGFILES_OPEN)
#define TX_DEFAULT_LOGFILES_OPEN 1000        /* Only allow 1,000 log file files handles to be open */
#endif

#if !defined(TX_TRANS_PER_FLUSH)
#define TX_TRANS_PER_FLUSH       2000        /* By default checkpoint all outstanding transactions before a flush */
#endif


/* transaction processing enumerations and structures */
typedef struct TX_REPLOG_ENTRY_S
{
    uint64_t        next_entry;        /**< offset to the next */
    uint32_t        number_actions;    /**< the number of replication actions in this entry */
    uint32_t        compressed_size;   /**< the compressed size of the page buffer */
    uint32_t        actual_size;       /**< the uncompressed size of the page buffer */
    uint16_t        compression_type;  /**< a RDM_COMPRESSION_TYPE enum value */
    uint16_t        dummy;             /**< a dummy field so the structure is a multiple of 8 bytes */
} TX_REPLOG_ENTRY;

typedef struct COPY_INFO_S 
{
    struct COPY_INFO_S *next;
    const char         *orgFile;
    uint16_t            orgFile_xflags;
    const char         *tmpFile;
    uint16_t            tmpFile_xflags;
} COPY_INFO;

typedef struct ROT_REC_S
{
    TXID              txid;
    struct ROT_REC_S *next;
} ROT_REC;

typedef enum IASYNC_MODE_E 
{
    IASYNC_OFF = 0,
    IASYNC_UNUSED,
    IASYNC_ON
} IASYNC_MODE; /*lint !e726 */

typedef const void *CHKPT;

typedef struct DB_REC_S {
    const char           *name;
    const char           *basename; /**< db file name, without relative path*/
    const char           *path;
    char                  endian;   /**< 'L' (little) or 'B' (big) */
    struct _user_db_xsec *users;    /**< USERs with this DB open */
    struct _file_rec     *files;    /**< FILEs in this DB that are open */
    struct _dbd_rec      *db_files; /**< list of all db files in this db */

    /* transaction related values */
    B_BT                  btTrans;                 /**< B-Tree for keeping transaction */
    uint32_t              max_logfile_trans;       /**< The maximum number of transactions in a log file */
    uint64_t              max_logfile_size;        /**< The maximum size of a single log file */
    uint64_t              next_lfid;               /**< The next log file id */
    TXID                  next_txid;               /**< the next transaction id to use */
    TXID                  committed_txid;          /**< the last transaction that has committed but not yet checkpointed */
    TXID                  checkpointed_txid;       /**< the last transaction that has been checkpointed */
    B_BT                  btLogFiles;              /**< a tree contain all of the current log files */
    LOG_FILE_CTX         *activeLogFile;           /**< the active log file (the one we are current writing transactions to) */
    uint16_t              syncLogFiles;            /**< flag to fsync the log file after writing to it */
    uint16_t              syncDbFiles;             /**< flag to fsync database files after checkpointing changes */
    uint32_t              num_logfiles;            /**< the current number of log files */
    uint32_t              max_logfiles;            /**< the number of logs to have before removing older ones */
    uint32_t              num_logfiles_open;       /**< the number of logs with open file handles */
    uint32_t              max_logfiles_open;       /**< the number of logs to keep open file handles for */
    uint32_t              trans_per_flush;         /**< the maximum number of log files to checkpoint before doing a flush */

#if defined(NOT_USED)
    B_BT                  btLocks;  /**< B-Tree for keeping track of lock info */
#endif
    B_BT                  btLMFiles;               /**< B-Tree for keeping track of lock manager file ids */
    char                 *buff;
    uint32_t              bufflen;
    ROT_REC              *rots;
    uint32_t              pathlen;
    uint32_t              magic;
    uint32_t              count;
    PSP_SEM               sem;
    PSP_SEM               syncsem;      /**< if db is synchronously mirrored */
    DB_BOOLEAN            inCommit;     /**< flag to indicate synch in commit */
    PSP_SEM               commit_sem;   /**< used by tx_LOGwaitForCommit */
    IASYNC_MODE           iaSyncMode;   /**< internal async mode flag */
    TXID                  lastSlaveTxid;
    int32_t               sync_error;
    int32_t               sync_timeout;
//#if defined(HA_STATUS_CODE)
    uint32_t              ha_timeout;
//#endif
    uint16_t              xflags;
    PSP_MEMTAG            tag;
    CHKPT                 chkpt;
    char                 *inifile;
    RDM_COMPRESSION_TYPE  compression_type;
    DFL_TYPE              db_file_location;
    COPY_INFO            *tmp_list;
    struct DB_REC_S       *next;
    struct DB_REC_S       *prev;
} DB_REC;

typedef struct TX_ENTRY_CTX_S 
{
    TX_ENTRY_STATUS         status;         /**< current transaction status */
    TXID                    txid;           /**< the transaction id */
    PSP_FILE_OFFSET         last_page;      /**< the offset to the latest TX_PAGE_HDR written to the log file */
    PSP_FILE_OFFSET         last_file;      /**< the offset to the latest TX_DB_FILE_HDR written to the log file */
    PSP_FILE_OFFSET         last_replog;    /**< the offset to the latest TX_REPLOG_ENTRY written to the log file */
    LOG_FILE_CTX           *lf_ctx;         /**< The log file context for the log file this transaction is stored in */
    TX_DB_FILE_HDR          dbfHdr;         /**< The database file header to be written to the file */
    uint32_t                num_files;      /**< The number of database files in this transaction */
    uint32_t                num_pages;      /**< The number of pages logged for the current database file */
    const struct _file_rec *log_file;       /**< The database file we are actively logging */
    struct TX_CTX_S        *tx_ctx;         /**< reference to the TFS transaction list entry */
} TX_ENTRY_CTX;

typedef struct TX_CTX_S
{
    TXID             txid;     /**< the transaction id for this transaction (b-tree ordered on this) */
    TX_ENTRY_STATUS  status;   /**< the status of this transaction entry */
    LOG_FILE_CTX    *lf_ctx;  /**< the context for the log file this transaction is stored in */
    //PSP_FILE_OFFSET  offset;   /**< the offset into the log file for the TX_ENTRY_HDR for this transaction */
} TX_CTX;

typedef uint16_t CRC;

#if defined(TASK_DEFN)
#include "dbxtrn.h"

#if !defined(INTERNAL_H)
#include "proto.h"
#endif /* INTERNAL_H */
#endif

#if defined(QNX)

#define LOCK_FCN   LK_LOCK
#define UNLOCK_FCN LK_UNLCK

#else /* QNX */

#define UNLOCK_FCN 0
#define LOCK_FCN   1

#endif /* QNX */

#define READ_FCN   0
#define WRITE_FCN  1

#endif  /* __DBTYPE_H */

