Skip to content

Commit fafeb65

Browse files
committed
Fixed an issue which stopped applications from connecting to Oracle Database with distinct TNS aliases from more than one tnsnames.ora file
1 parent e837557 commit fafeb65

File tree

2 files changed

+45
-43
lines changed

2 files changed

+45
-43
lines changed

doc/src/release_notes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ Common Changes
2323
Thin Mode Changes
2424
+++++++++++++++++
2525

26+
#) Fixed issue which stopped applications from connecting to Oracle Database
27+
with distinct TNS aliases from more than one tnsnames.ora file.
28+
2629
#) Fixed bug that fails to throw an error, when fetching data greater
2730
than the ``maxSize`` property of outbinds in Oracle Database 12.1.
2831

lib/thin/sqlnet/paramParser.js

Lines changed: 42 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2022, 2023, Oracle and/or its affiliates.
1+
// Copyright (c) 2022, 2024, Oracle and/or its affiliates.
22

33
//-----------------------------------------------------------------------------
44
//
@@ -26,7 +26,7 @@
2626

2727
'use strict';
2828

29-
const {createNVPair, findValue} = require("./nvStrToNvPair.js");
29+
const {createNVPair} = require("./nvStrToNvPair.js");
3030
const fs = require('fs');
3131
const process = require('process');
3232
const readline = require('readline');
@@ -59,12 +59,21 @@ function tnsnamesFilePath(configDir) {
5959
return filePathVal;
6060
}
6161
}
62+
//Structure for each tnsnames.ora file
63+
class tnsnamesElement {
6264

65+
constructor() {
66+
this.readInProgress = false;
67+
this.waiters = [];
68+
this.aliasht = new Map(); // It will have key as alias and value as its aliases value
69+
this.modTime = new Map(); // It will have tnsnames filename and also all its ifile and its modified time
70+
}
71+
}
6372
class NLParamParser {
6473

6574
constructor() {
66-
this.waiters = [];
67-
this.readInProgress = false;
75+
// key as tnsnames.ora(file_name) and value will be tnsnamesStruct<ht(alias key and value), modTime>
76+
this.tnsnamesHT = new Map();
6877
}
6978
/**
7079
* Reads the given file line by line and stores the
@@ -73,29 +82,35 @@ class NLParamParser {
7382
* @returns {Promise}
7483
*/
7584
async initializeNlpa(file_path) {
76-
if (this.readInProgress) {
85+
let tnsFileStruct;
86+
if (this.tnsnamesHT.has(file_path))
87+
tnsFileStruct = this.tnsnamesHT.get(file_path);
88+
else
89+
tnsFileStruct = new tnsnamesElement();
90+
if (tnsFileStruct.readInProgress) {
7791
await new Promise((resolve) => {
78-
this.waiters.push(resolve);
92+
tnsFileStruct.waiters.push(resolve);
7993
});
8094
}
81-
if (!this.checkModfTime()) {
95+
/* check modification time of all files in the cache
96+
including the file_path */
97+
if (!this.checkModfTime(tnsFileStruct)) {
8298
/* No File has been modified */
83-
return this.ht;
99+
return tnsFileStruct.aliasht;
84100
}
85-
this.ht = new Map();
86-
this.modTime = new Map(); //stores modified time of each IFile
87-
this.readInProgress = true;
88-
await this.start(file_path, 0); //start with 0 depth (tnsnames.ora)
89-
return this.ht;
101+
tnsFileStruct.readInProgress = true;
102+
await this.start(file_path, 0, tnsFileStruct); //start with 0 depth (tnsnames.ora)
103+
this.tnsnamesHT.set(file_path, tnsFileStruct);
104+
return tnsFileStruct.aliasht;
90105
}
91106

92-
async start(file_path, depth) {
107+
async start(file_path, depth, tnsFileStruct) {
93108

94109
if (depth > MAX_IFILE_DEPTH)
95110
return; //ignore after max depth
96111
const stat = fs.statSync(file_path);
97112
// store file path and its modified time.
98-
this.modTime.set(file_path, stat.mtime);
113+
tnsFileStruct.modTime.set(file_path, stat.mtime);
99114
// Creating a readable stream from file
100115
// readline module reads line by line
101116
// but from a readable stream only.
@@ -129,7 +144,7 @@ class NLParamParser {
129144
nvElem = nvElem + line;
130145

131146
} else if (nvElem.length != 0) {
132-
await this.addNLPListElement(nvElem, depth); // Add Parameter to Hashtable
147+
await this.addNLPListElement(nvElem, depth, tnsFileStruct); // Add Parameter to Hashtable
133148
nvElem = ""; // Clear first, before storing current line
134149

135150
line = this.checkNLPforComments(line);
@@ -138,12 +153,12 @@ class NLParamParser {
138153
}
139154
}
140155
if (nvElem.length != 0) { // at eof, still one more parameter to read
141-
await this.addNLPListElement(nvElem, depth);
156+
await this.addNLPListElement(nvElem, depth, tnsFileStruct);
142157
nvElem = ""; // clear nvElem buffer after added
143158
}
144-
this.readInProgress = false;
159+
tnsFileStruct.readInProgress = false;
145160
let waiter;
146-
while ((waiter = this.waiters.pop())) {
161+
while ((waiter = tnsFileStruct.waiters.pop())) {
147162
waiter();
148163
}
149164
}
@@ -173,9 +188,11 @@ class NLParamParser {
173188
return str1.join('');
174189
}
175190
// check if any of the IFiles has been changed
176-
checkModfTime() {
177-
if (this.modTime) {
178-
for (const [key, value] of this.modTime) {
191+
checkModfTime(tnsFileStruct) {
192+
// There may be multiple tnsnames.ora files. So check if the tnsnames.ora
193+
// in question is already cached
194+
if (tnsFileStruct.modTime.size != 0) {
195+
for (const [key, value] of tnsFileStruct.modTime) {
179196
if (fs.existsSync(key)) {
180197
const stat = fs.statSync(key);
181198
if ((stat.mtime - value > 0)) {
@@ -193,7 +210,7 @@ class NLParamParser {
193210
* adds name value pairs from the input buffer into the hash table.
194211
* @param {string} ibuf
195212
*/
196-
async addNLPListElement(ibuf, depth) {
213+
async addNLPListElement(ibuf, depth, tnsFileStruct) {
197214
const res = ibuf.split(/\r?\n/).filter(element => element);
198215
for (let i = 0; i < res.length; i++) {
199216
if (res[i].charAt(0) != '(') {
@@ -205,33 +222,15 @@ class NLParamParser {
205222
nvp.name = uname;
206223
// support for ifile
207224
if (uname == 'IFILE') {
208-
await this.start(nvp.atom, depth + 1);
225+
await this.start(nvp.atom, depth + 1, tnsFileStruct);
209226
} else {
210227
const unames = uname.split(","); //multiple aliases (alias1, alias2, alias3)
211228
for (let i = 0; i < unames.length; i++) {
212-
this.ht.set(unames[i], nvp);
229+
tnsFileStruct.aliasht.set(unames[i], nvp);
213230
}
214231
}
215232
}
216233
}
217-
toString() {
218-
let out = "";
219-
this.ht.forEach((value) => {
220-
out = out + value.toString() + "\n";
221-
});
222-
return out;
223-
}
224-
/**
225-
* if key is address/port then it returns the port value from the
226-
* address NVPAIR.
227-
* @param {string} key
228-
* @returns {string}
229-
*/
230-
findValueOf(key) {
231-
const myarr = key.split('/');
232-
return (findValue(this.ht.get(myarr[0].toUpperCase()), myarr));
233-
}
234-
235234
}
236235

237236
module.exports = {

0 commit comments

Comments
 (0)