/* ----------------------------------------------------------------------------
 * Raima Database Manager
 *
 * Copyright (c) 2007-2009 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(__LOGFCNS_H)
#define __LOGFCNS_H

#include "psp.h"
#include "rdm.h"
#include "rdmtype.h"
#include "tfs.h"

#define REP_SI_LOCAL_NAME       "rep.silocal"

#define REPCOL_NULL             ((uint32_t) -1)
#define SIZE_IS_VALID(s)        ((s) != REPCOL_NULL)

#define REPCOL_HASPREVAL(c)     \
    (SIZE_IS_VALID((c)->pre_size) && (c)->pre_size > 0)
#define REPCOL_HASPOSTVAL(c)    \
    (SIZE_IS_VALID((c)->post_size) && (c)->post_size > 0)

/* =======================================================
   Action types
*/
typedef enum {
    RLA_FILLNEW,
    RLA_RECWRITE,
    RLA_FLDWRITE,
    RLA_CONNECT,
    RLA_DISCON,
    RLA_DELETE,
    RLA_DISDEL,
    RLA_BLOBWRITE,
    RLA_BLOBDELETE,
    RLA_BLOBTRUNC,
    RLA_RECINIT,
    RLA_DISOWN,         /* for dbrepsql only */
    RLA_MAXVAL = 70000   /* NOTE */
} RDM_REP_ACTION_TYPE;

/* =======================================================
   File Header
*/
typedef struct {
    char     ver[DBD_COMPAT_LEN];   /* 6 chars */
    char     reserved[2];
    uint32_t has_schema;
    uint16_t rec_bm_size;
    uint16_t set_bm_size;
} RDM_REP_FILE_HEADER;

/* =======================================================
   Data Header
*/
typedef const void *DATA_HEADER;
typedef uint64_t    RDM_REP_TIMESTAMP;

/* =======================================================
   Action Header 
*/
typedef struct {
    uint32_t            action_type;
    uint32_t            action_size;
} RDM_REP_ACTION_HEADER;

/* =======================================================
   Data Headers
*/
/* INSERT (fillnew) */
/* UPDATE (recwrite) */
/* DELETE (delete, disdel */
typedef struct {
    uint64_t row_id;
    uint16_t has_nulls;
    uint16_t tab_index;
    uint16_t col_count;
    uint16_t reserved;
} RDM_REP_ACT_FILLNEW,
  RDM_REP_ACT_RECWRITE,
  RDM_REP_ACT_DELETE,
  RDM_REP_ACT_DISDEL;

/* UPDATE (fieldwrite) */
typedef struct {
    uint64_t row_id;
    uint32_t col_index;
    uint16_t tab_index;
    uint16_t reserved;
} RDM_REP_ACT_FLDWRITE;

/* UPDATE (connect) */
typedef struct {
    uint64_t own_row_id;
    uint64_t mem_row_id;
    uint64_t prev_row_id;
    uint16_t set_index;
    uint16_t own_tab_index;
    uint16_t mem_tab_index;
    uint16_t reserved;
} RDM_REP_ACT_CONNECT;

/* UPDATE (disconnect) */
typedef struct {
    uint64_t mem_row_id;
    uint16_t set_index;
    uint16_t own_tab_index;
    uint16_t mem_tab_index;
    uint16_t reserved;
} RDM_REP_ACT_DISCON;

/* UPDATE (blobwrite, blobtrunc) */
typedef struct {
    uint64_t row_id;
    uint32_t pos;      /* not used for BLOBDELETE */
    uint32_t col_index;
    uint16_t tab_index;
    uint16_t reserved[3];
} RDM_REP_ACT_BLOBWRITE,
  RDM_REP_ACT_BLOBDELETE,
  RDM_REP_ACT_BLOBTRUNC;

/* INITIALIZE (recinit) */
typedef struct {
    uint16_t tab_index;
} RDM_REP_ACT_RECINIT;

/* =======================================================
   Column Data
*/
/* Column header structure used to send data */
typedef struct {
    uint32_t    pre_size;   /* -1 for NULL */
    uint32_t    post_size;  /* -1 for NULL */
    uint32_t    col_index;
    uint16_t    tab_index;
    uint16_t    reserved;
} RDM_REP_COLUMN_HEADER;

typedef struct {
    /* Header portion */
    RDM_REP_COLUMN_HEADER hdr;

    /* Data portion */
    const void           *pvPreImage;
    const void           *pvPostImage;
} RDM_REP_ACTION_COLUMN;

#if defined(__cplusplus)
extern "C" {
#endif

/* ========================================================================
   External functions
*/
RDM_EXPORT int32_t EXTERNAL_FCN process_replog(
    const char          *log_name,
    const DB_ENTRY      *db,
    uint16_t             xflags);

RDM_EXPORT int32_t EXTERNAL_FCN getRepRowID(
    DB_TASK             *task,
    int32_t              dbn,
    uint64_t            *pRowID);

RDM_EXPORT int32_t EXTERNAL_FCN getRepDbAddr(
    const DB_INSTANCE   *dbi,
    const RECORD_ENTRY  *rt,
    uint64_t             row_id,
    DB_ADDR             *pDBA);

RDM_EXPORT void EXTERNAL_FCN freeActionColumns(
    const RDM_REP_ACTION_COLUMN *pCols,
    uint16_t                     usColCount,
    int16_t                      sFreeImage);

RDM_EXPORT uint32_t EXTERNAL_FCN getDataHeaderSize(
    RDM_REP_ACTION_TYPE          action_type);


RDM_EXPORT int32_t EXTERNAL_FCN buildOrderedRecordList(
    RDM_DB_C                     hdb,
    uint32_t                    *list,
    uint32_t                    *listsize);

/* =======================================================================
   Logify a d_fillnew action
*/
RDM_EXPORT int32_t EXTERNAL_FCN logify_fillnew(
    const RECORD_ENTRY *rt,
    const void         *data,
    const DB_ENTRY     *db);

/* =======================================================================
   Logify a d_fillnew action
*/
RDM_EXPORT int32_t EXTERNAL_FCN logify_blobwrite(
    const FIELD_ENTRY           *fd,
    const void                  *data,
    uint32_t                     size,
    uint32_t                     pos,
    const DB_ADDR               *p_dba,
    const DB_ENTRY              *db);

/* =======================================================================
   Logify a d_connect action
*/
RDM_EXPORT int32_t EXTERNAL_FCN logify_connect(
    const SET_ENTRY    *st,
    const RECORD_ENTRY *rt,
    const DB_ADDR      *p_odba,
    const DB_ADDR      *p_mdba,
    const DB_ADDR      *p_prevdba,
    const DB_ENTRY     *db);

/* =======================================================================
   Initialize the database logifying process
*/
RDM_EXPORT int32_t EXTERNAL_FCN init_logify(
    const DB_ENTRY *db);

/* =======================================================================
   Terminate the database logifying process
*/
RDM_EXPORT int32_t EXTERNAL_FCN term_logify(
    const DB_ENTRY *db,     /* IN:  db entry */
    TXID            txID);  /* IN:  current transaction ID */

/* =======================================================================
*/
RDM_EXPORT int32_t EXTERNAL_FCN check_rep_schema(
    DB_INSTANCE         *dbi);

/* =======================================================================
*/
int32_t EXTERNAL_FCN log_read_schema(
    TX_USER              userID,
    TX_FILE              fh,
    PSP_FILE_OFFSET     *pOffset,
    B_REP_DB           **ppRepDB,
    uint16_t             do_swap,
    PSP_MEMTAG           tag);

/* =======================================================================
*/
int32_t EXTERNAL_FCN log_write_schema(
    TX_USER                      userID,
    TX_FILE                      fh,
    PSP_FILE_OFFSET             *pOffset,
    const B_REP_DB              *pRepDB);

/** \brief Swap the bytes of the replication logfile header.
 *
 *  \return N/A
 */
RDM_EXPORT void EXTERNAL_FCN log_swap_file_header(
    RDM_REP_FILE_HEADER     *pHeader);

/** \brief Swap the bytes of the replication action header.
 *
 *  \return N/A
 */
RDM_EXPORT void EXTERNAL_FCN log_swap_action_header(
    RDM_REP_ACTION_HEADER   *pHeader);

/** \brief Swap the bytes of the replication action timestamp.
 *
 *  \return N/A
 */
RDM_EXPORT void EXTERNAL_FCN log_swap_action_timestamp(
    RDM_REP_TIMESTAMP       *pTS);

/** \brief Swap the action-specific data header (fillnew, etc)
 *
 *  \return N/A
 */
RDM_EXPORT void EXTERNAL_FCN log_swap_data_header(
    RDM_REP_ACTION_TYPE      type,  /* IN:  action type */
    void                    *buf);  /* IN:  data header buffer */

RDM_EXPORT void EXTERNAL_FCN log_swap_column_header(
    RDM_REP_COLUMN_HEADER   *pHeader);

/** \brief Swap the bytes of the specified column data value.
 *
 *  \return N/A
 */
RDM_EXPORT void EXTERNAL_FCN log_swap_column_value(
    RDM_TYPE                 rdm_type,
    uint16_t                 num_entries,
    void                    *pValue);    /* IN/OUT: column value */

#if defined(__cplusplus)
}
#endif

#endif /* __LOGFCNS_H */

