252 lines
7.9 KiB
C
252 lines
7.9 KiB
C
/****************************************************************
|
|
* *
|
|
* Copyright 2001, 2011 Fidelity Information Services, Inc *
|
|
* *
|
|
* This source code contains the intellectual property *
|
|
* of its copyright holder(s), and is made available *
|
|
* under a license. If you do not know the terms of *
|
|
* the license, please stop and do not read further. *
|
|
* *
|
|
****************************************************************/
|
|
|
|
#include "mdef.h"
|
|
|
|
#include <stddef.h> /* for offsetof macro */
|
|
#include "gtm_string.h"
|
|
#include "gtm_stdio.h"
|
|
|
|
#include "gdsroot.h" /* for filestruct.h */
|
|
#include "gdsbt.h" /* for gdsfhead.h */
|
|
#include "gtm_facility.h" /* for fileinfo.h */
|
|
#include "fileinfo.h" /* for gdsfhead.h */
|
|
#include "gdsfhead.h" /* for filestruct.h */
|
|
#include "filestruct.h" /* for jnl.h */
|
|
#include "jnl.h"
|
|
#include "copy.h" /* for REF_CHAR macro */
|
|
#include "repl_filter.h"
|
|
#include "format_targ_key.h"
|
|
#include "mlkdef.h"
|
|
#include "zshow.h"
|
|
#include "buddy_list.h" /* needed for muprec.h */
|
|
#include "hashtab_mname.h" /* needed for muprec.h */
|
|
#include "hashtab_int4.h" /* needed for muprec.h */
|
|
#include "hashtab_int8.h" /* needed for muprec.h */
|
|
#include "muprec.h"
|
|
#include "real_len.h" /* for real_len() prototype */
|
|
|
|
#define DELIMIT_CURR *curr++ = '\\';
|
|
#define ZERO_TIME_DELIM "0,0\\"
|
|
#define PIDS_DELIM "0\\0\\"
|
|
|
|
#define JNL2EXT_STRM_SEQNO(CURR, STRM_SEQNO) \
|
|
{ \
|
|
seq_num lcl_strm_seqno; \
|
|
uint4 lcl_strm_num; \
|
|
\
|
|
DELIMIT_CURR; \
|
|
lcl_strm_seqno = STRM_SEQNO; \
|
|
UNIX_ONLY(lcl_strm_num = GET_STRM_INDEX(lcl_strm_seqno);) \
|
|
VMS_ONLY(lcl_strm_num = 0;) \
|
|
CURR = (char *)i2ascl((uchar_ptr_t)CURR, lcl_strm_num); \
|
|
DELIMIT_CURR; \
|
|
UNIX_ONLY(lcl_strm_seqno = GET_STRM_SEQ60(lcl_strm_seqno);) \
|
|
VMS_ONLY(lcl_strm_seqno = 0;) \
|
|
CURR = (char *)i2ascl((uchar_ptr_t)CURR, lcl_strm_seqno); \
|
|
}
|
|
|
|
/*
|
|
* Generic function to convert a journal record into an extract format record.
|
|
* Expects a pointer to the journal record and the length of the buffer and
|
|
* returns the result in ext_buff. If there is a bad format record in between,
|
|
* it returns NULL. It sets jb_stop to the offset of the jnl_buff where
|
|
* the last jnlrecord was processed. On successful conversion, it returns a value
|
|
* ptr, such that ptr - ext_buff would be the length of the extracted buffer.
|
|
* If the ext_len is not enough for the conversion, it returns ext_buff + ext_len
|
|
*/
|
|
|
|
GBLREF char *jb_stop;
|
|
GBLREF char muext_code[][2];
|
|
|
|
static boolean_t first_tstart = FALSE;
|
|
static int4 num_tstarts = 0;
|
|
static int4 num_tcommits = 0;
|
|
|
|
|
|
char *jnl2extcvt(jnl_record *rec, int4 jnl_len, char *ext_buff)
|
|
{
|
|
int4 rec_len;
|
|
|
|
for ( ; jnl_len > JREC_PREFIX_UPTO_LEN_SIZE && jnl_len >= (rec_len = rec->prefix.forwptr) && rec_len > MIN_JNLREC_SIZE; )
|
|
{
|
|
ext_buff = jnl2ext((char *)rec, ext_buff);
|
|
jnl_len -= rec_len;
|
|
rec = (jnl_record *)((char *)rec + rec_len);
|
|
}
|
|
|
|
jb_stop = (char *)rec;
|
|
return ext_buff;
|
|
}
|
|
|
|
/* This was earlier declared as a local variable, but was moved up, because the HPIA compiler for some reason seems to
|
|
* optimize things, and thus not update the buffer correctly. Problem shows up only in optimized builds. Moving it to
|
|
* global status fixed the issue
|
|
*/
|
|
GBLDEF char key_buff[SIZEOF(gv_key) + MAX_KEY_SZ + 7];
|
|
|
|
char *jnl2ext(char *jnl_buff, char *ext_buff)
|
|
{
|
|
char *curr, *val_ptr, rectype;
|
|
unsigned char *ptr;
|
|
jnl_record *rec;
|
|
gv_key *key;
|
|
jnl_string *keystr, *ztwormstr;
|
|
int val_extr_len, val_len, rec_len, tid_len;
|
|
|
|
rec = (jnl_record *)jnl_buff;
|
|
rectype = rec->prefix.jrec_type;
|
|
rec_len = rec->prefix.forwptr;
|
|
if ((ROUND_DOWN2(rec_len, JNL_REC_START_BNDRY) != rec_len) || rec_len != REC_LEN_FROM_SUFFIX(jnl_buff, rec_len))
|
|
{
|
|
assert(FALSE);
|
|
return ext_buff;
|
|
}
|
|
if (!IS_REPLICATED(rectype))
|
|
{
|
|
assert(FALSE);
|
|
return ext_buff;
|
|
}
|
|
curr = ext_buff;
|
|
/* The following assumes the journal extract format is "GDSJEX06". Whenever that changes (in mur_jnl_ext.c),
|
|
* the below code as well as ext2jnl.c needs to change. Add an assert to let us know of that event.
|
|
*/
|
|
assert(!MEMCMP_LIT(JNL_EXTR_LABEL,"GDSJEX06"));
|
|
if (IS_TUPD(rectype))
|
|
{
|
|
if (FALSE == first_tstart)
|
|
{
|
|
GET_SHORTP(curr, &muext_code[MUEXT_TSTART][0]);
|
|
curr += 2;
|
|
DELIMIT_CURR;
|
|
MEMCPY_LIT(curr, ZERO_TIME_DELIM);
|
|
curr += STR_LIT_LEN(ZERO_TIME_DELIM);
|
|
curr = (char *)i2ascl((uchar_ptr_t)curr, rec->jrec_set_kill.prefix.tn);
|
|
DELIMIT_CURR;
|
|
MEMCPY_LIT(curr, PIDS_DELIM);
|
|
curr += STR_LIT_LEN(PIDS_DELIM);
|
|
curr = (char *)i2ascl((uchar_ptr_t)curr, rec->jrec_set_kill.token_seq.jnl_seqno);
|
|
JNL2EXT_STRM_SEQNO(curr, rec->jrec_set_kill.strm_seqno); /* Note: updates "curr" */
|
|
*curr++ = '\n';
|
|
*curr = '\0';
|
|
first_tstart = TRUE;
|
|
}
|
|
num_tstarts++;
|
|
} else if (JRT_TCOM == rectype)
|
|
{
|
|
num_tcommits++;
|
|
if (num_tcommits == num_tstarts)
|
|
{
|
|
num_tcommits = num_tstarts = 0;
|
|
first_tstart = FALSE;
|
|
GET_SHORTP(curr, &muext_code[MUEXT_TCOMMIT][0]);
|
|
curr += 2;
|
|
DELIMIT_CURR;
|
|
MEMCPY_LIT(curr, ZERO_TIME_DELIM);
|
|
curr += STR_LIT_LEN(ZERO_TIME_DELIM);
|
|
curr = (char *)i2ascl((uchar_ptr_t)curr, rec->jrec_tcom.prefix.tn);
|
|
DELIMIT_CURR;
|
|
MEMCPY_LIT(curr, PIDS_DELIM);
|
|
curr += STR_LIT_LEN(PIDS_DELIM);
|
|
curr = (char *)i2ascl((uchar_ptr_t)curr, rec->jrec_tcom.token_seq.jnl_seqno);
|
|
JNL2EXT_STRM_SEQNO(curr, rec->jrec_tcom.strm_seqno); /* Note: updates "curr" */
|
|
DELIMIT_CURR;
|
|
*curr = '1'; /* Only ONE TSTART..TCOM in the external filter format */
|
|
curr++;
|
|
DELIMIT_CURR;
|
|
ptr = (unsigned char *)rec->jrec_tcom.jnl_tid;
|
|
tid_len = real_len(SIZEOF(rec->jrec_tcom.jnl_tid), ptr);
|
|
memcpy(curr, ptr, tid_len);
|
|
curr += tid_len;
|
|
*curr++ = '\n';
|
|
*curr = '\0';
|
|
return curr;
|
|
}
|
|
return ext_buff;
|
|
}
|
|
if (IS_SET(rectype))
|
|
GET_SHORTP(curr, &muext_code[MUEXT_SET][0]);
|
|
else if (IS_KILL(rectype))
|
|
GET_SHORTP(curr, &muext_code[MUEXT_KILL][0]);
|
|
else if (IS_ZKILL(rectype))
|
|
GET_SHORTP(curr, &muext_code[MUEXT_ZKILL][0]);
|
|
else if (IS_ZTWORM(rectype))
|
|
GET_SHORTP(curr, &muext_code[MUEXT_ZTWORM][0]);
|
|
else if (IS_ZTRIG(rectype))
|
|
GET_SHORTP(curr, &muext_code[MUEXT_ZTRIG][0]);
|
|
else /* if (JRT_NULL == rectype) */
|
|
{
|
|
assert(JRT_NULL == rectype);
|
|
GET_SHORTP(curr, &muext_code[MUEXT_NULL][0]);
|
|
}
|
|
curr += 2;
|
|
DELIMIT_CURR;
|
|
MEMCPY_LIT(curr, ZERO_TIME_DELIM);
|
|
curr += STR_LIT_LEN(ZERO_TIME_DELIM);
|
|
curr = (char *)i2ascl((uchar_ptr_t)curr, rec->jrec_set_kill.prefix.tn);
|
|
DELIMIT_CURR;
|
|
MEMCPY_LIT(curr, PIDS_DELIM);
|
|
curr += STR_LIT_LEN(PIDS_DELIM);
|
|
curr = (char *)i2ascl((uchar_ptr_t)curr, rec->jrec_set_kill.token_seq.jnl_seqno);
|
|
JNL2EXT_STRM_SEQNO(curr, rec->jrec_set_kill.strm_seqno); /* Note: updates "curr" */
|
|
if (rectype == JRT_NULL)
|
|
{
|
|
*curr++ = '\n';
|
|
*curr='\0';
|
|
return curr;
|
|
}
|
|
DELIMIT_CURR;
|
|
/* print "update_num" */
|
|
assert(IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype));
|
|
assert(&rec->jrec_set_kill.update_num == &rec->jrec_ztworm.update_num);
|
|
curr = (char *)i2ascl((uchar_ptr_t)curr, rec->jrec_set_kill.update_num);
|
|
DELIMIT_CURR;
|
|
if (IS_ZTWORM(rectype))
|
|
{
|
|
ztwormstr = &rec->jrec_ztworm.ztworm_str;
|
|
val_len = ztwormstr->length;
|
|
val_ptr = &ztwormstr->text[0];
|
|
format2zwr((sm_uc_ptr_t)val_ptr, val_len, (uchar_ptr_t)curr, &val_extr_len);
|
|
curr += val_extr_len;
|
|
*curr++ = '\n';
|
|
*curr='\0';
|
|
return curr;
|
|
}
|
|
/* print "nodeflags" */
|
|
keystr = (jnl_string *)&rec->jrec_set_kill.mumps_node;
|
|
curr = (char *)i2ascl((uchar_ptr_t)curr, keystr->nodeflags);
|
|
DELIMIT_CURR;
|
|
/* print "node" */
|
|
key = (gv_key *)ROUND_UP((unsigned long)key_buff, 8);
|
|
key->top = MAX_KEY_SZ;
|
|
key->end = keystr->length;
|
|
if (key->end > key->top)
|
|
{
|
|
assert(FALSE);
|
|
return ext_buff;
|
|
}
|
|
memcpy(key->base, &keystr->text[0], keystr->length);
|
|
key->base[key->end] = 0;
|
|
curr = (char *)format_targ_key((uchar_ptr_t)curr, MAX_ZWR_KEY_SZ, key, TRUE);
|
|
if (IS_SET(rectype))
|
|
{
|
|
*curr++ = '=';
|
|
val_ptr = &keystr->text[keystr->length];
|
|
GET_MSTR_LEN(val_len, val_ptr);
|
|
val_ptr += SIZEOF(mstr_len_t);
|
|
format2zwr((sm_uc_ptr_t)val_ptr, val_len, (uchar_ptr_t)curr, &val_extr_len);
|
|
curr += val_extr_len;
|
|
}
|
|
*curr++ = '\n';
|
|
*curr='\0';
|
|
return curr;
|
|
}
|