Interpreting SEND MAP vectors for the CICS-MQ bridge
An outbound SEND MAP vector can contain an application data structure (ADS) and an application data structure descriptor in short form (ADSD) or long form (ADSDL).
To interpret a SEND MAP vector (assuming that the message contains both an ADS and an ADSD or ADSDL):
- Get the message containing the SEND MAP vector from the bridge reply queue into a message buffer.
- Locate the start of the outbound SEND MAP vector in the message buffer. This vector is
appended to the MQCIH, and so is at an offset equal to the length of the MQCIH from the start of the
message buffer. You can use the following code fragment as a model:
/* #includes */ #include cmqc.h /* IBM MQ header */ #include dfhbrmqh.h /* Vector structures */ ⋮ /* #defines */ ⋮ MQCHAR * MsgBuffer ; /* Message buffer pointer */ brmq_send_map * pVector ; /* Vector pointer */ ⋮ /* Get message from reply queue */ ⋮ /* Set the vector pointer to the start of the vector */ pVector = MsgBuffer + ((MQCIH *) MsgBuffer)->StrucLength ; -
Identify the starting addresses of the application data structure
(ADS) and the application data structure descriptor (ADSD or ADSDL)
from the SEND MAP vector.
The following diagram shows the structure of an outbound SEND MAP vector, assuming that you have set a pointer called
pVectorto address the start of thebrmq_send_mapvector, as in the previous code fragment:|---------------------------x'vvvvvvvv'-------------------------→| |---------------------x'zzzzzzzz'-------------------→| |----------------x'xxxxxxxx'------------→| |---------sizeof(brmq_send_map)---------→| --→ x'wwwwwwww' ←-- 1804 O --→ x'yyyyyyyy' ←-- -------------- ... ------------------------...---------...---- |vvvv|FFFF|D444| |wwww|xxxx|yyyy|zzzz| ADS | ADSD or | |vvvv|1804|6000| |wwww|xxxx|yyyy|zzzz| | ADSDL | -------------- ... ------------------------...---------...---- ↑ ↑ ↑ ↑ ↑ pVector | | | pVector->brmq_sm_adsd_offset | | pVector->brmq_sm_adsd_len | pVector->brmq_sm_data_offset pVector->brmq_sm_data_lenValues in the diagram shown like this:
show hexadecimal values as you see them in an ISPF editor with hex on . This value is equivalent to the hexadecimal value X'A1B2C3D4'.ABCD 1234Fields pVector->brmq_sm_data_offset and pVector->brmq_sm_data_len give the offset and length of the ADS, and fields pVector->brmq_sm_adsd_offset and pVector->brmq_sm_adsd_len give the offset and length of the ADSD or ADSDL.
Fields brmq_sm_adsd_offset and brmq_sm_adsd_len are both set to zero if no ADSD or ADSDL is included in the message.
-
Identify the fields in the ADSD or ADSDL.
The ADSD and ADSDL are both mapped to structures that are defined in header file dfhbrarh.h , which is distributed in CICS® library <hlq>.SDFHC370 . You can examine the structure definitions there to see how the fields are laid out. The fields of the ADSD are also described in Link3270 ADS descriptor .
To compile your bridge application on a workstation, copy file dfhbrarh.h to that environment.
Both the ADSD and the ADSDL are represented by two types of structure. The first structure is the descriptor, which occurs only once at the start of the ADSD or ADSDL. These types are defined as follows:- ads_descriptor
- Descriptor for the ADSD (short form)
- ads_long_descriptor
- Descriptor for the ADSDL (long form)
The second structure is the field descriptor, which is repeated once for each field in the map. These types are defined as follows:- ads_field_descriptor
- Field descriptor for the ADSD (short form)
- ads_long_field_descriptor
- Field descriptor for the ADSDL (long form)
The ADSDL:------------------------------------------------------ ... | ADS Descriptor | field descriptor | field descriptor | ------------------------------------------------------ ... ↑ ↑ ↑ | | ads_long_field_descriptor | ads_long_field_descriptor ads_long_descriptorThe ADSD:
Fields adsd_field_count and adsdl_field_count in the descriptors identify the number of field descriptors in the ADSD and ADSDL.------------------------------------------------------ ... | ADS Descriptor | field descriptor | field descriptor | ------------------------------------------------------ ... ↑ ↑ ↑ | | ads_field_descriptor | ads_field_descriptor ads_descriptorYou can use the following code fragment to set pointers to the start of the ADSD or ADSDL structures and process the field descriptors sequentially. It is assumed thatpVectoralready addresses the start of thebrmq_send_mapvector, and that you have an MQCIH structure namedmqcihthat contains the CIH from the inbound message./* #includes */ #include cmqc.h /* IBM MQ header */ #include dfhbrmqh.h /* Vector structures */ #include dfhbrarh.h /* ADSD structures */ ⋮ /* Ptr to ADSD descriptor */ ads_descriptor * pADSD_D ; /* Ptr to ADSDL descriptor */ ads_long_descriptor * pADSDL_D ; /* Ptr to ADSD field descriptor */ ads_field_descriptor * pADSD_FD ; /* Ptr to ADSDL field descriptor */ ads_long_field_descriptor * pADSDL_FD ; ⋮ /* Initialize the pointer to the ADSDL descriptor or the */ /* ADSD descriptor depending on mqcih.ADSDescriptor */ if (mqcih.ADSDescriptor && MQCADSD_MSGFORMAT) { pADSDL_D = pVector->brmq_sm_adsd_offset; /* Long form */ pADSDL_FD = pADSDL_D + sizeof(ads_long_descriptor) ; ⋮ /* Enter a loop where we process all field descriptors */ /* in the ADSDL sequentially */ do { /* Perform some processing */ ⋮ pADSDL_FD += sizeof(ads_long_field_descriptor) ; } while (pADSDL_FD < pADSDL_D->adsdl_length ) ; } else /* Short form */ { pADSD_D = pVector->brmq_sm_adsd_offset; /* Short form */ pADSD_FD = pADSD_D + sizeof(ads_descriptor) ; /* Enter a loop where we process all field descriptors */ /* in the ADSD sequentially */ do { /* Perform some processing */ ⋮ pADSD_FD += sizeof(ads_field_descriptor) ; } while (pADSD_FD < pADSD_D->adsd_length ) ; } ⋮ -
Identify the fields in the ADS.
The ADS is mapped to a structure that is generated when you assemble your map. If you include a
keyword=parametervalue ofDSECT=ADSDLin your mapset definition macro, you get the long form of the ADS. The output from map assembly is a union of two structures: an input structure and an output structure. This example shows part of such a union (only the first field definition is shown for each structure, and the comments have been added following map assembly).
The two structures are functionally identical, except that the input structure includes the extended attribute values in a 7–element array, and the output structure provides individually named fields.union { struct { char dfhms1[12]; /* 12 reserved bytes */ int dfhms2; /* Offset to next field */ int tranidl; /* Data length of this field */ int tranidf; /* Flag or attribute value */ int dfhms3[7]; /* Extended attributes array */ char tranidi[4]; /* Data value of field */ ... } bmstmp1i; /* Input structure */ struct { char dfhms56[12]; /* 12 reserved bytes */ int dfhms57; /* Offset to next field */ int dfhms58; /* Data length of this field */ int tranida; /* Flag or attribute value */ int tranidc; /* Extended attribute */ int tranidp; /* Extended attribute */ int tranidh; /* Extended attribute */ int tranidv; /* Extended attribute */ int tranidu; /* Extended attribute */ int tranidm; /* Extended attribute */ int tranidt; /* Extended attribute */ char tranido[4]; /* Data value of field */ ... } bmstmp1o; /* Output structure */ } bmstmp1; /* Union */You can use the following code fragment to set pointers to the start of the ADS. The structure names shown in the example DSECT, are used for illustration. Two pointers are set, the first to address inbound data and the second to address outbound data. It is assumed thatpVectoralready addresses the start of thebrmq_send_mapvector./* #includes */ #include cmqc.h /* IBM MQ header */ #include dfhbrmqh.h /* Vector structures */ #include dfhbrarh.h .. /* ADSD structures */ #include mydsect.h /* DSECT from map assembly */ ⋮ bmstmp1i * pADSI ; /* Pointer to the inbound ADS */ bmstmp1o * pADSO ; /* Pointer to the outbound ADS */ bmstmp1i * pADSI_An ; /* Inbound ADS Anchor */ bmstmp1o * pADSO_An ; /* Outbound ADS Anchor */ ⋮ /* We are dealing with an outbound vector, so we will */ /* initialize the outbound pointer to address the ADS */ pADSO = pVector->brmq_sm_adsd_offset ; /* Save initial value as anchor */ pADSO_An = pADSO ; /* Move to the start of the first field */ pADSO += pADSDL_FD->adsdl_field_offset ; /* Enter a loop where we process all fields in the ADS */ /* sequentially. It is assumed that the value of pADSDL_FD */ /* is being augmented to the next field descriptor in the */ /* ADSDL with every loop. A model for this is shown in the */ /* previous code fragment. Note that adsdl_field_offset */ /* contains the absolute offset of the field from the start */ /* of the ADS. */ do { /* Perform some processing */ ⋮ /* Add offset of next field to ADS Anchor value */ /* to address the next field */ pADSO = pADSO_An + pADSDL_FD->adsdl_field_offset ; } while (pADSDL_FD < pADSDL_D->adsd_length ) ; ⋮