Skip to content

Commit 711f44f

Browse files
committed
Incorporate changes to use end of data request flag set with data packets available in Oracle Database 23ai to improve handling the async reads.
1 parent 9d8ebdc commit 711f44f

File tree

12 files changed

+59
-17
lines changed

12 files changed

+59
-17
lines changed

doc/src/release_notes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ node-oracledb `v6.5.0 <https://github.com/oracle/node-oracledb/compare/v6.4.0...
1313
Common Changes
1414
++++++++++++++
1515

16+
#) Incorporate changes to use end of data request flag set with data packets
17+
available in Oracle database 23c to improve handling the async reads.
18+
1619
#) Added class :ref:`oracledb.JsonId <jsonid>` to represent JSON ID values
1720
returned by SODA in Oracle Database 23.4 and higher in the ``_id``
1821
attribute of documents stored in native collections.

lib/thin/protocol/capabilities.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ class Capabilities {
5555
this.compileCaps[constants.TNS_CCAP_FIELD_VERSION] =
5656
this.ttcFieldVersion;
5757
}
58+
if (this.ttcFieldVersion < constants.TNS_CCAP_FIELD_VERSION_23_4 ||
59+
!(serverCaps[constants.TNS_CCAP_TTC4] &
60+
constants.TNS_CCAP_END_OF_REQUEST)) {
61+
this.compileCaps[constants.TNS_CCAP_TTC4]
62+
^= constants.TNS_CCAP_END_OF_REQUEST;
63+
}
5864
}
5965

6066
adjustForServerRuntimeCaps(serverCaps) {
@@ -103,7 +109,8 @@ class Capabilities {
103109
this.compileCaps[constants.TNS_CCAP_CLIENT_FN] =
104110
constants.TNS_CCAP_CLIENT_FN_MAX;
105111
this.compileCaps[constants.TNS_CCAP_TTC4] =
106-
constants.TNS_CCAP_INBAND_NOTIFICATION;
112+
constants.TNS_CCAP_INBAND_NOTIFICATION |
113+
constants.TNS_CCAP_END_OF_REQUEST;
107114
this.compileCaps[constants.TNS_CCAP_CTB_FEATURE_BACKPORT] =
108115
constants.TNS_CCAP_CTB_IMPLICIT_POOL;
109116
this.compileCaps[constants.TNS_CCAP_TTC5] =

lib/thin/protocol/constants.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ module.exports = {
433433
TNS_MSG_TYPE_ONEWAY_FN: 26,
434434
TNS_MSG_TYPE_IMPLICIT_RESULTSET: 27,
435435
TNS_MSG_TYPE_RENEGOTIATE: 28,
436+
TNS_MSG_TYPE_END_OF_REQUEST: 29,
436437
TNS_MSG_TYPE_FAST_AUTH: 34,
437438

438439
// parameter keyword numbers,
@@ -627,6 +628,7 @@ module.exports = {
627628
TNS_CCAP_DRCP: 0x10,
628629
TNS_CCAP_ZLNP: 0x04,
629630
TNS_CCAP_INBAND_NOTIFICATION: 0x04,
631+
TNS_CCAP_END_OF_REQUEST: 0x20,
630632
TNS_CCAP_CLIENT_FN_MAX: 12,
631633
TNS_CCAP_LOB2_QUASI: 0x01,
632634
TNS_CCAP_LOB2_2GB_PREFETCH: 0x04,
@@ -742,6 +744,9 @@ module.exports = {
742744
NUMBER_AS_TEXT_CHARS: 172,
743745
CHUNKED_BYTES_CHUNK_SIZE: 65536,
744746

747+
// Network Header flags for Data packet
748+
TNS_DATA_FLAGS_END_OF_REQUEST: 0x2000,
749+
745750
TNS_BASE64_ALPHABET_ARRAY: Buffer.from('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'),
746751
TNS_EXTENT_OID: Buffer.from('00000000000000000000000000010001', 'hex')
747752
};

lib/thin/protocol/messages/base.js

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,9 @@ class Message {
4242
this.functionCode = 0;
4343
this.callStatus = 0;
4444
this.flushOutBinds = false;
45+
this.endOfResponse = false;
4546
this.endToEndSeqNum = 0;
4647
this.errorOccurred = false;
47-
this.flushOutBinds = false;
48-
this.processedError = false;
4948
this.warning = undefined;
5049
}
5150

@@ -161,7 +160,7 @@ class Message {
161160
*/
162161
this.errorInfo.message = this.errorInfo.message.trim();
163162
}
164-
this.processedError = true;
163+
this.endOfResponse = !this.connection.nscon.endOfRequestSupport;
165164
}
166165

167166
processReturnParameter() { }
@@ -178,22 +177,18 @@ class Message {
178177
}
179178
}
180179

181-
hasMoreData(buf) {
182-
return buf.numBytesLeft() > 0 && !this.flushOutBinds;
183-
}
184-
185180
decode(buf) {
186181
this.process(buf);
187182
}
188183

189184
process(buf) {
185+
this.endOfResponse = false;
190186
this.flushOutBinds = false;
191-
this.processedError = false;
192187
do {
193188
this.savePoint(buf);
194189
const messageType = buf.readUInt8();
195190
this.processMessage(buf, messageType);
196-
} while (this.hasMoreData(buf));
191+
} while (!this.endOfResponse);
197192
}
198193

199194
savePoint(buf) {
@@ -208,10 +203,13 @@ class Message {
208203
} else if (messageType === constants.TNS_MSG_TYPE_STATUS) {
209204
this.callStatus = buf.readUB4();
210205
this.endToEndSeqNum = buf.readUB2();
206+
this.endOfResponse = !this.connection.nscon.endOfRequestSupport;
211207
} else if (messageType === constants.TNS_MSG_TYPE_PARAMETER) {
212208
this.processReturnParameter(buf);
213209
} else if (messageType === constants.TNS_MSG_TYPE_SERVER_SIDE_PIGGYBACK) {
214210
this.processServerSidePiggyBack(buf);
211+
} else if (messageType === constants.TNS_MSG_TYPE_END_OF_REQUEST) {
212+
this.endOfResponse = true;
215213
} else {
216214
errors.throwErr(errors.ERR_UNEXPECTED_MESSAGE_TYPE, messageType, buf.pos, buf.packetNum);
217215
}

lib/thin/protocol/messages/dataType.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class DataTypeMessage extends Message {
4848
if (convDataType !== 0)
4949
buf.skipBytes(4);
5050
}
51+
this.endOfResponse = !this.connection.nscon.endOfRequestSupport;
5152
} else {
5253
super.processMessage(buf, messageType);
5354
}

lib/thin/protocol/messages/fastAuth.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class FastAuthMessage extends Message {
6969
this.dataTypeMessage.processMessage(buf, messageType);
7070
} else {
7171
this.authMessage.processMessage(buf, messageType);
72+
this.endOfResponse = this.authMessage.endOfResponse;
7273
}
7374
}
7475

lib/thin/protocol/messages/protocol.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class ProtocolMessage extends Message {
5353
processMessage(buf, messageType) {
5454
if (messageType === constants.TNS_MSG_TYPE_PROTOCOL) {
5555
this.processProtocolInfo(buf);
56+
this.endOfResponse = !this.connection.nscon.endOfRequestSupport;
5657
} else {
5758
super.processMessage(buf, messageType);
5859
}

lib/thin/protocol/messages/withData.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,17 +85,14 @@ class MessageWithData extends Message {
8585
this.processIOVector(buf);
8686
} else if (messageType === constants.TNS_MSG_TYPE_FLUSH_OUT_BINDS) {
8787
this.flushOutBinds = true;
88+
this.endOfResponse = true;
8889
} else if (messageType === constants.TNS_MSG_TYPE_ERROR) {
8990
this.processErrorInfo(buf);
9091
} else {
9192
super.processMessage(buf, messageType);
9293
}
9394
}
9495

95-
hasMoreData() {
96-
return !this.processedError && !this.flushOutBinds;
97-
}
98-
9996
processErrorInfo(buf) {
10097
super.processErrorInfo(buf);
10198
if (this.errorInfo.cursorId !== 0) {

lib/thin/protocol/packet.js

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const errors = require("../../errors.js");
3737
const TNS_BASE64_ALPHABET_ARRAY = Buffer.from("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", 'utf8');
3838
const FAST_AUTH_END_OF_RPC_VALUE = 0x800;
3939
const FAST_AUTH_END_OF_RPC_OFFSET = 0x8;
40+
const MSG_TYPE_OFFSET = 11;
4041

4142
/**
4243
* Class used for byte chunks used in the ChunkedBytesBuffer.
@@ -292,14 +293,38 @@ class ReadPacket extends BaseBuffer {
292293
this.packetNum = packet.num;
293294
}
294295

295-
async waitForPackets() {
296-
const packet = await this.nsi.recvPacket();
296+
/**
297+
* Read packets from network.
298+
* If checkRequestBoundary is passed as true, it
299+
* would read all packets until end of request
300+
* boundary is seen in nwk header.
301+
*/
302+
async waitForPackets(checkRequestBoundary = false) {
303+
let packet = await this.nsi.recvPacket();
297304
if (!this.savedPackets) {
298305
this.savedPackets = [packet];
299306
this.savedPacketPos = 0;
300307
} else {
301308
this.savedPackets.push(packet);
302309
}
310+
if (checkRequestBoundary && this.nsi.endOfRequestSupport) {
311+
while (packet.type === constants.TNS_PACKET_TYPE_DATA) {
312+
// End Marker
313+
if ((packet.buf.readUInt16BE(8) &
314+
constants.TNS_DATA_FLAGS_END_OF_REQUEST)) {
315+
break;
316+
}
317+
318+
// Single Byte 1D packet
319+
if (packet.buf.length === MSG_TYPE_OFFSET &&
320+
packet.buf[MSG_TYPE_OFFSET - 1] ===
321+
constants.TNS_MSG_TYPE_END_OF_REQUEST) {
322+
break;
323+
}
324+
packet = await this.nsi.recvPacket();
325+
this.savedPackets.push(packet);
326+
}
327+
}
303328
this.startPacket(this.savedPackets[this.savedPacketPos++]);
304329
}
305330

lib/thin/protocol/protocol.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class Protocol {
6767
*/
6868
async _decodeMessage(message) {
6969
message.preProcess();
70-
await this.readBuf.waitForPackets();
70+
await this.readBuf.waitForPackets(true);
7171
while (true) { // eslint-disable-line
7272
if (this.nsi.isBreak) {
7373
await this.resetMessage();

0 commit comments

Comments
 (0)