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; } }
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; }
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; }
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; }
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; }
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; } }
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; }
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; }
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); }
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); } } }
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; }
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; }