void gvcmz_doop(unsigned char query_code, unsigned char reply_code, mval *v) { unsigned char *ptr; short len, temp_short; int4 status, max_reply_len; struct CLB *lnk; unsigned char buff[MAX_ZWR_KEY_SZ], *end; error_def(ERR_BADSRVRNETMSG); error_def(ERR_UNIMPLOP); error_def(ERR_TEXT); error_def(ERR_GVIS); lnk = gv_cur_region->dyn.addr->cm_blk; if (!((link_info *)lnk->usr)->server_supports_long_names && (PRE_V5_MAX_MIDENT_LEN < strlen((char *)gv_currkey->base))) { end = format_targ_key(buff, MAX_ZWR_KEY_SZ, gv_currkey, TRUE); rts_error(VARLSTCNT(14) ERR_UNIMPLOP, 0, ERR_TEXT, 2, LEN_AND_LIT("GT.CM server does not support global names longer than 8 characters"), ERR_GVIS, 2, end - buff, buff, ERR_TEXT, 2, DB_LEN_STR(gv_cur_region)); } lnk->ast = 0; /* all database queries are sync */ lnk->cbl = 1 + /* HDR */ gv_currkey->end + /* key */ sizeof(unsigned short) + /* gv_key.top */ sizeof(unsigned short) + /* gv_key.end */ sizeof(unsigned short) + /* gv_key.prev */ sizeof(unsigned char) + /* gv_key.base */ sizeof(unsigned char) + /* regnum */ sizeof(unsigned short); /* size for variable len SUBSC */ /* the current GT.CM maximum message buffer length is bounded by the size of a short which is 64K. but the * calculation below of lnk->cbl and max_reply_len takes into account the fact that the value that is sent in as * input or read in from the server side can be at most MAX_DBSTRLEN in size. therefore, there is a dependency * that MAX_DBSTRLEN always be less than the GT.CM maximum message buffer length. to ensure this is always the * case, the following assert is added so that whenever MAX_DBSTRLEN is increased, we will fail this assert * and reexamine the code below. */ assert(sizeof(lnk->cbl) == 2); /* assert it is a short. when it becomes a uint4 the assert can be removed * if the macro CM_MAX_BUF_LEN (used below) is changed appropriately */ assert(MAX_DBSTRLEN == (32 * 1024 - 1)); if (CMMS_Q_PUT == query_code || CMMS_Q_INCREMENT == query_code) { if (CMMS_Q_INCREMENT == query_code) { /* 1-byte boolean value of "undef_inhibit" passed to the server for $INCREMENT although, effective V5.0-000, undef_inhibit is no longer relevant as $INCREMENT() implicitly does a $GET() on the global. We keep this byte to ensure compatibility with V5.0-FT01 */ lnk->cbl++; } assert((uint4)lnk->cbl + sizeof(unsigned short) + (uint4)MAX_DBSTRLEN <= (uint4)CM_MAX_BUF_LEN); lnk->cbl += (sizeof(unsigned short) + v->str.len); /* VALUE + length */ } if ((CMMS_Q_GET == query_code) || (CMMS_Q_INCREMENT == query_code) || (CMMS_Q_QUERY == query_code) && ((link_info *)lnk->usr)->query_is_queryget) max_reply_len = lnk->mbl + SIZEOF(unsigned short) + MAX_DBSTRLEN; /* can't predict the length of data value */ else max_reply_len = lnk->mbl; assert(max_reply_len <= (int4)CM_MAX_BUF_LEN); if (stringpool.top < stringpool.free + max_reply_len) stp_gcol(max_reply_len); lnk->mbf = stringpool.free; ptr = lnk->mbf; *ptr++ = query_code; /* temp_short = gv_currkey->end + sizeof(gv_key) + 1; */ temp_short = gv_currkey->end + sizeof(unsigned short) + sizeof(unsigned short) + sizeof(unsigned short) + sizeof(char) + 1; CM_PUT_SHORT(ptr, temp_short, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(short); *ptr++ = gv_cur_region->cmx_regnum; CM_PUT_SHORT(ptr, gv_currkey->top, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(short); CM_PUT_SHORT(ptr, gv_currkey->end, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(short); CM_PUT_SHORT(ptr, gv_currkey->prev, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(short); memcpy(ptr, gv_currkey->base, gv_currkey->end + 1); if (CMMS_Q_PUT == query_code || CMMS_Q_INCREMENT == query_code) { ptr += gv_currkey->end + 1; temp_short = (short)v->str.len; assert((int4)temp_short == v->str.len); /* short <- int4 assignment lossy? */ CM_PUT_SHORT(ptr, temp_short, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(short); memcpy(ptr,v->str.addr, v->str.len); if (CMMS_Q_INCREMENT == query_code) { /* UNDEF flag is no longer relevant, but set the flag to ensure compatibility with V5.0-FT01 */ assert(sizeof(undef_inhibit) == 1); ptr[v->str.len] = (unsigned char)undef_inhibit; } } status = cmi_write(lnk); if (CMI_ERROR(status)) { ((link_info *)(lnk->usr))->neterr = TRUE; gvcmz_error(query_code, status); return; } status = cmi_read(lnk); if (CMI_ERROR(status)) { ((link_info *)(lnk->usr))->neterr = TRUE; gvcmz_error(query_code, status); return; } ptr = lnk->mbf; if (CMMS_Q_PUT == query_code || CMMS_Q_ZWITHDRAW == query_code || CMMS_Q_KILL == query_code) { if (reply_code != *ptr) { if (*ptr != CMMS_E_ERROR) rts_error(VARLSTCNT(1) ERR_BADSRVRNETMSG); gvcmz_errmsg(lnk,FALSE); } return; } if (reply_code != *ptr) { if ((CMMS_R_UNDEF != *ptr) || ((CMMS_Q_GET != query_code) && (CMMS_Q_INCREMENT != query_code))) { if (CMMS_E_ERROR != *ptr) rts_error(VARLSTCNT(1) ERR_BADSRVRNETMSG); gvcmz_errmsg(lnk, FALSE); } if (CMMS_Q_INCREMENT == query_code) v->mvtype = 0; /* set the result to be undefined */ return; } ptr++; if (CMMS_R_DATA == reply_code) { CM_GET_SHORT(temp_short, ptr, ((link_info *)(lnk->usr))->convert_byteorder); if (1 != temp_short) rts_error(VARLSTCNT(1) ERR_BADSRVRNETMSG); ptr += sizeof(short); status = *ptr; /* Temp assignment to status gets rid of compiler warning in MV_FORCE_MVAL macro */ MV_FORCE_MVAL(v, status); return; } if (reply_code == CMMS_R_PREV || reply_code == CMMS_R_QUERY || reply_code == CMMS_R_ORDER) { CM_GET_SHORT(len, ptr, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(short); if (1 == len) { MV_FORCE_MVAL(v, 0); } else { if (*ptr++ != gv_cur_region->cmx_regnum) rts_error(VARLSTCNT(1) ERR_BADSRVRNETMSG); /* memcpy(gv_altkey, ptr, len - 1); */ CM_GET_USHORT(gv_altkey->top, ptr, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(unsigned short); CM_GET_USHORT(gv_altkey->end, ptr, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(unsigned short); CM_GET_USHORT(gv_altkey->prev, ptr, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(unsigned short); memcpy(gv_altkey->base, ptr, len - 1 - sizeof(unsigned short) - sizeof(unsigned short) - sizeof(unsigned short)); ptr += (len - 1 - sizeof(unsigned short) - sizeof(unsigned short) - sizeof(unsigned short)); MV_FORCE_MVAL(v, 1); } if (CMMS_R_QUERY != reply_code || 1 == len || !((link_info *)lnk->usr)->query_is_queryget) { if (CMMS_R_QUERY == reply_code && ((link_info *)lnk->usr)->query_is_queryget) v->mvtype = 0; /* force undefined to distinguish $Q returning "" from value of QUERYGET being 0 */ return; } } assert(CMMS_R_GET == reply_code || CMMS_R_INCREMENT == reply_code || CMMS_R_QUERY == reply_code && ((link_info *)lnk->usr)->query_is_queryget && 1 < len); CM_GET_SHORT(len, ptr, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(unsigned short); assert(ptr >= stringpool.base && ptr + len < stringpool.top); /* incoming message is in stringpool */ v->mvtype = MV_STR; v->str.len = len; v->str.addr = (char *)stringpool.free; /* we don't need the reply msg anymore, can overwrite reply */ memcpy(v->str.addr, ptr, len); /* so that we don't leave a gaping hole in the stringpool */ stringpool.free += len; return; }
void gvcmz_doop(unsigned char query_code, unsigned char reply_code, mval *v) { unsigned char *ptr; short len, temp_short; int4 status, max_reply_len; struct CLB *lnk; error_def(ERR_BADSRVRNETMSG); lnk = gv_cur_region->dyn.addr->cm_blk; lnk->ast = 0; /* all database queries are sync */ lnk->cbl = 1 + /* HDR */ gv_currkey->end + /* key */ sizeof(unsigned short) + /* gv_key.top */ sizeof(unsigned short) + /* gv_key.end */ sizeof(unsigned short) + /* gv_key.prev */ sizeof(unsigned char) + /* gv_key.base */ sizeof(unsigned char) + /* regnum */ sizeof(unsigned short); /* size for variable len SUBSC */ if (CMMS_Q_PUT == query_code) lnk->cbl += (sizeof(unsigned short) + v->str.len); /* VALUE + length */ if (CMMS_Q_GET == query_code || CMMS_Q_QUERY == query_code && ((link_info *)lnk->usr)->query_is_queryget) max_reply_len = lnk->mbl + sizeof(unsigned short) + MAX_STRLEN; /* can't predict the length of data value */ else max_reply_len = lnk->mbl; if (stringpool.top < stringpool.free + max_reply_len) stp_gcol(max_reply_len); lnk->mbf = stringpool.free; ptr = lnk->mbf; *ptr++ = query_code; /* temp_short = gv_currkey->end + sizeof(gv_key) + 1; */ temp_short = gv_currkey->end + sizeof(unsigned short) + sizeof(unsigned short) + sizeof(unsigned short) + sizeof(char) + 1; CM_PUT_SHORT(ptr, temp_short, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(short); *ptr++ = gv_cur_region->cmx_regnum; CM_PUT_SHORT(ptr, gv_currkey->top, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(short); CM_PUT_SHORT(ptr, gv_currkey->end, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(short); CM_PUT_SHORT(ptr, gv_currkey->prev, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(short); memcpy(ptr, gv_currkey->base, gv_currkey->end + 1); if (query_code == CMMS_Q_PUT) { ptr += gv_currkey->end + 1; temp_short = (short)v->str.len; assert((int4)temp_short == v->str.len); /* short <- int4 assignment lossy? */ CM_PUT_SHORT(ptr, temp_short, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(short); memcpy(ptr,v->str.addr, v->str.len); } status = cmi_write(lnk); if (CMI_ERROR(status)) { ((link_info *)(lnk->usr))->neterr = TRUE; gvcmz_error(query_code, status); return; } if (CMMS_Q_PUT == query_code || CMMS_Q_ZWITHDRAW == query_code || CMMS_Q_KILL == query_code) { status = cmi_read(lnk); if (CMI_ERROR(status)) { ((link_info *)(lnk->usr))->neterr = TRUE; gvcmz_error(query_code, status); return; } ptr = lnk->mbf; if (reply_code != *ptr) { if (*ptr != CMMS_E_ERROR) rts_error(VARLSTCNT(1) ERR_BADSRVRNETMSG); gvcmz_errmsg(lnk,FALSE); } return; } status = cmi_read(lnk); if (CMI_ERROR(status)) { ((link_info *)(lnk->usr))->neterr = TRUE; gvcmz_error(query_code, status); return; } ptr = lnk->mbf; if (reply_code != *ptr) { if (CMMS_R_UNDEF != *ptr || CMMS_Q_GET != query_code) { if (CMMS_E_ERROR != *ptr) rts_error(VARLSTCNT(1) ERR_BADSRVRNETMSG); gvcmz_errmsg(lnk, FALSE); } return; } ptr++; if (CMMS_R_DATA == reply_code) { CM_GET_SHORT(temp_short, ptr, ((link_info *)(lnk->usr))->convert_byteorder); if (1 != temp_short) rts_error(VARLSTCNT(1) ERR_BADSRVRNETMSG); ptr += sizeof(short); status = *ptr; /* Temp assignment to status gets rid of compiler warning in MV_FORCE_MVAL macro */ MV_FORCE_MVAL(v, status); return; } if (reply_code == CMMS_R_PREV || reply_code == CMMS_R_QUERY || reply_code == CMMS_R_ORDER) { CM_GET_SHORT(len, ptr, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(short); if (1 == len) { MV_FORCE_MVAL(v, 0); } else { if (*ptr++ != gv_cur_region->cmx_regnum) rts_error(VARLSTCNT(1) ERR_BADSRVRNETMSG); /* memcpy(gv_altkey, ptr, len - 1); */ CM_GET_USHORT(gv_altkey->top, ptr, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(unsigned short); CM_GET_USHORT(gv_altkey->end, ptr, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(unsigned short); CM_GET_USHORT(gv_altkey->prev, ptr, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(unsigned short); memcpy(gv_altkey->base, ptr, len - 1 - sizeof(unsigned short) - sizeof(unsigned short) - sizeof(unsigned short)); ptr += (len - 1 - sizeof(unsigned short) - sizeof(unsigned short) - sizeof(unsigned short)); MV_FORCE_MVAL(v, 1); } if (CMMS_R_QUERY != reply_code || 1 == len || !((link_info *)lnk->usr)->query_is_queryget) { if (CMMS_R_QUERY == reply_code && ((link_info *)lnk->usr)->query_is_queryget) v->mvtype = 0; /* force undefined to distinguish $Q returning "" from value of QUERYGET being 0 */ return; } } assert(CMMS_R_GET == reply_code || CMMS_R_QUERY == reply_code && ((link_info *)lnk->usr)->query_is_queryget && 1 < len); CM_GET_SHORT(len, ptr, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(unsigned short); assert(ptr >= stringpool.base && ptr + len < stringpool.top); /* incoming message is in stringpool */ v->mvtype = MV_STR; v->str.len = len; v->str.addr = (char *)stringpool.free; /* we don't need the reply msg anymore, can overwrite reply */ memcpy(v->str.addr, ptr, len); /* so that we don't leave a gaping hole in the stringpool */ stringpool.free += len; return; }