204 lines
5.2 KiB
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++;
|
|
}
|