Taka Cho | 1851089 | 2019-05-14 17:37:24 -0400 | [diff] [blame^] | 1 | /* |
| 2 | ============LICENSE_START========================================== |
| 3 | =================================================================== |
| 4 | Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. |
| 5 | =================================================================== |
| 6 | |
| 7 | Unless otherwise specified, all software contained herein is licensed |
| 8 | under the Apache License, Version 2.0 (the License); |
| 9 | you may not use this software except in compliance with the License. |
| 10 | You may obtain a copy of the License at |
| 11 | |
| 12 | http://www.apache.org/licenses/LICENSE-2.0 |
| 13 | |
| 14 | Unless required by applicable law or agreed to in writing, software |
| 15 | distributed under the License is distributed on an "AS IS" BASIS, |
| 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 17 | See the License for the specific language governing permissions and |
| 18 | limitations under the License. |
| 19 | |
| 20 | ============LICENSE_END============================================ */ |
| 21 | //.. subnproc.js -to be started by parent server process |
| 22 | const fs = require('fs'); |
| 23 | const Chproc = require('child_process'); |
| 24 | |
| 25 | var clName= "subnproc"; |
| 26 | var thePid= 0; |
| 27 | var taskId= ''; |
| 28 | //.. assuming all these files are in CDT_HOME |
| 29 | var inpFilePfx= "posted_data_"; |
| 30 | var outFilePfx= "sync_template_res_"; //.. processing results |
| 31 | var errFilePfx= "sync_template_err_"; //.. error found while processing |
| 32 | var parmFilePfx= "template_params_"; |
| 33 | var pstatfNamePfx= "proc_status_"; |
| 34 | //.. pDlm -delimiter of params |
| 35 | // (cant be: alphanumeric,underbar,dollar,dot,comma,brackets,dash,equal sign,etc) |
| 36 | var pDlm= '\n'; |
| 37 | var logfname= clName+".log"; |
| 38 | var logfname_o= logfname+".save"; //.. to keep old content |
| 39 | var fdL; |
| 40 | var fdIn; |
| 41 | var fdOut; |
| 42 | var errMsgBadParm= ''; //.. create error message to report to client |
| 43 | //var checkSpecialCharsReg= new RegExp(/[^\w\s-]/); |
| 44 | var checkSpecialCharsReg= new RegExp(/[^\w\s-\.]/); |
| 45 | var doStopOnSpecChars= 'Y'; |
| 46 | var doCheckComments= 'Y'; |
| 47 | //var SYNC_T_KEY_EXPRES= '\\${.+?\\}'; |
| 48 | var VSTART= '${'; |
| 49 | var VEND= '}'; |
| 50 | var lenVS= VSTART.length, lenVE= VEND.length; |
| 51 | var KEY_START= '${('; |
| 52 | var KEY_MID= ')=('; |
| 53 | var KEY_END= ')}'; |
| 54 | var LD= "\n"; //.. LD -line delimeter in the input file |
| 55 | var lenLD= LD.length; |
| 56 | var percAtRngs= 55; //.. percentage defining report to client |
| 57 | |
| 58 | var traceLvl= 1; |
| 59 | //var CCnt= 52; |
| 60 | var 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 | |
| 70 | try { |
| 71 | //.. need renameSync (not asynchronous) ! |
| 72 | fs.renameSync( LOG_DIR+"/"+logfname, LOG_DIR+"/"+logfname_o); |
| 73 | } |
| 74 | catch( 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 | }; |
| 79 | fs.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 | |
| 152 | exports.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 | |
| 527 | exports.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 | |
| 566 | exports.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) |
| 618 | exports.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 | |
| 756 | exports.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 | |
| 779 | exports.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 |
| 796 | exports.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 | |
| 826 | exports.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 | }; |