fis-gtm/sr_unix/go_load.c

304 lines
8.1 KiB
C

/****************************************************************
* *
* Copyright 2001, 2010 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 "gtm_string.h"
#include "stringpool.h"
#include "stp_parms.h"
#include "gdsroot.h"
#include "gdskill.h"
#include "gdsblk.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "error.h"
#include "muextr.h"
#include "util.h"
#include "mupip_exit.h"
#include "mlkdef.h"
#include "zshow.h"
#include "file_input.h"
#include "load.h"
#include "mu_gvis.h"
#include "mupip_put_gvdata.h"
#include "str2gvkey.h"
#include "gtmmsg.h"
#include "gtm_utf8.h"
#include <rtnhdr.h>
#include "gv_trigger.h"
GBLREF bool mupip_error_occurred;
GBLREF bool mu_ctrly_occurred;
GBLREF bool mu_ctrlc_occurred;
GBLREF spdesc stringpool;
GBLREF gv_key *gv_currkey;
#define GO_PUT_SUB 0
#define GO_PUT_DATA 1
#define DEFAULT_MAX_REC_SIZE 3096
#define ISSUE_TRIGDATAIGNORE_IF_NEEDED(KEYLENGTH, PTR, HASHT_GBL) \
{ \
/* The ordering of the && below is important as the caller uses HASHT_GBL to be set to TRUE if the global pointed to \
* by PTR is ^#t. \
*/ \
if ((HASHT_GBL = IS_GVKEY_HASHT_FULL_GBLNAME(KEYLENGTH, PTR)) && !hasht_ignored) \
{ \
gtm_putmsg(VARLSTCNT(4) ERR_TRIGDATAIGNORE, 2, KEYLENGTH, PTR); \
hasht_ignored = TRUE; \
} \
}
static readonly unsigned char gt_lit[] = "LOAD TOTAL";
void go_call_db(int routine, char *parm1, int parm2);
void go_load(uint4 begin, uint4 end)
{
char *ptr;
int len, fmt, keylength, keystate;
uint4 iter, max_data_len, max_subsc_len, key_count, max_rec_size;
mstr src, des;
unsigned char *rec_buff, ch;
boolean_t utf8_extract, format_error = FALSE, hasht_ignored = FALSE, hasht_gbl = FALSE;
error_def(ERR_LOADCTRLY);
error_def(ERR_LOADEOF);
error_def(ERR_LOADFILERR);
error_def(ERR_MUNOFINISH);
error_def(ERR_LOADINVCHSET);
error_def(ERR_TRIGDATAIGNORE);
gvinit();
max_rec_size = DEFAULT_MAX_REC_SIZE;
rec_buff = (unsigned char *)malloc(max_rec_size);
fmt = MU_FMT_ZWR; /* by default, the extract format is ZWR (not GO) */
len = file_input_get(&ptr);
if (mupip_error_occurred)
{
free(rec_buff);
return;
}
if (len >= 0)
{
util_out_print("!AD", TRUE, len, ptr);
utf8_extract = ((len >= STR_LIT_LEN(UTF8_NAME)) &&
(0 == MEMCMP_LIT(ptr + len - STR_LIT_LEN("UTF-8"), "UTF-8"))) ? TRUE : FALSE;
if ((utf8_extract && !gtm_utf8_mode) || (!utf8_extract && gtm_utf8_mode))
{ /* extract CHSET doesn't match $ZCHSET */
if (utf8_extract)
gtm_putmsg(VARLSTCNT(4) ERR_LOADINVCHSET, 2, LEN_AND_LIT("UTF-8"));
else
gtm_putmsg(VARLSTCNT(4) ERR_LOADINVCHSET, 2, LEN_AND_LIT("M"));
mupip_error_occurred = TRUE;
free(rec_buff);
return;
}
} else
mupip_exit(ERR_LOADFILERR);
len = file_input_get(&ptr);
if (mupip_error_occurred)
{
free(rec_buff);
return;
}
if (len >= 0)
{
util_out_print("!AD", TRUE, len, ptr);
fmt = (0 == memcmp(ptr + len - STR_LIT_LEN("ZWR"), "ZWR", STR_LIT_LEN("ZWR"))) ? MU_FMT_ZWR : MU_FMT_GO;
} else
mupip_exit(ERR_LOADFILERR);
if (begin < 3)
begin = 3;
for (iter = 3; iter < begin; iter++)
{
len = file_input_get(&ptr);
if (len < 0) /* The IO device has signalled an end of file */
{
gtm_putmsg(VARLSTCNT(3) ERR_LOADEOF, 1, begin);
mupip_error_occurred = TRUE;
}
if (mupip_error_occurred)
{
util_out_print("Error reading record number: !UL\n", TRUE, iter);
free(rec_buff);
return;
}
}
assert(iter == begin);
util_out_print("Beginning LOAD at record number: !UL\n", TRUE, begin);
max_data_len = 0;
max_subsc_len = 0;
key_count = 0;
for (iter = begin - 1; ; )
{
if (++iter > end)
break;
if (mu_ctrly_occurred)
break;
if (mu_ctrlc_occurred)
{
util_out_print("!AD:!_ Key cnt: !UL max subsc len: !UL max data len: !UL", TRUE,
LEN_AND_LIT(gt_lit), key_count, max_subsc_len, max_data_len);
util_out_print("Last LOAD record number: !UL", TRUE, key_count ? iter : 0);
mu_gvis();
util_out_print(0, TRUE);
mu_ctrlc_occurred = FALSE;
}
if (0 > (len = file_input_get(&ptr)))
break;
if (mupip_error_occurred)
{
mu_gvis();
break;
}
if ('\n' == *ptr)
{
if ('\n' == *(ptr+1))
break;
ptr++;
}
stringpool.free = stringpool.base;
if (0 == len)
continue;
if (MU_FMT_GO != fmt)
{
/* Determine the ZWR key length. -1 (SIZEOF(=)) is needed since ZWR allows '^x(1,2)='*/
keylength = zwrkeylength(ptr, len - 1);
ISSUE_TRIGDATAIGNORE_IF_NEEDED(keylength, ptr, hasht_gbl);
if (hasht_gbl)
{
hasht_gbl = FALSE;
continue;
}
go_call_db(GO_PUT_SUB, ptr, keylength);
if (mupip_error_occurred)
{
mu_gvis();
util_out_print("Error loading record number: !UL\n", TRUE, iter);
mupip_error_occurred = FALSE;
continue;
}
assert(keylength < len - 1);
if (max_subsc_len < (gv_currkey->end + 1))
max_subsc_len = gv_currkey->end + 1;
src.len = len - keylength - 1;
src.addr = (char *)(ptr + keylength + 1);
des.len = 0;
if (src.len > max_rec_size)
{
max_rec_size = src.len;
free(rec_buff);
rec_buff = (unsigned char *)malloc(max_rec_size);
}
des.addr = (char *)rec_buff;
if (FALSE == zwr2format(&src, &des))
{
util_out_print("Format error in record number !8UL: !/!AD", TRUE, iter, src.len, src.addr);
format_error = TRUE;
continue;
}
if (max_data_len < des.len)
max_data_len = des.len;
stringpool.free = stringpool.base;
go_call_db(GO_PUT_DATA, (char *)rec_buff, des.len);
if (mupip_error_occurred)
{
mu_gvis();
util_out_print("Error loading record number: !UL\n", TRUE, iter);
mupip_error_occurred = FALSE;
continue;
}
key_count++;
} else
{
ISSUE_TRIGDATAIGNORE_IF_NEEDED(len, ptr, hasht_gbl);
if (hasht_gbl)
{
if (0 > (len = file_input_get(&ptr)))
break;
iter++;
hasht_gbl = FALSE;
continue;
}
go_call_db(GO_PUT_SUB, ptr, len);
if (mupip_error_occurred)
{
mu_gvis();
util_out_print("Error loading record number: !UL\n", TRUE, iter);
mupip_error_occurred = FALSE;
continue;
}
if (max_subsc_len < (gv_currkey->end + 1))
max_subsc_len = gv_currkey->end + 1;
if (++iter > end)
{
iter--; /* Decrement as didn't load key */
break;
}
if ((len = file_input_get(&ptr)) < 0)
break;
if (mupip_error_occurred)
{
mu_gvis();
util_out_print("Error loading record number: !UL\n", TRUE, iter);
break;
}
stringpool.free = stringpool.base;
if (max_data_len < len)
max_data_len = len;
go_call_db(GO_PUT_DATA, ptr, len);
if (mupip_error_occurred)
{
mu_gvis();
util_out_print("Error loading record number: !UL\n", TRUE, iter);
mupip_error_occurred = FALSE;
continue;
}
key_count++;
}
}
free(rec_buff);
file_input_close();
if (mu_ctrly_occurred)
{
gtm_putmsg(VARLSTCNT(1) ERR_LOADCTRLY);
mupip_exit(ERR_MUNOFINISH);
}
util_out_print("LOAD TOTAL!_!_Key Cnt: !UL Max Subsc Len: !UL Max Data Len: !UL",TRUE,key_count,max_subsc_len,
max_data_len);
util_out_print("Last LOAD record number: !UL\n", TRUE, key_count ? (iter - 1) : 0);
if (format_error)
mupip_exit(ERR_LOADFILERR);
}
void go_call_db(int routine, char *parm1, int parm2)
{
/* In order to duplicate the VMS functionality, which is to trap all errors in mupip_load_ch
* and continue in go_load after they occur, it is necessary to call these routines from a
* subroutine due to the limitations of condition handlers and unwinding on UNIX.
*/
ESTABLISH(mupip_load_ch);
switch(routine)
{ case GO_PUT_SUB:
gv_currkey->end = 0;
str2gvkey_gvfunc(parm1, parm2);
break;
case GO_PUT_DATA:
mupip_put_gvdata(parm1 , parm2);
break;
}
REVERT;
}