diff options
Diffstat (limited to 'src/app/subnproc.js')
-rw-r--r-- | src/app/subnproc.js | 840 |
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"); } +}; |