@@ -32,6 +32,7 @@ const process = require('process');
32
32
const readline = require ( 'readline' ) ;
33
33
const errors = require ( "../../errors.js" ) ;
34
34
35
+ const MAX_IFILE_DEPTH = 4 ;
35
36
/**
36
37
* Returns File path of the tnsnames.ora if it exists.
37
38
*/
@@ -59,23 +60,42 @@ function tnsnamesFilePath(configDir) {
59
60
}
60
61
}
61
62
62
- let prevmtime = 0 ;
63
-
64
63
class NLParamParser {
64
+
65
+ constructor ( ) {
66
+ this . waiters = [ ] ;
67
+ this . readInProgress = false ;
68
+ }
65
69
/**
66
70
* Reads the given file line by line and stores the
67
71
* network service names mapped to connect descriptors in the hashtable.
68
72
* @param {string } file_path
69
73
* @returns {Promise }
70
74
*/
71
75
async initializeNlpa ( file_path ) {
72
- const stat = fs . statSync ( file_path ) ;
73
-
74
- if ( ! ( stat . mtime - prevmtime ) ) {
75
- /* File has been read */
76
+ if ( this . readInProgress ) {
77
+ await new Promise ( ( resolve ) => {
78
+ this . waiters . push ( resolve ) ;
79
+ } ) ;
80
+ }
81
+ if ( ! this . checkModfTime ( ) ) {
82
+ /* No File has been modified */
76
83
return this . ht ;
77
84
}
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 ;
90
+ }
91
+
92
+ async start ( file_path , depth ) {
78
93
94
+ if ( depth > MAX_IFILE_DEPTH )
95
+ return ; //ignore after max depth
96
+ const stat = fs . statSync ( file_path ) ;
97
+ // store file path and its modified time.
98
+ this . modTime . set ( file_path , stat . mtime ) ;
79
99
// Creating a readable stream from file
80
100
// readline module reads line by line
81
101
// but from a readable stream only.
@@ -84,52 +104,49 @@ class NLParamParser {
84
104
output : process . stdout ,
85
105
terminal : false
86
106
} ) ;
87
- this . ht = new Map ( ) ;
88
-
89
- const start = async ( ) => {
90
- let nvElem = "" ;
91
- for await ( let line of file ) {
92
- if ( line . length == 0 ) { // ignore empty lines
93
- continue ;
94
- } else if ( line [ 0 ] == '#' ) { // comment line
107
+ let nvElem = "" ;
108
+ for await ( let line of file ) {
109
+ if ( line . length == 0 ) { // ignore empty lines
110
+ continue ;
111
+ } else if ( line [ 0 ] == '#' ) { // comment line
112
+ continue ;
113
+ } else if ( ( line [ 0 ] == ' ' ) || // continued input on new line
114
+ ( line [ 0 ] == '\t' ) ||
115
+ ( line [ 0 ] == ')' ) ||
116
+ ( line [ 0 ] == '(' ) ) {
117
+ line = line . replace ( / \s + / g, '' ) ;
118
+ line = this . checkNLPforComments ( line ) ;
119
+ if ( line . length == 0 )
95
120
continue ;
96
- } else if ( ( line [ 0 ] == ' ' ) || // continued input on new line
97
- ( line [ 0 ] == '\t' ) ||
98
- ( line [ 0 ] == ')' ) ||
99
- ( line [ 0 ] == '(' ) ) {
100
- line = line . replace ( / \s + / g, '' ) ;
101
- line = this . checkNLPforComments ( line ) ;
102
- if ( line . length == 0 )
103
- continue ;
104
- else {
105
- nvElem = nvElem + line ;
106
- }
121
+ else {
122
+ nvElem = nvElem + line ;
123
+ }
107
124
108
- } else { // new NV Element starting here
109
- if ( nvElem . length == 0 ) {
125
+ } else { // new NV Element starting here
126
+ if ( nvElem . length == 0 ) {
110
127
111
- line = this . checkNLPforComments ( line ) ;
112
- nvElem = nvElem + line ;
128
+ line = this . checkNLPforComments ( line ) ;
129
+ nvElem = nvElem + line ;
113
130
114
- } else if ( nvElem . length != 0 ) {
115
- this . addNLPListElement ( nvElem ) ; // Add Parameter to Hashtable
116
- nvElem = "" ; // Clear first, before storing current line
131
+ } else if ( nvElem . length != 0 ) {
132
+ await this . addNLPListElement ( nvElem , depth ) ; // Add Parameter to Hashtable
133
+ nvElem = "" ; // Clear first, before storing current line
117
134
118
- line = this . checkNLPforComments ( line ) ;
119
- nvElem = nvElem + line ;
120
- }
135
+ line = this . checkNLPforComments ( line ) ;
136
+ nvElem = nvElem + line ;
121
137
}
122
138
}
123
- if ( nvElem . length != 0 ) { // at eof, still one more parameter to read
124
- this . addNLPListElement ( nvElem ) ;
125
- nvElem = "" ; // clear nvElem buffer after added
126
- }
127
- prevmtime = stat . mtime ;
128
- return this . ht ;
129
- } ;
130
- return await start ( ) ;
139
+ }
140
+ if ( nvElem . length != 0 ) { // at eof, still one more parameter to read
141
+ await this . addNLPListElement ( nvElem , depth ) ;
142
+ nvElem = "" ; // clear nvElem buffer after added
143
+ }
144
+ this . readInProgress = false ;
145
+ let waiter ;
146
+ while ( ( waiter = this . waiters . pop ( ) ) ) {
147
+ waiter ( ) ;
148
+ }
131
149
}
132
-
133
150
/**
134
151
* Given a string, this method looks if the '#' character is present.
135
152
* If true, the line is truncated from that point onwards until the end
@@ -155,11 +172,28 @@ class NLParamParser {
155
172
}
156
173
return str1 . join ( '' ) ;
157
174
}
175
+ // check if any of the IFiles has been changed
176
+ checkModfTime ( ) {
177
+ if ( this . modTime ) {
178
+ for ( const [ key , value ] of this . modTime ) {
179
+ if ( fs . existsSync ( key ) ) {
180
+ const stat = fs . statSync ( key ) ;
181
+ if ( ( stat . mtime - value > 0 ) ) {
182
+ return true ;
183
+ }
184
+ } else
185
+ return true ;
186
+ }
187
+ } else {
188
+ return true ;
189
+ }
190
+ return false ;
191
+ }
158
192
/**
159
193
* adds name value pairs from the input buffer into the hash table.
160
194
* @param {string } ibuf
161
195
*/
162
- addNLPListElement ( ibuf ) {
196
+ async addNLPListElement ( ibuf , depth ) {
163
197
const res = ibuf . split ( / \r ? \n / ) . filter ( element => element ) ;
164
198
for ( let i = 0 ; i < res . length ; i ++ ) {
165
199
if ( res [ i ] . charAt ( 0 ) != '(' ) {
@@ -169,14 +203,17 @@ class NLParamParser {
169
203
const name = nvp . name ;
170
204
const uname = name . toUpperCase ( ) ;
171
205
nvp . name = uname ;
172
- const unames = uname . split ( "," ) ; //multiple aliases (alias1, alias2, alias3)
173
- for ( let i = 0 ; i < unames . length ; i ++ ) {
174
- this . ht . set ( unames [ i ] , nvp ) ;
206
+ // support for ifile
207
+ if ( uname == 'IFILE' ) {
208
+ await this . start ( nvp . atom , depth + 1 ) ;
209
+ } else {
210
+ const unames = uname . split ( "," ) ; //multiple aliases (alias1, alias2, alias3)
211
+ for ( let i = 0 ; i < unames . length ; i ++ ) {
212
+ this . ht . set ( unames [ i ] , nvp ) ;
213
+ }
175
214
}
176
215
}
177
216
}
178
-
179
-
180
217
toString ( ) {
181
218
let out = "" ;
182
219
this . ht . forEach ( ( value ) => {
0 commit comments