From VisualWorks®, 7.6 of February 1, 2008 on February 1, 2008 at 1:10:57 pm (Dialog confirm: 'You are filing-in a Parcel source file!\\While this is possible it will not have\the same effect as loading the parcel.\None of the Parcel''s prerequisites will\be loaded and none of its load actions\will be performed.\\Are you sure you want to file-in?' withCRs) ifFalse: [self error: 'Parcel file-in abandoned. Choose terminate or close.'] <class> <name>MQMessage</name> <environment>MQ</environment> <super>Core.Object</super> <private>false</private> none messageHndl data targetQueue reportOptions msgTypeNumber <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.MQMessage
MQMessage is the abstract superclass for all message classes of the MQ-Interface. An instance of subclasses of MQMessage can only be created in the context of a Queue, thus the use of instance creation methods #newFor: and #newFor:type is necessary to pass the desired sender/receiver queue directly to the new message instance. Basic subclasses are derived from the basic MQ message types: datagram AsynchronousMessage request Request reply Reply report Report Each of these classes implement a class method #messageTypeNumber which returns the message type of the underlying MQ library. Because this type number system is extensible, a developer can choose from a special range of numbers for his own message types (between MQMT_APPL_FIRST and MQMT_APPL_LAST, which are the numbers between 65536 and 999999999). If the VisualWorks application does not implement a special class for a new message type number, it will always represent such a message as an AsynchronousMessage. If the developer implements an application specific message class corresponding to his new number, he has to implement class method #messageTypeNumber to return the corresponding message type number. This way his implementation will create instances of this new message type class on receiving such a message. Subclasses must implement the following messages: class protocol accessing messageTypeNumber Instance Variables: data <ByteArray> net contents of the message messageHndl <CCompositePointer> pointer to the underlying message object in the heap, read or to be sent via C library call reportOptions <Set of: Symbol> defines the kind of report to be done by MQ; each symbol is the name of an external interface method returning a report flag bit, e.g. #MQRO_NAN, #MQRO_PAN, #MQRO_COA, #MQRO_COD, etc. targetQueue <ReceiverQueue | SenderQueue> the queue where the message has been read from or is going to be sent to Shared Variables: DefaultMessageBufferSize <Integer> default size of buffer for data to be exchanged via MQ; a proper size is application dependent: - large value may be waste of heap memory, - low value will prevent delivery with the first MQGET and enforce a second try SystemMessageClassMap <Array of: MQMessage class> fast mapping of message type numbers to specific subclasses modeling the message type Class Instance Variables: msgTypeNumber <Integer> MsgType number that the class is modeling. The value is an Integer from intervals - [MQMT_SYSTEM_FIRST .. MQMT_SYSTEM_LAST] for system-defined message types, or - [MQMT_APPL_FIRST .. MQMT_APPL_LAST] for application-defined message types. See Application Programming Reference, Chapter 10. MQMD - Message descriptor, pp. 172
</comment> <class> <name>ActionMessage</name> <environment>MQ</environment> <super>MQ.MQMessage</super> <private>false</private> none actionDecorator <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.ActionMessage
This is an abstract class. An ActionMessage is either a request or a datagram message. On receiving an ActionMessage, its instances know how to create a Reply or Report with required settings of MsgId and CorrelId.
</comment> <class> <name>Request</name> <environment>MQ</environment> <super>MQ.ActionMessage</super> <private>false</private> none <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.Request
The Request message asks for a reply message in return.
</comment> <class> <name>MQError</name> <environment>MQ</environment> <super>Core.Error</super> <private>false</private> none <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.MQError
MQError is the superclass for all MQ-related Errors.
</comment> <class> <name>MQPutError</name> <environment>MQ</environment> <super>MQ.MQError</super> <private>false</private> none <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.MQPutError
MQPutError is raised when a PUT on an MQQueue fails.
</comment> <class> <name>QueueManager</name> <environment>MQ</environment> <super>Core.Object</super> <private>false</private> none xif state managerHndl name senderQueues receiverQueues browseQueues <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.QueueManager
This is an abstract class. QueueManager is the base object for an MQ communication interaction. Subclasses imlement local/remote managers. The QueueManager provides the context for accessing MQQueues which then are used to send/receive MQMessages. Therefore it holds the correct external interface instance in its instVar 'xif', either a local or client interface, or their THAPI versions. QueueManager is registered with Objectmemory to release external resources on returnFromSnapshot. A registry on the class side holds weak references of all instances of QueueManager subclasses.
</comment> <class> <name>RemoteQueueManager</name> <environment>MQ</environment> <super>MQ.QueueManager</super> <private>false</private> none host port channel clientConnPtr connectOptionsPtr <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.RemoteQueueManager
RemoteQueueManager - A concrete queue manager class that connects the VisualWorks image to a queue manager that is installed on a different machine using the WebSphere MQ none threaded client library The instance creation is similar to the instance creation of a local queue manager but you have to provide the connection parameters. | manager | manager := QueueManager new: #remote threaded: false. manager name: 'foo.queue.manager'. manager host: 'SomeHost'. manager port: 1423. manager channel: 'cei.snk99.srvconn'. manager connect.
</comment> <class> <name>RemoteTHAPIQueueManager</name> <environment>MQ</environment> <super>MQ.RemoteQueueManager</super> <private>false</private> none xifMutex <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.RemoteTHAPIQueueManager
RemoteTHAPIQueueManager - A concrete queue manager class that connects the VisualWorks image to a queue manager that is installed on a different machine using the WebSphere MQ threaded client library | manager | manager := QueueManager new: #remote threaded: true. manager name: 'foo.queue.manager'. manager host: 'SomeHost'. manager port: 1423. manager channel: 'cei.snk99.srvconn'. manager connect. Instance Variables: xifMutex <Semphore> serializing interface calls, thus avoiding a 'call-in-progress' exception (threaded xif rejects more than one active call)
</comment> <class> <name>LocalQueueManager</name> <environment>MQ</environment> <super>MQ.QueueManager</super> <private>false</private> none <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.LocalQueueManager
A concrete queue manager class that connects the VisualWorks image to a queue manager that is installed on the same machine as the image. It is using the WebSphere MQ non threaded server library
</comment> <class> <name>LocalTHAPIQueueManager</name> <environment>MQ</environment> <super>MQ.LocalQueueManager</super> <private>false</private> none <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.LocalTHAPIQueueManager
LocalTHAPIQueueManager - A concrete queue manager class that connects the VisualWorks image to a queue manager that is installed on the same machine as the image. It is using the WebSphere MQ threaded server library
</comment> <class> <name>MQResult</name> <environment>MQ</environment> <super>Core.Object</super> <private>false</private> none queueManager compCode reason <imports></imports> <category>ECS-MQS</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.MQResult
MQResult is used for combining the completion code and the reason code of an MQ procedure call for raising errors in VisualWorks. MQResult knows about decoding reason codes into MQ error names. Instance Variables: queueManager <QueueManager> the queueManager in which context the error occured compCode <Integer> compCode of the precedure call reason <Integer> reason code of the precedure call
</comment> <class> <name>AsynchronousMessage</name> <environment>MQ</environment> <super>MQ.ActionMessage</super> <private>false</private> none <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.AsynchronousMessage
AsynchronousMessage is the normal datagram message. It doesn't cause the receiver to create a report or reply.
</comment> <class> <name>Report</name> <environment>MQ</environment> <super>MQ.MQMessage</super> <private>false</private> none <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.Report
The Report message is reporting on some expected or unexpected occurrence, usually related to some other message (for example, a request message was received which contained data that was not valid). The message should be sent to the queue indicated by the ReplyToQ field of the message descriptor of the original message. The Feedback field should be set to indicate the nature of the report. The Report field of the original message can be used to control how the MsgId and CorrelId of the report message should be set. Report messages generated by the queue manager or message channel agent are always sent to the ReplyToQ queue, with the Feedback and CorrelId fields set as described above.
</comment> <class> <name>ActionDecorator</name> <environment>MQ</environment> <super>Core.Object</super> <private>false</private> none target <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.ActionDecorator
MessageActionDecorator is an abstract class. Its instances are decorators for setting/retrieving the action and data parameter of an MQMessage. Subclasses must implement the following messages: services action action: Subclasses may want to overwrite: services data data: Instance Variables: target <MQMessage> the target message the decorator works on
</comment> <class> <name>DefaultActionDecorator</name> <environment>MQ</environment> <super>MQ.ActionDecorator</super> <private>false</private> none action data source <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.DefaultActionDecorator
DefaultActionDecorator combines the action and the data into one ByteArray of the form: 1. Byte: length of action 2.- (action size +1): the action itself (action size + 2) - full size: the data It relies on accessors basicData/basicData: to access the raw contents of the data field in the message.
</comment> <class> <name>MessageQueue</name> <environment>MQ</environment> <super>Core.Object</super> <private>false</private> none queueManager name queueHndl messageOptions state syncSetting <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.MessageQueue
MessageQueue is the abstract superclass for implementing receiver and sender queues of MQ Series. Subclasses must implement the following messages: accessing queueOption private initializeMessageOptions setMessageOptions syncpoint options noSyncpoint syncpoint testing isSender Instance Variables: messageOptions <CCompositePointer> holds a struct tagMQPMO, a structure with settings like Timeout, Options bit vector, etc. name <String> queue name in the MQ format (max 48 characters, filled up with blanks) queueHndl <CPointer> pointer to the queue as known to the external interface library queueManager <QueueManager> the queue manager holding this queue state <Symbol> one of #new, #connected, #disconnected syncSetting <Number> one of MQGMO_NO_SYNCPOINT (=4), MQGMO_SYNCPOINT (=2), MQGMO_SYNCPOINT_IF_PERSISTENT (=4096)
</comment> <class> <name>ReceiverQueue</name> <environment>MQ</environment> <super>MQ.MessageQueue</super> <private>false</private> none waitInterval matchOptionArray matchEnabled <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.ReceiverQueue
ReceiverQueue is the concrete implementation for a receiver queue in MQ Series. Instance Variables: matchEnabled <Boolean> Enables/disables filtering according to match fields during MQGET. matchOptionArray <Array of: Symbol> Names of MQ message fields to be matched in MQGET; names are from terminology of MQ Series (i.e. MQMO_MATCH_CORREL_ID, MQMO_MATCH_GROUP_ID, MQMO_MATCH_MSG_ID, MQMO_MATCH_MSG_SEQ_NUMBER, MQMO_MATCH_Offset). waitInterval <Number> Time in milliseconds, that a MQGET waits for a suitable message to arrive. If no suitable message has arrived within this time, the call completes with MQCC_FAILED and reason code MQRC_NO_MSG_AVAILABLE. Using values other than 0 is apprpriate for threaded API, otherwise the image blocks for the given time.
</comment> <class> <name>BrowseQueue</name> <environment>MQ</environment> <super>MQ.ReceiverQueue</super> <private>false</private> none browseMode <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <class> <name>MQQueueCloseError</name> <environment>MQ</environment> <super>MQ.MQError</super> <private>false</private> none <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.MQQueueCloseError
MQQueueCloseError is raised when an MQQueue cannot be closed.
</comment> <class> <name>MQGetError</name> <environment>MQ</environment> <super>MQ.MQError</super> <private>false</private> none <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.MQGetError
MQGetError is raised when a GET on an MQQueue fails.
</comment> <class> <name>MQNotConnectedError</name> <environment>MQ</environment> <super>MQ.MQError</super> <private>false</private> none <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.MQNotConnectedError
MQNotConnectedError is raised when a QueueManager is not connected to MQ and a queue is accessed.
</comment> <class> <name>SenderQueue</name> <environment>MQ</environment> <super>MQ.MessageQueue</super> <private>false</private> none receiver options destinationManagerName <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.SenderQueue
SenderQueue is for PUTing messages of any type into a queue. The idea is that you set up the options for sending messages in the SenderQueue once, and all messages send will use this option set. This includes: - syncpoint - auto generation of MsgID/CorrelID by the queue manager Instance Variables: options <Set of: Symbol> option selectors to be used in MQ calls; each element is the name of a getter method of the (external) MQInterface receiver <ReceiverQueue> the receiver queue used for replies/reports for messages sent through this queue destinationManagerName <String> Name of the (external) MQ queue manager that manages the sender queue. This name may differ from the name of the queue manager that receives the open request. The differing name is assigned to field #ObjectQMgrName in the MQOD struct used for MQOPEN. This way it is possible to refine the destination or route that a reply takes.
</comment> <class> <name>DefaultDataDecorator</name> <environment>MQ</environment> <super>MQ.ActionDecorator</super> <private>false</private> none <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.DefaultDataDecorator
DefaultDataDecorator ignores any action/action: messages. It provides plain access to the data field in a message.
</comment> <class> <name>AMDActionDecorator</name> <environment>MQ</environment> <super>MQ.ActionDecorator</super> <private>false</private> none <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.AMDActionDecorator
AMDActionDecorator is a decorator for setting/retrieving the action parameter of an MQMessage. AMD wishes to use the #PutApplName field to squeeze an message action parameter into the message descriptor. This field is 28 bytes long, so all adaptations to this length is done in method action: in this class. CAUTION: This solution only works when switchin the sender queue and the message send to SET_ALL_CONTEXT, otherwise the #PutApplName field is overwritten by the queue manager! If SET_ALL_CONTEXT is active, no COD reports are send by the queue managers! Instance Variables: target <ActionMessage> the message the decorator accesses directly
</comment> <class> <name>MQWrongMessageType</name> <environment>MQ</environment> <super>MQ.MQError</super> <private>false</private> none <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.MQWrongMessageType
MQWrongMessageType is raised when a specific message type was to be fetched from a ReceiverQueue, but a different type was received.
</comment> <class> <name>MQQueueOpenError</name> <environment>MQ</environment> <super>MQ.MQError</super> <private>false</private> none <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.MQQueueOpenError
MQQueueOpenError is raised when an MQQueue cannot be opened.
</comment> <class> <name>ExclusiveInputQueue</name> <environment>MQ</environment> <super>MQ.ReceiverQueue</super> <private>false</private> none <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <class> <name>Reply</name> <environment>MQ</environment> <super>MQ.MQMessage</super> <private>false</private> none <imports></imports> <category>MQ-Domain</category> <attributes> <package>MQ-Domain</package> </attributes> </class> <comment> MQ.Reply
The Reply message is the reply to an earlier request message (MQMT_REQUEST). The message should be sent to the queue indicated by the ReplyToQ field of the request message. The Report field of the request should be used to control how the MsgId and CorrelId of the reply are set.
</comment> <name>QueueManagerRegistry</name> <environment>MQ.QueueManager</environment> <private>false</private> <constant>false</constant> <category>registry</category> <initializer>WeakArray new: 10</initializer> <attributes> <package>MQ-Domain</package> </attributes> <name>RunMode</name> <environment>MQ.QueueManager</environment> <private>false</private> <constant>false</constant> <category>error handling</category> <initializer>#production</initializer> <attributes> <package>MQ-Domain</package> </attributes> <name>DefaultMatchOptionsArray</name> <environment>MQ.ReceiverQueue</environment> <private>false</private> <constant>false</constant> <category>constants</category> <initializer>#(#MQMO_MATCH_CORREL_ID)</initializer> <attributes> <package>MQ-Domain</package> </attributes> <name>MatchOptionsSelectorMapping</name> <environment>MQ.ReceiverQueue</environment> <private>false</private> <constant>false</constant> <category>constants</category> <initializer>nil</initializer> <attributes> <package>MQ-Domain</package> </attributes> <name>ActionDecoratorClass</name> <environment>MQ.ActionMessage</environment> <private>false</private> <constant>false</constant> <category>As yet unclassified</category> <attributes> <package>MQ-Domain</package> </attributes> <name>DefaultMessageBufferSize</name> <environment>MQ.MQMessage</environment> <private>false</private> <constant>false</constant> <category>As yet unclassified</category> <initializer>4 * 1024</initializer> <attributes> <package>MQ-Domain</package> </attributes> <name>SystemMessageClassMap</name> <environment>MQ.MQMessage</environment> <private>false</private> <constant>true</constant> <category>As yet unclassified</category> <initializer>MQMessage createSystemMessageClassMap</initializer> <attributes> <package>MQ-Domain</package> </attributes> <name>UseChannelTable</name> <environment>MQ.RemoteQueueManager</environment> <private>false</private> <constant>false</constant> <category>settings</category> <initializer>false</initializer> <attributes> <package>MQ-Domain</package> </attributes> <methods> MQ.MQMessage <category>reporting</category>
addReportOption: anOptionSymbol "add anOptionSymbol to the reportOptions Set" self reportOptions add: anOptionSymbol
flushReports "reset the reports flag, no report will be requested" self reportOptions: Set new
removeReportOptions: aCollection "remove all report options in aCollection from the reportOptions Set" aCollection do: [ :sym | self reportOptions remove: sym ifAbsent: []]
reportCOA "report 'confirm of arrival'" " Confirm-on-arrival reports required. This type of report is generated by the queue manager that owns the destination queue, when the message is placed on the destination queue. Message data from the original message is not included with the report message." self removeReportOptions: #(#MQRO_COA_WITH_DATA #MQRO_COA_WITH_FULL_DATA). self addReportOption: #MQRO_COA
reportCOA_WITH_DATA "Confirm-on-arrival reports with data required. This is the same as MQRO_COA, except that the first 100 bytes of the application message data from the original message are included in the report message. If the original message contains one or more MQ header structures, they are included in the report message, in addition to the 100 bytes of application data. Do not specify more than one of MQRO_COA, MQRO_COA_WITH_DATA, and MQRO_COA_WITH_FULL_DATA. MQRO_COA_WITH_FULL_DATA MQMD Report field" self removeReportOptions: #(#MQRO_COA #MQRO_COA_WITH_FULL_DATA). self addReportOption: #MQRO_COA_WITH_DATA
reportCOA_WITH_FULL_DATA self removeReportOptions: #(#MQRO_COA_WITH_DATA #MQRO_COA). self addReportOption: #MQRO_COA_WITH_FULL_DATA
reportCOD "Confirm-on-delivery reports required. This type of report is generated by the queue manager when an application retrieves the message from the destination queue in a way that causes the message to be deleted from the queue. Message data from the original message is not included with the report message. If the message is retrieved as part of a unit of work, the report message is generated within the same unit of work, so that the report is not available until the unit of work is committed. If the unit of work is backed out, the report is not sent." self removeReportOptions: #(#MQRO_COD_WITH_DATA #MQRO_COD_WITH_FULL_DATA). self addReportOption: #MQRO_COD
reportCOD_WITH_DATA "Confirm-on-delivery reports with data required. This is the same as MQRO_COD, except that the first 100 bytes of the application message data from the original message are included in the Chapter 10. MQMD Message descriptor 187 report message. MQMD Report field" self removeReportOptions: #(#MQRO_COD #MQRO_COD_WITH_FULL_DATA). self addReportOption: #MQRO_COD_WITH_DATA
reportCOD_WITH_FULL_DATA "Confirm-on-delivery reports with full data required. This is the same as MQRO_COD, except that all of the application message data from the original message is included in the report message." self removeReportOptions: #(#MQRO_COD_WITH_DATA #MQRO_COD). self addReportOption: #MQRO_COD_WITH_FULL_DATA
reportCopyMessageIDToCorrelationID "If a report or reply is generated as a result of this message, the message id of this message is to be copied to the correlation id of the report or reply message. " self removeReportOptions: #(MQRO_NEW_CORREL_ID MQRO_PASS_CORREL_ID). self addReportOption: #MQRO_COPY_MSG_ID_TO_CORREL_ID
reportEXCEPTION self addReportOption: #MQRO_EXCEPTION
reportEXPIRATION "Expiration reports required. This type of report is generated by the queue manager if the message is discarded prior to delivery to an application because its expiry time has passed (see the Expiry field). If this option is not set, no report message is generated if a message is discarded for this reason (even if one of the MQRO_EXCEPTION_* options is specified). Message data from the original message is not included with the report message. Do not specify more than one of MQRO_EXPIRATION, MQRO_EXPIRATION_WITH_DATA, and MQRO_EXPIRATION_WITH_FULL_DATA." self removeReportOptions: #(#MQRO_EXPIRATION_WITH_DATA #MQRO_EXPIRATION_WITH_FULL_DATA). self addReportOption: #MQRO_EXPIRATION
reportEXPIRATION_WITH_DATA "Expiration reports with data required. This is the same as MQRO_EXPIRATION, except that the first 100 bytes of the application message data from the original message are included in the report message. If the original message contains one or more MQ header structures, they are included in the report message, in addition to the 100 bytes of application data." self removeReportOptions: #(#MQRO_EXPIRATION #MQRO_EXPIRATION_WITH_FULL_DATA). self addReportOption: #MQRO_EXPIRATION_WITH_DATA
reportEXPIRATION_WITH_FULL_DATA "Expiration reports with full data required. This is the same as MQRO_EXPIRATION, except that all of the application message data from the original message is included in the report message." self removeReportOptions: #(#MQRO_EXPIRATION #MQRO_EXPIRATION_WITH_DATA). self addReportOption: #MQRO_EXPIRATION_WITH_FULL_DATA
reportGetsNewCorellationID "This is the default action, and indicates that if a report or reply is generated as a result of this message, a new correlation is to be generated for the report or reply message. " self removeReportOptions: #(MQRO_COPY_MSG_ID_TO_CORREL_ID MQRO_PASS_CORREL_ID). self addReportOption: #MQRO_NEW_CORREL_ID
reportGetsNewMsgID "This is the default action, and indicates that if a report or reply is generated as a result of this message, a new MsgId is to be generated for the report or reply message. " self removeReportOptions: #(MQRO_PASS_MSG_ID). self addReportOption: #MQRO_NEW_MSG_ID
reportGetsSameCorellationID "If a report or reply is generated as a result of this message, the correlation id of this message is to be copied to the correlation id of the report or reply message." self removeReportOptions: #(MQRO_COPY_MSG_ID_TO_CORREL_ID MQRO_NEW_CORREL_ID). self addReportOption: #MQRO_PASS_CORREL_ID
reportGetsSameMsgID "If a report or reply is generated as a result of this message, the MsgId of this message is to be copied to the MsgId of the report or reply message. If this option is not specified, MQRO_NEW_MSG_ID is assumed." self removeReportOptions: #(#MQRO_NEW_MSG_ID). self addReportOption: #MQRO_PASS_MSG_ID
</methods> <methods> MQ.MQMessage <category>private</category>
basicCorrelID: aByteArray self messageHandleBytesAt: #CorrelId put: aByteArray size: 24
basicData "return the ByteArray just received" ^ data
basicData: aByteArray "set up the ByteArray to be transfered to the receiver" data := aByteArray
basicGroupID: aByteArray self messageHandleBytesAt: #GroupId put: aByteArray size: 24
basicMessageID: aByteArray self messageHandleBytesAt: #MsgId put: aByteArray size: 24
initializeMessageDescriptor "Initialize a datagram message descriptor as a basis for all message types. Values set here correspond to those in MQMD_DEFAULT. Subclasses have to set their specific message type (request, reply, report, async). The ReplyToQueue is set to the targetQueues receiver queue, if available. MQMD { MQCHAR4 StrucId; MQLONG Version, Report, MsgType, Expiry, Feedback, Encoding, CodedCharSetId; MQCHAR8 Format; MQLONG Priority, Persistence; MQBYTE24 MsgId, CorrelId; MQLONG BackoutCount; MQCHAR48 ReplyToQ, ReplyToQMgr; MQCHAR12 UserIdentifier; MQBYTE32 AccountingToken; MQCHAR32 ApplIdentityData; MQLONG PutApplType; MQCHAR28 PutApplName; MQCHAR8 PutDate, PutTime; MQCHAR4 ApplOriginData; MQBYTE24 GroupId; MQLONG MsgSeqNumber, Offset, MsgFlags, OriginalLength;" | xif params rec | xif := self xif. params := xif alloc64KAlignedMessageDescriptor. (rec := self targetQueue receiver) notNil ifTrue: [(params refMemberAt: #ReplyToQ) copyAt: 0 from: rec name asByteArray size: xif MQ_Q_NAME_LENGTH startingAt: 1]. ^params
messageHandleBytesAt: aMemberName put: aByteArray size: aNumber | temp | temp := aByteArray size < aNumber ifTrue: [| fill | fill := ByteArray new: aNumber - aByteArray size withAll: 32. aByteArray , fill] ifFalse: [aByteArray]. (messageHndl refMemberAt: aMemberName) copyAt: 0 from: temp size: aNumber startingAt: 1
messageHandleBytesAt: aMemberName size: aNumber "Answer a ByteArray of size N=aNumber, holding N bytes stored at structure field named <aMemberName>" | ptr contents | ptr := messageHndl memberAt: aMemberName. contents := ByteArray new: aNumber. 0 to: aNumber - 1 do: [:i | contents at: i + 1 put: (ptr at: i)]. ^contents
setMessageHandle: aHandle messageHndl := aHandle
setReportField "set the report field for this message" | temp xif | xif := self xif. temp := xif MQRO_NONE. self reportOptions do: [:sym | temp := temp bitOr: (xif perform: sym)]. messageHndl memberAt: #Report put: temp
xif ^ self targetQueue xif
</methods> <methods> MQ.MQMessage <category>accessing</category>
correlationID "Answer the contents of MQ message field #CorrelId (24 bytes). Return: ByteArray" ^self messageHandleBytesAt: #CorrelId size: self xif MQ_CORREL_ID_LENGTH
correlationID: aString | temp | temp := aString isNil ifTrue: [self xif MQMI_NONE] ifFalse: [aString fillUpWithSpacesTo: 24]. self basicCorrelID: temp asByteArray
data "return the ByteArray just received" ^self basicData
data: aByteArray "set up the ByteArray to be transfered to the receiver" self basicData: aByteArray
dataSize ^ data size
expiry "See 'expiry:' for a comment" ^ messageHndl memberAt: #Expiry
expiry: aNumber "Message lifetime. This is a period of time expressed in tenths of a second, set by the application that puts the message. The message becomes eligible to be discarded if it has not been removed from the destination queue before this period of time elapses. If one of reportEXPIRATION* is set for this message, a report is generated by the queue manager on expiry." messageHndl memberAt: #Expiry put: aNumber
messageGroupID ^self messageHandleBytesAt: #GroupId size: self xif MQ_GROUP_ID_LENGTH
messageGroupID: aString | temp | temp := aString isNil ifTrue: [self xif MQMI_NONE] ifFalse: [aString fillUpWithSpacesTo: 24]. self basicGroupID: temp asByteArray
messageHandle ^messageHndl
messageID "Answer the contents of MQ message field #MsgId (24 bytes). Return: ByteArray" ^self messageHandleBytesAt: #MsgId size: self xif MQ_MSG_ID_LENGTH
messageID: aString | temp | temp := aString isNil ifTrue: [self xif MQMI_NONE] ifFalse: [aString fillUpWithSpacesTo: 24]. self basicMessageID: temp asByteArray
messageOffset ^ messageHndl memberAt: #Offset
messageOffset: aNumber messageHndl memberAt: #Offset put: aNumber
messageSeqNumber ^ messageHndl memberAt: #MsgSeqNumber
messageSeqNumber: aNumber messageHndl memberAt: #MsgSeqNumber put: aNumber
messageType "Return the field MsgType (Number) from the messageDescriptor." ^messageHndl isNil ifTrue: [self class messageTypeNumber] ifFalse: [messageHndl memberAt: #MsgType]
putDate "Answer the contents of MQ message field #PutDate (8 bytes). Bytes represent a Date string with format 'YYYYMMDD' with YYYY=year, MM=month, DD=day. Return: ByteArray" ^self messageHandleBytesAt: #PutDate size: self xif MQ_PUT_DATE_LENGTH
putTime "Answer the contents of MQ message field #PutTime (8 bytes). Bytes represent a Time string with format 'HHMMSSTH' with HH=hours, MM=minutes, SS=seconds, T=tenths of a second, H=hundredths of a second. Return: ByteArray" ^self messageHandleBytesAt: #PutTime size: self xif MQ_PUT_TIME_LENGTH
reportOptionBits "Answer the report options mask from the MQ structure. Return: Integer" ^self messageHandle memberAt: #Report
reportOptions ^reportOptions
reportOptions: anObject reportOptions := anObject
setReplyQueueManagerName: aString "Define the queue manager that contains the queue where we expect to retrieve replies and reports" | length padded | length := self xif MQ_Q_MGR_NAME_LENGTH. padded := aString fillUpWithSpacesTo: length. (messageHndl refMemberAt: #ReplyToQMgr) copyAt: 0 from: padded asByteArray size: length startingAt: 1
setReplyQueueName: aString "Define the queue where we expect to retrieve replies and reports" | length padded | length := self xif MQ_Q_NAME_LENGTH. padded := aString fillUpWithSpacesTo: length. (messageHndl refMemberAt: #ReplyToQ) copyAt: 0 from: padded asByteArray size: length startingAt: 1
source "Only asynchronous messages and requests must know which application created them. Return: empty String" ^String new
source: aString "Only asynchronous messages and requests must know what application created them"
targetQueue ^targetQueue
targetQueue: anObject targetQueue := anObject
userIdentifier "Answer the contents of MQ message field #UserIdentifier (12 bytes). Return: ByteArray" ^self messageHandleBytesAt: #UserIdentifier size: self xif MQ_USER_ID_LENGTH
</methods> <methods> MQ.MQMessage <category>initialize-release</category>
initialize "Instances are allways created in the context of a connected Queue, so use this queue to initialize messageDescriptor" messageHndl := self initializeMessageDescriptor. data := ByteArray new: DefaultMessageBufferSize. self flushReports
</methods> <methods> MQ.MQMessage <category>testing</category>
isAsynchronous "Answer true if this message is an asynchronous one (i.e. datagram), false otherwise. NOTE: It is not sufficient to answer based on class membership. Queue reading starts with an AsynchronousMessage which has to be converted to target type if necessary. See also MQ.ReceiverQueue>>adaptMessageToType:" ^self messageType = AsynchronousMessage messageTypeNumber
isReply ^false
isRequest ^ false
validCorrelID "A valid correlation id is a byte array whose values are not 0" | correlationID | correlationID := self correlationID. ^correlationID notNil and: [correlationID anySatisfy: [:aByte | aByte > 0]]
validMessageID "A valid message id is a byte array whose values are not 0" | msgID | msgID := self messageID. ^msgID notNil and: [ msgID anySatisfy: [:aByte | aByte > 0]]
</methods> <methods> MQ.MQMessage <category>sending</category>
addaptOptions: aCollection "We have to secure already set message parameter. Currently we only secure the parameter message id and correlation id" self validMessageID ifTrue: [aCollection remove: #MQPMO_NEW_MSG_ID ifAbsent: []]. self validCorrelID ifTrue: [aCollection remove: #MQPMO_NEW_CORREL_ID ifAbsent: []].
prepareMessageForSend "Set up all fields that should be send by this message" self setReportField
</methods> <methods> MQ.MQMessage class <category>instance creation</category>
new "Only #newFor: and #newFor:type: are used for instance creation." self shouldNotImplement
newAsyncMessage "Create a new async message" ^AsynchronousMessage new
newFor: aQueue "Create a new message to be send to aQueue. Initialize it right away so messageDescriptor and messageOptions are set" | mess | mess := self basicNew. mess targetQueue: aQueue. mess initialize. ^ mess
newFor: aQueue type: aMessageType "Create a new message to be used by aQueue. Choose the correct MQMessage class corresponding to aMessageType. If none is found, assume a datagram message as a correct one. Initialize it right away so messageDescriptor and messageOptions are set" | class | class := self classForMsgType: aMessageType. ^class newFor: aQueue
</methods> <methods> MQ.MQMessage class <category>accessing</category>
classForMsgType: aMessageType "Answer the subclass that implements MQ messages of given type. Return AsynchronousMessage if no such class found." | theClass | theClass := (aMessageType between: 1 and: SystemMessageClassMap size) ifTrue: [SystemMessageClassMap at: aMessageType] ifFalse: []. theClass isNil ifTrue: [(theClass := self findClassForMsgType: aMessageType) isNil ifTrue: [theClass := AsynchronousMessage]]. ^theClass
findClassForMsgType: aMessageType "Search the class hierarchy for the subclass that implements MQ messages of given type. This is a hook for mapping system or application defined classes that are not in the fast map. Answer the class (nil if no matching class found)." ^self allSubclasses detect: [:aClass | [aClass messageTypeNumber = aMessageType] on: SubclassResponsibilityError do: [:ex | ex return: false]] ifNone: []
messageTypeNumber "MQ Messages are modeled by specific classes according to the MsgType-field in the header. Answer the MsgType value that this class is standing for. The value is an Integer from intervals - [MQMT_SYSTEM_FIRST .. MQMT_SYSTEM_LAST] for system-defined message types, or - [MQMT_APPL_FIRST .. MQMT_APPL_LAST] for application-defined message types. See Application Programming Reference, Chapter 10. MQMD - Message descriptor, pp. 172" self subclassResponsibility
</methods> <methods> MQ.MQMessage class <category>initialize-release</category>
createSystemMessageClassMap "Define the mapping of system MsgType numbers to classes. <MQMessage createSystemMessageClassMap>" | map | map := Array new: 8. (Array with: AsynchronousMessage with: Request with: Reply with: Report) do: [:each | map at: each messageTypeNumber put: each]. ^map
</methods> <methods> MQ.ActionMessage <category>accessing</category>
action ^ actionDecorator action
action: aString "Action to be performed by the receiver of this message" actionDecorator action: aString
actionDecorator ^actionDecorator
actionDecorator: anObject actionDecorator := anObject
data ^ actionDecorator data
data: aString "Action to be performed by the receiver of this message" actionDecorator data: aString
replyQueue: aQueue "Define the queue where we expect to retrieve a reply to a request" self setReplyQueueName: aQueue name. self setReplyQueueManagerName: aQueue queueManager name
replyQueueName "Queue name of the queue to be used by the receiver for replys and reports" ^(self messageHandleBytesAt: #ReplyToQ size: self xif MQ_Q_NAME_LENGTH) asString trimMQTrailer
source "The source of a message. This is the application that send the mesage" ^actionDecorator source
source: aString "The source of a message. This is the application that send the mesage" actionDecorator source: aString
</methods> <methods> MQ.ActionMessage <category>reporting</category>
createReply "Create a new Reply. Copy all necessary parameters from this message over to the reply." | replyToQ reply | replyToQ := self targetQueue queueManager getQueueForReplyTo: self. reply := Reply newFor: replyToQ. self copyRequestedContextInto: reply. ^reply
createReport: reportType "Create a new Report instance of reportType. Copy all necessary parameters from this message over to the report. reportType is either #PAN or #NAN, so the Report has to have one of those in its #Feedback field." | rep type replyToQ | replyToQ := self targetQueue queueManager getSenderQueue: self replyQueueName. rep := Report newFor: replyToQ. type := reportType == #PAN ifTrue: [self xif MQFB_PAN] ifFalse: [self xif MQFB_NAN]. rep messageHandle memberAt: #Feedback put: type. self copyRequestedContextInto: rep. ^ rep
reportNAN "Negative action notification reports required. This type of report is generated by the application that retrieves the message and acts upon it. It indicates that the action requested in the message has not been performed successfully." self addReportOption: #MQRO_NAN
reportPAN "Positive action notification reports required. This type of report is generated by the application that retrieves the message and acts upon it. It indicates that the action requested in the message has been performed successfully." self addReportOption: #MQRO_PAN
</methods> <methods> MQ.ActionMessage <category>initialize-release</category>
initialize super initialize. actionDecorator := self class actionDecoratorClass newForTarget: self
</methods> <methods> MQ.ActionMessage <category>testing</category>
requiresErrorReport "Answer true/false, if this message requires an error report" ^self reportOptionBits allMask: self xif MQRO_EXCEPTION
requiresMsgIdToCorrelId "Answer true, if message is configured for copying its MsgID to Correl ID field of a reply on this message. Note: Do not #allMask: with MQRO_COPY_MSG_ID_TO_CORREL_ID, since it is zero." | xif mask | xif := self xif. mask := xif MQRO_PASS_MSG_ID bitOr: xif MQRO_PASS_CORREL_ID. "=128+64" ^self reportOptionBits noMask: mask
requiresNAN "Answer true/false, if this message requires a 'negative action notification' " ^self reportOptionBits allMask: self xif MQRO_NAN
requiresPAN "Answer true/false, if this message requires a 'positive action notification'" ^self reportOptionBits allMask: self xif MQRO_PAN
requiresPassCorrelId "Answer true/false, if this message is configured for copying its Correl ID to the Correl ID field of a reply on this message." ^self reportOptionBits allMask: self xif MQRO_PASS_CORREL_ID
</methods> <methods> MQ.ActionMessage <category>private</category>
copyRequestedContextInto: reply "Beware of any MsgID/CorrelID copying requested. MQRO_PASS_MSG_ID Pass message identifier. If a report or reply is generated as a result of this message, the MsgId of this message is to be copied to the MsgId of the report or reply message. If this option is not specified, MQRO_NEW_MSG_ID is assumed. MQRO_COPY_MSG_ID_TO_CORREL_ID Copy message identifier to correlation identifier. This is the default action, and indicates that if a report or reply is generated as a result of this message, the MsgId of this message is to be copied to the CorrelId of the report or reply message. MQRO_PASS_CORREL_ID Pass correlation identifier. If a report or reply is generated as a result of this message, the CorrelId of this message is to be copied to the CorrelId of the report or reply message. If this option is not specified, MQRO_COPY_MSG_ID_TO_CORREL_ID is assumed." | reportFlags cid | reportFlags := self reportOptionBits. (reportFlags allMask: self xif MQRO_PASS_MSG_ID) ifTrue: [reply basicMessageID: self messageID. reply targetQueue resetAutoMsgIDOption]. cid := self requiresPassCorrelId ifTrue: [self correlationID] ifFalse: [self messageID]. reply basicCorrelID: cid
</methods> <methods> MQ.ActionMessage class <category>class accessing</category>
actionDecoratorClass ^ ActionDecoratorClass
setActionDecoratorClass: aMessageActionDecorator ActionDecoratorClass := aMessageActionDecorator
</methods> <methods> MQ.ActionMessage class <category>ADvance</category>
ad2ClassInfo ^'This is an abstract class. An ActionMessage is either a request or a datagram message. On receiving an ActionMessage, its instances know how to create a Reply or Report with required settings of MsgId and CorrelId. This comment is generated by ADvance. Instance Variables: actionDecorator <ActionDecorator> '
</methods> <methods> MQ.ActionMessage class <category>class initialization</category>
initialize "Initialize the ActionDecoratorClass shared variabel, so messages only support direct access to their data field. Alternatives are: DefaultActionDecorator - an action and a data parameter are combined into the data field. - both action and data have to be set for all messages. AMDActionDecorator - the action is stored in the #PutApplName field of a message - such messages only transport this field, if they are send with the SET_ALL_CONTEXT option. - there will be no COD reports for such messages, if the SET_ALL_CONTEXT option is set" ActionDecoratorClass := DefaultDataDecorator
</methods> <methods> MQ.Request <category>private</category>
initializeMessageDescriptor "Initialize a request message descriptor. Modified MsgType to MQMT_REQUEST." | params | params := super initializeMessageDescriptor. params memberAt: #MsgType put: self xif MQMT_REQUEST. ^params
</methods> <methods> MQ.Request <category>testing</category>
isRequest ^ true
</methods> <methods> MQ.Request <category>accessing</category>
replyQueueManagerName "Answer the name of the QueueManager holding the queue to be used for reply. The message field may contain 48 characters, cut off trailing blanks. Return: String" ^(self messageHandleBytesAt: #ReplyToQMgr size: self xif MQ_Q_MGR_NAME_LENGTH) asString trimMQTrailer
</methods> <methods> MQ.Request class <category>accessing</category>
messageTypeNumber msgTypeNumber isNil ifTrue: [msgTypeNumber := MQInterface new MQMT_REQUEST]. ^ msgTypeNumber
</methods> <methods> MQ.MQError class <category>signalling</category>
signalWith: aParameter "Raise an an exception with parameter set to aParameter. aParameter is always an MQResult object. Set the messageText to contain the decoded reason code of aParameter" ^self new searchFrom: thisContext sender; originator: thisContext sender homeReceiver; messageText: aParameter decodedReasonString; parameter: aParameter; raiseSignal.
</methods> <methods> MQ.QueueManager <category>private-activation</category>
acquireExternal "Acquire the external queueManager handel." ^self subclassResponsibility
disconnectExternal "Disconnect from MQ (basic library call) and release the manager handle. Assume receiver is registered." | compCodePtr reasonPtr return | compCodePtr := xif MQLONG perform: xif gcMallocSelector with: 1. reasonPtr := xif MQLONG perform: xif gcMallocSelector with: 1. self serializeLibraryCall: [xif MQDISC: managerHndl with: compCodePtr with: reasonPtr]. return := self getReturnFrom: compCodePtr and: reasonPtr. return isOK ifFalse: ["no error handling yet"]. managerHndl := nil
dismiss "Time to release any external resources. Assume: receiver is registered." self isConnected ifFalse: [^self]. self closeQueues. self disconnectExternal. self dismissInternal
dismissAfterFailure "Similar to #dismiss, but w/o closing queues and external disconnect. Avoid external calls because they could block the entire image; the external resources are invalid anyway." self dismissInternal
dismissInternal "Release internal resources, unregister from instance registry." self state: #disconnecting. self class unregister: self. self resetQueueMgrName
</methods> <methods> MQ.QueueManager <category>accessing</category>
allQueues ^(OrderedCollection new) addAll: senderQueues; addAll: receiverQueues; addAll: browseQueues; yourself
getBrowseQueue: aString "Return a receiver queue for browsing named aString, but only, if this manager is connected" self isConnected ifFalse: [^MQNotConnectedError raise]. ^browseQueues at: aString ifAbsentPut: [BrowseQueue newFor: self name: aString]
getExclusiveInputQueue: aString "Return a receiver queue with exclusive access named aString, but only, if this manager is connected" self isConnected ifFalse: [^ MQNotConnectedError raise]. ^receiverQueues at: aString ifAbsentPut: [ExclusiveInputQueue newFor: self name: aString]
getQueueForReplyTo: aRequest "Answer a sender queue for replying to <aRequest>. The queue name is read from the request. Exception MQNotConnectedError, if this manager is connected." | qname mgrName theQueue | self isConnected ifFalse: [^MQNotConnectedError raise]. qname := aRequest replyQueueName. mgrName := aRequest replyQueueManagerName. theQueue := senderQueues at: qname ifAbsentPut: [(SenderQueue newFor: self name: qname) destinationManagerName: mgrName]. theQueue destinationManagerName = mgrName ifFalse: [theQueue close. senderQueues removeKey: qname ifAbsent: []. theQueue := (SenderQueue newFor: self name: qname) destinationManagerName: mgrName]. ^theQueue
getReceiverQueue: aString "Return a receiver queue named aString, but only, if this manager is connected" self isConnected ifFalse: [^ MQNotConnectedError raise]. ^receiverQueues at: aString ifAbsentPut: [ReceiverQueue newFor: self name: aString]
getSenderQueue: aString "Return a sender queue named aString, but only, if this manager is connected" self isConnected ifFalse: [^ MQNotConnectedError raise]. ^senderQueues at: aString ifAbsentPut: [SenderQueue newFor: self name: aString]
managerHandle ^ managerHndl
name ^name
name: stringOrNil "Assign the name; ensure it is 48 characters long." | aString | (aString := stringOrNil) isNil ifTrue: [aString := '']. name := aString fillUpWithSpacesTo: self xif MQ_Q_NAME_LENGTH
state: aSymbol "Assign the connection state of the receiver to one of #active, #new, #disconnecting, #paused." state := aSymbol
xif ^xif
xif: anObject xif := anObject
</methods> <methods> MQ.QueueManager <category>initialize-release</category>
closeQueue: aMessageQueue "Close the given queue, ignore #MQRC_CONNECTION_BROKEN error. No longer handle #MQRC_CONNECTION_BROKEN because it is handled in the #close method." aMessageQueue close
closeQueues "Close all sender and receiver queues." senderQueues do: [:q | self closeQueue: q]. receiverQueues do: [:q | self closeQueue: q]. browseQueues do: [:q | self closeQueue: q]
initialize xif := self class externalInterfaceClass new. self initializeQueueDictionaries. managerHndl := nil. state := #new
initializeQueueDictionaries senderQueues := Dictionary new. receiverQueues := Dictionary new. browseQueues := Dictionary new
resetQueueMgrName self name: nil.
</methods> <methods> MQ.QueueManager <category>actions</category>
connect "Establish connection with the MQ-environment. Return: self (nil if connect fails)" self isConnected ifTrue: [^self]. ^self acquireExternal == true ifTrue: [self class register: self. self state: #active] ifFalse: []
disconnect "Disconnect from this Queue Manager." state == #new ifTrue: [^self]. self dismiss. self state: #new
disconnectAfterFailure "An MQ error which recommends reconnecting has occurred (e.g. #MQRC_CONNECTION_BROKEN). Disconnect all MQ resources (queue manager and queues)" state == #new ifTrue: [^self]. self dismissAfterFailure. self state: #new
serializeLibraryCall: aBlock "Using a threaded external interface may cause problems: They reject more than one active call. This method helps serializing interface calls with a proper semaphore. Non-threaded external interface do not require serialization since the VM itself provides it: By blocking any execution until the library call return, no second call can enter the stack." aBlock value
updateRegistry: aMessageQueue newName: qmName "After opening a dynamic queue the name of the queue may change. Thus we have to update the key of the queue in the regitry" | registry key | registry := aMessageQueue isSender ifTrue: [senderQueues] ifFalse: [receiverQueues]. key := aMessageQueue name trimMQTrailer. registry removeKey: key ifAbsent: []. registry at: qmName put: aMessageQueue
</methods> <methods> MQ.QueueManager <category>testing</category>
isConnected "Answer whether receiver is connected to MQ" ^(state == #new or: [state == #paused]) not and: [self isManagerHandleValid]
isManagerHandleValid "Return true if manager handle is assigned and valid, false otherwise. Cold restart of an image that has been saved with an active QueueManager will return with invalid manager handle" ^managerHndl notNil and: [managerHndl isValid]
</methods> <methods> MQ.QueueManager <category>error handling</category>
getReturnFrom: compCodePtr and: reasonPtr "Return an MQResult object containing the completion code and the reason value" | compCode reason | compCode := compCodePtr contents. reason := reasonPtr contents. ^(MQResult newFor: self) compCode: compCode; reason: reason
</methods> <methods> MQ.QueueManager class <category>ADvance</category>
ad2ClassInfo ^'This is an abstract class. This comment is generated by ADvance. Instance Variables: name <String> receiverQueues <Dictionary key: Object value: MessageQueue> dictionary of named queues used for receiving senderQueues <Dictionary key: Object value: MessageQueue> dictionary of named queues used for sending'
</methods> <methods> MQ.QueueManager class <category>accessing</category>
externalInterfaceClass "Provide the name of the desired external interface class for MQ access." ^ self subclassResponsibility
</methods> <methods> MQ.QueueManager class <category>private</category>
getFreeIndexInArray: anArray "Get the next free slot in anArray, beware of WeakArrays" ^anArray indexOf: nil ifAbsent: [anArray indexOf: 0 ifAbsent: [anArray grow. anArray indexOf: nil]]
</methods> <methods> MQ.QueueManager class <category>class initialization</category>
initialize "Establish class variables." "QueueManager initialize" (ObjectMemory dependents includes: self) ifFalse: [ObjectMemory addDependent: self]. self initRegistry. RunMode := #production
obsolete "This class is being removed from the system." (ObjectMemory dependents includes: self) ifTrue: [ ObjectMemory removeDependent: self ]. super obsolete
</methods> <methods> MQ.QueueManager class <category>registry</category>
initRegistry "Initialize the registry to the proper form of collection." self registry: (WeakArray new: 10).
register: aQueueManager "Register the given QueueManager." | registry | ((registry := self registry) includes: aQueueManager) ifTrue: ["reconnect?"] ifFalse: [| idx | idx := self getFreeIndexInArray: registry. registry at: idx put: aQueueManager]
registry QueueManagerRegistry isNil ifTrue: [self initRegistry]. ^ QueueManagerRegistry
registry: aWeakArray QueueManagerRegistry := aWeakArray
unregister: uh "Remove the argument from the active registry." | registry index | registry := self registry. index := registry indexOf: uh ifAbsent: [^self]. registry at: index put: 0
</methods> <methods> MQ.QueueManager class <category>error handling</category>
isInDevelopment "self isInDevelopment" ^RunMode == #development
isInProduction "self isInProduction" ^self isInDevelopment not
setDevelopment "self setDevelopment" RunMode := #development
setProduction "self setProduction" RunMode := #production
</methods> <methods> MQ.QueueManager class <category>instance creation</category>
new ^ super new initialize
new: aTypeSymbol threaded: aBoolean "Create an instance of the desired QueueManager subclass. - aTypeSymbol can be either #local or #remote - aBoolean selects wether its a THAPI interface or not" | managerClass | managerClass := aTypeSymbol == #local ifTrue: [aBoolean ifTrue: [LocalTHAPIQueueManager] ifFalse: [LocalQueueManager]] ifFalse: [aTypeSymbol == #remote ifTrue: [aBoolean ifTrue: [RemoteTHAPIQueueManager] ifFalse: [RemoteQueueManager]]]. ^managerClass new
</methods> <methods> MQ.QueueManager class <category>private-updating</category>
returnFromSnapshot "No external resources can be held at this point. Reset all appropriate control information as if operation had been paused." | registry | (registry := self registry) isNil ifTrue: [^self]. registry do: [:each | each == 0 | each isNil ifFalse: [each state: #paused. each isManagerHandleValid ifFalse: [each connect]]]
update: anAspectSymbol with: aParameter from: aSender "'pause' all registered instances, if ObjectMemory sends returnFromSnapshot" aSender == ObjectMemory ifTrue: [anAspectSymbol == #returnFromSnapshot ifTrue: [self returnFromSnapshot]]
</methods> <methods> MQ.RemoteQueueManager <category>accessing</category>
channel ^channel
channel: aString channel := aString
host ^host
host: anObject host := anObject
port ^port
port: integerOrNil "Assign the port number of the MQ service." port := integerOrNil
</methods> <methods> MQ.RemoteQueueManager <category>initialize-release</category>
initialize "Ensure that an empty String is set as my name" super initialize. self resetQueueMgrName
releaseConnectionStructs "These two have been held in instVars because they have been gcMalloced. To free them, set the instVars to nil right now." clientConnPtr := connectOptionsPtr := nil
</methods> <methods> MQ.RemoteQueueManager <category>private prepare</category>
createChannelDefinition "Setup an MQCD struct (Connection channel description). The connection name is a connection of the host and the port number string." | connName length mqcdPtr | connName := self host. self port isNil ifFalse: [connName := connName , '(' , self port printString, ')'.]. mqcdPtr := xif alloc64KAlignedMQCDWithClientConnectDefaults. length := xif MQ_CONN_NAME_LENGTH. (mqcdPtr refMemberAt: #ConnectionName) copyAt: 0 from: (connName fillUpWithSpacesTo: length) asByteArray size: length startingAt: 1. length := xif MQ_CHANNEL_NAME_LENGTH. (mqcdPtr refMemberAt: #ChannelName) copyAt: 0 from: (self channel fillUpWithSpacesTo: length) asByteArray size: length startingAt: 1. ^mqcdPtr
prepareChannelDefinition "Setup an MQCD struct (Connection channel description). The connection name is a connection of the host and the port number string." ^clientConnPtr := self createChannelDefinition
prepareConnectOptions "Setup an MQCNO struct referencing an MQCD struct. Connection name is a connection of host and portnumber string. From MQ documentation (Application Programming Reference, csqzak.pdf, page 62): ClientConnPtr (MQPTR) - Address of MQCD structure for client connection. ClientConnOffset and ClientConnPtr are used only when the application issuing the MQCONNX call is running as a WebSphere MQ client. By specifying one or other of these fields, the application can control the definition of the client connection channel by providing an MQCD channel definition structure that contains the values required. If the application is running as a WebSphere MQ client but the application does not provide an MQCD structure, the MQSERVER environment variable is used to select the channel definition. If MQSERVER is not set, the client channel table is used." (connectOptionsPtr := xif alloc64KAlignedMQCNONewParameters) memberAt: #Version put: xif MQCNO_VERSION_2. (self class useChannelTable and: [self class ensurePrerequisitesForChannelTableUse]) ifTrue: ["leave field #ClientConnPtr nil"] ifFalse: [connectOptionsPtr memberAt: #ClientConnPtr put: self prepareChannelDefinition]. ^connectOptionsPtr
</methods> <methods> MQ.RemoteQueueManager <category>private-activation</category>
acquireExternal "Acquire the external resources MQ-environment. Answer true on success, false on failure" | qMgrNamePtr compCodePtr reasonPtr return success | managerHndl := xif MQHCONN perform: xif mallocSelector with: 1. qMgrNamePtr := self name perform: xif gcCopyToHeapSelector. compCodePtr := xif MQLONG perform: xif gcMallocSelector with: 1. reasonPtr := xif MQLONG perform: xif gcMallocSelector with: 1. self prepareConnectOptions. self serializeLibraryCall: [xif MQCONNX: qMgrNamePtr with: connectOptionsPtr with: managerHndl with: compCodePtr with: reasonPtr]. return := self getReturnFrom: compCodePtr and: reasonPtr. (success := return isOK or: [return isWarning and: [return reason = xif MQRC_ALREADY_CONNECTED]]) ifFalse: [MQNotConnectedError signalWith: return]. ^success
dismissInternal "s. super implementor; release connection structures." self releaseConnectionStructs. super dismissInternal
</methods> <methods> MQ.RemoteQueueManager class <category>ADvance</category>
ad2ClassInfo ^' Instance Variables: channel <String> port <SmallInteger> host <String> '
</methods> <methods> MQ.RemoteQueueManager class <category>accessing</category>
externalInterfaceClass "Provide the name of the desired external interface class for MQ access." ^ MQClientInterface
</methods> <methods> MQ.RemoteQueueManager class <category>settings</category>
checkPrerequisitesForChannelTableUse "Check env.var. prerequisites for using the channel definition table: - MQSERVER must be undefined - MQCHLLIB must point to directory /var/mqm/channelTables - MQCHLTAB must hold the name of the channel table file in MQCHLLIB (e.g. 'AMQCLCHL_CEI.TAB') Return: nil if prerequisites satisfied, String with error message otherwise" | lib tab asFilename aFilename | "basic defined/undefined check" (CEnvironment getenv: 'MQSERVER') isEmpty ifFalse: [^(#MQSERVER << #MQSeries >> 'MQSERVER must be undefined for channel table use!') asString ]. (lib := CEnvironment getenv: 'MQCHLLIB') isEmpty ifTrue: [^(#MQCHLLIB <<#MQSeries >> 'MQCHLLIB must be undefined for channel table use!') asString]. (tab := CEnvironment getenv: 'MQCHLTAB') isEmpty ifTrue: [^(#MQCHLTAB<< #MQSeries >> 'MQCHLLIB must be undefined for channel table use!') asString ]. "basic filename check" asFilename := [:var :aString | [aString asFilename] on: Error do: [:ex | ex return: ('<1s>''s value (<2s>) is not a valid filename (<3s>)' expandMacrosWith: var with: aString with: ex description)]]. (lib := asFilename value: 'MQCHLLIB' value: lib) isString ifTrue: [^lib]. (aFilename := asFilename value: 'MQCHLTAB' value: tab) isString ifTrue: [^aFilename]. "filename existence check" lib exists ifFalse: [^(#MQCHLLIBvalue << #MQSeries >> 'MQCHLLIB''s value (<1s>) is not an existing directory name') expandMacrosWith: lib asString]. lib isDirectory ifFalse: [^(#MQCHLLIBvalue2 << #MQSeries >> 'MQCHLLIB''s value (<1s>) is not a directory' ) expandMacrosWith: lib asString]. (aFilename := lib construct: tab) exists ifFalse: [^ (#MQCHLLIBvalue3 << #MQSeries >> 'MQCHLLIB does not contain a file named MQCHLTAB''s value (<1s>)' ) expandMacrosWith: tab]. "file accessibility check" aFilename isReadable ifFalse: [^(#ChannelTable << #MQSeries >> 'Channel table file (<1s>) is not readable') expandMacrosWith: aFilename asString]. ^nil
ensurePrerequisitesForChannelTableUse "Ensure env.var. prerequisites for using the channel definition table: - MQSERVER must be UNdefined - MQCHLLIB must point to directory /var/mqm/channelTables - MQCHLTAB must hold the name of the channel table file in MQCHLLIB (e.g. 'AMQCLCHL_CEI.TAB' Raise Object notifySignal if prerequisites not satisfied, return true otherwise." | msg | ^(msg := self checkPrerequisitesForChannelTableUse) isNil or: [self notify: msg. false]
useChannelTable "Answer true/false dependent on the desired connection mode: - true = transparent connection via env.var. MQSERVER or client channel table - false = connecting should use host, port and channel as defined by configured inst.vars" ^UseChannelTable isNil ifTrue: [UseChannelTable := false] ifFalse: [UseChannelTable]
useChannelTable: aBoolean "Assign true/false dependent on the desired connection mode: - true = transparent connection via env.var. MQSERVER or client channel table - false = connecting should use host, port and channel as defined by configured inst.vars See also method comment of #createConnectOptionsForUnknownChannel." | useTable | (useTable := aBoolean) ifTrue: [useTable := self ensurePrerequisitesForChannelTableUse]. UseChannelTable := useTable
</methods> <methods> MQ.RemoteTHAPIQueueManager <category>initialize-release</category>
initialize "Ensure that an empty String is set as my name" super initialize. xifMutex := Semaphore forMutualExclusion
</methods> <methods> MQ.RemoteTHAPIQueueManager <category>actions</category>
serializeLibraryCall: aBlock "s. super implementor; serialize interface calls, thus avoiding a 'call-in-progress' exception (threaded xif rejects more than one active call)" xifMutex critical: aBlock
</methods> <methods> MQ.RemoteTHAPIQueueManager class <category>accessing</category>
externalInterfaceClass "Provide the name of the desired external interface class for MQ access." ^ MQTHAPIClientInterface
</methods> <methods> MQ.LocalQueueManager <category>private-activation</category>
acquireExternal "Acquire the external resources MQ-environment. Answer true on success, false on failure" | qMgrNamePtr compCodePtr reasonPtr return success | managerHndl := xif MQHCONN perform: xif mallocSelector with: 1. qMgrNamePtr := self name perform: xif gcCopyToHeapSelector. compCodePtr := xif MQLONG perform: xif gcMallocSelector with: 1. reasonPtr := xif MQLONG perform: xif gcMallocSelector with: 1. self serializeLibraryCall: [xif MQCONN: qMgrNamePtr with: managerHndl with: compCodePtr with: reasonPtr]. return := self getReturnFrom: compCodePtr and: reasonPtr. (success := return isOK or: [return isWarning and: [return reason = xif MQRC_ALREADY_CONNECTED]]) ifFalse: [MQNotConnectedError signalWith: return]. ^success
</methods> <methods> MQ.LocalQueueManager class <category>accessing</category>
externalInterfaceClass "Provide the name of the desired external interface class for MQ access." ^ MQInterface
</methods> <methods> MQ.LocalTHAPIQueueManager class <category>accessing</category>
externalInterfaceClass "Provide the name of the desired external interface class for MQ access." ^ MQTHAPIInterface
</methods> <methods> MQ.MQResult <category>accessing</category>
beFailed self compCode: self interfaceClass MQCC_FAILED
compCode ^compCode
compCode: aValue compCode := aValue
queueManager: aQM queueManager := aQM
reason ^reason
reason: aValue reason := aValue
</methods> <methods> MQ.MQResult <category>printing</category>
decodedReasonString ^self interfaceClass errorDict at: self reason ifAbsent: ['?' , self reason printString]
printOn: aStream super printOn: aStream. aStream cr; nextPutAll: ' completion: '; print: self compCode; cr. aStream nextPutAll: ' reason: '. aStream nextPutAll: self decodedReasonString.
shortComment "Return a short description of this MQReturn object" | aStream | aStream := WriteStream on: (String new: 30). aStream nextPutAll: 'CompletionCode: '; print: self compCode. aStream nextPutAll: ' Reason: '. aStream nextPutAll: self decodedReasonString. ^aStream contents
</methods> <methods> MQ.MQResult <category>private-accessing</category>
interfaceClass ^ queueManager xif
</methods> <methods> MQ.MQResult <category>testing</category>
isCallInProgress "Answer true if receiver has (failure) reason code MQRC_CALL_IN_PROGRESS (=2219)." ^self reason = self interfaceClass MQRC_CALL_IN_PROGRESS
isConnectionBroken "Answer true if this result encodes the #MQRC_CONNECTION_BROKEN error." ^self reason = self interfaceClass MQRC_CONNECTION_BROKEN
isConnectionFailure "Answer true if this result encodes one of the major MQ Manager connection errors." | aSymbol | aSymbol := self decodedReasonString. ^#( #MQRC_CONNECTION_BROKEN #MQRC_CONNECTION_QUIESCING #MQRC_Q_MGR_NOT_AVAILABLE #MQRC_Q_MGR_STOPPING #MQRC_Q_MGR_QUIESCING #MQRC_HOBJ_ERROR #MQRC_HCONN_ERROR ) includes: aSymbol
isFailed ^self compCode = self interfaceClass MQCC_FAILED
isManagerNotAvailable "Answer true if this MQ result denotes that the connection to the MQ manager is broken." | xif symbolic | xif := self interfaceClass. symbolic := #(#MQRC_Q_MGR_QUIESCING #MQRC_Q_MGR_STOPPING #MQRC_Q_MGR_NOT_ACTIVE) detect: [:getter | self reason = (xif perform: getter)] ifNone: []. ^symbolic notNil
isMessageTooLarge "Return true if the last MQGET failed because the message size exceeds the message result buffer. A MQGET is normally issued without specifying MQGMO_ACCEPT_TRUNCATED_MSG, i.e. we don't want the QueueManager to truncate our message, if it doesn't fit. If the queue manager responds with a warning of MQRC_TRUNCATED_MSG_FAILED, he tried to truncate, but was not allowed." ^self reason = self interfaceClass MQRC_TRUNCATED_MSG_FAILED
isNoMessagesAvailable "on a GET, no messages available on the queue" ^self reason = self interfaceClass MQRC_NO_MSG_AVAILABLE
isOK ^self compCode = self interfaceClass MQCC_OK
isWarning ^self compCode = self interfaceClass MQCC_WARNING
</methods> <methods> MQ.MQResult <category>initialize-release</category>
initialize | xif | compCode := (xif := self interfaceClass) isNil ifTrue: [0] ifFalse: [xif MQCC_OK]
</methods> <methods> MQ.MQResult class <category>instance creation</category>
new "Only use newFor: to get a new instance!" self shouldNotImplement
newFor: aQueueManager "Only way to create an instance" | newInst | newInst := self basicNew. newInst queueManager: aQueueManager. ^newInst initialize
</methods> <methods> MQ.AsynchronousMessage <category>accessing</category>
setMessageType: aNumber "Directly set the message type of the current messageHndl. Only meaning full when using message type numbers not represented as MQMessage subclasses." messageHndl memberAt: #MsgType put: aNumber
</methods> <methods> MQ.AsynchronousMessage <category>private</category>
initializeMessageDescriptor "Initialize a datagram message descriptor. Modified MsgType to MQMT_DATAGRAM." | params | params := super initializeMessageDescriptor. params memberAt: #MsgType put: self class messageTypeNumber. ^params
</methods> <methods> MQ.AsynchronousMessage class <category>accessing</category>
messageTypeNumber msgTypeNumber isNil ifTrue: [msgTypeNumber := MQInterface new MQMT_DATAGRAM]. ^ msgTypeNumber
</methods> <methods> MQ.Report <category>private</category>
initializeMessageDescriptor "Initialize a report message descriptor. Modified MsgType to MQMT_REPORT." | params | params := super initializeMessageDescriptor. params memberAt: #MsgType put: self xif MQMT_REPORT. ^params
</methods> <methods> MQ.Report <category>testing</category>
isCOA "Confirmation of arrival on the destination queue (see MQRO_COA)" ^(self messageHandle memberAt: #Feedback) = self xif MQFB_COA
isCOD "Confirmation of delivery to the receiving application (see MQRO_COD)." ^(self messageHandle memberAt: #Feedback) = self xif MQFB_COD
isEXCEPTION "Return true if the #Feedback field of this message is any one of the exception recturn codes." | feedback xif | feedback := self messageHandle memberAt: #Feedback. xif := self xif. ^#(#MQRC_PUT_INHIBITED #MQRC_Q_FULL #MQRC_NOT_AUTHORIZED #MQRC_Q_SPACE_NOT_AVAILABLE #MQRC_PERSISTENT_NOT_ALLOWED #MQRC_MSG_TOO_BIG_FOR_Q_MGR #MQRC_MSG_TOO_BIG_FOR_Q) detect: [:sel | (xif perform: sel) = feedback] ifNone: [false]
isExpired "Message expired. Message was discarded because it had not been removed from the destination queue before its expiry time had elapsed." ^(self messageHandle memberAt: #Feedback) = self xif MQFB_EXPIRATION
isNAN "Negative action notification (see MQRO_NAN)." ^(self messageHandle memberAt: #Feedback) = self xif MQFB_NAN
isPAN "Positive action notification (see MQRO_PAN)." ^(self messageHandle memberAt: #Feedback) = self xif MQFB_PAN
</methods> <methods> MQ.Report class <category>accessing</category>
messageTypeNumber msgTypeNumber isNil ifTrue: [msgTypeNumber := MQInterface new MQMT_REPORT]. ^ msgTypeNumber
</methods> <methods> MQ.ActionDecorator <category>services</category>
action self subclassResponsibility
action: aParameter self subclassResponsibility
data ^ self target basicData
data: aParameter self target basicData: aParameter
source "By default we are not interested about the source of a message. Return: empty String" ^String new
source: aString "By default we are not interested about the sourceof a message"
</methods> <methods> MQ.ActionDecorator <category>accessing</category>
target ^target
target: anObject target := anObject
</methods> <methods> MQ.ActionDecorator class <category>ADvance</category>
ad2ClassInfo ^'MessageActionDecorator is an abstract class. Its instances are decorators for setting/retrieving the action and data parameter of an MQMessage. Subclasses must implement the following messages: services action action: Subclasses may want to overwrite: services data data: Instance Variables: target <MQ.ActionMessage> the target message the decorator works on '
</methods> <methods> MQ.ActionDecorator class <category>instance creation</category>
newForTarget: anActionMessage "The target for the decorator has to be set" | newInstance | newInstance := self new. newInstance target: anActionMessage. ^newInstance
</methods> <methods> MQ.DefaultActionDecorator <category>services</category>
action "Answers a string that contains the action selector of the message" action isNil ifTrue: [self split]. ^action
action: aString "Defines the action selector for the message" action := aString. self complete ifTrue: [self join]
data "Answers a application data of the message" data isNil ifTrue: [self split]. ^data
data: aByteArray "Defines the application data for the message" data := aByteArray. self complete ifTrue: [self join]
source "Answers the source (the application that created the message)" source isNil ifTrue: [self split]. ^source
source: aString "Defines the source (the application that created the message)" source := aString. self complete ifTrue: [self join]
</methods> <methods> MQ.DefaultActionDecorator <category>testing</category>
complete "The decorater is prepared to join the message content when the action, the source and the data is defined" ^data notNil and: [action notNil and: [source notNil]]
</methods> <methods> MQ.DefaultActionDecorator <category>processing</category>
join "Combine the action and the application into a byte array and set this as data part of the message" | joined actionArray sourceArray actionStart sourceStart dataStart | actionArray := action asByteArray. sourceArray := source asByteArray. joined := ByteArray new: (actionArray size + sourceArray size + data size + 2). actionStart := 3. sourceStart := actionStart + actionArray size. dataStart := sourceStart + sourceArray size. joined at: 1 put: actionArray size. joined at: 2 put: sourceArray size. joined replaceFrom: actionStart to: sourceStart - 1 with: actionArray. joined replaceFrom: sourceStart to: dataStart - 1 with: sourceArray. joined replaceFrom: dataStart to: joined size with: data. self target basicData: joined
split "Extract the action selector and the application data from the data part of a message" | raw actionStart sourceStart dataStart | raw := self target basicData. actionStart := 3. sourceStart := actionStart + raw first. dataStart := sourceStart + (raw at: 2). action := (raw copyFrom: actionStart to: sourceStart - 1) asString. source := (raw copyFrom: sourceStart to: dataStart - 1) asString. data := (raw copyFrom: dataStart to: raw size)
</methods> <methods> MQ.MessageQueue <category>actions</category>
close "Close this queue." | qm mHandle xif compCodePtr reasonPtr optionsPtr return | self isConnected ifFalse: [^self]. (qm := self queueManager) isConnected ifFalse: [^self freeQueueHndl; state: #disconnected]. xif := self xif. compCodePtr := xif MQLONG perform: xif gcMallocSelector with: 1. reasonPtr := xif MQLONG perform: xif gcMallocSelector with: 1. optionsPtr := xif MQLONG perform: xif gcMallocSelector with: 1. optionsPtr contents: xif MQCO_NONE. [mHandle := qm managerHandle contents] on: Error do: [:ex | | param | "handle exception if managerHandle is nil (MNU #contents) or any error from external pointer" (param := MQResult newFor: qm) beFailed; reason: xif MQRC_UNEXPECTED_ERROR. MQNotConnectedError raiseWith: param errorString: ('<1s> (MQ manager=<2p>)' expandMacrosWith: ex description with: qm managerHandle)]. qm serializeLibraryCall: [xif MQCLOSE: mHandle with: queueHndl with: optionsPtr contents with: compCodePtr with: reasonPtr]. return := qm getReturnFrom: compCodePtr and: reasonPtr. return isOK ifFalse: [return isConnectionBroken | (return reason = xif MQRC_HOBJ_ERROR) ifTrue: ["Reason code 2019: object handle is not valid. Ignore the error which originates from a stale handle, obviously discarded by MQ itself"] ifFalse: [MQQueueCloseError signalWith: return]]. self freeQueueHndl; state: #disconnected
ensureOpenQueue "Ensure that this queue is opened" self isConnected ifTrue: [^self]. self queueManager isConnected ifFalse: [MQNotConnectedError raise]. self open
open "open this queue for Gets if I am a receiver, and for Puts if I am a sender queue" self open: nil
open: queueName "Open this queue for Gets if I am a receiver, and for Puts if I am a sender queue. If <queueName> is not nil then open this queue as dynamic queue. Use a differing destination queue manager name if specified." self open: queueName destinationQueueManager: self destinationManagerName
open: queueName destinationQueueManager: managerName "Open this queue for GET if it is a receiver, and for PUT if it is a sender queue. If <queueName> is not nil, then open this queue as a dynamic queue. If <managerNameOrNil> is not nil, then assign the ObjectQMgrName field." | qm xif objDescPtr compCodePtr reasonPtr optionsPtr return mHandle | self isConnected ifTrue: [^self]. (qm := self queueManager) isConnected ifFalse: [MQNotConnectedError raise]. objDescPtr := self initializeObjectDescriptor. self setTargetQueueManager: managerName descriptor: objDescPtr. self setDynamicQueue: queueName descriptor: objDescPtr. xif := self xif. compCodePtr := xif MQLONG perform: xif gcMallocSelector with: 1. reasonPtr := xif MQLONG perform: xif gcMallocSelector with: 1. queueHndl := xif MQHOBJ perform: xif mallocSelector with: 1. (optionsPtr := xif MQLONG perform: xif gcMallocSelector with: 1) contents: self queueOption. [mHandle := qm managerHandle contents] on: Error do: [:ex | | param | "handle exception if managerHandle is nil (MNU #contents) or any error from external pointer" (param := MQResult newFor: qm) beFailed; reason: xif MQRC_UNEXPECTED_ERROR. MQNotConnectedError raiseWith: param errorString: ('<1s> (MQ manager=<2p>)' expandMacrosWith: ex description with: qm managerHandle)]. qm serializeLibraryCall: [xif MQOPEN: mHandle with: objDescPtr with: optionsPtr contents with: queueHndl with: compCodePtr with: reasonPtr]. return := qm getReturnFrom: compCodePtr and: reasonPtr. return isOK ifTrue: [queueName notNil ifTrue: ["dynamic queue: read concrete name given by queue manager" self updateQueueName: objDescPtr]. self state: #connected] ifFalse: [MQQueueOpenError signalWith: return]
openDynamic "Open this queue as a Dynamic Queue. The name of the new dynamic queue is generated by the queue manager when the queue is created. The queue name may have an wild card (*) at the end. It is also valid to use only the wildcard." self open: '*'
</methods> <methods> MQ.MessageQueue <category>private</category>
freeQueueHndl queueHndl isNil ifTrue: [^self]. queueHndl free. queueHndl := nil
initializeMessageOptions self subclassResponsibility
initializeObjectDescriptor "used to specify a queue, process definition or queue manager. currently used only for queues" | xif aMQOD | aMQOD := (xif := self xif) alloc64KAlignedObjectDescriptor. (aMQOD refMemberAt: #ObjectName) copyAt: 0 from: self queueName size: xif MQ_Q_NAME_LENGTH startingAt: 1. ^aMQOD
orOptionsFieldWith: optionBitMask "Add 1-bits in <optionBitMask> to value of field #Options." | oldBits newBits | optionBitMask isZero ifTrue: [^self]. oldBits := messageOptions memberAt: #Options. newBits := oldBits bitOr: optionBitMask. oldBits = newBits ifFalse: [messageOptions memberAt: #Options put: newBits]
privateSetSyncpointOption: aNumber self syncSetting: aNumber. self resetMessageOptions
setDynamicQueue: queueName descriptor: objDescPtr "Set a flag in the object descriptor indicating to open a dynamic queue. Attributes for a dynamic queue are copied from a model queue defined in the queue name parameter " | sz padded | queueName isNil ifTrue: [^self]. sz := self xif MQ_Q_NAME_LENGTH. padded := queueName fillUpWithSpacesTo: sz. (objDescPtr refMemberAt: #DynamicQName) copyAt: 0 from: padded size: sz startingAt: 1
setMessageOptions "Set the normal get/put message options for sending amessage now" self subclassResponsibility
setSyncOptions "OR the syncSetting value with the #Options slot of the messageOptions struct for Gets" self orOptionsFieldWith: self syncSetting.
setTargetQueueManager: managerName descriptor: objDescPtr "Assign the target queue manager name that manages the desired queue. Note: This may differ from the name of the manager we are connected to." | sz padded | managerName isNil ifTrue: [^self]. sz := self xif MQ_Q_MGR_NAME_LENGTH. padded := managerName fillUpWithSpacesTo: sz. (objDescPtr refMemberAt: #ObjectQMgrName) copyAt: 0 from: padded size: sz startingAt: 1
updateQueueName: objDescPtr "When opening a dynamic queue the name will be defined by the queue manager. We have to update the queue name and the manager's registry." | sz qName | sz := self xif MQ_Q_NAME_LENGTH. qName := String new: sz. (objDescPtr refMemberAt: #ObjectName) copyAt: 0 to: qName size: sz startingAt: 1. queueManager updateRegistry: self newName: qName. self name: qName
xif ^self queueManager xif
</methods> <methods> MQ.MessageQueue <category>initialize-release</category>
initialize "Establish initial value for instance variables. Queues normally choose to work without sync points" self resetQueueName. self state: #new. self noSyncpoint
resetQueueName self name: nil.
</methods> <methods> MQ.MessageQueue <category>testing</category>
isConnected "Answer whether this queue is connected to MQ" ^state == #connected and: [self isQueueHandleValid]
isQueueHandleValid "Return true if queue handle is assigned and valid, false otherwise. Cold restart of an image that has been saved with an active MessageQueue will return with invalid handle" ^queueHndl isValid or: ["if the queue handle is invalid, then message options are invalid as well " self resetMessageOptions. false]
isSender self subclassResponsibility
</methods> <methods> MQ.MessageQueue <category>accessing</category>
destinationManagerName "Answer the name of the (external) MQ queue manager that effectively manages the sender queue. Default is nil, but subclass SenderQueue overwrites. See also comment in #destinationManagerName:. Return: String (nil if no different queue manager to be used)" ^nil
name ^ name
name: stringOrNil | sz padded | sz := self xif MQ_Q_NAME_LENGTH. padded := (stringOrNil isNil or: [stringOrNil isEmpty]) ifTrue: [String new: sz withAll: Character space] ifFalse: [stringOrNil fillUpWithSpacesTo: sz]. name := padded
queueManager ^queueManager
queueManager: anObject queueManager := anObject
queueName ^ name
queueOption "Return the correct queue option value, like MQOO_OUTPUT for a sender queue." self subclassResponsibility
resetMessageOptions messageOptions := nil
state ^state
state: anObject state := anObject
syncSetting ^syncSetting
syncSetting: anObject syncSetting := anObject
</methods> <methods> MQ.MessageQueue <category>syncpoint options</category>
noSyncpoint "Put messages without syncpoint control. The request is to operate outside the normal unit-of-work protocols. A message is available immediately, and it cannot be deleted by backing out a unit of work." self subclassResponsibility
syncpoint "Put message with syncpoint control. The request is to operate within the normal unit-of-work protocols. A message is not visible outside the unit of work until the unit of work is committed. If the unit of work is backed out, the message is deleted." self subclassResponsibility
</methods> <methods> MQ.MessageQueue <category>message creation</category>
newAsynchronousMessage "Return a new AsynchronousMessage object to be sent/received by this queue." ^AsynchronousMessage newFor: self
newReply "Return a new Reply object to be sent/received by this queue." ^Reply newFor: self
newReport "Return a new Report object to be sent/received by this queue." ^Report newFor: self
newRequest "Return a new Request object to be send/received by this queue" "self ensureOpenQueue." ^Request newFor: self.
</methods> <methods> MQ.MessageQueue <category>printing</category>
printOn: aStream "Append the queue name." super printOn: aStream. aStream space; print: self name trimBlanks
</methods> <methods> MQ.MessageQueue class <category>instance creation</category>
newFor: aQueueManager "Create a new queue and insert the target queueManager right away" | newInstance | newInstance := self new . newInstance queueManager: aQueueManager. newInstance initialize. ^ newInstance
newFor: aQueueManager name: aString "Create a new queue and insert the target queueManager right away along with the queue's name" | newInstance | newInstance := self newFor: aQueueManager. newInstance name: aString. ^ newInstance
</methods> <methods> MQ.ReceiverQueue <category>match options</category>
disableMessageMatching matchEnabled := false. self resetMessageOptions
enableMessageMatching matchEnabled := true. self resetMessageOptions
matchOptionArray "Lazy initialize the matchOptionArray to a default, if it is not set to something else." matchOptionArray isNil ifTrue: [ matchOptionArray := DefaultMatchOptionsArray]. ^matchOptionArray
matchOptionArray: anObject matchOptionArray := anObject
</methods> <methods> MQ.ReceiverQueue <category>actions</category>
getIncomingMessage "Perform an MQGET and beware of message buffer overflow." | result | self initializeMessageOptions. result := self getAnyMessageLike: self newAsynchronousMessage. ^self adaptMessageToType: result
getIncommingMessageWait: aNumber "Set the waitInterval to aNumber just for this GET, perform the MQGET and reset the waitInterval afterwards. The intervall represents milliseconds of wait time." | oldWait | oldWait := self waitInterval. self waitInterval: aNumber. ^[self getIncomingMessage] ensure: [self waitInterval: oldWait]
getReplyFor: aMessage "Retrieve all relevant parameters from aMessage, like MsgID, CorrelID etc. Then perform an MQGET and use the matchOptions." | template result | self initializeMessageOptions. template := self newReply. self copyMatchFieldsFrom: aMessage to: template. (result := self getAnyMessageLike: template) notNil ifTrue: [| mType msg | (mType := result messageType) = template class messageTypeNumber ifFalse: [msg := (#MQRecieveMessage << #MQSeries >> 'Received Msg is not a Reply! Received type: ') asString , mType printString. MQWrongMessageType raiseSignal: msg]]. ^result
getReplyFor: aMessage wait: aNumber "Set the waitInterval to aNumber just for this GET, perform the MQGET and reset the waitInterval afterwards. The intervall represents milliseconds of wait time." | temp oldWait | oldWait := self waitInterval. self waitInterval: aNumber. temp := self getReplyFor: aMessage. self waitInterval: oldWait. ^ temp
getReportFor: aMessage "Retriev all relevant parameters from aMessage, like MsgID, CorrelID etc. Then perform an MQGET and use the matchOptions." | template | self initializeMessageOptions. template := self newReport. self copyMatchFieldsFrom: aMessage to: template. ^self getAnyMessageLike: template
getReportFor: aMessage wait: aNumber "Set the waitInterval to aNumber just for this GET, perform the MQGET and reset the waitInterval afterwards. The intervall represents milliseconds of wait time." | temp oldWait | oldWait := self waitInterval. self waitInterval: aNumber. temp := self getReportFor: aMessage. self waitInterval: oldWait. ^ temp
</methods> <methods> MQ.ReceiverQueue <category>initialize-release</category>
initialize "Initialize the waitInterval to 0, so Gets return immediately, wether there is or is no message in the queue. Disable matching of incoming messages. Set the matchOptionArray to a default (#MQMO_MATCH_CORREL_ID)." super initialize. self noWait. self disableMessageMatching.
</methods> <methods> MQ.ReceiverQueue <category>testing</category>
isSender ^ false
matchEnabled ^ matchEnabled
</methods> <methods> MQ.ReceiverQueue <category>syncpoint options</category>
noSyncpoint self privateSetSyncpointOption: self xif MQGMO_NO_SYNCPOINT
syncpoint self privateSetSyncpointOption: self xif MQGMO_SYNCPOINT
syncpointIfPersistent self privateSetSyncpointOption: self xif MQGMO_SYNCPOINT_IF_PERSISTENT
</methods> <methods> MQ.ReceiverQueue <category>wait options</category>
noWait self waitInterval: 0
waitForever self waitInterval: self xif MQWI_UNLIMITED
</methods> <methods> MQ.ReceiverQueue <category>accessing</category>
queueOption "Return the correct queue option value, like MQOO_INPUT_SHARED for a non exclusive receiver queue." ^ self xif MQOO_INPUT_SHARED
receiver "On receiving a Request, the init code for Requests will send this." ^nil
waitInterval ^ waitInterval
waitInterval: aNumber "This is the approximate time, expressed in milliseconds, that the MQGET call waits for a suitable message to arrive (that is, a message satisfying the selection criteria specified in the MsgDesc parameter of the MQGET call; ...). If no suitable message has arrived after this time has elapsed, the call completes with MQCC_FAILED and reason code MQRC_NO_MSG_AVAILABLE." waitInterval := aNumber. self resetMessageOptions
</methods> <methods> MQ.ReceiverQueue <category>private</category>
adaptMessageToType: aMQMessage "Create a new MQ message of the class associated with the given message type. If it is a datagram message, do nothing." aMQMessage isNil ifTrue: [^nil]. aMQMessage isAsynchronous ifTrue: [^aMQMessage]. ^(MQMessage newFor: self type: aMQMessage messageType) basicData: aMQMessage basicData; setMessageHandle: aMQMessage messageHandle
allocateDataBufferFor: aMQMessage "Allocate external heap memory with proper size and all data of given message. Answer the CPointer to this memory." ^aMQMessage basicData gcCopyToHeap
clearMessageOption: anOption "anOption <aSymbol> e.g. #MQGMO_WAIT " | oldBits newBits | oldBits := messageOptions memberAt: #Options. newBits := oldBits maskClear: (self xif perform: anOption). oldBits = newBits ifFalse: [messageOptions memberAt: #Options put: newBits]
copyMatchFieldsFrom: aMessage to: queryTemplate "<queryTemplate> is a MQ Message to be used for next MQ query. If matching is enabled, copy all relevant parameters from aMessage, like MsgID, CorrelID etc. over to <queryTemplate>, which is then used to get the actual message." | special initialValuesOnly | self matchEnabled ifFalse: [^self]. special := aMessage requiresMsgIdToCorrelId. initialValuesOnly := true. self matchOptionArray do: [:optionSelector | | assoc getter setter matchValue isInitial | assoc := MatchOptionsSelectorMapping at: optionSelector. getter := assoc key. setter := assoc value. optionSelector == #MQMO_MATCH_CORREL_ID & special ifTrue: [getter := #messageID "force message ID to correl ID"]. matchValue := aMessage perform: getter. queryTemplate perform: setter with: matchValue. isInitial := matchValue isInteger ifTrue: [matchValue isZero] ifFalse: [matchValue allSatisfy: [:byte | byte = 0]]. initialValuesOnly := initialValuesOnly & isInitial]. initialValuesOnly ifTrue: ["Avoid getting tricked by weak MQ query: Specifying message matching (e.g. match correl id) and placing initial values only (e.g. MQMI_NONE and/or MQCI_NONE) will return the first message in the queue. (see 'MQ Application Programming Guide.pdf', chapter 'Chapter 10. Getting messages from a queue', section 'Getting a particular message', page 133 ff.)" MQError raiseWith: aMessage errorString: 'Undefined match arguments']
getAnyMessageLike: aMQMessage "Get the next message from the queue matching current match options and given template message. Retry if data buffer was too small during first request. Put received data into <aMQMessage>. Evaluate the return code and raise an MQGetError if an error occurred. Return <aMQMessage>, nil if no matching message was found" | qm dataBufferPtr dataLengthPtr xif return reasonPtr compCodePtr bytes mHandle qHandle | self ensureOpenQueue. dataBufferPtr := self allocateDataBufferFor: aMQMessage. xif := self xif. dataLengthPtr := xif MQLONG perform: xif gcMallocSelector with: 1. compCodePtr := xif MQLONG perform: xif gcMallocSelector with: 1. reasonPtr := xif MQLONG perform: xif gcMallocSelector with: 1. qm := self queueManager. [mHandle := qm managerHandle contents. qHandle := queueHndl contents] on: Error do: [:ex | | param | "handle exception if managerHandle is nil (MNU #contents) or any error from external pointer" (param := MQResult newFor: qm) beFailed; reason: xif MQRC_UNEXPECTED_ERROR. MQNotConnectedError raiseWith: param errorString: ('<1s> (MQ manager=<2p>, queue=<3p>)' expandMacrosWith: ex description with: qm managerHandle with: queueHndl)]. qm serializeLibraryCall: [xif MQGET: mHandle with: qHandle with: aMQMessage messageHandle with: messageOptions with: aMQMessage dataSize with: dataBufferPtr with: dataLengthPtr with: compCodePtr with: reasonPtr]. return := qm getReturnFrom: compCodePtr and: reasonPtr. return isMessageTooLarge ifTrue: [aMQMessage basicData: (ByteArray new: dataLengthPtr contents). ^self getAnyMessageLike: aMQMessage]. return isOK ifFalse: [return isNoMessagesAvailable ifFalse: [MQGetError signalWith: return]. ^nil]. bytes := aMQMessage dataSize = dataLengthPtr contents ifTrue: ["on retry we know the exact data size, save superfluous allocation" aMQMessage data] ifFalse: [ByteArray new: dataLengthPtr contents]. dataBufferPtr copyAt: 0 to: bytes size: bytes size startingAt: 1. ^aMQMessage basicData: bytes
initializeMessageOptions "This method initializes the message options for Gets. Use a lazy initialize mechanism, so if no general setting has changed, the same option struct can be re-used. All methods changing a get-message-option (waitInterval:, matchOnly: etc) have to set instVar messageOptions to nil." messageOptions isNil ifFalse: [^self]. messageOptions := self xif alloc64KAlignedGetMessageOptions. "Now adapt some fields in the GMO " messageOptions memberAt: #WaitInterval put: self waitInterval. self setMessageOptions. ^messageOptions
setMatchOptions "If matching is enabled, set all match options as listed in the matchOptionArray" | matchFlags | matchFlags := 0. self matchEnabled ifTrue: [self matchOptionArray do: [:optionSymbol | matchFlags := matchFlags bitOr: (self xif perform: optionSymbol)]]. messageOptions memberAt: #MatchOptions put: matchFlags
setMessageOptions "Update option settings in MQGMO fields #Options and #MatchOptions." self setMatchOptions. self setOptionsToZero. self setWaitOptions. self setSyncOptions
setOptionsToZero messageOptions memberAt: #Options put: 0
setWaitOptions "Set the wait options for Gets depending on the value of the waitInterval." | xif opt | xif := self xif. opt := waitInterval = 0 ifTrue: [self clearMessageOption: #MQGMO_WAIT. xif MQGMO_NO_WAIT] ifFalse: [self clearMessageOption: #MQGMO_NO_WAIT. xif MQGMO_WAIT]. self orOptionsFieldWith: opt
</methods> <methods> MQ.ReceiverQueue class <category>class initialization</category>
initialize MatchOptionsSelectorMapping := Dictionary new. MatchOptionsSelectorMapping at: #MQMO_MATCH_CORREL_ID put: #correlationID -> #basicCorrelID:. MatchOptionsSelectorMapping at: #MQMO_MATCH_MSG_ID put: #messageID -> #basicMessageID:. MatchOptionsSelectorMapping at: #MQMO_MATCH_GROUP_ID put: #messageGroupID -> #basicGroupID:. MatchOptionsSelectorMapping at: #MQMO_MATCH_MSG_SEQ_NUMBER put: #messageSeqNumber -> #messageSeqNumber:. MatchOptionsSelectorMapping at: #MQMO_MATCH_Offset put: #messageOffset -> #messageOffset:.
</methods> <methods> MQ.BrowseQueue <category>browse options</category>
browseFirst self setBrowseMode: self xif MQGMO_BROWSE_FIRST
browseMsgUnderCursor self setBrowseMode: self xif MQGMO_BROWSE_MSG_UNDER_CURSOR
browseNext self setBrowseMode: self xif MQGMO_BROWSE_NEXT
</methods> <methods> MQ.BrowseQueue <category>initialize-release</category>
initialize "Initialize a BrowserQueue to browse_next mode and no_syncpoint." super initialize. self noSyncpoint. self browseNext
</methods> <methods> MQ.BrowseQueue <category>accessing</category>
queueOption "Return the correct queue option value, like MQOO_BROWSE for a browse queue." ^ self xif MQOO_BROWSE
</methods> <methods> MQ.BrowseQueue <category>private</category>
setBrowseMode: aNumber "Set the internal browseMode value to aNumber." browseMode := aNumber. self resetMessageOptions
setBrowseOptions "OR the browseMode value with the #Options slot of the messageOptions struct for Gets" self orOptionsFieldWith: browseMode
setMessageOptions "Set the normal get message options" super setMessageOptions. self setBrowseOptions
</methods> <methods> MQ.MQNotConnectedError <category>initialize-release</category>
initialize "Initialize a newly created instance. This method must answer the receiver." super initialize. " *** Replace this comment with the appropriate initialization code *** " ^self
</methods> <methods> MQ.SenderQueue <category>accessing</category>
defaultOptions "Answers a copy of the put options. We answer a copy of the defined option to enable messages to manipulate the option set when it isd sent" ^options copy
destinationManagerName "Answer the name of the (external) MQ queue manager that effectively manages the sender queue. (See also comment in #destinationManagerName:) Return: String" ^destinationManagerName
destinationManagerName: aString "Assign the name of the (external) MQ queue manager that effectively manages the sender queue. This name may differ from the name of the queue manager that receives the MQOPEN request. The differing name is assigned to field #ObjectQMgrName in the MQOD struct used for MQOPEN. This way it is possible to refine the destination or route that a reply takes." destinationManagerName := aString
options ^ options
queueOption "Return the correct queue option value, like MQOO_OUTPUT for a sender queue." ^ self xif MQOO_OUTPUT bitOr: (self xif MQOO_SET_ALL_CONTEXT)
receiver ^receiver
setReceiverQueue: aMessageQueue receiver := aMessageQueue
</methods> <methods> MQ.SenderQueue <category>initialize-release</category>
initialize "Sender queues will initially create no syncpoint (like all queues), and will force new MsgIDs provided by the queue manager for each message send." self resetOptions. super initialize. self setAutoMsgIDOption. " self setAllContextOption"
resetOptions "Reset any option later written into the Option field of the Put-Message-Option struct. These are all of kind MQPMO_*" options := Set new
</methods> <methods> MQ.SenderQueue <category>private</category>
initializeMessageOptions "used to specify message options for Puts" | xif | xif := self xif. messageOptions := xif alloc64KAlignedPutMessageOptions. self setMessageOptions. ^messageOptions
initializeMessageOptions: aCollection "used to specify message options for Puts" | xif | xif := self xif. messageOptions := xif alloc64KAlignedPutMessageOptions. self setMessageOptions: aCollection. ^messageOptions
setMessageOptions "Set the normal put message options for sending amessage now" messageOptions memberAt: #Options put: (self xif MQPMO_NONE). self setOptionsField. messageOptions memberAt: #Timeout put: -1.
setMessageOptions: aCollection "Set the normal put message options for sending amessage now" messageOptions memberAt: #Options put: (self xif MQPMO_NONE). self setOptionsField: aCollection. messageOptions memberAt: #Timeout put: -1.
setOptionsField "Set the normal put message options for sending a message now" self setOptionsField: self options
setOptionsField: aCollection "Set the normal put message options for sending a message now" | flags | flags := messageOptions memberAt: #Options. aCollection do: [:optionSelector | flags := flags bitOr: (self xif perform: optionSelector)]. messageOptions memberAt: #Options put: flags
setTargetQueueManager: managerName descriptor: objDescPtr "s. super implementor; remember the destination queue manager in a private inst.var." super setTargetQueueManager: managerName descriptor: objDescPtr. self destinationManagerName: managerName
</methods> <methods> MQ.SenderQueue <category>testing</category>
isSender ^ true
</methods> <methods> MQ.SenderQueue <category>syncpoint options</category>
noSyncpoint self options remove: #MQPMO_SYNCPOINT ifAbsent: []. self options add: #MQPMO_NO_SYNCPOINT
syncpoint self options remove: #MQPMO_NO_SYNCPOINT ifAbsent: []. self options add: #MQPMO_SYNCPOINT
</methods> <methods> MQ.SenderQueue <category>id options</category>
resetAutoCorrelIDOption "disable CorrelID generation by the queue manager" self options remove: #MQPMO_NEW_CORREL_ID ifAbsent: []
resetAutoMsgIDOption "disable MsgID generation by the queue manager" self options remove: #MQPMO_NEW_MSG_ID ifAbsent: []
setAllContextOption "Set all context from the application. The message is to have context information associated with it. The application specifies the identity and origin context in the MQMD structure." self options add: #MQPMO_SET_ALL_CONTEXT
setAutoCorrelIDOption "Generate a new correlation identifier. This option causes the queue manager to replace the contents of the CorrelId field in MQMD with a new correlation identifier. This correlation identifier is sent with the message, and returned to the application on output from the MQPUT or MQPUT1 call." self options add: #MQPMO_NEW_CORREL_ID
setAutoMsgIDOption "Generate a new message identifier. This option causes the queue manager to replace the contents of the MsgId field in MQMD with a new message identifier. This message identifier is sent with the message, and returned to the application on output from the MQPUT or MQPUT1 call." self options add: #MQPMO_NEW_MSG_ID
</methods> <methods> MQ.SenderQueue <category>actions</category>
put: aMessage | qm xif compCodePtr reasonPtr return putOptions buffPtr mHandle qHandle | self ensureOpenQueue. putOptions := self defaultOptions. aMessage addaptOptions: putOptions. self initializeMessageOptions: putOptions. aMessage prepareMessageForSend. xif := self xif. compCodePtr := xif MQLONG perform: xif gcMallocSelector with: 1. reasonPtr := xif MQLONG perform: xif gcMallocSelector with: 1. buffPtr := aMessage basicData gcCopyToHeap. qm := self queueManager. [mHandle := qm managerHandle contents. qHandle := queueHndl contents] on: Error do: [:ex | | param | "handle exception if managerHandle is nil (MNU #contents) or any error from external pointer" (param := MQResult newFor: qm) beFailed; reason: xif MQRC_UNEXPECTED_ERROR. MQNotConnectedError raiseWith: param errorString: ('<1s> (MQ manager=<2p>, queue=<3p>)' expandMacrosWith: ex description with: qm managerHandle with: queueHndl)]. qm serializeLibraryCall: [xif MQPUT: mHandle with: qHandle with: aMessage messageHandle with: messageOptions with: aMessage dataSize with: buffPtr with: compCodePtr with: reasonPtr]. return := qm getReturnFrom: compCodePtr and: reasonPtr. return isOK ifFalse: [MQPutError signalWith: return]
</methods> <methods> MQ.SenderQueue class <category>ADvance</category>
ad2ClassInfo ^' Instance Variables: receiver <ReceiverQueue> queue for receiving a reply'
</methods> <methods> MQ.DefaultDataDecorator <category>services</category>
action "Return nothing, this decorator ignores actions" ^ nil
action: aParameter "Do nothing, this decorator ignores actions"
</methods> <methods> MQ.AMDActionDecorator <category>services</category>
action "AMD wishes to use the #ApplIdentityData field to squeeze an message action parameter into the message descriptor" | sz applId | sz := self target targetQueue xif MQ_APPL_IDENTITY_DATA_LENGTH. applId := String new: sz. (self target messageHandle memberAt: #ApplIdentityData) copyAt: 0 to: applId size: sz startingAt: 1. ^applId trimMQTrailer
action: aString "AMD wishes to use the #ApplIdentityData field to squeeze an message action parameter into the message descriptor This field is 32 bytes long, so all adaptations to this length is done here." | theQueue sz xif padded | theQueue := self target targetQueue. sz := (xif := theQueue xif) MQ_APPL_IDENTITY_DATA_LENGTH. padded := aString isNil ifTrue: [xif MQMI_NONE padWith: Character nul upTo: sz] ifFalse: [aString fillUpWithSpacesTo: sz]. (self target messageHandle refMemberAt: #ApplIdentityData) copyAt: 0 from: padded size: sz startingAt: 1
source "AMD wishes to use the parameter #PutApplName field to add the application that created a message to the message descriptor" | sz applName | sz := self target targetQueue xif MQ_APPL_NAME_LENGTH. applName := String new: sz. (self target messageHandle memberAt: #PutApplName) copyAt: 0 to: applName size: sz startingAt: 1. ^applName trimMQTrailer
source: aString "AMD wishes to use the parameter #PutApplName field to add the application that created a message to the message descriptor. This field is 28 bytes long, so all adaptations to this length is done here." | theQueue xif sz padded | theQueue := self target targetQueue. sz := (xif := theQueue xif) MQ_APPL_NAME_LENGTH. padded := aString isNil ifTrue: [xif MQMI_NONE padWith: Character nul upTo: sz] ifFalse: [aString fillUpWithSpacesTo: sz]. (self target messageHandle refMemberAt: #PutApplName) copyAt: 0 from: padded size: sz startingAt: 1
</methods> <methods> MQ.ExclusiveInputQueue <category>accessing</category>
queueOption "Return the correct queue option value, like MQOO_INPUT_EXCLUSIVE for an exclusive receiver queue." ^ self xif MQOO_INPUT_EXCLUSIVE
</methods> <methods> MQ.Reply <category>testing</category>
isReply ^true
</methods> <methods> MQ.Reply <category>private</category>
initializeMessageDescriptor "Initialize a reply message descriptor. Modified #MsgType to MQMT_REPLY." | desc | (desc := super initializeMessageDescriptor) memberAt: #MsgType put: self class messageTypeNumber. ^desc
</methods> <methods> MQ.Reply class <category>accessing</category>
messageTypeNumber msgTypeNumber isNil ifTrue: [msgTypeNumber := MQInterface new MQMT_REPLY]. ^ msgTypeNumber
</methods> <initialize> MQ.ActionMessage </initialize> <initialize> MQ.QueueManager </initialize> <initialize> MQ.ReceiverQueue </initialize> "Imported Classes:" self error: 'Attempting to file-in parcel imports. Choose terminate or close' <class> <name>Object</name> <environment>Core</environment> <super></super> <private>false</private> none <imports></imports> <category>Kernel-Objects</category> <attributes> <package>Kernel-Objects</package> </attributes> </class> <class> <name>Error</name> <environment>Core</environment> <super>Core.Exception</super> <private>false</private> none <imports></imports> <category>Kernel-Exception Handling</category> <attributes> <package>Kernel-Exception Handling</package> </attributes> </class>