blob: 671936606d60e3cc5d530c95fc6cde6ecc1ec06a [file] [log] [blame]
Taka Cho18510892019-05-14 17:37:24 -04001/*
2============LICENSE_START==========================================
3===================================================================
4Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
5===================================================================
6
7Unless otherwise specified, all software contained herein is licensed
8under the Apache License, Version 2.0 (the License);
9you may not use this software except in compliance with the License.
10You may obtain a copy of the License at
11
12 http://www.apache.org/licenses/LICENSE-2.0
13
14Unless required by applicable law or agreed to in writing, software
15distributed under the License is distributed on an "AS IS" BASIS,
16WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17See the License for the specific language governing permissions and
18limitations under the License.
19
20============LICENSE_END============================================ */
21//.. subnproc.js -to be started by parent server process
22const fs = require('fs');
23const Chproc = require('child_process');
24
25var clName= "subnproc";
26var thePid= 0;
27var taskId= '';
28//.. assuming all these files are in CDT_HOME
29var inpFilePfx= "posted_data_";
30var outFilePfx= "sync_template_res_"; //.. processing results
31var errFilePfx= "sync_template_err_"; //.. error found while processing
32var parmFilePfx= "template_params_";
33var pstatfNamePfx= "proc_status_";
34//.. pDlm -delimiter of params
35// (cant be: alphanumeric,underbar,dollar,dot,comma,brackets,dash,equal sign,etc)
36var pDlm= '\n';
37var logfname= clName+".log";
38 var logfname_o= logfname+".save"; //.. to keep old content
39var fdL;
40var fdIn;
41var fdOut;
42var errMsgBadParm= ''; //.. create error message to report to client
43//var checkSpecialCharsReg= new RegExp(/[^\w\s-]/);
44var checkSpecialCharsReg= new RegExp(/[^\w\s-\.]/);
45var doStopOnSpecChars= 'Y';
46var doCheckComments= 'Y';
47//var SYNC_T_KEY_EXPRES= '\\${.+?\\}';
48var VSTART= '${';
49var VEND= '}';
50var lenVS= VSTART.length, lenVE= VEND.length;
51var KEY_START= '${(';
52var KEY_MID= ')=(';
53var KEY_END= ')}';
54var LD= "\n"; //.. LD -line delimeter in the input file
55var lenLD= LD.length;
56var percAtRngs= 55; //.. percentage defining report to client
57
58var traceLvl= 1;
59//var CCnt= 52;
60var CCnt= 2;
61
62 var taskIdArgstr= process.argv[ 2 ];
63 var CDT_HOME= process.argv[ 3 ];
64 var LOG_DIR= process.argv[ 4 ];
65 this.thePid= process.pid;
66 console.log(clName+": Start: thePid="+this.thePid );
67 console.log(clName+": CDT_HOME:["+CDT_HOME+"]" );
68 console.log(clName+": LOG_DIR:["+LOG_DIR+"]" );
69
70try {
71 //.. need renameSync (not asynchronous) !
72 fs.renameSync( LOG_DIR+"/"+logfname, LOG_DIR+"/"+logfname_o);
73}
74catch( err ) {
75 console.log(clName+": log rename error: code="+ err.code );
76 console.log(clName+": log rename error.msg:["+err.message+"]");
77 //throw err;
78};
79fs.open( LOG_DIR+"/"+logfname, 'a', (err, fd) => {
80 if( err ) {
81 console.log(clName+": log file open error:"+err.message );
82 throw err;
83 }
84 this.fdL= fd;
85 console.log(clName+": log opened. fdL="+this.fdL);
86
87 this.logWr( clName+": Start: thePid="+this.thePid+"\n");
88
89 this.logWr( clName+
90 ": execArgv:["+process.execArgv+"]\n argv:["+process.argv+"]\n");
91 var indT= taskIdArgstr.indexOf('=', 0);
92 if( indT < 0 ) {
93 // this.logWr(clName+": Error: Failed to extract taskId from args:["+
94 // taskIdArgstr+"]\n");
95 // this.taskId= "000";
96 this.taskId= taskIdArgstr;
97 } else {
98 this.taskId= taskIdArgstr.substr( indT+1 );
99 }
100 this.logWr(clName+": taskId:["+this.taskId+"]\n");
101 if( this.taskId == null || this.taskId == undefined || this.taskId.length < 1 )
102 {
103 var errMsg= clName+": Error: taskId is empty !\n";
104 console.log( errMsg );
105 this.logWr( errMsg );
106 throw new Error( errMsg );
107 };
108 this.logWr(clName+": CDT_HOME:["+CDT_HOME+"]\n");
109
110 var timeStampI = Date.now();
111 this.logWr(clName+": timeStampI="+timeStampI+" \n");
112 var timeStamp = new Date( timeStampI ).toISOString();
113 this.logWr(clName+": timeStamp:["+timeStamp+"]\n");
114
115 //.. setup callback waiting for message from parent
116 // process.on('message', (msg) => {
117 // console.log('subnp: got message:', msg);
118 // });
119
120 //this.logWr("subnp: sending msg to parent.\n");
121 // var msg2parent = { taskid: taskId };
122 // this.logWr("subnp: msg2parent:["+JSON.stringify(msg2parent)+"]\n");
123 // process.send( msg2parent );
124
125 var inpFile= CDT_HOME+"/"+ inpFilePfx +this.taskId +".txt";
126 this.logWr(clName+": opening inpFile for reading:["+inpFile+"]\n");
127
128 fs.open( inpFile, 'r', (err, fd0) => {
129 if( err ) {
130 console.log(clName+": inpFile file open: Error: code="+err.code );
131 this.logWr(clName+": inpFile file open: Error: code="+err.code+"\n");
132 throw err;
133 }
134 this.fdIn= fd0;
135 console.log(clName+": Input file opened. fdIn="+this.fdIn);
136
137 fs.readFile( this.fdIn, (err, data) => {
138 if( err ) {
139 console.log(clName+": Failed to read inpFile: Error: code="+err.code );
140 this.logWr(clName+": Failed to read inpFile: Error: code="+err.code+"\n");
141 throw err;
142 }
143 this.processData( data );
144 //.. close log
145 console.log(clName+": close: fdL="+this.fdL );
146 fs.closeSync( this.fdL );
147 this.fdL= -1;
148 });
149 });
150});
151
152exports.processData = function ( data ) {
153 //.. processing data content from already opened input file
154 var methName= "processData";
155 this.logWr(methName+": start...\n");
156 var timeStamp = new Date().toISOString();
157 this.logWr( methName+": timeStamp:["+timeStamp+"]\n");
158 var fcontStr= new String( data );
159 let fcontLen= fcontStr.length;
160 this.logWr(methName+": fcontLen="+fcontLen+"\n");
161
162 this.logWr(methName+": trying to close inpFile: fdIn="+this.fdIn+"\n");
163 fs.closeSync( this.fdIn );
164 this.logWr(methName+": inpFile closed.\n");
165
166 var pstatfName= CDT_HOME+"/"+ pstatfNamePfx +this.taskId+".json";
167 var percent= 1;
168 var stmsg= '{\"percentage\":'+percent+'}';
169 this.updateProcStatus( pstatfName, stmsg );
170
171 timeStamp = new Date().toISOString();
172 this.logWr( methName+": timeStamp:["+timeStamp+"]\n");
173
174 var perrorfName= CDT_HOME+"/"+ errFilePfx+ this.taskId+".txt";
175 var formatErr= '';
176 var lineEnds= new Array( 0 ); //.. indexes of new-line chars
177 var selecRanges= new Array( 0 ); //.. indexes of ${variables}
178 var parmNamVals= new Map(); //.. parameter Name-Value pairs from inside ${...}
179 var ind0= 0;
180 var ind1= fcontStr.indexOf( LD,ind0 ); //.. line delimeter
181 var rn= 0, li= 0;
182 while( ind1 > -1 ) {
183 lineEnds.push( ind1 );
184 this.logWr(
185 methName+":--line #:"+li+" beg: ind0="+ind0+" end: ind1="+ind1+
186 " array:"+lineEnds[li]+"\n");
187 var line0= fcontStr.substring( ind0, ind1 ); //.. not including LD
188 var liLen= line0.length;
189 this.logWr( methName+": liLen="+liLen+"\n");
190 if( liLen > 60 ) {
191 this.logWr( methName+": line(p):["+line0.substr(0,60)+"]\n");
192 } else {
193 this.logWr( methName+": line:["+line0+"]\n");
194 }
195 //.. look for ${param variables}
196 rn= this.getRangesForVars( line0, li, rn, selecRanges );
197 if( rn < 0 ) {
198 this.logWr( methName+": got Error:\n["+errMsgBadParm+"]");
199 this.reportParamBadFmt( li, '', errMsgBadParm, perrorfName, pstatfName );
200 this.logWr( methName+": Stopping processing !\n");
201 return;
202 }
203 if( traceLvl > 1 )
204 this.logWr( methName+": added ranges at li="+li+": next rn="+rn+"\n");
205 ind0= ind1 +lenLD; //.. for next search of LD
206 if( ind0 >= fcontLen ) { break; };
207 li++;
208 ind1= fcontStr.indexOf( LD,ind0 ); //.. line delimeter
209 }; //.. loop
210 //.. process the last line
211 if( ind0 < fcontLen ) {
212 this.logWr( methName+": have the last line: ind0="+ind0+"\n");
213 lineEnds.push( fcontLen );
214 var line0= fcontStr.substring( ind0 ); //.. up to the end
215 var liLen= line0.length;
216 this.logWr( methName+": liLen="+liLen+"\n");
217 if( liLen > 60 ) {
218 this.logWr( methName+": line(p):["+line0.substr(0,60)+"]\n");
219 } else {
220 this.logWr( methName+": line:["+line0+"]\n");
221 }
222 //.. look for ${param variables}
223 rn= this.getRangesForVars( line0, li, rn, selecRanges );
224 if( rn < 0 ) {
225 this.logWr( methName+": got Error in getRangesForVars:\n["+
226 errMsgBadParm+"]");
227 this.reportParamBadFmt( li, '', errMsgBadParm, perrorfName, pstatfName );
228 this.logWr( methName+": Stopping processing !\n");
229 return;
230 }
231 };
232 this.logWr( methName+": -=- lineEnds array length="+lineEnds.length+"\n");
233 timeStamp = new Date().toISOString();
234 this.logWr( methName+": timeStamp:["+timeStamp+"]\n");
235
236 percent= percAtRngs;
237 stmsg= '{\"percentage\":'+percent+'}';
238 this.updateProcStatus( pstatfName, stmsg );
239
240 //.. Cycle through Ranges
241 this.logWr( methName+": selecRanges array length="+selecRanges.length+"\n");
242 if( doCheckComments ) {
243 this.logWr( methName+": doCheckComments is True.\n");
244 } else {
245 this.logWr( methName+": doCheckComments is False\n");
246 };
247 var rnAtUpd= Math.floor( selecRanges.length/ 3.);
248 var percStep= (100.0 - percAtRngs);
249 this.logWr( methName+": range number for proc.status update="+rnAtUpd+
250 "\n percentage step="+percStep );
251 var outLinBuf= new Array( 0 ); //.. array of output lines
252 var outLnLast=-1; //.. last processed
253 var rngLnLast=-1;
254 for( var rn0=0; rn0 < selecRanges.length; rn0++ ) {
255 var rng= selecRanges[rn0];
256 this.logWr( methName+":--- range #:"+rn0+" lineNm="+rng.lineNm+
257 " colBg="+rng.colBg+" colEn="+rng.colEn+"\n");
258 this.logWr( methName+": outLnLast="+outLnLast+"\n");
259 if( rn0 > 0 && (rn0 % rnAtUpd) == 0 && rn0 < selecRanges.length -rnAtUpd )
260 {
261 percent= Math.floor( percAtRngs + percStep *(rn0/selecRanges.length) );
262 this.logWr( methName+": need to update proc.status: percent="+percent+"\n");
263 stmsg= '{\"percentage\":'+percent+'}';
264 this.updateProcStatus( pstatfName, stmsg );
265 };
266 rngLnLast= rng.lineNm;
267 //.. prepare previous lines with no ranges
268 if( rng.lineNm - outLnLast > 1 ) {
269 this.logWr( methName+": prepare previous lines...\n");
270 var plinNm0= outLnLast +1;
271 var plinesIndB= 0;
272 if( plinNm0 > 0 ) { plinesIndB= lineEnds[outLnLast] + lenLD; };
273 var plinesIndE= lineEnds[rng.lineNm -1] + lenLD;
274 this.logWr( methName+": plinesIndB="+plinesIndB+
275 " plinesIndE="+plinesIndE+"\n");
276 var plinStr= fcontStr.substring( plinesIndB, plinesIndE );
277 if( traceLvl > 1 ) {
278 if( plinStr.length > 60 ) {
279 this.logWr( methName+": plinStr(p):["+plinStr.substr(0, 60)+"]\n");
280 } else {
281 this.logWr( methName+": plinStr:["+plinStr+"]\n");
282 }
283 };
284 outLinBuf.push( plinStr );
285 outLnLast= rng.lineNm -1;
286 };
287 var linIndB= 0;
288 var linIndE= lineEnds[rng.lineNm];
289 if( rng.lineNm > 0 ) { linIndB= lineEnds[rng.lineNm - 1] + lenLD; };
290 var linLen= linIndE - linIndB;
291 var line0= fcontStr.substr( linIndB, linLen );
292 this.logWr( methName+": linIndB="+linIndB+" linIndE="+linIndE+
293 " line length="+linLen+"\n");
294 if( traceLvl > 1 ) {
295 if( linLen > 60 ) {
296 this.logWr( methName+": line0(p):\n["+line0.substr(0,60)+"]\n");
297 } else {
298 this.logWr( methName+": line0:\n["+line0+"]\n");
299 }
300 };
301 //.. content between ${ and }
302 var vword= line0.substring( rng.colBg+lenVS, rng.colEn+1-lenVE );
303 this.logWr( methName+": vword:["+vword+"]\n");
304 //.. try to check for (pvalue)=(pname)
305 let specialKeys= null;
306 var parmNamAndVal= Array( 0 );
307 var pName= null;
308 var pValue= null;
309 formatErr= this.parseParmValAndName( vword, parmNamAndVal )
310 if( formatErr ) {
311 this.reportParamBadFmt(
312 rng.lineNm, vword, formatErr, perrorfName, pstatfName );
313 this.logWr( methName+": Stopping processing !\n");
314 return;
315 }
316 //.. No errors - parsing done OK
317 pName= parmNamAndVal[0]; //.. to be added to parmNamVals
318 pValue= parmNamAndVal[1];
319 this.logWr( methName+": parsing done: param.name:["+
320 pName+"] value:["+pValue+"]\n");
321
322 if( pName != null && pName.length > 0 ) {
323 this.logWr( methName+": check spec.chars in Non empty pName.\n");
324 specialKeys= checkSpecialCharsReg.exec( pName );
325 if( specialKeys == null ) {
326 this.logWr( methName+": specialKeys obj is null\n");
327 }
328 else
329 if( specialKeys.length > 0 ) {
330 this.logWr( methName+": specialKeys obj Not null:["+specialKeys+
331 "] length="+specialKeys.length+"\n");
332 if( doStopOnSpecChars ) {
333 formatErr=
334 "The parameter name("+pName+") contains prohibited character(s):("+
335 specialKeys+") !";
336 this.logWr( methName+": formatErr:["+formatErr+"]\n");
337 this.reportParamBadFmt(
338 rng.lineNm, vword, formatErr, perrorfName, pstatfName );
339 this.logWr( methName+": Stopping processing !\n");
340 return;
341 };
342 };
343 };
344 var haveComment= '';
345 if( doCheckComments ) {
346 this.logWr( methName+": doCheckComments is True.\n");
347 if( line0.trim().startsWith("//") ) haveComment= 'Y';
348 };
349 if( haveComment ) {
350 this.logWr( methName+": haveComment is True !\n");
351 };
352 //.. prepare parameter name and value
353 if( pName != null && pName.length > 0 && !specialKeys && !haveComment )
354 {
355 this.logWr( methName+": checking non-empty param.name:["+pName+"]\n");
356 if( parmNamVals.has(pName) ) {
357 this.logWr( methName+": the param. is already accounted.\n");
358 } else {
359 this.logWr( methName+": adding new param. with value:["+pValue+"]\n");
360 parmNamVals.set( pName, pValue );
361 };
362 };
363 //.. prepare for template output
364 var colB= 0;
365 if( rn0 > 0 ) {
366 var rngP= selecRanges[rn0 - 1];
367 if( rngP.lineNm == rng.lineNm ) { colB= rngP.colEn+lenVE; };
368 };
369 var colE= rng.colEn;
370 //.. check range content for replacement
371 let checkApplForNamOn=
372 this.checkAppliedForNamesOnly( line0, rng.colBg, rng.colEn );
373 this.logWr( methName+": checkApplForNamOn:["+checkApplForNamOn+"]\n");
374 if( checkApplForNamOn && !specialKeys && !haveComment )
375 {
376 this.logWr( methName+": Need Name Replacement... \n");
377 var replacWrd= KEY_START +KEY_MID +vword +KEY_END; // ${()=(...)}
378 this.logWr( methName+": replacWrd:["+replacWrd+"]\n");
379 var colM= rng.colBg; //.. not including beginning of VSTART
380 var brngStr= line0.substring( colB, colM );
381 this.logWr( methName+": part before word:["+brngStr+"]\n");
382 outLinBuf.push( brngStr + replacWrd );
383 }
384 else {
385 this.logWr( methName+": No Replacement for this range !\n");
386 var rsubs= line0.substring( colB, colE+lenVE );
387 this.logWr( methName+": rsubs:["+rsubs+"]\n");
388 outLinBuf.push( rsubs );
389 };
390 outLnLast= rng.lineNm;
391 //.. check tail of the line
392 if( rn0 == selecRanges.length - 1 ) {
393 var tailStr= line0.substring(colE+lenVE) + LD;
394 this.logWr( methName+": last range: adding line tail:\n["+tailStr+"]\n");
395 outLinBuf.push( tailStr );
396 }
397 else { //.. not the last range
398 var rngN= selecRanges[rn0 + 1];
399 if( rngN.lineNm == rng.lineNm ) {
400 //.. next range on the same line - no tail yet
401 }
402 else { //.. next range on different line
403 var tailStr= line0.substring(colE+lenVE) + LD;
404 this.logWr( methName+": adding line tail:\n["+tailStr+"]\n");
405 outLinBuf.push( tailStr );
406 };
407 };
408 }; //... loop
409 if( rngLnLast < lineEnds.length - 1) {
410 this.logWr( methName+": adding last lines having no ranges...\n");
411 var llinesIndB= 0;
412 if( rngLnLast > 0 ) { llinesIndB= lineEnds[rngLnLast] + lenLD; };
413 var llinesIndE= lineEnds[lineEnds.length -1] + lenLD;
414 this.logWr( methName+": llinesIndB="+llinesIndB+
415 " llinesIndE="+llinesIndE+"\n");
416 var llinStr= fcontStr.substring( llinesIndB, llinesIndE );
417 if( traceLvl > 1 ) {
418 if( llinStr.length > 60 ) {
419 this.logWr( methName+": llinStr(p):\n["+llinStr.substr(0,60)+"]\n");
420 } else {
421 this.logWr( methName+": llinStr:["+llinStr+"]\n");
422 }
423 }
424 outLinBuf.push( llinStr );
425 };
426 this.logWr( methName+": -=- outLinBuf: array length="+outLinBuf.length+"\n");
427 timeStamp = new Date().toISOString();
428 this.logWr( methName+": timeStamp:["+timeStamp+"]\n");
429
430 var outFile= CDT_HOME+"/"+ outFilePfx+ this.taskId+".txt";
431 var outFile_o= outFile+".save";
432 try {
433 fs.renameSync( outFile, outFile_o );
434 }
435 catch( err ) {
436 this.logWr(clName+": old output file rename: error:["+err.message+"]\n");
437 // throw err;
438 };
439 try {
440 this.fdOut= fs.openSync( outFile, 'a' );
441 }
442 catch( err ) {
443 this.logWr(clName+": output file open: error:["+err.message+"]\n");
444 throw err;
445 }
446 this.logWr(methName+": output file opened: fdOut="+this.fdOut+"\n");
447 for( let outLine of outLinBuf ) {
448 try {
449 fs.appendFileSync( this.fdOut, outLine, 'utf8' );
450 }
451 catch( err ) {
452 this.logWr(clName+": output file append: error: code="+err.code );
453 throw err;
454 }
455 }; //... loop
456 this.logWr(methName+": closing output file: fdOut="+this.fdOut+"\n");
457 fs.closeSync( this.fdOut );
458 this.logWr(methName+": output file closed.\n");
459 timeStamp = new Date().toISOString();
460 this.logWr( methName+": timeStamp:["+timeStamp+"]\n");
461
462 this.logWr( methName+": -=- parmNamVals (Parameters): map.size="+
463 parmNamVals.size+"\n");
464 var parmFile= CDT_HOME+"/"+ parmFilePfx+ this.taskId+".txt";
465 var parmFile_o= parmFile+".save";
466 try {
467 fs.renameSync( parmFile, parmFile_o );
468 }
469 catch( err ) {
470 this.logWr(clName+": old Params file rename: error:["+err.message+"]\n");
471 // throw err;
472 };
473 try {
474 this.fdParm= fs.openSync( parmFile, 'a' );
475 }
476 catch( err ) {
477 this.logWr(clName+": Params file open: error:["+err.message+"]\n");
478 throw err;
479 };
480 this.logWr(methName+": Params file opened: fdParm="+this.fdParm+"\n");
481 //.. writing parameters into parameter-output file
482 try {
483 // fs.appendFileSync( this.fdParm, "[\n", 'utf8' );
484 var iw= 0;
485 for( let pnm of parmNamVals.keys() ) {
486 let pv= parmNamVals.get( pnm );
487 let pnv= pnm+"="+pv;
488 this.logWr( methName+": iw="+iw+" param.Name-Value:["+pnv+"]\n");
489 //.. need delimiter after each item !
490 fs.appendFileSync( this.fdParm, pnv+pDlm, 'utf8' );
491 iw++;
492 }; //... loop
493 // fs.appendFileSync( this.fdParm, "]", 'utf8' );
494 }
495 catch( err ) {
496 this.logWr(clName+": Params file append: error: code="+err.code );
497 throw err;
498 }
499 this.logWr(methName+": closing Params file: fdParm="+this.fdParm+"\n");
500 fs.closeSync( this.fdParm );
501 this.logWr(methName+": Params file closed.\n");
502
503 timeStamp = new Date().toISOString();
504 this.logWr( methName+": timeStamp:["+timeStamp+"]\n");
505
506 percent= 100;
507 stmsg= '{\"percentage\":'+percent+'}';
508 this.updateProcStatus( pstatfName, stmsg );
509
510 //.. simulated updates
511/*
512 for( var i1=0; i1 < this.CCnt; i1++ ) {
513 this.wait( 2 );
514 percent += 2;
515 if( percent > 100 ) { percent= 100; };
516 stmsg= '{\"percentage\":'+percent+'}';
517 this.updateProcStatus( pstatfName, stmsg );
518 };
519
520 this.wait( 1 );
521*/
522 this.logWr(methName+": finishing.\n");
523 timeStamp = new Date().toISOString();
524 this.logWr( methName+": timeStamp:["+timeStamp+"]\n");
525};
526
527exports.checkAppliedForNamesOnly = function( line, colBg, colEn )
528{
529 var methName= "checkAppliedForNamesOnly";
530 this.logWr( methName+": start: colBg="+colBg+" colEn="+colEn+"\n");
531 if( traceLvl > 1 ) {
532 if( line.length > 60 ) {
533 this.logWr( methName+": line(p):\n["+line.substr(0,60)+"]\n");
534 } else {
535 this.logWr( methName+": line:\n["+line+"]\n");
536 }
537 };
538 this.logWr( methName+": check for: KEY_START:["+KEY_START+"]\n");
539 var lenKS= KEY_START.length;
540 var indMax= colBg + lenKS
541 var subline= line.substring( 0, indMax );
542 var indKS= subline.lastIndexOf( KEY_START, subline.length ); //.. ${(
543 if( indKS < 0 ) {
544 if( traceLvl > 1 )
545 this.logWr( methName+": No KEY_START at all - return true.\n");
546 return true; //.. no KEY_START at all
547 }
548 else { //.. have KEY_START, check KEY_END
549 this.logWr( methName+": check for: KEY_END:["+KEY_END+"]\n");
550 indMax= colBg + KEY_END.length;
551 subline= line.substring( indKS +lenKS, indMax );
552 var indKE= subline.indexOf( KEY_END, 0 ); //.. )}
553 if( indKE < 0 ) {
554 if( traceLvl > 1 )
555 this.logWr( methName+": Only KEY_START there - return false.\n");
556 return false; //..only KEY_START there
557 }
558 else {
559 if( traceLvl > 1 )
560 this.logWr( methName+": Have both - return true.\n");
561 return true; //.. have both: KEY_START and then KEY_END
562 }
563 }
564}
565
566exports.getRangesForVars = function( line, lnum, rnum, selRangesArr )
567{
568 var methName= "getRangesForVars";
569 this.logWr( methName+": start: lnum="+lnum+" rnum="+rnum+"\n");
570 if( traceLvl > 0 ) {
571 if( line.length > 60 ) {
572 this.logWr( methName+": line(p):["+line.substr(0,60)+"]\n");
573 } else {
574 this.logWr( methName+": line:["+line+"]\n");
575 }
576 };
577 var haveComment= '';
578 if( line.trim().startsWith("//") ) haveComment= 'Y';
579 //.. look for ${variables}
580 var indV0= 0;
581 var indV1= line.indexOf( VSTART, indV0 );
582 while( indV1 > -1 ) {
583 var indB= indV1;
584 indV0= indB + 1;
585 indV1= line.indexOf( VEND, indV0 );
586 if( indV1 < 0 ) {
587 errMsgBadParm=
588 methName+": Parameter ending delimiter ("+VEND+
589 ") not found in line #="+lnum+" after pos.#="+indV0+" !\n"
590 this.logWr( "Error: "+errMsgBadParm);
591 if( ! haveComment ) {
592 return -1;
593 } else { //.. haveComment - do not stop processing
594 this.logWr( methName+": This line is commented out -ignore the error.");
595 break;
596 };
597 };
598 var indE= indV1 + lenVE-1;
599 //.. check for VSTART inside the range (must find either old or new one)
600 indB= line.lastIndexOf( VSTART, indE );
601 this.logWr( methName+": found a ${param} at:"+indB+" - "+indE+"\n");
602 //.. lineNm - line number in the input file
603 //.. colBg - begin index of VSTART
604 //.. colEn - after end index of VEND (both within the line)
605 var range = { lineNm: lnum, colBg: indB, colEn: indE };
606 selRangesArr.push( range );
607 this.logWr( methName+": range #:"+rnum+
608 " param.string:["+JSON.stringify(selRangesArr[rnum])+"]\n");
609 rnum++;
610 indV0= indV1 + lenVE;
611 indV1= line.indexOf( VSTART, indV0 );
612 };
613 return rnum;
614};
615
616//.. assuming the word format is like: "(value)=(name)" or "name"
617// returning error message or empty string (which means no errors)
618exports.parseParmValAndName = function( word, parmNamAndVal )
619{
620 var methName= "parseParmValAndName";
621 this.logWr( methName+": start: input word:["+word+"]\n");
622 var lenW= word.length;
623 var errorMsg= '';
624 if( traceLvl > 0 )
625 this.logWr( methName+": word length="+lenW+"\n");
626 if( lenW < 1 ) {
627 errorMsg= methName+": the parameter string is empty !\n";
628 errMsgBadParm= errorMsg;
629 this.logWr( "Error: "+errorMsg );
630 return errorMsg;
631 };
632 var lastCh= lenW - 1;
633 var OBR= '(';
634 var lenOBR= OBR.length;
635 var CBR= ')';
636 var lenCBR= CBR.length;
637 var EQS= '=';
638 var lenEQS= EQS.length;
639 var name, val;
640 var ic0= 0;
641 var ic1= word.indexOf( OBR, ic0 );
642 if( ic1 < 0 ) {
643 if( traceLvl > 0 )
644 this.logWr( methName+": no open round brackets -assuming the word has "+
645 "param.name only.\n");
646 parmNamAndVal.push( word );
647 parmNamAndVal.push( '' );
648 return ''; //.. empty errorMsg means OK
649 };
650 //.. got 1-st open round bracket
651 if( traceLvl > 0 )
652 this.logWr( methName+": found 1-st open round bracket at:"+ic1+"\n");
653 if( ic1 > 0 ) {
654 errorMsg= methName+": Unexpected chars before open round bracket at:"+ic1+"\n";
655 errMsgBadParm= errorMsg;
656 this.logWr( "Error: "+errorMsg );
657 return errorMsg;
658 };
659
660 ic0= ic1 + lenOBR;
661 if( ic0 >= lastCh ) {
662 errorMsg=
663 methName+": missing next expected round brackets after pos.#="+ic1+
664 " -bad format\n";
665 errMsgBadParm= errorMsg;
666 this.logWr( "Error: "+errorMsg );
667 return errorMsg;
668 };
669 var ic2= word.indexOf( CBR, ic0 );
670 if( ic2 < 0 ) {
671 errorMsg=
672 methName+": no closing round bracket after 1-st open bracket -bad format\n";
673 errMsgBadParm= errorMsg;
674 this.logWr( "Error: "+errorMsg );
675 return errorMsg;
676 };
677 //.. got 1-st closing round bracket (after Value)
678 if( traceLvl > 0 )
679 this.logWr( methName+": found 1-st closing round bracket at:"+ic2+"\n");
680 val= word.substring( ic0, ic2 );
681 if( traceLvl > 0 )
682 this.logWr( methName+": got val:["+val+"]\n");
683 ic0= ic2 + lenCBR;
684 if( ic0 >= lastCh ) {
685 errorMsg=
686 methName+": missing next expected round brackets after pos.#="+ic2+
687 " -bad format\n";
688 errMsgBadParm= errorMsg;
689 this.logWr( "Error: "+errorMsg );
690 return errorMsg;
691 };
692 var ic3= -1;
693 if( word.substr(ic0).startsWith(EQS) ) {
694 //.. found EQS
695 ic3= ic0;
696 }
697 else {
698 errorMsg=
699 methName+": no equal sign after 1-st closing round bracket at pos.#="+ic2+
700 " -bad format";
701 errMsgBadParm= errorMsg;
702 this.logWr( "Error: "+errorMsg+"\n" );
703 return errorMsg;
704 };
705 //.. got Equal sign after 1-st closing round bracket
706 ic0= ic3 + lenEQS;
707 if( ic0 >= lastCh ) {
708 errorMsg= methName+": missing next expected round brackets after pos.#="+ic3+
709 " -bad format";
710 errMsgBadParm= errorMsg;
711 this.logWr( "Error: "+errorMsg+"\n" );
712 return errorMsg;
713 };
714 var ic4= -1;
715 if( word.substr(ic0).startsWith(OBR) ) {
716 //.. found
717 ic4= ic0;
718 }
719 else {
720 errorMsg=
721 methName+": no 2-nd open round bracket after equal sign at pos.#="+ic3+
722 " -bad format";
723 errMsgBadParm= errorMsg;
724 this.logWr( "Error: "+errorMsg+"\n" );
725 return errorMsg;
726 };
727 //.. got 2-nd open round bracket
728 ic0= ic4 + lenOBR;
729 if( ic0 >= lastCh ) {
730 errorMsg=
731 methName+": missing next expected round bracket after pos.#="+ic4+
732 " -bad format";
733 errMsgBadParm= errorMsg;
734 this.logWr( "Error: "+errorMsg+"\n" );
735 return errorMsg;
736 };
737 var ic5= word.indexOf( CBR, ic0 );
738 if( ic5 < 0 ) {
739 errorMsg=
740 methName+": no 2-nd closing round bracket after 2-nd open bracket at pos.#="+
741 ic4+" -bad format";
742 errMsgBadParm= errorMsg;
743 this.logWr( "Error: "+errorMsg+"\n" );
744 return errorMsg;
745 };
746 //.. got 2-nd closing round bracket
747 // (also assuming the remaining chars are whitespaces)
748 parmNamAndVal.push( word.substring(ic0, ic5) );
749 parmNamAndVal.push( val );
750 if( traceLvl > 1 )
751 this.logWr( methName+": got param: name:["+parmNamAndVal[0]+"]\n value:["+
752 parmNamAndVal[1]+"]\n");
753 return ''; //.. empty error message means OK
754};
755
756exports.reportParamBadFmt = function (
757 lineNm, pword, formatErr, perrorFName, pstatFName )
758{
759 var methName= "reportParamBadFmt";
760 this.logWr( methName+": start: the param.name-value format is bad -Error!\n");
761 this.logWr( methName+": signalling error via percent = -1 \n");
762 var percent=-1;
763 var stmsg= '{\"percentage\":'+percent+'}';
764 this.updateProcStatus( pstatFName, stmsg );
765 this.logWr( methName+": writing the error message into a file "+
766 "for next request from the server...");
767 procErrorMsg= "Error: Bad Format of the parameter string";
768 if( pword != null && pword.length > 0 ) {
769 procErrorMsg += ":["+pword+"]";
770 };
771 var lineNmE= lineNm + 1; //.. line numbering in screen editor starts from 1
772 procErrorMsg += "\n Error found at line #:"+lineNmE;
773 procErrorMsg += "\n Error Details:["+formatErr+"]";
774 procErrorMsg += "\n Please, correct the error and try again.";
775 //.. using updateProcStatus to save the error message in a file
776 this.updateProcStatus( perrorFName, procErrorMsg );
777};
778
779exports.logWr = function ( msg ) {
780 // console.log(clName+": logWr: fdL="+this.fdL+" msg:["+msg+"]");
781 try {
782 fs.appendFileSync( this.fdL, msg, 'utf8' );
783 }
784 catch( err ) {
785 console.log(clName+": log uppend: error:"+err.message );
786 throw err;
787 };
788 // fs.appendFile( this.fdL, msg, 'utf8', (err) => {
789 // if( err ) {
790 // throw err;
791 // }
792 // });
793};
794
795 //.. processing percentage or error message
796exports.updateProcStatus = function ( pstfname, statusMsg ) {
797 var methName= "updateProcStatus";
798 this.logWr(methName+": start: pstfname:["+pstfname+"]\n");
799 var pstfname_p= pstfname+".pre";
800 this.logWr(methName+": new status: message["+statusMsg+"]\n");
801 var timeStamp = new Date().toISOString();
802 this.logWr( methName+": timeStamp:["+timeStamp+"]\n");
803 //.. pre-file
804 try {
805 this.fdPSt= fs.openSync( pstfname_p, 'a' );
806 }
807 catch( err ) {
808 this.logWr(clName+": status file open: error:["+err.message+"]\n");
809 throw err;
810 }
811 this.logWr(methName+": writing status: fdPSt="+this.fdPSt+"\n");
812 try {
813 fs.appendFileSync( this.fdPSt, statusMsg, 'utf8' );
814 }
815 catch( err ) {
816 this.logWr(clName+": status file append: error: code="+err.code );
817 throw err;
818 }
819 this.logWr(methName+": closing status file: fdPSt="+this.fdPSt+"\n");
820 fs.closeSync( this.fdPSt );
821 this.logWr(methName+": status file closed - final renaming...\n");
822 fs.renameSync( pstfname_p, pstfname );
823 this.logWr(methName+": status file renamed - finished.\n");
824};
825
826exports.wait = function ( secs ) {
827 var methName= "wait";
828 this.logWr(methName+": start: secs="+secs+"\n");
829 var inStr= String( secs );
830 // this.logWr(methName+": inStr:["+inStr+"]\n");
831 var s_args= new Array( 0 );
832 s_args.push( inStr );
833 var tmoutms= 500 +1000*secs;
834 var mopts= { timeout: tmoutms };
835 // this.logWr(methName+": mopts:["+ JSON.stringify(mopts)+"]\n");
836 var moutObj= Chproc.spawnSync( 'sleep', s_args, mopts);
837 this.logWr(methName+": moutObj: status:["+moutObj.status+"](0=ok)\n");
838 if( moutObj.error != null ) {
839 console.log(methName+": moutObj: Error:["+JSON.stringify(moutObj.error)+"]\n"); }
840};