@@ -32,6 +32,7 @@ const process = require('process');
3232const readline = require ( 'readline' ) ;
3333const errors = require ( "../../errors.js" ) ;
3434
35+ const MAX_IFILE_DEPTH = 4 ;
3536/**
3637 * Returns File path of the tnsnames.ora if it exists.
3738 */
@@ -59,23 +60,42 @@ function tnsnamesFilePath(configDir) {
5960 }
6061}
6162
62- let prevmtime = 0 ;
63-
6463class NLParamParser {
64+
65+ constructor ( ) {
66+ this . waiters = [ ] ;
67+ this . readInProgress = false ;
68+ }
6569 /**
6670 * Reads the given file line by line and stores the
6771 * network service names mapped to connect descriptors in the hashtable.
6872 * @param {string } file_path
6973 * @returns {Promise }
7074 */
7175 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 */
7683 return this . ht ;
7784 }
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 ) {
7893
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 ) ;
7999 // Creating a readable stream from file
80100 // readline module reads line by line
81101 // but from a readable stream only.
@@ -84,52 +104,49 @@ class NLParamParser {
84104 output : process . stdout ,
85105 terminal : false
86106 } ) ;
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 )
95120 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+ }
107124
108- } else { // new NV Element starting here
109- if ( nvElem . length == 0 ) {
125+ } else { // new NV Element starting here
126+ if ( nvElem . length == 0 ) {
110127
111- line = this . checkNLPforComments ( line ) ;
112- nvElem = nvElem + line ;
128+ line = this . checkNLPforComments ( line ) ;
129+ nvElem = nvElem + line ;
113130
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
117134
118- line = this . checkNLPforComments ( line ) ;
119- nvElem = nvElem + line ;
120- }
135+ line = this . checkNLPforComments ( line ) ;
136+ nvElem = nvElem + line ;
121137 }
122138 }
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+ }
131149 }
132-
133150 /**
134151 * Given a string, this method looks if the '#' character is present.
135152 * If true, the line is truncated from that point onwards until the end
@@ -155,11 +172,28 @@ class NLParamParser {
155172 }
156173 return str1 . join ( '' ) ;
157174 }
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+ }
158192 /**
159193 * adds name value pairs from the input buffer into the hash table.
160194 * @param {string } ibuf
161195 */
162- addNLPListElement ( ibuf ) {
196+ async addNLPListElement ( ibuf , depth ) {
163197 const res = ibuf . split ( / \r ? \n / ) . filter ( element => element ) ;
164198 for ( let i = 0 ; i < res . length ; i ++ ) {
165199 if ( res [ i ] . charAt ( 0 ) != '(' ) {
@@ -169,14 +203,17 @@ class NLParamParser {
169203 const name = nvp . name ;
170204 const uname = name . toUpperCase ( ) ;
171205 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+ }
175214 }
176215 }
177216 }
178-
179-
180217 toString ( ) {
181218 let out = "" ;
182219 this . ht . forEach ( ( value ) => {
0 commit comments