fis-gtm/sr_port_cm/gvcmz_netopen.c

246 lines
7.1 KiB
C

/****************************************************************
* *
* Copyright 2001, 2009 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"
#ifdef VMS
# include <descrip.h>
# include <ssdef.h>
#endif
#include "gdsroot.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "filestruct.h"
#include "jnl.h"
#include "hashtab_mname.h" /* needed for cmmdef.h */
#include "cmidef.h"
#include "cmmdef.h"
#include "stringpool.h"
#include "gtm_string.h"
#include "gvcmy_close.h"
#include "gvcmz.h"
#include "gt_timer.h"
#include "copy.h"
#include "iosp.h"
#include "gtcm_protocol.h"
#include "gtcm_is_query_queryget.h"
#include "gtcm_err_compat.h"
#include "error.h"
GBLREF boolean_t gtcm_connection;
GBLREF jnl_process_vector *prc_vec;
GBLREF spdesc stringpool;
GBLREF struct NTD *ntd_root;
static volatile boolean_t second_attempt = FALSE;
static protocol_msg myproto;
static struct CLB *clb;
int v010_jnl_process_vector_size(void);
void v010_jnl_prc_vector(void *);
CONDITION_HANDLER(gvcmz_netopen_ch)
{
error_def(CMERR_INVPROT);
START_CH;
if (SIGNAL != CMERR_INVPROT || second_attempt)
{
second_attempt = FALSE;
assert(clb);
gvcmy_close(clb);
NEXTCH;
}
second_attempt = TRUE;
UNWIND(NULL, NULL);
}
void gvcmz_netopen_attempt(struct CLB *c)
{
unsigned char *ptr, *proto_str;
int prc_vec_size;
int status;
#ifdef BIGENDIAN
jnl_process_vector temp_vect;
#endif
error_def(ERR_BADSRVRNETMSG);
error_def(ERR_NETDBOPNERR);
VMS_ONLY(
ESTABLISH(gvcmz_netopen_ch); /* our old servers run only on VMS; no need for retry on other OSs */
clb = c; /* need this assignment since we can't pass c to gvcmz_netopen_ch */
)
c->mbf = stringpool.free;
c->mbl = CM_MINBUFSIZE;
ptr = c->mbf;
*ptr++ = CMMS_S_INITPROC;
if (!second_attempt)
{
proto_str = (unsigned char *)&myproto;
if (!prc_vec)
{
prc_vec = malloc(SIZEOF(*prc_vec));
jnl_prc_vector(prc_vec);
}
prc_vec_size = SIZEOF(*prc_vec);
#ifdef BIGENDIAN
memcpy((unsigned char *)&temp_vect, (unsigned char *)prc_vec, SIZEOF(jnl_process_vector));
temp_vect.jpv_pid = GTM_BYTESWAP_32(temp_vect.jpv_pid);
temp_vect.jpv_image_count = GTM_BYTESWAP_32(temp_vect.jpv_image_count);
temp_vect.jpv_time = GTM_BYTESWAP_64(temp_vect.jpv_time);
temp_vect.jpv_login_time = GTM_BYTESWAP_64(temp_vect.jpv_login_time);
memcpy(ptr + S_PROTSIZE, (unsigned char *)&temp_vect, SIZEOF(jnl_process_vector));
#else
memcpy(ptr + S_PROTSIZE, (unsigned char *)prc_vec, prc_vec_size);
#endif
} else
{
#ifdef VMS
/* We connected with V010 server; let's behave like a V010 client. */
proto_str = (unsigned char *)S_PROTOCOL;
assert(prc_vec);
assert(SIZEOF(*prc_vec) > v010_jnl_process_vector_size());
v010_jnl_prc_vector(prc_vec);
prc_vec_size = v010_jnl_process_vector_size();
memcpy(ptr + S_PROTSIZE, (unsigned char *)prc_vec, prc_vec_size);
#elif defined(UNIX)
GTMASSERT;
#else
#error Unsupported platform
#endif
}
memcpy(ptr, proto_str, S_PROTSIZE);
ptr += S_PROTSIZE;
c->cbl = S_HDRSIZE + S_PROTSIZE + prc_vec_size;
status = cmi_write(c); /* INITPROC */
if (CMI_ERROR(status))
{
gvcmy_close(c);
rts_error(VARLSTCNT(3) ERR_NETDBOPNERR, 0, status);
}
status = cmi_read(c); /* return message should be same size */
if (CMI_ERROR(status))
{
gvcmy_close(c);
rts_error(VARLSTCNT(3) ERR_NETDBOPNERR, 0, status);
}
if (CMMS_T_INITPROC != *c->mbf)
{
if (CMMS_E_ERROR != *c->mbf)
{
gvcmy_close(c);
rts_error(VARLSTCNT(3) ERR_NETDBOPNERR, 0, ERR_BADSRVRNETMSG);
}
gvcmz_errmsg(c, FALSE);
}
VMS_ONLY(
REVERT;
clb = NULL; /* defensive programming */
second_attempt = FALSE; /* we succesfully connected; no need for one more try */
)
}
struct CLB *gvcmz_netopen(struct CLB *c, cmi_descriptor *node, cmi_descriptor *task)
{
static readonly int4 wait[2] = {-100000, -1};
static readonly int4 reptim[2] = {-10000, -1};
unsigned char *ptr;
link_info *li;
int len, i;
uint4 status;
protocol_msg *server_proto;
error_def(ERR_BADSRVRNETMSG);
error_def(ERR_NETDBOPNERR);
error_def(ERR_TEXT);
error_def(CMERR_INVPROT);
c = UNIX_ONLY(cmi_alloc_clb())VMS_ONLY(cmu_makclb());
c->usr = malloc(SIZEOF(link_info));
li = c->usr;
memset(li, 0, SIZEOF(*li));
c->err = gvcmz_neterr_set;
#ifdef VMS
c->nod.dsc$b_dtype = c->tnd.dsc$b_dtype = DSC$K_DTYPE_T;
c->nod.dsc$b_class = c->tnd.dsc$b_class = DSC$K_CLASS_S;
c->nod.dsc$w_length = node->dsc$w_length;
c->nod.dsc$a_pointer = malloc(c->nod.dsc$w_length);
memcpy(c->nod.dsc$a_pointer, node->dsc$a_pointer, node->dsc$w_length);
c->tnd.dsc$w_length = task->dsc$w_length;
c->tnd.dsc$a_pointer = malloc(c->tnd.dsc$w_length);
memcpy(c->tnd.dsc$a_pointer, task->dsc$a_pointer, task->dsc$w_length);
for (i = 0; i < 2; i++) /* This retry should really be pushed down into cmi_open */
{
status = cmi_open(c);
if (!CMI_ERROR(status))
break;
hiber_start_wait_any(10);
}
#elif defined(UNIX)
c->nod.addr = malloc(node->len);
c->nod.len = node->len;
memcpy(c->nod.addr, node->addr, node->len);
c->tnd.len = task->len;
c->tnd.addr = malloc(c->tnd.len);
memcpy(c->tnd.addr, task->addr, task->len);
status = cmi_open(c);
#else
#error Unsupported platform
#endif
if (CMI_ERROR(status))
{
free(c->usr);
free(VMS_ONLY(c->nod.dsc$a_pointer) UNIX_ONLY(c->nod.addr));
free(VMS_ONLY(c->tnd.dsc$a_pointer) UNIX_ONLY(c->tnd.addr));
VMS_ONLY(lib$free_vm(&SIZEOF(*c), &c, 0);)
UNIX_ONLY(cmi_free_clb(c));
rts_error(VARLSTCNT(3) ERR_NETDBOPNERR, 0, status);
}
if (0 == ntd_root)
ntd_root = cmu_ntdroot();
gtcm_protocol(&myproto);
li->lnk_active = TRUE;
ENSURE_STP_FREE_SPACE(CM_MINBUFSIZE);
do
{
gvcmz_netopen_attempt(c);
} while (second_attempt);
if (S_HDRSIZE + S_PROTSIZE + 2 != c->cbl)
{
gvcmy_close(c);
rts_error(VARLSTCNT(3) ERR_NETDBOPNERR, 0, ERR_BADSRVRNETMSG);
}
server_proto = (protocol_msg *)(c->mbf + 1);
if (!gtcm_protocol_match(server_proto, &myproto))
{
gvcmy_close(c);
rts_error(VARLSTCNT(3) ERR_NETDBOPNERR, 0, CMERR_INVPROT);
}
li->convert_byteorder = (gtcm_is_big_endian(&myproto) != gtcm_is_big_endian(server_proto));
li->query_is_queryget = gtcm_is_query_queryget(server_proto, &myproto);
li->server_supports_dollar_incr = (0 <= memcmp(server_proto->msg + CM_LEVEL_OFFSET, CMM_INCREMENT_MIN_LEVEL, 3));
li->server_supports_std_null_coll = (0 <= memcmp(server_proto->msg + CM_LEVEL_OFFSET, CMM_STDNULLCOLL_MIN_LEVEL, 3));
li->server_supports_long_names = (0 <= memcmp(server_proto->msg + CM_LEVEL_OFFSET, CMM_LONGNAMES_MIN_LEVEL, 3));
if (!(li->err_compat = gtcm_err_compat((protocol_msg *)(c->mbf + 1), &myproto)))
{
gvcmy_close(c);
rts_error(VARLSTCNT(6) ERR_NETDBOPNERR, 0, ERR_TEXT, 2,
LEN_AND_LIT("GTCM functionality not implemented between UNIX and VMS yet"));
}
gtcm_connection = TRUE;
CM_GET_USHORT(li->procnum, (c->mbf + S_HDRSIZE + S_PROTSIZE), li->convert_byteorder);
return c;
}