Example #1
0
void gvcmz_lkcancel_ast(struct CLB *lnk)
{
	uint4 status;

	if (CMI_CLB_ERROR(lnk))
	{
		((link_info *)(lnk->usr))->neterr = TRUE;
		lkerror = CMMS_L_LKCANCEL;
		lkerrlnk = lnk;
		return;
	}
	if (*(lnk->mbf) == CMMS_M_LKDELETED ||
	    *(lnk->mbf) == CMMS_M_LKABORT ||         /* per spec */
	    *(lnk->mbf) == CMMS_L_LKCANCEL)
	{      /* above are end of conversation */
		lnk->ast = 0;
		lkcancel_count++;
	} else if (*(lnk->mbf) == CMMS_M_LKSUSPENDED || *(lnk->mbf) == CMMS_M_LKGRANTED || *(lnk->mbf) == CMMS_M_LKBLOCKED)
	{      /* above are response from prior message, ours is to come */
		status = cmi_read(lnk);
		if (CMI_ERROR(status))
		{
			((link_info *)(lnk->usr))->neterr = TRUE;
			lkerror = CMMS_L_LKCANCEL;
			lkerrlnk = lnk;
		} else
		        lkresponse_count++;
	} else
	{
		lkerror = CMMS_L_LKCANCEL;
		lkerrlnk = lnk;
	}
}
Example #2
0
struct CLB *cmu_getclb(cmi_descriptor *node, cmi_descriptor *task)
{
	cmi_status_t status;
	struct CLB *p;
	que_ent_ptr_t qp;
	sigset_t oset;
	struct sockaddr_in in;
	int rc;

	status = cmj_resolve_nod_tnd(node, task, &in);
	if (CMI_ERROR(status))
		return NULL;

	if (ntd_root)
	{
		SIGPROCMASK(SIG_BLOCK, &ntd_root->mutex_set, &oset, rc);
		for (qp = RELQUE2PTR(ntd_root->cqh.fl) ; qp != &ntd_root->cqh ;
				qp = RELQUE2PTR(p->cqe.fl))
		{
			p = QUEENT2CLB(qp, cqe);
			if (p->peer.sin_port == in.sin_port && 0 == memcmp(&p->peer.sin_addr, &in.sin_addr, SIZEOF(in.sin_addr)))
			{ /* (port, address) pair is necessary and sufficient for uniqueness. There might be other fields in
			     sockaddr_in that might be implementation dependent. So, compare only (port, address) pair. */
				sigprocmask(SIG_SETMASK, &oset, NULL);
				return p;
			}
		}
		SIGPROCMASK(SIG_SETMASK, &oset, NULL, rc);
	}
	return NULL;
}
Example #3
0
cmi_status_t cmi_write(struct CLB *lnk)
{
	sigset_t oset;
	cmi_status_t status;
	struct NTD *tsk = lnk->ntd;
	int rc;

	CMI_DPRINT(("ENTER CMI_WRITE, AST 0x%x\n", lnk->ast));

	SIGPROCMASK(SIG_BLOCK, &tsk->mutex_set, &oset, rc);
	status = cmj_write_start(lnk);
	if (CMI_ERROR(status))
	{
		SIGPROCMASK(SIG_SETMASK, &oset, NULL, rc);
		CMI_DPRINT(("EXIT CMI_WRITE ERROR %d\n", status));
		return status;
	}
	cmj_housekeeping();
	while (lnk->sta == CM_CLB_WRITE && !lnk->ast)
	{
		sigsuspend(&oset);
		cmj_housekeeping();
		/* recover status */
		if (lnk->sta != CM_CLB_WRITE)
			status = CMI_CLB_IOSTATUS(lnk);
	}
	SIGPROCMASK(SIG_SETMASK, &oset, NULL, rc);

	CMI_DPRINT(("EXIT CMI_WRITE sta = %d\n", lnk->sta));
	return status;
}
Example #4
0
struct CLB *cmu_getclb(cmi_descriptor *node, cmi_descriptor *task)
{
	cmi_status_t status;
	struct CLB *p;
	que_ent_ptr_t qp;
	sigset_t oset;
	struct addrinfo *ai_ptr;
	int rc;

	status = cmj_getsockaddr(node, task, &ai_ptr);
	if (CMI_ERROR(status))
		return NULL;

	if (ntd_root)
	{
		SIGPROCMASK(SIG_BLOCK, &ntd_root->mutex_set, &oset, rc);
		for (qp = RELQUE2PTR(ntd_root->cqh.fl) ; qp != &ntd_root->cqh ;
				qp = RELQUE2PTR(p->cqe.fl))
		{
			p = QUEENT2CLB(qp, cqe);
			if (0 == memcpy(ai_ptr->ai_addr, (sockaddr_ptr)(&p->peer_sas), ai_ptr->ai_addrlen))
			{
				SIGPROCMASK(SIG_SETMASK, &oset, NULL, rc);
				return p;
			}
		}
		SIGPROCMASK(SIG_SETMASK, &oset, NULL, rc);
	}
	return NULL;
}
Example #5
0
cmi_status_t cmj_resolve_nod_tnd(cmi_descriptor *nod, cmi_descriptor *tnd, struct sockaddr_in *inp)
{
	cmi_status_t status = SS_NORMAL;
	char hn[MAX_HOST_NAME_LEN];
	struct hostent *hp;
	int loop_limit = MAX_GETHOST_TRIES;

	/* tnd may contain host:port */
	status = cmj_getsockaddr(tnd, inp);
	if (CMI_ERROR(status))
		return status;

	if (inp->sin_addr.s_addr == INADDR_ANY)
	{
		/* use nod as a host name if tnd was just a port */
		assert(CMI_DESC_LENGTH(nod) < (SIZEOF(hn)-1));
		memcpy(hn, CMI_DESC_POINTER(nod), CMI_DESC_LENGTH(nod));
		hn[CMI_DESC_LENGTH(nod)] = '\0';

		/* test to see if nod is a dotted quad text string */
		inp->sin_addr.s_addr = INET_ADDR(hn);
		if (inp->sin_addr.s_addr == (in_addr_t)-1)
		{
			/* assume hn is a host and query netdb */
			for (; 0 < loop_limit && (NULL == (hp = GETHOSTBYNAME(hn))) && TRY_AGAIN == h_errno; loop_limit--)
				;
			endhostent();
			if (!hp)
				return CMI_NETFAIL;
			inp->sin_addr = *(struct in_addr *)hp->h_addr;
		}
	}
	return status;
}
Example #6
0
bool gtcmtr_lke_showreq(struct CLB *lnk, char rnum, bool all, bool wait, int4 pid, mstr *node)
{
	show_request	sreq;
	show_reply	srep;
	bool		locks = FALSE;
	uint4		status;

	sreq.code = CMMS_U_LKESHOW;
	sreq.rnum = rnum;
	sreq.all = all;
	sreq.wait = wait;
	sreq.pid = pid;
	assert(node && node->addr);
	sreq.nodelength = node->len;
	memcpy(sreq.node, node->addr, node->len);
	lnk->cbl = sizeof(sreq);
	lnk->mbf = (unsigned char *)&sreq;
	lnk->ast = NULL;
	status = cmi_write(lnk);
	if (CMI_ERROR(status))
	{
		((link_info *)(lnk->usr))->neterr = TRUE;
		gvcmz_error(CMMS_U_LKESHOW, status);
		return FALSE;
	}
	lnk->mbl = sizeof(srep);
	lnk->mbf = (unsigned char *)&srep;
	for (;;)
	{
		status = cmi_read(lnk);
		if (CMI_ERROR(status))
		{
			((link_info *)(lnk->usr))->neterr = TRUE;
			gvcmz_error(CMMS_V_LKESHOW, status);
			return FALSE;
		}
		if (srep.code != CMMS_V_LKESHOW)
			return locks;
		util_out_print(srep.line, FLUSH);
		locks = TRUE;
	}
}
Example #7
0
char gtcmtr_lke_showrep(struct CLB *lnk, show_request *sreq)
{
	gd_region		*cur_region;
	sgmnt_addrs		*cs_adr;
	mlk_ctldata		*lke_ctl;
	ssize_t			ls_len;
	mstr 			dnode;
	show_reply		srep;
	uint4			status;
	boolean_t		was_crit;

	cur_region = gv_cur_region = gtcm_find_region(curr_entry, sreq->rnum)->reghead->reg;
	if (dba_bg == cur_region->dyn.addr->acc_meth || dba_mm == cur_region->dyn.addr->acc_meth)
	{
		cs_adr = &FILE_INFO(cur_region)->s_addrs;
		ls_len = cs_adr->lock_addrs[1] - cs_adr->lock_addrs[0];
		lke_ctl = (mlk_ctldata *)malloc(ls_len);
		/* Prevent any modification of the lock space while we make a local copy of it */
		if (cs_adr->critical != NULL)
			crash_count = cs_adr->critical->crashcnt;
		was_crit = cs_adr->now_crit;
		if (!was_crit)
			grab_crit(cur_region);
		longcpy((uchar_ptr_t)lke_ctl, cs_adr->lock_addrs[0], ls_len);
		if (!was_crit)
			rel_crit(cur_region);
		util_cm_print(lnk, 0, NULL, RESET);
		dnode.len = sreq->nodelength;
		dnode.addr = sreq->node;
		if (lke_ctl->blkroot != 0)
			(void)lke_showtree(lnk, (mlk_shrblk_ptr_t)R2A(lke_ctl->blkroot), sreq->all, sreq->wait, sreq->pid, dnode,
					   FALSE, NULL);
		free(lke_ctl);
	}
	srep.code = CMMS_U_LKESHOW;
	lnk->cbl = SIZEOF(srep.code);
	lnk->ast = NULL;
#ifndef vinu_marker
	assert(0 == offsetof(show_reply, code));
	lnk->mbf = (unsigned char *)&srep; /* no need since lnk->mbf can be re-used. vinu 06/27/01 */
	status = cmi_write(lnk);
	if (CMI_ERROR(status))
	{ /* This routine is a server routine; not sure why it does error processing similar to a client. vinu 06/27/01 */
		((link_info *)(lnk->usr))->neterr = TRUE;
		gvcmz_error(CMMS_U_LKESHOW, status);
	} else
		lnk->mbf = (unsigned char *)sreq; /* don't restore if lnk->mbf isn't modified. vinu 06/27/01 */
#else
	/* server calls to cmi_* should do error processing as a callback. vinu 06/27/01 */
	*lnk->mbf = srep.code;
	cmi_write(lnk);
#endif
	return CM_READ;
}
char gtcmtr_lke_clearrep(struct CLB *lnk, clear_request	*creq)
{
	gd_region		*cur_region;
	sgmnt_addrs		*cs_adr;
	mlk_ctldata_ptr_t	lke_ctl;
	mstr			dnode;
	show_reply		srep;
	uint4			status;

	cur_region = gv_cur_region = gtcm_find_region(curr_entry, creq->rnum)->reghead->reg;
	if (dba_bg == cur_region->dyn.addr->acc_meth || dba_mm == cur_region->dyn.addr->acc_meth)
	{
		cs_adr = &FILE_INFO(cur_region)->s_addrs;
		lke_ctl = (mlk_ctldata_ptr_t)cs_adr->lock_addrs[0];
		util_cm_print(lnk, 0, NULL, RESET);
		dnode.len = creq->nodelength;
		dnode.addr = creq->node;
		if (cs_adr->critical != NULL)
			crash_count = cs_adr->critical->crashcnt;
		grab_crit(cur_region);
		if (lke_ctl->blkroot != 0)
			lke_cleartree(cur_region, lnk, lke_ctl, (mlk_shrblk_ptr_t)R2A(lke_ctl->blkroot), creq->all,
				      creq->interactive, creq->pid, dnode);
		rel_crit(cur_region);
	}
	srep.code = CMMS_U_LKEDELETE;
	lnk->cbl = sizeof(srep.code);
	lnk->ast = NULL;
#ifndef vinu_marker
	assert(0 == offsetof(show_reply, code));
	lnk->mbf = (unsigned char *)&srep; /* no need since lnk->mbf can be re-used. vinu 06/27/01 */
	status = cmi_write(lnk);
	if (CMI_ERROR(status))
	{ /* This routine is a server routine; not sure why it does error processing similar to a client. vinu 06/27/01 */
		((link_info *)(lnk->usr))->neterr = TRUE;
		gvcmz_error(CMMS_U_LKEDELETE, status);
	} else
		lnk->mbf = (unsigned char *)creq; /* don't restore if lnk->mbf isn't modified. vinu 06/27/01 */
#else
	/* server calls to cmi_* should do error processing as a callback. vinu 06/27/01 */
	*lnk->mbf = srep.code;
	cmi_write(lnk);
#endif
	return CM_READ;
}
Example #9
0
cmi_status_t cmi_read(struct CLB *lnk)
{
    sigset_t oset;
    cmi_status_t status;
    struct NTD *tsk = lnk->ntd;
    int rc;

    CMI_DPRINT(("ENTER CMI_READ, AST 0x%x\n", lnk->ast));

    lnk->cbl = lnk->mbl;
    SIGPROCMASK(SIG_BLOCK, &tsk->mutex_set, &oset, rc);
    status = cmj_read_start(lnk);
    if (CMI_ERROR(status))
    {
        SIGPROCMASK(SIG_SETMASK, &oset, NULL, rc);
        CMI_DPRINT(("EXIT CMI_READ ERROR CODE %d\n", status));
        return status;
    }
    /*
     * At this point see if the I/O has completed
     * by probing the sta CLB field.
     */
    cmj_housekeeping();
    while (lnk->sta == CM_CLB_READ && !lnk->ast)
    {
        sigsuspend(&oset);
        cmj_housekeeping();
        /* recover status */
        if (lnk->sta != CM_CLB_READ)
            status = CMI_CLB_IOSTATUS(lnk);
    }
    SIGPROCMASK(SIG_SETMASK, &oset, NULL, rc);

    CMI_DPRINT(("EXIT CMI_READ sta = %d\n", lnk->sta));
    return status;
}
Example #10
0
void cmj_read_interrupt(struct CLB *lnk, int signo)
{
	int rval;
	cmi_status_t status = SS_NORMAL;
	error_def(CMI_OVERRUN);
	char peekchar;
	struct iovec vec[NUM_IOVECS];
	struct msghdr msg;

	if (-1 == lnk->mun)
		return;
	if (CM_CLB_IDLE == lnk->sta)
	{
		/* potential eof, error */
		/* just peek to see if a 0 or error comes back */
		while ((-1 == (rval = recv(lnk->mun, (void *)&peekchar, 1, MSG_PEEK))) && EINTR == errno)
			;
		if (0 == rval)
			cmj_err(lnk, CMI_REASON_STATUS, (cmi_status_t)ECONNRESET);
		else
		{
			if (-1 ==  rval && !CMI_IO_WOULDBLOCK(errno))
				cmj_err(lnk, CMI_REASON_STATUS, (cmi_status_t)errno);
		}
		/* no I/O outstand - return leaving data in socket */
		return;
	}
	/* setup I/O vec based on past history */
	memset(&msg, 0, sizeof(msg));
	msg.msg_iov = vec;
	if (CMI_TCP_PREFIX_LEN > lnk->ios.len_len)
	{
		/* length not entirely read */
		msg.msg_iovlen = NUM_IOVECS_BOTH;
		vec[0].iov_len = CMI_TCP_PREFIX_LEN - lnk->ios.len_len;
		vec[0].iov_base = (lnk->ios.u.lenbuf + lnk->ios.len_len);
		vec[1].iov_len = lnk->mbl;
		vec[1].iov_base = (caddr_t)lnk->mbf;
	}
	else
	{
		/* length had been read, need to complete data */
		msg.msg_iovlen = NUM_IOVECS_DATA;
		vec[0].iov_len = lnk->ios.u.len - lnk->ios.xfer_count;
		vec[0].iov_base = (caddr_t)(lnk->mbf + lnk->ios.xfer_count);
	}

	while ((-1 == (rval = recvmsg(lnk->mun, &msg, 0))) && EINTR == errno)
		;
	/* weed out the bad things first */
	if (0 == rval)
	{
		cmj_err(lnk, CMI_REASON_STATUS, (cmi_status_t)ECONNRESET);
		return;
	}
	if (-1 == rval && !CMI_IO_WOULDBLOCK(errno))
	{
		cmj_err(lnk, CMI_REASON_STATUS, (cmi_status_t)errno);
		return;
	}

	/* now we either have a positive rval or a no data error */
	if (0 < rval)
	{
		if (NUM_IOVECS_BOTH == msg.msg_iovlen)
		{
			if ((CMI_TCP_PREFIX_LEN - lnk->ios.len_len) <= rval)
			{
				/* we now have the whole length */
				rval -= (CMI_TCP_PREFIX_LEN - lnk->ios.len_len);
				lnk->ios.len_len = CMI_TCP_PREFIX_LEN;
				lnk->ios.u.len = ntohs(lnk->ios.u.len);
			}
			else
			{
				/* we just read part of the length */
				assert(CMI_TCP_PREFIX_LEN > rval);
				lnk->ios.len_len +=  rval;
				status = cmj_clb_set_async(lnk);
				if (CMI_ERROR(status))
					cmj_err(lnk, CMI_REASON_STATUS, status);
				return;
			}
		}
		if (rval == (int)(lnk->ios.u.len - lnk->ios.xfer_count))
		{
			lnk->ios.xfer_count += rval;
			cmj_fini(lnk);
			return;
		}
		lnk->ios.xfer_count += rval;
	}
	status = cmj_clb_set_async(lnk);
	if (CMI_ERROR(status))
		cmj_err(lnk, CMI_REASON_STATUS, status);
}
Example #11
0
void gvcmx_susremlk(unsigned char rmv_locks)
{
	uint4		status,count,buffer;
	unsigned char	*ptr;
	struct CLB	*p;

	error_def(ERR_BADSRVRNETMSG);

	if (!ntd_root)
		return;
	buffer = lksusp_sent = lksusp_rec = 0;
	for (p = (struct CLB *)RELQUE2PTR(ntd_root->cqh.fl); p != (struct CLB *)ntd_root; p = (struct CLB *)RELQUE2PTR(p->cqe.fl))
	{
		if (((link_info*)(p->usr))->lck_info & REQUEST_PENDING)
			buffer += p->mbl;
	}
	ENSURE_STP_FREE_SPACE(buffer);
	ptr = stringpool.free;
	for (p = (struct CLB *)RELQUE2PTR(ntd_root->cqh.fl); p != (struct CLB *)ntd_root; p = (struct CLB *)RELQUE2PTR(p->cqe.fl))
	{
		if (((link_info *)(p->usr))->lck_info & REQUEST_PENDING)
		{
			p->mbf = ptr;
			*ptr++ = CMMS_L_LKSUSPEND;
			*ptr++ = rmv_locks;
			p->cbl = 2;
			p->ast = 0;
			status = cmi_write(p);
			if (CMI_ERROR(status))
			{
				((link_info *)(p->usr))->neterr = TRUE;
				gvcmz_error(CMMS_M_LKSUSPENDED, status);
				return;
			}
			p->ast = gvcmz_lksuspend_ast;
			status = cmi_read(p);
			if (CMI_ERROR(status))
			{
				((link_info *)(p->usr))->neterr = TRUE;
				gvcmz_error(CMMS_M_LKSUSPENDED, status);
				return;
			}
			lksusp_sent++;
			ptr = p->mbf + p->mbl;
		}
	}
	while (lksusp_sent != lksusp_rec && !lkerror)
		CMI_IDLE(CM_LKSUSPEND_TIME);
	if (lkerror)
	{
		if (CMI_CLB_ERROR(lkerrlnk))
			gvcmz_error(lkerror, CMI_CLB_IOSTATUS(lkerrlnk));
		else
		{
			if (*(lkerrlnk->mbf) != CMMS_E_ERROR)
				rts_error(VARLSTCNT(1) ERR_BADSRVRNETMSG);
			else
				gvcmz_errmsg(lkerrlnk, FALSE);
		}
	}
}
Example #12
0
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;
}
Example #13
0
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;
}
Example #14
0
cmi_status_t cmi_init(cmi_descriptor *tnd, unsigned char tnr,
                void (*err)(struct NTD *, struct CLB *, cmi_reason_t reason),
		void (*crq)(struct CLB *),
		bool (*acc)(struct CLB *),
		void (*urg)(struct CLB *, unsigned char data),
		size_t pool_size,
		size_t usr_size,
		size_t mbl)
{
	cmi_status_t status = SS_NORMAL;
	char *envvar;
	struct protoent *p;
	unsigned short myport;
	struct sockaddr_in in;
	sigset_t oset;
	int on = 1;
	int rval, rc, save_errno;

	status = cmj_netinit();
	if (CMI_ERROR(status))
		return status;

	status = cmj_getsockaddr(tnd, &in);
	if (CMI_ERROR(status))
		return status;
	ntd_root->pool_size = pool_size;
	ntd_root->usr_size = usr_size;
	ntd_root->mbl = mbl;

	p = getprotobyname(GTCM_SERVER_PROTOCOL);
	endprotoent();
	if (!p)
		return CMI_NETFAIL;

	/* create the listening socket */
	ntd_root->listen_fd = socket(AF_INET, SOCK_STREAM, p->p_proto);
	if (FD_INVALID == ntd_root->listen_fd)
		return errno;

	/* make sure we can re-run quickly w/o reuse problems */
	status = setsockopt(ntd_root->listen_fd, SOL_SOCKET, SO_REUSEADDR,
		(void*)&on, SIZEOF(on));
	if (-1 == status)
	{
		save_errno = errno;
		CLOSEFILE_RESET(ntd_root->listen_fd, rc);	/* resets "ntd_root->listen_fd" to FD_INVALID */
		return save_errno;
	}

	status = bind(ntd_root->listen_fd, (struct sockaddr*)&in, SIZEOF(in));
	if (-1 == status)
	{
		save_errno = errno;
		CLOSEFILE_RESET(ntd_root->listen_fd, rc);	/* resets "ntd_root->listen_fd" to FD_INVALID */
		return save_errno;
	}

	status = cmj_setupfd(ntd_root->listen_fd);
	if (CMI_ERROR(status))
	{
		CLOSEFILE_RESET(ntd_root->listen_fd, rc);	/* resets "ntd_root->listen_fd" to FD_INVALID */
		return status;
	}

	SIGPROCMASK(SIG_BLOCK, &ntd_root->mutex_set, &oset, rc);
	rval = listen(ntd_root->listen_fd, MAX_CONN_IND);
	if (-1 == rval)
	{
		save_errno = errno;
		CLOSEFILE_RESET(ntd_root->listen_fd, rc);	/* resets "ntd_root->listen_fd" to FD_INVALID */
		SIGPROCMASK(SIG_SETMASK, &oset, NULL, rc);
		return save_errno;
	}
	status = cmj_set_async(ntd_root->listen_fd);
	if (CMI_ERROR(status))
	{
		CLOSEFILE_RESET(ntd_root->listen_fd, rc);	/* resets "ntd_root->listen_fd" to FD_INVALID */
		SIGPROCMASK(SIG_SETMASK, &oset, NULL, rc);
		return status;
	}
	FD_SET(ntd_root->listen_fd, &ntd_root->rs);
	FD_SET(ntd_root->listen_fd, &ntd_root->es);
	ntd_root->err = err;
	ntd_root->crq = crq;
	ntd_root->acc = acc;
	ntd_root->urg = urg;
	if (ntd_root->listen_fd > ntd_root->max_fd)
		ntd_root->max_fd = ntd_root->listen_fd;
	cmj_housekeeping(); /* will establish listening pools */
	SIGPROCMASK(SIG_SETMASK, &oset, NULL, rc);
	return SS_NORMAL;
}