summaryrefslogtreecommitdiffstats
path: root/src/app/subnproc.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/subnproc.js')
-rw-r--r--src/app/subnproc.js840
1 files changed, 840 insertions, 0 deletions
diff --git a/src/app/subnproc.js b/src/app/subnproc.js
new file mode 100644
index 0000000..6719366
--- /dev/null
+++ b/src/app/subnproc.js
@@ -0,0 +1,840 @@
+/*
+============LICENSE_START==========================================
+===================================================================
+Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+===================================================================
+
+Unless otherwise specified, all software contained herein is licensed
+under the Apache License, Version 2.0 (the License);
+you may not use this software except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+============LICENSE_END============================================ */
+//.. subnproc.js -to be started by parent server process
+const fs = require('fs');
+const Chproc = require('child_process');
+
+var clName= "subnproc";
+var thePid= 0;
+var taskId= '';
+//.. assuming all these files are in CDT_HOME
+var inpFilePfx= "posted_data_";
+var outFilePfx= "sync_template_res_"; //.. processing results
+var errFilePfx= "sync_template_err_"; //.. error found while processing
+var parmFilePfx= "template_params_";
+var pstatfNamePfx= "proc_status_";
+//.. pDlm -delimiter of params
+// (cant be: alphanumeric,underbar,dollar,dot,comma,brackets,dash,equal sign,etc)
+var pDlm= '\n';
+var logfname= clName+".log";
+ var logfname_o= logfname+".save"; //.. to keep old content
+var fdL;
+var fdIn;
+var fdOut;
+var errMsgBadParm= ''; //.. create error message to report to client
+//var checkSpecialCharsReg= new RegExp(/[^\w\s-]/);
+var checkSpecialCharsReg= new RegExp(/[^\w\s-\.]/);
+var doStopOnSpecChars= 'Y';
+var doCheckComments= 'Y';
+//var SYNC_T_KEY_EXPRES= '\\${.+?\\}';
+var VSTART= '${';
+var VEND= '}';
+var lenVS= VSTART.length, lenVE= VEND.length;
+var KEY_START= '${(';
+var KEY_MID= ')=(';
+var KEY_END= ')}';
+var LD= "\n"; //.. LD -line delimeter in the input file
+var lenLD= LD.length;
+var percAtRngs= 55; //.. percentage defining report to client
+
+var traceLvl= 1;
+//var CCnt= 52;
+var CCnt= 2;
+
+ var taskIdArgstr= process.argv[ 2 ];
+ var CDT_HOME= process.argv[ 3 ];
+ var LOG_DIR= process.argv[ 4 ];
+ this.thePid= process.pid;
+ console.log(clName+": Start: thePid="+this.thePid );
+ console.log(clName+": CDT_HOME:["+CDT_HOME+"]" );
+ console.log(clName+": LOG_DIR:["+LOG_DIR+"]" );
+
+try {
+ //.. need renameSync (not asynchronous) !
+ fs.renameSync( LOG_DIR+"/"+logfname, LOG_DIR+"/"+logfname_o);
+}
+catch( err ) {
+ console.log(clName+": log rename error: code="+ err.code );
+ console.log(clName+": log rename error.msg:["+err.message+"]");
+ //throw err;
+};
+fs.open( LOG_DIR+"/"+logfname, 'a', (err, fd) => {
+ if( err ) {
+ console.log(clName+": log file open error:"+err.message );
+ throw err;
+ }
+ this.fdL= fd;
+ console.log(clName+": log opened. fdL="+this.fdL);
+
+ this.logWr( clName+": Start: thePid="+this.thePid+"\n");
+
+ this.logWr( clName+
+ ": execArgv:["+process.execArgv+"]\n argv:["+process.argv+"]\n");
+ var indT= taskIdArgstr.indexOf('=', 0);
+ if( indT < 0 ) {
+ // this.logWr(clName+": Error: Failed to extract taskId from args:["+
+ // taskIdArgstr+"]\n");
+ // this.taskId= "000";
+ this.taskId= taskIdArgstr;
+ } else {
+ this.taskId= taskIdArgstr.substr( indT+1 );
+ }
+ this.logWr(clName+": taskId:["+this.taskId+"]\n");
+ if( this.taskId == null || this.taskId == undefined || this.taskId.length < 1 )
+ {
+ var errMsg= clName+": Error: taskId is empty !\n";
+ console.log( errMsg );
+ this.logWr( errMsg );
+ throw new Error( errMsg );
+ };
+ this.logWr(clName+": CDT_HOME:["+CDT_HOME+"]\n");
+
+ var timeStampI = Date.now();
+ this.logWr(clName+": timeStampI="+timeStampI+" \n");
+ var timeStamp = new Date( timeStampI ).toISOString();
+ this.logWr(clName+": timeStamp:["+timeStamp+"]\n");
+
+ //.. setup callback waiting for message from parent
+ // process.on('message', (msg) => {
+ // console.log('subnp: got message:', msg);
+ // });
+
+ //this.logWr("subnp: sending msg to parent.\n");
+ // var msg2parent = { taskid: taskId };
+ // this.logWr("subnp: msg2parent:["+JSON.stringify(msg2parent)+"]\n");
+ // process.send( msg2parent );
+
+ var inpFile= CDT_HOME+"/"+ inpFilePfx +this.taskId +".txt";
+ this.logWr(clName+": opening inpFile for reading:["+inpFile+"]\n");
+
+ fs.open( inpFile, 'r', (err, fd0) => {
+ if( err ) {
+ console.log(clName+": inpFile file open: Error: code="+err.code );
+ this.logWr(clName+": inpFile file open: Error: code="+err.code+"\n");
+ throw err;
+ }
+ this.fdIn= fd0;
+ console.log(clName+": Input file opened. fdIn="+this.fdIn);
+
+ fs.readFile( this.fdIn, (err, data) => {
+ if( err ) {
+ console.log(clName+": Failed to read inpFile: Error: code="+err.code );
+ this.logWr(clName+": Failed to read inpFile: Error: code="+err.code+"\n");
+ throw err;
+ }
+ this.processData( data );
+ //.. close log
+ console.log(clName+": close: fdL="+this.fdL );
+ fs.closeSync( this.fdL );
+ this.fdL= -1;
+ });
+ });
+});
+
+exports.processData = function ( data ) {
+ //.. processing data content from already opened input file
+ var methName= "processData";
+ this.logWr(methName+": start...\n");
+ var timeStamp = new Date().toISOString();
+ this.logWr( methName+": timeStamp:["+timeStamp+"]\n");
+ var fcontStr= new String( data );
+ let fcontLen= fcontStr.length;
+ this.logWr(methName+": fcontLen="+fcontLen+"\n");
+
+ this.logWr(methName+": trying to close inpFile: fdIn="+this.fdIn+"\n");
+ fs.closeSync( this.fdIn );
+ this.logWr(methName+": inpFile closed.\n");
+
+ var pstatfName= CDT_HOME+"/"+ pstatfNamePfx +this.taskId+".json";
+ var percent= 1;
+ var stmsg= '{\"percentage\":'+percent+'}';
+ this.updateProcStatus( pstatfName, stmsg );
+
+ timeStamp = new Date().toISOString();
+ this.logWr( methName+": timeStamp:["+timeStamp+"]\n");
+
+ var perrorfName= CDT_HOME+"/"+ errFilePfx+ this.taskId+".txt";
+ var formatErr= '';
+ var lineEnds= new Array( 0 ); //.. indexes of new-line chars
+ var selecRanges= new Array( 0 ); //.. indexes of ${variables}
+ var parmNamVals= new Map(); //.. parameter Name-Value pairs from inside ${...}
+ var ind0= 0;
+ var ind1= fcontStr.indexOf( LD,ind0 ); //.. line delimeter
+ var rn= 0, li= 0;
+ while( ind1 > -1 ) {
+ lineEnds.push( ind1 );
+ this.logWr(
+ methName+":--line #:"+li+" beg: ind0="+ind0+" end: ind1="+ind1+
+ " array:"+lineEnds[li]+"\n");
+ var line0= fcontStr.substring( ind0, ind1 ); //.. not including LD
+ var liLen= line0.length;
+ this.logWr( methName+": liLen="+liLen+"\n");
+ if( liLen > 60 ) {
+ this.logWr( methName+": line(p):["+line0.substr(0,60)+"]\n");
+ } else {
+ this.logWr( methName+": line:["+line0+"]\n");
+ }
+ //.. look for ${param variables}
+ rn= this.getRangesForVars( line0, li, rn, selecRanges );
+ if( rn < 0 ) {
+ this.logWr( methName+": got Error:\n["+errMsgBadParm+"]");
+ this.reportParamBadFmt( li, '', errMsgBadParm, perrorfName, pstatfName );
+ this.logWr( methName+": Stopping processing !\n");
+ return;
+ }
+ if( traceLvl > 1 )
+ this.logWr( methName+": added ranges at li="+li+": next rn="+rn+"\n");
+ ind0= ind1 +lenLD; //.. for next search of LD
+ if( ind0 >= fcontLen ) { break; };
+ li++;
+ ind1= fcontStr.indexOf( LD,ind0 ); //.. line delimeter
+ }; //.. loop
+ //.. process the last line
+ if( ind0 < fcontLen ) {
+ this.logWr( methName+": have the last line: ind0="+ind0+"\n");
+ lineEnds.push( fcontLen );
+ var line0= fcontStr.substring( ind0 ); //.. up to the end
+ var liLen= line0.length;
+ this.logWr( methName+": liLen="+liLen+"\n");
+ if( liLen > 60 ) {
+ this.logWr( methName+": line(p):["+line0.substr(0,60)+"]\n");
+ } else {
+ this.logWr( methName+": line:["+line0+"]\n");
+ }
+ //.. look for ${param variables}
+ rn= this.getRangesForVars( line0, li, rn, selecRanges );
+ if( rn < 0 ) {
+ this.logWr( methName+": got Error in getRangesForVars:\n["+
+ errMsgBadParm+"]");
+ this.reportParamBadFmt( li, '', errMsgBadParm, perrorfName, pstatfName );
+ this.logWr( methName+": Stopping processing !\n");
+ return;
+ }
+ };
+ this.logWr( methName+": -=- lineEnds array length="+lineEnds.length+"\n");
+ timeStamp = new Date().toISOString();
+ this.logWr( methName+": timeStamp:["+timeStamp+"]\n");
+
+ percent= percAtRngs;
+ stmsg= '{\"percentage\":'+percent+'}';
+ this.updateProcStatus( pstatfName, stmsg );
+
+ //.. Cycle through Ranges
+ this.logWr( methName+": selecRanges array length="+selecRanges.length+"\n");
+ if( doCheckComments ) {
+ this.logWr( methName+": doCheckComments is True.\n");
+ } else {
+ this.logWr( methName+": doCheckComments is False\n");
+ };
+ var rnAtUpd= Math.floor( selecRanges.length/ 3.);
+ var percStep= (100.0 - percAtRngs);
+ this.logWr( methName+": range number for proc.status update="+rnAtUpd+
+ "\n percentage step="+percStep );
+ var outLinBuf= new Array( 0 ); //.. array of output lines
+ var outLnLast=-1; //.. last processed
+ var rngLnLast=-1;
+ for( var rn0=0; rn0 < selecRanges.length; rn0++ ) {
+ var rng= selecRanges[rn0];
+ this.logWr( methName+":--- range #:"+rn0+" lineNm="+rng.lineNm+
+ " colBg="+rng.colBg+" colEn="+rng.colEn+"\n");
+ this.logWr( methName+": outLnLast="+outLnLast+"\n");
+ if( rn0 > 0 && (rn0 % rnAtUpd) == 0 && rn0 < selecRanges.length -rnAtUpd )
+ {
+ percent= Math.floor( percAtRngs + percStep *(rn0/selecRanges.length) );
+ this.logWr( methName+": need to update proc.status: percent="+percent+"\n");
+ stmsg= '{\"percentage\":'+percent+'}';
+ this.updateProcStatus( pstatfName, stmsg );
+ };
+ rngLnLast= rng.lineNm;
+ //.. prepare previous lines with no ranges
+ if( rng.lineNm - outLnLast > 1 ) {
+ this.logWr( methName+": prepare previous lines...\n");
+ var plinNm0= outLnLast +1;
+ var plinesIndB= 0;
+ if( plinNm0 > 0 ) { plinesIndB= lineEnds[outLnLast] + lenLD; };
+ var plinesIndE= lineEnds[rng.lineNm -1] + lenLD;
+ this.logWr( methName+": plinesIndB="+plinesIndB+
+ " plinesIndE="+plinesIndE+"\n");
+ var plinStr= fcontStr.substring( plinesIndB, plinesIndE );
+ if( traceLvl > 1 ) {
+ if( plinStr.length > 60 ) {
+ this.logWr( methName+": plinStr(p):["+plinStr.substr(0, 60)+"]\n");
+ } else {
+ this.logWr( methName+": plinStr:["+plinStr+"]\n");
+ }
+ };
+ outLinBuf.push( plinStr );
+ outLnLast= rng.lineNm -1;
+ };
+ var linIndB= 0;
+ var linIndE= lineEnds[rng.lineNm];
+ if( rng.lineNm > 0 ) { linIndB= lineEnds[rng.lineNm - 1] + lenLD; };
+ var linLen= linIndE - linIndB;
+ var line0= fcontStr.substr( linIndB, linLen );
+ this.logWr( methName+": linIndB="+linIndB+" linIndE="+linIndE+
+ " line length="+linLen+"\n");
+ if( traceLvl > 1 ) {
+ if( linLen > 60 ) {
+ this.logWr( methName+": line0(p):\n["+line0.substr(0,60)+"]\n");
+ } else {
+ this.logWr( methName+": line0:\n["+line0+"]\n");
+ }
+ };
+ //.. content between ${ and }
+ var vword= line0.substring( rng.colBg+lenVS, rng.colEn+1-lenVE );
+ this.logWr( methName+": vword:["+vword+"]\n");
+ //.. try to check for (pvalue)=(pname)
+ let specialKeys= null;
+ var parmNamAndVal= Array( 0 );
+ var pName= null;
+ var pValue= null;
+ formatErr= this.parseParmValAndName( vword, parmNamAndVal )
+ if( formatErr ) {
+ this.reportParamBadFmt(
+ rng.lineNm, vword, formatErr, perrorfName, pstatfName );
+ this.logWr( methName+": Stopping processing !\n");
+ return;
+ }
+ //.. No errors - parsing done OK
+ pName= parmNamAndVal[0]; //.. to be added to parmNamVals
+ pValue= parmNamAndVal[1];
+ this.logWr( methName+": parsing done: param.name:["+
+ pName+"] value:["+pValue+"]\n");
+
+ if( pName != null && pName.length > 0 ) {
+ this.logWr( methName+": check spec.chars in Non empty pName.\n");
+ specialKeys= checkSpecialCharsReg.exec( pName );
+ if( specialKeys == null ) {
+ this.logWr( methName+": specialKeys obj is null\n");
+ }
+ else
+ if( specialKeys.length > 0 ) {
+ this.logWr( methName+": specialKeys obj Not null:["+specialKeys+
+ "] length="+specialKeys.length+"\n");
+ if( doStopOnSpecChars ) {
+ formatErr=
+ "The parameter name("+pName+") contains prohibited character(s):("+
+ specialKeys+") !";
+ this.logWr( methName+": formatErr:["+formatErr+"]\n");
+ this.reportParamBadFmt(
+ rng.lineNm, vword, formatErr, perrorfName, pstatfName );
+ this.logWr( methName+": Stopping processing !\n");
+ return;
+ };
+ };
+ };
+ var haveComment= '';
+ if( doCheckComments ) {
+ this.logWr( methName+": doCheckComments is True.\n");
+ if( line0.trim().startsWith("//") ) haveComment= 'Y';
+ };
+ if( haveComment ) {
+ this.logWr( methName+": haveComment is True !\n");
+ };
+ //.. prepare parameter name and value
+ if( pName != null && pName.length > 0 && !specialKeys && !haveComment )
+ {
+ this.logWr( methName+": checking non-empty param.name:["+pName+"]\n");
+ if( parmNamVals.has(pName) ) {
+ this.logWr( methName+": the param. is already accounted.\n");
+ } else {
+ this.logWr( methName+": adding new param. with value:["+pValue+"]\n");
+ parmNamVals.set( pName, pValue );
+ };
+ };
+ //.. prepare for template output
+ var colB= 0;
+ if( rn0 > 0 ) {
+ var rngP= selecRanges[rn0 - 1];
+ if( rngP.lineNm == rng.lineNm ) { colB= rngP.colEn+lenVE; };
+ };
+ var colE= rng.colEn;
+ //.. check range content for replacement
+ let checkApplForNamOn=
+ this.checkAppliedForNamesOnly( line0, rng.colBg, rng.colEn );
+ this.logWr( methName+": checkApplForNamOn:["+checkApplForNamOn+"]\n");
+ if( checkApplForNamOn && !specialKeys && !haveComment )
+ {
+ this.logWr( methName+": Need Name Replacement... \n");
+ var replacWrd= KEY_START +KEY_MID +vword +KEY_END; // ${()=(...)}
+ this.logWr( methName+": replacWrd:["+replacWrd+"]\n");
+ var colM= rng.colBg; //.. not including beginning of VSTART
+ var brngStr= line0.substring( colB, colM );
+ this.logWr( methName+": part before word:["+brngStr+"]\n");
+ outLinBuf.push( brngStr + replacWrd );
+ }
+ else {
+ this.logWr( methName+": No Replacement for this range !\n");
+ var rsubs= line0.substring( colB, colE+lenVE );
+ this.logWr( methName+": rsubs:["+rsubs+"]\n");
+ outLinBuf.push( rsubs );
+ };
+ outLnLast= rng.lineNm;
+ //.. check tail of the line
+ if( rn0 == selecRanges.length - 1 ) {
+ var tailStr= line0.substring(colE+lenVE) + LD;
+ this.logWr( methName+": last range: adding line tail:\n["+tailStr+"]\n");
+ outLinBuf.push( tailStr );
+ }
+ else { //.. not the last range
+ var rngN= selecRanges[rn0 + 1];
+ if( rngN.lineNm == rng.lineNm ) {
+ //.. next range on the same line - no tail yet
+ }
+ else { //.. next range on different line
+ var tailStr= line0.substring(colE+lenVE) + LD;
+ this.logWr( methName+": adding line tail:\n["+tailStr+"]\n");
+ outLinBuf.push( tailStr );
+ };
+ };
+ }; //... loop
+ if( rngLnLast < lineEnds.length - 1) {
+ this.logWr( methName+": adding last lines having no ranges...\n");
+ var llinesIndB= 0;
+ if( rngLnLast > 0 ) { llinesIndB= lineEnds[rngLnLast] + lenLD; };
+ var llinesIndE= lineEnds[lineEnds.length -1] + lenLD;
+ this.logWr( methName+": llinesIndB="+llinesIndB+
+ " llinesIndE="+llinesIndE+"\n");
+ var llinStr= fcontStr.substring( llinesIndB, llinesIndE );
+ if( traceLvl > 1 ) {
+ if( llinStr.length > 60 ) {
+ this.logWr( methName+": llinStr(p):\n["+llinStr.substr(0,60)+"]\n");
+ } else {
+ this.logWr( methName+": llinStr:["+llinStr+"]\n");
+ }
+ }
+ outLinBuf.push( llinStr );
+ };
+ this.logWr( methName+": -=- outLinBuf: array length="+outLinBuf.length+"\n");
+ timeStamp = new Date().toISOString();
+ this.logWr( methName+": timeStamp:["+timeStamp+"]\n");
+
+ var outFile= CDT_HOME+"/"+ outFilePfx+ this.taskId+".txt";
+ var outFile_o= outFile+".save";
+ try {
+ fs.renameSync( outFile, outFile_o );
+ }
+ catch( err ) {
+ this.logWr(clName+": old output file rename: error:["+err.message+"]\n");
+ // throw err;
+ };
+ try {
+ this.fdOut= fs.openSync( outFile, 'a' );
+ }
+ catch( err ) {
+ this.logWr(clName+": output file open: error:["+err.message+"]\n");
+ throw err;
+ }
+ this.logWr(methName+": output file opened: fdOut="+this.fdOut+"\n");
+ for( let outLine of outLinBuf ) {
+ try {
+ fs.appendFileSync( this.fdOut, outLine, 'utf8' );
+ }
+ catch( err ) {
+ this.logWr(clName+": output file append: error: code="+err.code );
+ throw err;
+ }
+ }; //... loop
+ this.logWr(methName+": closing output file: fdOut="+this.fdOut+"\n");
+ fs.closeSync( this.fdOut );
+ this.logWr(methName+": output file closed.\n");
+ timeStamp = new Date().toISOString();
+ this.logWr( methName+": timeStamp:["+timeStamp+"]\n");
+
+ this.logWr( methName+": -=- parmNamVals (Parameters): map.size="+
+ parmNamVals.size+"\n");
+ var parmFile= CDT_HOME+"/"+ parmFilePfx+ this.taskId+".txt";
+ var parmFile_o= parmFile+".save";
+ try {
+ fs.renameSync( parmFile, parmFile_o );
+ }
+ catch( err ) {
+ this.logWr(clName+": old Params file rename: error:["+err.message+"]\n");
+ // throw err;
+ };
+ try {
+ this.fdParm= fs.openSync( parmFile, 'a' );
+ }
+ catch( err ) {
+ this.logWr(clName+": Params file open: error:["+err.message+"]\n");
+ throw err;
+ };
+ this.logWr(methName+": Params file opened: fdParm="+this.fdParm+"\n");
+ //.. writing parameters into parameter-output file
+ try {
+ // fs.appendFileSync( this.fdParm, "[\n", 'utf8' );
+ var iw= 0;
+ for( let pnm of parmNamVals.keys() ) {
+ let pv= parmNamVals.get( pnm );
+ let pnv= pnm+"="+pv;
+ this.logWr( methName+": iw="+iw+" param.Name-Value:["+pnv+"]\n");
+ //.. need delimiter after each item !
+ fs.appendFileSync( this.fdParm, pnv+pDlm, 'utf8' );
+ iw++;
+ }; //... loop
+ // fs.appendFileSync( this.fdParm, "]", 'utf8' );
+ }
+ catch( err ) {
+ this.logWr(clName+": Params file append: error: code="+err.code );
+ throw err;
+ }
+ this.logWr(methName+": closing Params file: fdParm="+this.fdParm+"\n");
+ fs.closeSync( this.fdParm );
+ this.logWr(methName+": Params file closed.\n");
+
+ timeStamp = new Date().toISOString();
+ this.logWr( methName+": timeStamp:["+timeStamp+"]\n");
+
+ percent= 100;
+ stmsg= '{\"percentage\":'+percent+'}';
+ this.updateProcStatus( pstatfName, stmsg );
+
+ //.. simulated updates
+/*
+ for( var i1=0; i1 < this.CCnt; i1++ ) {
+ this.wait( 2 );
+ percent += 2;
+ if( percent > 100 ) { percent= 100; };
+ stmsg= '{\"percentage\":'+percent+'}';
+ this.updateProcStatus( pstatfName, stmsg );
+ };
+
+ this.wait( 1 );
+*/
+ this.logWr(methName+": finishing.\n");
+ timeStamp = new Date().toISOString();
+ this.logWr( methName+": timeStamp:["+timeStamp+"]\n");
+};
+
+exports.checkAppliedForNamesOnly = function( line, colBg, colEn )
+{
+ var methName= "checkAppliedForNamesOnly";
+ this.logWr( methName+": start: colBg="+colBg+" colEn="+colEn+"\n");
+ if( traceLvl > 1 ) {
+ if( line.length > 60 ) {
+ this.logWr( methName+": line(p):\n["+line.substr(0,60)+"]\n");
+ } else {
+ this.logWr( methName+": line:\n["+line+"]\n");
+ }
+ };
+ this.logWr( methName+": check for: KEY_START:["+KEY_START+"]\n");
+ var lenKS= KEY_START.length;
+ var indMax= colBg + lenKS
+ var subline= line.substring( 0, indMax );
+ var indKS= subline.lastIndexOf( KEY_START, subline.length ); //.. ${(
+ if( indKS < 0 ) {
+ if( traceLvl > 1 )
+ this.logWr( methName+": No KEY_START at all - return true.\n");
+ return true; //.. no KEY_START at all
+ }
+ else { //.. have KEY_START, check KEY_END
+ this.logWr( methName+": check for: KEY_END:["+KEY_END+"]\n");
+ indMax= colBg + KEY_END.length;
+ subline= line.substring( indKS +lenKS, indMax );
+ var indKE= subline.indexOf( KEY_END, 0 ); //.. )}
+ if( indKE < 0 ) {
+ if( traceLvl > 1 )
+ this.logWr( methName+": Only KEY_START there - return false.\n");
+ return false; //..only KEY_START there
+ }
+ else {
+ if( traceLvl > 1 )
+ this.logWr( methName+": Have both - return true.\n");
+ return true; //.. have both: KEY_START and then KEY_END
+ }
+ }
+}
+
+exports.getRangesForVars = function( line, lnum, rnum, selRangesArr )
+{
+ var methName= "getRangesForVars";
+ this.logWr( methName+": start: lnum="+lnum+" rnum="+rnum+"\n");
+ if( traceLvl > 0 ) {
+ if( line.length > 60 ) {
+ this.logWr( methName+": line(p):["+line.substr(0,60)+"]\n");
+ } else {
+ this.logWr( methName+": line:["+line+"]\n");
+ }
+ };
+ var haveComment= '';
+ if( line.trim().startsWith("//") ) haveComment= 'Y';
+ //.. look for ${variables}
+ var indV0= 0;
+ var indV1= line.indexOf( VSTART, indV0 );
+ while( indV1 > -1 ) {
+ var indB= indV1;
+ indV0= indB + 1;
+ indV1= line.indexOf( VEND, indV0 );
+ if( indV1 < 0 ) {
+ errMsgBadParm=
+ methName+": Parameter ending delimiter ("+VEND+
+ ") not found in line #="+lnum+" after pos.#="+indV0+" !\n"
+ this.logWr( "Error: "+errMsgBadParm);
+ if( ! haveComment ) {
+ return -1;
+ } else { //.. haveComment - do not stop processing
+ this.logWr( methName+": This line is commented out -ignore the error.");
+ break;
+ };
+ };
+ var indE= indV1 + lenVE-1;
+ //.. check for VSTART inside the range (must find either old or new one)
+ indB= line.lastIndexOf( VSTART, indE );
+ this.logWr( methName+": found a ${param} at:"+indB+" - "+indE+"\n");
+ //.. lineNm - line number in the input file
+ //.. colBg - begin index of VSTART
+ //.. colEn - after end index of VEND (both within the line)
+ var range = { lineNm: lnum, colBg: indB, colEn: indE };
+ selRangesArr.push( range );
+ this.logWr( methName+": range #:"+rnum+
+ " param.string:["+JSON.stringify(selRangesArr[rnum])+"]\n");
+ rnum++;
+ indV0= indV1 + lenVE;
+ indV1= line.indexOf( VSTART, indV0 );
+ };
+ return rnum;
+};
+
+//.. assuming the word format is like: "(value)=(name)" or "name"
+// returning error message or empty string (which means no errors)
+exports.parseParmValAndName = function( word, parmNamAndVal )
+{
+ var methName= "parseParmValAndName";
+ this.logWr( methName+": start: input word:["+word+"]\n");
+ var lenW= word.length;
+ var errorMsg= '';
+ if( traceLvl > 0 )
+ this.logWr( methName+": word length="+lenW+"\n");
+ if( lenW < 1 ) {
+ errorMsg= methName+": the parameter string is empty !\n";
+ errMsgBadParm= errorMsg;
+ this.logWr( "Error: "+errorMsg );
+ return errorMsg;
+ };
+ var lastCh= lenW - 1;
+ var OBR= '(';
+ var lenOBR= OBR.length;
+ var CBR= ')';
+ var lenCBR= CBR.length;
+ var EQS= '=';
+ var lenEQS= EQS.length;
+ var name, val;
+ var ic0= 0;
+ var ic1= word.indexOf( OBR, ic0 );
+ if( ic1 < 0 ) {
+ if( traceLvl > 0 )
+ this.logWr( methName+": no open round brackets -assuming the word has "+
+ "param.name only.\n");
+ parmNamAndVal.push( word );
+ parmNamAndVal.push( '' );
+ return ''; //.. empty errorMsg means OK
+ };
+ //.. got 1-st open round bracket
+ if( traceLvl > 0 )
+ this.logWr( methName+": found 1-st open round bracket at:"+ic1+"\n");
+ if( ic1 > 0 ) {
+ errorMsg= methName+": Unexpected chars before open round bracket at:"+ic1+"\n";
+ errMsgBadParm= errorMsg;
+ this.logWr( "Error: "+errorMsg );
+ return errorMsg;
+ };
+
+ ic0= ic1 + lenOBR;
+ if( ic0 >= lastCh ) {
+ errorMsg=
+ methName+": missing next expected round brackets after pos.#="+ic1+
+ " -bad format\n";
+ errMsgBadParm= errorMsg;
+ this.logWr( "Error: "+errorMsg );
+ return errorMsg;
+ };
+ var ic2= word.indexOf( CBR, ic0 );
+ if( ic2 < 0 ) {
+ errorMsg=
+ methName+": no closing round bracket after 1-st open bracket -bad format\n";
+ errMsgBadParm= errorMsg;
+ this.logWr( "Error: "+errorMsg );
+ return errorMsg;
+ };
+ //.. got 1-st closing round bracket (after Value)
+ if( traceLvl > 0 )
+ this.logWr( methName+": found 1-st closing round bracket at:"+ic2+"\n");
+ val= word.substring( ic0, ic2 );
+ if( traceLvl > 0 )
+ this.logWr( methName+": got val:["+val+"]\n");
+ ic0= ic2 + lenCBR;
+ if( ic0 >= lastCh ) {
+ errorMsg=
+ methName+": missing next expected round brackets after pos.#="+ic2+
+ " -bad format\n";
+ errMsgBadParm= errorMsg;
+ this.logWr( "Error: "+errorMsg );
+ return errorMsg;
+ };
+ var ic3= -1;
+ if( word.substr(ic0).startsWith(EQS) ) {
+ //.. found EQS
+ ic3= ic0;
+ }
+ else {
+ errorMsg=
+ methName+": no equal sign after 1-st closing round bracket at pos.#="+ic2+
+ " -bad format";
+ errMsgBadParm= errorMsg;
+ this.logWr( "Error: "+errorMsg+"\n" );
+ return errorMsg;
+ };
+ //.. got Equal sign after 1-st closing round bracket
+ ic0= ic3 + lenEQS;
+ if( ic0 >= lastCh ) {
+ errorMsg= methName+": missing next expected round brackets after pos.#="+ic3+
+ " -bad format";
+ errMsgBadParm= errorMsg;
+ this.logWr( "Error: "+errorMsg+"\n" );
+ return errorMsg;
+ };
+ var ic4= -1;
+ if( word.substr(ic0).startsWith(OBR) ) {
+ //.. found
+ ic4= ic0;
+ }
+ else {
+ errorMsg=
+ methName+": no 2-nd open round bracket after equal sign at pos.#="+ic3+
+ " -bad format";
+ errMsgBadParm= errorMsg;
+ this.logWr( "Error: "+errorMsg+"\n" );
+ return errorMsg;
+ };
+ //.. got 2-nd open round bracket
+ ic0= ic4 + lenOBR;
+ if( ic0 >= lastCh ) {
+ errorMsg=
+ methName+": missing next expected round bracket after pos.#="+ic4+
+ " -bad format";
+ errMsgBadParm= errorMsg;
+ this.logWr( "Error: "+errorMsg+"\n" );
+ return errorMsg;
+ };
+ var ic5= word.indexOf( CBR, ic0 );
+ if( ic5 < 0 ) {
+ errorMsg=
+ methName+": no 2-nd closing round bracket after 2-nd open bracket at pos.#="+
+ ic4+" -bad format";
+ errMsgBadParm= errorMsg;
+ this.logWr( "Error: "+errorMsg+"\n" );
+ return errorMsg;
+ };
+ //.. got 2-nd closing round bracket
+ // (also assuming the remaining chars are whitespaces)
+ parmNamAndVal.push( word.substring(ic0, ic5) );
+ parmNamAndVal.push( val );
+ if( traceLvl > 1 )
+ this.logWr( methName+": got param: name:["+parmNamAndVal[0]+"]\n value:["+
+ parmNamAndVal[1]+"]\n");
+ return ''; //.. empty error message means OK
+};
+
+exports.reportParamBadFmt = function (
+ lineNm, pword, formatErr, perrorFName, pstatFName )
+{
+ var methName= "reportParamBadFmt";
+ this.logWr( methName+": start: the param.name-value format is bad -Error!\n");
+ this.logWr( methName+": signalling error via percent = -1 \n");
+ var percent=-1;
+ var stmsg= '{\"percentage\":'+percent+'}';
+ this.updateProcStatus( pstatFName, stmsg );
+ this.logWr( methName+": writing the error message into a file "+
+ "for next request from the server...");
+ procErrorMsg= "Error: Bad Format of the parameter string";
+ if( pword != null && pword.length > 0 ) {
+ procErrorMsg += ":["+pword+"]";
+ };
+ var lineNmE= lineNm + 1; //.. line numbering in screen editor starts from 1
+ procErrorMsg += "\n Error found at line #:"+lineNmE;
+ procErrorMsg += "\n Error Details:["+formatErr+"]";
+ procErrorMsg += "\n Please, correct the error and try again.";
+ //.. using updateProcStatus to save the error message in a file
+ this.updateProcStatus( perrorFName, procErrorMsg );
+};
+
+exports.logWr = function ( msg ) {
+ // console.log(clName+": logWr: fdL="+this.fdL+" msg:["+msg+"]");
+ try {
+ fs.appendFileSync( this.fdL, msg, 'utf8' );
+ }
+ catch( err ) {
+ console.log(clName+": log uppend: error:"+err.message );
+ throw err;
+ };
+ // fs.appendFile( this.fdL, msg, 'utf8', (err) => {
+ // if( err ) {
+ // throw err;
+ // }
+ // });
+};
+
+ //.. processing percentage or error message
+exports.updateProcStatus = function ( pstfname, statusMsg ) {
+ var methName= "updateProcStatus";
+ this.logWr(methName+": start: pstfname:["+pstfname+"]\n");
+ var pstfname_p= pstfname+".pre";
+ this.logWr(methName+": new status: message["+statusMsg+"]\n");
+ var timeStamp = new Date().toISOString();
+ this.logWr( methName+": timeStamp:["+timeStamp+"]\n");
+ //.. pre-file
+ try {
+ this.fdPSt= fs.openSync( pstfname_p, 'a' );
+ }
+ catch( err ) {
+ this.logWr(clName+": status file open: error:["+err.message+"]\n");
+ throw err;
+ }
+ this.logWr(methName+": writing status: fdPSt="+this.fdPSt+"\n");
+ try {
+ fs.appendFileSync( this.fdPSt, statusMsg, 'utf8' );
+ }
+ catch( err ) {
+ this.logWr(clName+": status file append: error: code="+err.code );
+ throw err;
+ }
+ this.logWr(methName+": closing status file: fdPSt="+this.fdPSt+"\n");
+ fs.closeSync( this.fdPSt );
+ this.logWr(methName+": status file closed - final renaming...\n");
+ fs.renameSync( pstfname_p, pstfname );
+ this.logWr(methName+": status file renamed - finished.\n");
+};
+
+exports.wait = function ( secs ) {
+ var methName= "wait";
+ this.logWr(methName+": start: secs="+secs+"\n");
+ var inStr= String( secs );
+ // this.logWr(methName+": inStr:["+inStr+"]\n");
+ var s_args= new Array( 0 );
+ s_args.push( inStr );
+ var tmoutms= 500 +1000*secs;
+ var mopts= { timeout: tmoutms };
+ // this.logWr(methName+": mopts:["+ JSON.stringify(mopts)+"]\n");
+ var moutObj= Chproc.spawnSync( 'sleep', s_args, mopts);
+ this.logWr(methName+": moutObj: status:["+moutObj.status+"](0=ok)\n");
+ if( moutObj.error != null ) {
+ console.log(methName+": moutObj: Error:["+JSON.stringify(moutObj.error)+"]\n"); }
+};