fis-gtm/sr_port_cm/gvcmz_bunch.c

204 lines
5.2 KiB
C

/****************************************************************
* *
* Copyright 2001, 2012 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 "cmidef.h"
#include "hashtab_mname.h" /* needed for cmmdef.h */
#include "cmmdef.h"
#include "gdsroot.h"
#include "gdsblk.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "stringpool.h"
#include "copy.h"
#include "gtm_string.h"
#include "gvcmz.h"
#define FORWARD_REC(x) buffptr += x->len + SIZEOF(*x) - 1; CM_GET_USHORT(tmp_short, buffptr, usr->convert_byteorder);\
buffptr += tmp_short + SIZEOF(unsigned short); x = (bunch_rec *)buffptr;
GBLDEF bool zdefactive;
GBLDEF unsigned short zdefbufsiz;
GBLREF gd_region *gv_cur_region;
GBLREF gv_key *gv_currkey;
GBLREF spdesc stringpool;
typedef struct bunch_rec_struct {
unsigned char rn;
unsigned short len;
unsigned short cc;
unsigned short prv;
unsigned char base[1];
} bunch_rec;
void gvcmz_bunch(mval *v)
{
struct CLB *lnk;
link_info *usr;
unsigned char *buffptr, *bufftop, *insert_record, *msgptr;
unsigned char *new_key, *rec_key;
unsigned short cc, len, i;
signed char is_gt;
bool overlay;
unsigned short newrec_len, oldrec_len, tmp_short;
short new_space;
bunch_rec *brec, nrec;
int4 status;
error_def(ERR_ZDEFOFLOW);
error_def(ERR_BADSRVRNETMSG);
assert(zdefactive);
lnk = gv_cur_region->dyn.addr->cm_blk;
usr = (link_info *)lnk->usr;
if (zdefbufsiz > usr->buffer_size)
{
if (!usr->buffer)
{
ENSURE_STP_FREE_SPACE(lnk->mbl);
msgptr = lnk->mbf = stringpool.free;
} else
msgptr = lnk->mbf = usr->buffer;
*msgptr++ = CMMS_B_BUFRESIZE;
CM_PUT_USHORT(msgptr, zdefbufsiz, usr->convert_byteorder);
msgptr += SIZEOF(unsigned short);
lnk->ast = 0;
lnk->cbl = S_HDRSIZE + SIZEOF(unsigned short);
status = cmi_write(lnk);
if (CMI_ERROR(status))
{
((link_info *)(lnk->usr))->neterr = TRUE;
gvcmz_error(CMMS_B_BUFRESIZE, status);
return;
}
status = cmi_read(lnk);
if (CMI_ERROR(status))
{
((link_info *)(lnk->usr))->neterr = TRUE;
gvcmz_error(CMMS_B_BUFRESIZE, status);
return;
}
if (*lnk->mbf != CMMS_C_BUFRESIZE)
{
if (*lnk->mbf != CMMS_E_ERROR)
rts_error(VARLSTCNT(1) ERR_BADSRVRNETMSG);
gvcmz_errmsg(lnk,FALSE);
return;
}
usr->buffer_size = zdefbufsiz;
if (usr->buffer)
{
free(usr->buffer);
usr->buffer = 0;
}
}
if (!usr->buffer)
usr->buffer = malloc(usr->buffer_size);
if (!usr->buffer_used)
{
buffptr = usr->buffer;
*buffptr++ = CMMS_B_BUFFLUSH;
buffptr += SIZEOF(short);
usr->buffer_used = (unsigned char *)buffptr - usr->buffer;
} else
buffptr = usr->buffer + 3; /* trancode + # of transactions */
bufftop = usr->buffer + usr->buffer_used;
cc = 0;
overlay = FALSE;
brec = (bunch_rec *)buffptr;
for (; buffptr < bufftop ;)
{
if (cc < brec->cc)
{
FORWARD_REC(brec);
continue;
}
if (cc > brec->cc)
break;
new_key = &gv_currkey->base[cc];
len = (brec->len > gv_currkey->end - cc + 1 ? gv_currkey->end - cc + 1 : brec->len);
rec_key = &brec->base[0];
for (i = 0; i < len; i++)
{
is_gt = *new_key++ - *rec_key++;
if (is_gt)
break;
}
if (i == len)
{
len = brec->len + brec->cc - 1;
if (gv_currkey->end > len)
{
cc += i;
FORWARD_REC(brec);
continue;
}
if( gv_currkey->end == len)
{
if (brec->rn != gv_cur_region->cmx_regnum)
{
cc += i;
FORWARD_REC(brec);
continue;
} else
overlay = TRUE;
}
break;
} else if (is_gt > 0)
{
cc += i;
FORWARD_REC(brec);
continue;
} else
break;
}
nrec.rn = gv_cur_region->cmx_regnum;
nrec.len = gv_currkey->end - cc + 1;
nrec.prv = gv_currkey->prev;
nrec.cc = cc;
newrec_len = SIZEOF(nrec) - 1 + nrec.len + SIZEOF(unsigned short) + v->str.len;
if (overlay)
{
oldrec_len = SIZEOF(*brec) - 1 + brec->len;
CM_GET_USHORT(tmp_short, buffptr + oldrec_len, usr->convert_byteorder);
oldrec_len += tmp_short + SIZEOF(unsigned short);
new_space = newrec_len - oldrec_len;
insert_record = buffptr;
FORWARD_REC(brec);
} else
{ insert_record = buffptr;
new_space = newrec_len;
}
if (usr->buffer_used + new_space >= usr->buffer_size)
VMS_ONLY(rts_error(VARLSTCNT(4) ERR_ZDEFOFLOW, 2, lnk->nod.dsc$w_length, lnk->nod.dsc$a_pointer);)
UNIX_ONLY(rts_error(VARLSTCNT(4) ERR_ZDEFOFLOW, 2, lnk->nod.len, lnk->nod.addr);)
memcpy(buffptr + new_space, buffptr, bufftop - buffptr); /* shuffle buffer to make room for new record */
memcpy(insert_record, &nrec, SIZEOF(nrec) - 1);
insert_record += SIZEOF(nrec) - 1;
memcpy(insert_record, &gv_currkey->base[cc], nrec.len);
insert_record += nrec.len;
tmp_short = (unsigned short)v->str.len;
assert((int4)tmp_short == v->str.len); /* ushort <- int4 assignment lossy? */
CM_PUT_USHORT(insert_record, tmp_short, usr->convert_byteorder);
insert_record += SIZEOF(unsigned short);
memcpy(insert_record, v->str.addr, v->str.len);
usr->buffer_used += new_space;
if (!overlay)
usr->buffered_count++;
}