# -*-c-*- # # $Id: 34MQPUT-v5,v 33.1 2009/07/02 21:11:03 biersma Exp $ # # (c) 1999-2009 Morgan Stanley & Co. Incorporated # See ..../src/LICENSE for terms of distribution. # void MQPUT(Hconn,Hobj,MsgDesc,PutMsgOpts,Msg,CompCode,Reason) MQHCONN Hconn MQHOBJ Hobj MQMD MsgDesc MQPMO PutMsgOpts SV *Msg MQLONG CompCode = NO_INIT MQLONG Reason = NO_INIT PREINIT: char *Key, *pPutMsgRecPtr = NULL, *String; STRLEN KeyLength, StringLength; int index, subindex, FieldSize; int PutMsgRecSize = 0; PMQRR pResponseRecPtr = NULL; PMQCHAR Buffer; SV **svp; AV *PutMsgRecs, *ValidPutMsgRecFieldsArray; AV *ResponseRecArray; HV *PutMsgRecFields = NULL, *PutMsgRecHash; HV *ValidPutMsgRecFieldsHash; HV *ValidPutMsgRecFieldsSubHash, *ResponseRecHash; PPCODE: CompCode = MQCC_FAILED; Reason = MQRC_UNEXPECTED_ERROR; sv_setiv(ST(5),(IV)CompCode); sv_setiv(ST(6),(IV)Reason); /* * We set the MQMD version to 2, so users of segmentation or * grouping won't have to do this manually. */ if (MsgDesc.Version < MQMD_VERSION_2) { MsgDesc.Version = MQMD_VERSION_2; } if ( hv_exists((HV*)SvRV(ST(3)),"PutMsgRecs",10) ) { /* * Using the put-msg records (distribution list features) * requires MQPMO version 2. We enable that automatically * if distribution lists are used. */ if (PutMsgOpts.Version < MQPMO_VERSION_2) { PutMsgOpts.Version = MQPMO_VERSION_2; } /* We will need this configuration hash, but only when handling dist lists. */ if ( (ValidPutMsgRecFieldsHash = perl_get_hv("MQSeries::Constants::ValidPutMsgRecFields",FALSE)) == NULL ) { warn("Unable to see %%MQSeries::Constants::ValidPutMsgRecFields\n"); XSRETURN_EMPTY; } if ( (ValidPutMsgRecFieldsArray = perl_get_av("MQSeries::Constants::ValidPutMsgRecFields",FALSE)) == NULL ) { warn("Unable to see @MQSeries::Constants::ValidPutMsgRecFields\n"); XSRETURN_EMPTY; } svp = hv_fetch((HV*)SvRV(ST(3)),"PutMsgRecs",10,FALSE); if ( svp == NULL ) { warn("Unable to fetch value for key PutMsgRecs\n"); XSRETURN_EMPTY; } if ( !SvROK(*svp) || ( SvROK(*svp) && SvTYPE(SvRV(*svp)) != SVt_PVAV ) ) { warn("Invalid data for 'PutMsgRecs', not an ARRAY reference\n"); XSRETURN_EMPTY; } PutMsgRecs = (AV*)SvRV(*svp); PutMsgOpts.RecsPresent = av_len(PutMsgRecs) + 1; /* OK, here we go... First, look at the *first* PutMsgRecs hash, and from that set the PutMsgOpts.PutMsgRecFields value, and malloc() the necessary memory for the MQMPR and MQRR structures. NOTE: When we scan the entire list of PutMsgRecs hashes, they will be required to have the *same* keys as the first one. */ for ( index = -1 ; index < PutMsgOpts.RecsPresent ; index++ ) { svp = av_fetch(PutMsgRecs,(index == -1 ? 0 : index),FALSE); if ( svp == NULL ) { warn("Unable to retreive array element from PutMsgRecs!!\n"); XSRETURN_EMPTY; } if ( !SvROK(*svp) || ( SvROK(*svp) && SvTYPE(SvRV(*svp)) != SVt_PVHV ) ) { warn("Invalid data for PutMsgRecs->[%d], not a HASH reference\n", (index == -1 ? 0 : index)); XSRETURN_EMPTY; } PutMsgRecHash = (HV*)SvRV(*svp); if ( index == -1 ) { PutMsgRecFields = (HV*)SvRV(*svp); } for ( subindex = 0 ; subindex < av_len(ValidPutMsgRecFieldsArray) + 1 ; subindex++ ) { svp = av_fetch(ValidPutMsgRecFieldsArray,subindex,FALSE); if ( svp == NULL ) { warn("Unable to retreive array element from ValidPutMsgRecFieldsArray!!\n"); XSRETURN_EMPTY; } Key = SvPV(*svp,KeyLength); if ( !hv_exists(PutMsgRecFields,Key,KeyLength) ) { continue; } svp = hv_fetch(ValidPutMsgRecFieldsHash,Key,KeyLength,FALSE); if ( svp == NULL ) { warn("Unable to retreive hash value from ValidPutMsgRecFieldsHash!!\n"); XSRETURN_EMPTY; } if ( !SvROK(*svp) || ( SvROK(*svp) && SvTYPE(SvRV(*svp)) != SVt_PVHV ) ) { warn("Invalid data for ValidPutMsgRecFields->{%s}, not a HASH reference\n",Key); XSRETURN_EMPTY; } ValidPutMsgRecFieldsSubHash = (HV*)SvRV(*svp); if ( index == -1 ) { svp = hv_fetch(ValidPutMsgRecFieldsSubHash,"Flag",4,FALSE); if ( svp == NULL ) { warn("Invalid data for ValidPutMsgRecFields->{%s} HASH, no 'Flag' key\n",Key); XSRETURN_EMPTY; } PutMsgOpts.PutMsgRecFields |= SvIV(*svp); } svp = hv_fetch(ValidPutMsgRecFieldsSubHash,"Size",4,FALSE); if ( svp == NULL ) { warn("Invalid data for ValidPutMsgRecFields->{%s} HASH, no 'Size' key\n",Key); XSRETURN_EMPTY; } FieldSize = SvIV(*svp); if ( index == -1 ) { PutMsgRecSize += FieldSize ? FieldSize : sizeof(MQLONG); } else { svp = hv_fetch(PutMsgRecHash,Key,KeyLength,FALSE); if ( svp == NULL ) { warn("Unable to retrieve hash value from PutMsgRecs->[%d]\n",index); XSRETURN_EMPTY; } if ( FieldSize ) { String = SvPV(*svp,StringLength); strncpy(pPutMsgRecPtr, String, StringLength > FieldSize ? FieldSize : StringLength); pPutMsgRecPtr += FieldSize; } else { *(PMQLONG)pPutMsgRecPtr = SvIV(*svp); pPutMsgRecPtr += sizeof(MQLONG); } } } if ( index == -1 ) { if ( (pPutMsgRecPtr = malloc(PutMsgOpts.RecsPresent * PutMsgRecSize)) == NULL ) { perror("Unable to allocate memory"); XSRETURN_EMPTY; } memset(pPutMsgRecPtr,'\0',PutMsgOpts.RecsPresent * PutMsgRecSize); if ( (pResponseRecPtr = malloc(PutMsgOpts.RecsPresent * sizeof(MQRR))) == NULL ) { perror("Unable to allocate memory"); XSRETURN_EMPTY; } memset(pResponseRecPtr,'\0',PutMsgOpts.RecsPresent * sizeof(MQRR)); PutMsgOpts.PutMsgRecPtr = pPutMsgRecPtr; PutMsgOpts.ResponseRecPtr = pResponseRecPtr; } } } Buffer = SvPV(Msg,PL_na); MQPUT(Hconn,Hobj,&MsgDesc,&PutMsgOpts,SvCUR(Msg),Buffer,&CompCode,&Reason); /* If there were multiple reason codes imbedded in the "Response Records", then we have to decode these. */ if ( Reason == MQRC_MULTIPLE_REASONS ) { ResponseRecArray = newAV(); for ( index = 0 ; index < PutMsgOpts.RecsPresent ; index++ ) { ResponseRecHash = newHV(); hv_store(ResponseRecHash,"CompCode",8,newSViv(pResponseRecPtr->CompCode),FALSE); hv_store(ResponseRecHash,"Reason",6,newSViv(pResponseRecPtr->Reason),FALSE); av_push(ResponseRecArray,newRV_noinc((SV*)ResponseRecHash)); pResponseRecPtr++; } hv_store((HV*)SvRV(ST(3)),"ResponseRecs",12,newRV_noinc((SV*)ResponseRecArray),FALSE); } hv_store((HV*)SvRV(ST(2)),"Version",7, (newSViv(MsgDesc.Version)),0); hv_store((HV*)SvRV(ST(2)),"Report",6, (newSViv(MsgDesc.Report)),0); hv_store((HV*)SvRV(ST(2)),"MsgType",7, (newSViv(MsgDesc.MsgType)),0); hv_store((HV*)SvRV(ST(2)),"Expiry",6, (newSViv(MsgDesc.Expiry)),0); hv_store((HV*)SvRV(ST(2)),"Feedback",8, (newSViv(MsgDesc.Feedback)),0); hv_store((HV*)SvRV(ST(2)),"Encoding",8, (newSViv(MsgDesc.Encoding)),0); hv_store((HV*)SvRV(ST(2)),"CodedCharSetId",14, (newSViv(MsgDesc.CodedCharSetId)),0); hv_store((HV*)SvRV(ST(2)),"Format",6, (newSVpv(MsgDesc.Format, 8)),0); hv_store((HV*)SvRV(ST(2)),"Priority",8, (newSViv(MsgDesc.Priority)),0); hv_store((HV*)SvRV(ST(2)),"Persistence",11, (newSViv(MsgDesc.Persistence)),0); hv_store((HV*)SvRV(ST(2)),"MsgId",5, (newSVpv((char *)MsgDesc.MsgId,24)),0); hv_store((HV*)SvRV(ST(2)),"CorrelId",8, (newSVpv((char *)MsgDesc.CorrelId,24)),0); hv_store((HV*)SvRV(ST(2)),"BackoutCount",12, (newSViv(MsgDesc.BackoutCount)),0); hv_store((HV*)SvRV(ST(2)),"ReplyToQ",8, (newSVpv(MsgDesc.ReplyToQ, 48)),0); hv_store((HV*)SvRV(ST(2)),"ReplyToQMgr",11, (newSVpv(MsgDesc.ReplyToQMgr, 48)),0); hv_store((HV*)SvRV(ST(2)),"UserIdentifier",14, (newSVpv(MsgDesc.UserIdentifier, 12)),0); hv_store((HV*)SvRV(ST(2)),"AccountingToken",15, (newSVpv((char *)MsgDesc.AccountingToken,32)),0); hv_store((HV*)SvRV(ST(2)),"ApplIdentityData",16, (newSVpv(MsgDesc.ApplIdentityData, 32)),0); hv_store((HV*)SvRV(ST(2)),"PutApplType",11, (newSViv(MsgDesc.PutApplType)),0); hv_store((HV*)SvRV(ST(2)),"PutApplName",11, (newSVpv(MsgDesc.PutApplName, 28)),0); hv_store((HV*)SvRV(ST(2)),"PutDate",7, (newSVpv(MsgDesc.PutDate, 8)),0); hv_store((HV*)SvRV(ST(2)),"PutTime",7, (newSVpv(MsgDesc.PutTime, 8)),0); hv_store((HV*)SvRV(ST(2)),"ApplOriginData",14, (newSVpv(MsgDesc.ApplOriginData, 4)),0); hv_store((HV*)SvRV(ST(2)),"GroupId",7, (newSVpv((char *)MsgDesc.GroupId,24)),0); hv_store((HV*)SvRV(ST(2)),"MsgSeqNumber",12, (newSViv(MsgDesc.MsgSeqNumber)),0); hv_store((HV*)SvRV(ST(2)),"Offset",6, (newSViv(MsgDesc.Offset)),0); hv_store((HV*)SvRV(ST(2)),"MsgFlags",8, (newSViv(MsgDesc.MsgFlags)),0); hv_store((HV*)SvRV(ST(2)),"OriginalLength",14, (newSViv(MsgDesc.OriginalLength)),0); SvSETMAGIC(ST(2)); /* output a MQPMO: */ hv_store((HV*)SvRV(ST(3)),"Version",7, (newSViv(PutMsgOpts.Version)),0); hv_store((HV*)SvRV(ST(3)),"Options",7, (newSViv(PutMsgOpts.Options)),0); hv_store((HV*)SvRV(ST(3)),"Timeout",7, (newSViv(PutMsgOpts.Timeout)),0); hv_store((HV*)SvRV(ST(3)),"Context",7, (newSViv(PutMsgOpts.Context)),0); hv_store((HV*)SvRV(ST(3)),"KnownDestCount",14, (newSViv(PutMsgOpts.KnownDestCount)),0); hv_store((HV*)SvRV(ST(3)),"UnknownDestCount",16, (newSViv(PutMsgOpts.UnknownDestCount)),0); hv_store((HV*)SvRV(ST(3)),"InvalidDestCount",16, (newSViv(PutMsgOpts.InvalidDestCount)),0); hv_store((HV*)SvRV(ST(3)),"ResolvedQName",13, (newSVpv(PutMsgOpts.ResolvedQName, 48)),0); hv_store((HV*)SvRV(ST(3)),"ResolvedQMgrName",16, (newSVpv(PutMsgOpts.ResolvedQMgrName, 48)),0); hv_store((HV*)SvRV(ST(3)),"RecsPresent",11, (newSViv(PutMsgOpts.RecsPresent)),0); hv_store((HV*)SvRV(ST(3)),"PutMsgRecFields",15, (newSViv(PutMsgOpts.PutMsgRecFields)),0); hv_store((HV*)SvRV(ST(3)),"PutMsgRecOffset",15, (newSViv(PutMsgOpts.PutMsgRecOffset)),0); hv_store((HV*)SvRV(ST(3)),"ResponseRecOffset",17, (newSViv(PutMsgOpts.ResponseRecOffset)),0); SvSETMAGIC(ST(3)); sv_setiv(ST(5), (IV)CompCode); SvSETMAGIC(ST(5)); sv_setiv(ST(6), (IV)Reason); SvSETMAGIC(ST(6));