-
Notifications
You must be signed in to change notification settings - Fork 27
Expand file tree
/
Copy pathtesting_giop.html
More file actions
225 lines (209 loc) · 10.6 KB
/
Copy pathtesting_giop.html
File metadata and controls
225 lines (209 loc) · 10.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
<!DOCTYPE HTML PUBLIC "-//SoftQuad Software//DTD HoTMetaL PRO 6.0::19990601::extensions to HTML 4.0//EN" "hmpro6.dtd">
<!--
Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0 which is available at
http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
v. 1.0 which is available at
http://www.eclipse.org/org/documents/edl-v10.php.
This Source Code may also be made available under the following Secondary
Licenses when the conditions for such availability set forth in the Eclipse
Public License v. 2.0 are satisfied: GNU General Public License v2.0
w/Classpath exception which is available at
https://www.gnu.org/software/classpath/license.html.
SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause OR GPL-2.0 WITH
Classpath-exception-2.0
-->
<HTML>
<HEAD>
<TITLE></TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000EE" ALINK="#FF0000"
VLINK="#990066" BACKGROUND="images/backgrounds/p12c08.gif">
<H1 ALIGN="CENTER">ORB Support for GIOP Testing</H1>
<P> </P> <HR WIDTH="75%">
<P> Last Modified: <I>May 17, 2004</I> </P>
<P> Version: 1.6 </P>
<ADDRESS> <A HREF="mailto:ken.cavanaugh@sun.com"><Ken Cavanaugh></A>
</ADDRESS>
<P> We often need to examine problems in CORBA that are related to the
details of marshalling messages for CDR encoded GIOP messages. This is
currently a difficult and time-consuming problem due to the lack of tools for
this task. Harsha Godugu is working on a GIOP analyzer to make this process
easier. This note discusses some ORB changes needed to support the GIOP
analyzer, and also to make other debugging tasks easier. </P>
<P> What we need is the following: </P>
<UL>
<LI>An API for capturing the messages sent and received by a particular
invocation. This will allow us to gather data for testing the GIOP analyzer .
</LI>
<LI>An API for taking a sequence of messages and converting that sequence
into an input stream. Utilities for converting an array of strings or a text
file in the GIOP dump format will also be useful. </LI>
</UL>
<H2>Getting an Input Stream from Messages</H2>
<P>Probably the simplest possible representation for the data contained in
a sequence of messages is simply byte[][]. Wherever I use this type to
represent a sequence of messages, we will assume that: </P>
<OL>
<LI>The first message in the sequence is either a (GIOP) request or
reply. </LI>
<LI>Subsequent messages are all fragment messages. </LI>
<LI>Every message except the last has the more fragment bit set. </LI>
<LI>All messages in the sequence share the same request ID. </LI>
</OL>
<P>If any of these conditions fail, getMessageData should throw an
appropriate exception. getMessageData is a new method on the ORB SPI defined as
follows: </P>
<PRE>
/** Messages must be an array of GIOP messages. The first message must
* be a GIOP request or response. Any subsequent messages must be
* fragment messages with the same request ID as the first message.
* This returns a MessageData interface, in which all of the Messages
* have been unmarshalled, and the result of getStream is a stream
* that is prepared to unmarshal the request or reply body.
*/
MessageData getMessageData( byte[][] messages ) ;
</PRE>
<P> MessageData is an interface defined as follows: </P>
<PRE>
public interface MessageData {
/** An array GIOP Messages. The first message is a request or reply,
* all subsequent messages are fragments with the same request ID.
*/
Message[] getMessages() ;
/** A fully initialized input stream for the message data, positioned
* at the first element of the body.
*/
CDRInputStream getStream() ;
}
</PRE>
<P> To support this, we need a Connection that is backed by a byte[][] or
equivalent. I am currently testing this, which us called
BufferedConnectionImpl. </P>
<H2>Capturing Messages from an Invocation</H2>
<P>The idea here is to provide an interface that allows the programmer to
obtain the sequence of messages in the request and reply from a CORBA method
invocation. The model I have designed for this is fairly simple and easy to
use. First, we define a new interface called a MessageTraceManager: </P>
<PRE>
public interface MessageTraceManager {
/** Returns true if messages are to be captured on this thread, otherwise
* false.
*/
boolean isEnabled() ;
/** Called with flag=true to enable capture of messages
*/
void enable( boolean flag ) ;
/** Return an array of messages (represented as byte[]) for the
* message(s) sent for the request in the last invocation. In the
* event of a location forward, this is the sequence for the last
* invocation.
*/
byte[][] getRequestData() ;
/** Return an array of messages (represented as byte[]) for the
* message(s) received for the last invocation. In the event of
* a location forward, this is the sequence received from the last
* invocation.
*/
byte[][] getResponseData() ;
}
</PRE>
<P> This interface allows access to the messages sent and received in the
last request. To obtain an instance of MessageTraceManager, we add the
following API to the ORB SPI: </P>
<PRE>
/** Return a MessageTraceManager for the current thread. Each thread that
* calls this method gets its own MessageTraceManager.
*/
MessageTraceManager getMessageTraceManager()
</PRE>
<P> This API allows message data to be collected from any synchronous CORBA
invocation. This include RMI-IIOP, IDL, and DII (but not deferred synchronous
invocations). A test could also simulate a stub invocation if desired. </P>
<H2>ORB Code Notes</H2>
<P> Start with receipt of read event on a connection: </P>
<OL>
<LI> SocketOrChannelAcceptorImpl.createMessageMediator( Broker,
Connection )
<OL>
<LI>CorbaContactInfoBase.createMessageMediator( Broker, Connection )
line 130 </LI>
<LI>MessageBase.readGIOPMessage( orb, connection )
<OL>
<LI>reads 12 byte GIOP header buf = connection.read( 12, 0, 12 )
; </LI>
<LI>constructs appropriate Message type </LI>
<LI>read size data for message buf = connection.read( buf, 12,
size-12 ) ; </LI>
<LI>msg.setByteBuffer( buf ) ; </LI>
</OL></LI>
<LI>byteBuffer = msg.getByteBuffer() ; </LI>
<LI>msg.setByteBuffer( null ) ; </LI>
<LI>messageMediator = new CorbaMessageMediatorImpl( orb, connection,
msg, byteBuffer ) </LI>
</OL></LI>
<LI>After creating the message mediator, we end up going through the
double dispatch and end up in CorbaMessageMediatorImpl.handleInput(
RequestMessage_1_2 ). This calls:
<OL>
<LI>header.unmarshalRequestID </LI>
<LI>setInputObject (line 872), which calls
CorbaContactInfoBase.setInputObject(), which creates the CDRInputObject. </LI>
<LI>handleRequest(RequestMessage_1_2, CorbaMessageMediator </LI>
<LI>beginRequest(messageMediator) </LI>
<LI>handleRequestRequest(messageMediator)
<OL>
<LI>This calls unmarshalHeader, then finally does the dispatch.
</LI>
</OL></LI>
</OL></LI>
</OL>
<P>Note that we generally always need to call unmarshalRequestID before we
can do much else, since the transport does not know where to put anything
without knowing the request ID (it's obvious from the code that one of GIOP's
minor blunders is not putting the request ID in the GIOP message header, since
it is so frequently needed). Here is a sketch of the code for getMessageData(
byte[][] data ): </P>
<PRE>
public MessageData getMessageData( byte[][] data )
{
connection = new BufferedConnectionImpl() ;
for (int ctr=0; ctr<data.length; ctr++)
// write data[ctr] to connection
final Message[] messages = new Message[data.length] ;
int requestID = 0 ;
Message firstMessage = null ;
Message msg = null ;
CDRInputObject inobj = null ;
BufferManagerRead buffman = null ;
for (int ctr=0; ctr<data.length; ctr++) {
msg = MessageBase.readGIOPMessage( orb, connectionCopy ) ;
messages[ctr] = msg ;
msg.unmarshalRequestID() ; // Do we always do this?
// Check that moreFragments == (ctr < data.length)
if (ctr==0) {
// Check that we have a request or reply
requestID = msg.getRequestID() ;
firstMessage = msg ;
requestID = msg.getRequestID() ;
inobj = new CDRInputObject( orb, connection,
msg.getByteBuffer(), msg ) ;
buffman = inobj.getBufferManager() ;
} else {
// Check that the request ID is as expected
buffman.processFragment( msg, msg.getByteBuffer() ) ;
}
}
// Unmarshal all the data in the first message. This may
// cause other fragments to be read.
firstMessage.unmarshalHeader( stream ) ;
final CDRInputObject resultObj = inobj ;
return new MessageData() {
Message[] getMessages() { return messages ; }
CDRInputStream getInputStream() { return resultObj ; }
} ;
}
</PRE>
</BODY>
</HTML>