Skip to content

Commit f1fa258

Browse files
authored
Merge pull request #629 from aguibert/db2-connect-flow-optimization
Reduce initial handshake from 2 server round-trips to 1 round-trip
2 parents 74caf09 + cc47995 commit f1fa258

File tree

2 files changed

+39
-59
lines changed

2 files changed

+39
-59
lines changed

vertx-db2-client/src/main/java/io/vertx/db2client/impl/codec/InitialHandshakeCommandCodec.java

Lines changed: 39 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,9 @@
3030

3131
class InitialHandshakeCommandCodec extends AuthenticationCommandBaseCodec<Connection, InitialHandshakeCommand> {
3232

33-
private static final int ST_CONNECTING = 0;
34-
private static final int ST_AUTHENTICATING = 1;
35-
private static final int ST_CONNECTED = 2;
36-
private static final int ST_CONNECT_FAILED = 3;
33+
private static enum ConnectionState {
34+
CONNECTING, AUTHENTICATING, CONNECTED, CONNECT_FAILED
35+
}
3736

3837
private static final int TARGET_SECURITY_MEASURE = DRDAConstants.SECMEC_USRIDPWD;
3938

@@ -42,7 +41,7 @@ class InitialHandshakeCommandCodec extends AuthenticationCommandBaseCodec<Connec
4241
// It is saved like the prddta in case it is needed for a connect reflow.
4342
private byte[] correlationToken;
4443

45-
private int status = ST_CONNECTING;
44+
private ConnectionState status = ConnectionState.CONNECTING;
4645

4746
InitialHandshakeCommandCodec(InitialHandshakeCommand cmd) {
4847
super(cmd);
@@ -53,66 +52,20 @@ void encode(DB2Encoder encoder) {
5352
super.encode(encoder);
5453
encoder.connMetadata.databaseName = cmd.database();
5554
encoder.socketConnection.closeHandler(h -> {
56-
if (status == ST_CONNECTING) {
55+
if (status == ConnectionState.CONNECTING) {
5756
// Sometimes DB2 closes the connection when sending an invalid Database name.
5857
// -4499 = A fatal error occurred that resulted in a disconnect from the data
5958
// source.
6059
// 08001 = "The connection was unable to be established"
61-
cmd.fail(new DB2Exception("The connection was closed by the database server.",
62-
SqlCode.CONNECTION_REFUSED,
60+
cmd.fail(new DB2Exception("The connection was closed by the database server.", SqlCode.CONNECTION_REFUSED,
6361
SQLState.AUTH_DATABASE_CONNECTION_REFUSED));
6462
}
6563
});
66-
sendInitialHandshake();
67-
}
68-
69-
@Override
70-
void decodePayload(ByteBuf payload, int payloadLength) {
71-
DRDAConnectResponse response = new DRDAConnectResponse(payload, encoder.connMetadata);
72-
switch (status) {
73-
case ST_CONNECTING:
74-
response.readExchangeServerAttributes();
75-
// readAccessSecurity can throw a DB2Exception if there are problems connecting.
76-
// In that case, we want to catch that exception and
77-
// make sure to set the status to something other than ST_CONNECTING so we don't
78-
// try to complete the result twice (when we hit encode)
79-
try {
80-
response.readAccessSecurity(TARGET_SECURITY_MEASURE);
81-
} catch (DB2Exception de) {
82-
status = ST_CONNECT_FAILED;
83-
throw de;
84-
}
85-
status = ST_AUTHENTICATING;
86-
ByteBuf packet = allocateBuffer();
87-
int packetStartIdx = packet.writerIndex();
88-
DRDAConnectRequest securityCheck = new DRDAConnectRequest(packet, encoder.connMetadata);
89-
correlationToken = securityCheck.getCorrelationToken(encoder.socketConnection.socket().localAddress().port());
90-
securityCheck.buildSECCHK(TARGET_SECURITY_MEASURE, cmd.database(), cmd.username(), cmd.password(), null, // sectkn,
91-
null); // sectkn2
92-
securityCheck.buildACCRDB(cmd.database(), false, // readOnly,
93-
correlationToken, DRDAConstants.SYSTEM_ASC);
94-
securityCheck.completeCommand();
95-
int lenOfPayload = packet.writerIndex() - packetStartIdx;
96-
sendPacket(packet, lenOfPayload);
97-
return;
98-
case ST_AUTHENTICATING:
99-
response.readSecurityCheck();
100-
RDBAccessData accData = response.readAccessDatabase();
101-
if (accData.correlationToken != null)
102-
correlationToken = accData.correlationToken;
103-
status = ST_CONNECTED;
104-
completionHandler.handle(CommandResponse.success(cmd.connection()));
105-
return;
106-
default:
107-
throw new IllegalStateException("Unknown state: " + status);
108-
}
109-
}
11064

111-
private void sendInitialHandshake() {
11265
ByteBuf packet = allocateBuffer();
11366
int packetStartIdx = packet.writerIndex();
114-
DRDAConnectRequest cmd = new DRDAConnectRequest(packet, encoder.connMetadata);
115-
cmd.buildEXCSAT(DRDAConstants.EXTNAM, // externalName,
67+
DRDAConnectRequest connectRequest = new DRDAConnectRequest(packet, encoder.connMetadata);
68+
connectRequest.buildEXCSAT(DRDAConstants.EXTNAM, // externalName,
11669
0x0A, // targetAgent,
11770
DRDAConstants.TARGET_SQL_AM, // targetSqlam,
11871
0x0C, // targetRdb,
@@ -124,11 +77,40 @@ private void sendInitialHandshake() {
12477
0, // targetRsyncmgr,
12578
CCSIDConstants.TARGET_UNICODE_MGR // targetUnicodemgr
12679
);
127-
cmd.buildACCSEC(TARGET_SECURITY_MEASURE, this.cmd.database(), null);
128-
cmd.completeCommand();
80+
connectRequest.buildACCSEC(TARGET_SECURITY_MEASURE, this.cmd.database(), null);
81+
correlationToken = connectRequest.getCorrelationToken(encoder.socketConnection.socket().localAddress().port());
82+
connectRequest.buildSECCHK(TARGET_SECURITY_MEASURE, cmd.database(), cmd.username(), cmd.password(), null, // sectkn,
83+
null); // sectkn2
84+
connectRequest.buildACCRDB(cmd.database(), false, // readOnly,
85+
correlationToken, DRDAConstants.SYSTEM_ASC);
86+
connectRequest.completeCommand();
12987

13088
int lenOfPayload = packet.writerIndex() - packetStartIdx;
13189
sendPacket(packet, lenOfPayload);
13290
}
13391

92+
@Override
93+
void decodePayload(ByteBuf payload, int payloadLength) {
94+
DRDAConnectResponse response = new DRDAConnectResponse(payload, encoder.connMetadata);
95+
response.readExchangeServerAttributes();
96+
// readAccessSecurity can throw a DB2Exception if there are problems connecting.
97+
// In that case, we want to catch that exception and
98+
// make sure to set the status to something other than ST_CONNECTING so we don't
99+
// try to complete the result twice (when we hit encode)
100+
try {
101+
response.readAccessSecurity(TARGET_SECURITY_MEASURE);
102+
} catch (DB2Exception de) {
103+
status = ConnectionState.CONNECT_FAILED;
104+
throw de;
105+
}
106+
status = ConnectionState.AUTHENTICATING;
107+
response.readSecurityCheck();
108+
RDBAccessData accData = response.readAccessDatabase();
109+
if (accData.correlationToken != null) {
110+
correlationToken = accData.correlationToken;
111+
}
112+
status = ConnectionState.CONNECTED;
113+
completionHandler.handle(CommandResponse.success(cmd.connection()));
114+
}
115+
134116
}

vertx-db2-client/src/main/java/io/vertx/db2client/impl/drda/DB2Package.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,6 @@ public DB2Package(boolean isSmallPackage, int pkgNum) {
6363
String pkgNumStr = pkgNum < 16 ? "0" + Integer.toHexString(pkgNum) : Integer.toHexString(pkgNum);
6464
name = "SYS" + config + pkgNumStr;
6565
cursorNamePrefix = "SQL_CUR" + config + pkgNumStr + 'C';
66-
if (LOG.isLoggable(Level.FINE))
67-
LOG.fine("<init> " + this);
6866
}
6967

7068
boolean isSmallPackage() {

0 commit comments

Comments
 (0)