aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTaka Cho <takamune.cho@att.com>2019-05-14 17:37:24 -0400
committerPatrick Brady <patrick.brady@att.com>2019-05-15 13:37:58 -0700
commit1b147c2600face751f5cfe1f106d56e9558a5eff (patch)
tree9a8396947545062ed660c7c4322ed7d14c75e73d /src
parent163d9fede8614e721a8b754a556ab0443f546430 (diff)
add node.js api server for CDT
/api call need node.js api server to fix when clicking the Synchronize Definition Parameter. Change-Id: I4a3fd1ba045ed41fb2fdfec3b8f0364cd6ec05f5 Issue-ID: APPC-1600 Signed-off-by: Taka Cho <takamune.cho@att.com>
Diffstat (limited to 'src')
-rw-r--r--src/app/deleteOldData.js117
-rw-r--r--src/app/ndserver.js253
-rw-r--r--src/app/server-data-svc.js656
-rwxr-xr-xsrc/app/srvlogger.js96
-rw-r--r--src/app/subnproc.js840
5 files changed, 1962 insertions, 0 deletions
diff --git a/src/app/deleteOldData.js b/src/app/deleteOldData.js
new file mode 100644
index 0000000..f219633
--- /dev/null
+++ b/src/app/deleteOldData.js
@@ -0,0 +1,117 @@
+/*
+============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============================================ */
+//... deleteOldData.js - to be started by parent server process
+const fs = require('fs');
+
+var logger = require('./srvlogger');
+
+var clName= "deleteOldData";
+var cdt_home = ".";
+
+ this.thePid= process.pid;
+ console.log(clName+": thePid="+this.thePid );
+
+ console.log(clName+
+ ": execArgv:["+process.execArgv+"]\n argv:["+process.argv+"]");
+ var taskIdArgstr= process.argv[ 2 ];
+ var CDT_HOME= process.argv[ 3 ];
+ var LOG_DIR= process.argv[ 4 ];
+ console.log( clName+": argv: CDT_HOME:["+CDT_HOME+"]" );
+ var LogF= LOG_DIR+"/ndserver.log";
+ logger.addLog( clName+": start: CDT_HOME:["+CDT_HOME+"]\n",LogF);
+
+ var indT= taskIdArgstr.indexOf('=', 0);
+ if( indT < 0 ) {
+ this.taskId= taskIdArgstr;
+ } else {
+ this.taskId= taskIdArgstr.substr( indT+1 );
+ }
+ console.log(clName+": taskId:["+this.taskId+"]\n");
+ logger.addLog( clName+": taskId:["+this.taskId+"]\n",LogF);
+ if( this.taskId == null || this.taskId == undefined || this.taskId.length < 1 )
+ {
+ var errMsg= clName+": Error: taskId is empty !\n";
+ console.log( errMsg );
+ throw new Error( errMsg );
+ };
+ var inpFilePfx= CDT_HOME+"/posted_data_";
+ var outFilePfx= CDT_HOME+"/sync_template_res_";
+ var parmFilePfx= CDT_HOME+"/template_params_";
+ var pstatfNamePfx= CDT_HOME+"/proc_status_";
+
+ let timeStamp = new Date().toISOString();
+ // console.log(clName+": timeStamp:["+timeStamp+"]\n");
+ logger.addLog( clName+": timeStamp:["+timeStamp+"]\n",LogF);
+
+ var inpFile= inpFilePfx +this.taskId +".txt";
+ // console.log(clName+": deleting inpFile:\n"+inpFile );
+ logger.addLog( clName+": deleting inpFile:\n"+inpFile+"\n",LogF);
+
+ fs.unlink( inpFile, (err) => {
+ if( err) {
+ console.log(clName+
+ ": Error while deleting "+inpFile+"\n "+err.message+"]\n");
+ }
+ });
+
+ timeStamp = new Date().toISOString();
+ console.log(clName+": timeStamp:["+timeStamp+"]\n");
+
+ var pstatfName= pstatfNamePfx +this.taskId+".json";
+ console.log(clName+": deleting proc.status File:\n"+pstatfName );
+
+ fs.unlink( pstatfName, (err) => {
+ if( err) {
+ console.log(clName+
+ ": Error while deleting "+pstatfName+"\n "+err.message+"]\n");
+ }
+ });
+
+ timeStamp = new Date().toISOString();
+ console.log(clName+": timeStamp:["+timeStamp+"]\n");
+
+ var outFile= outFilePfx+ this.taskId+".txt";
+ console.log(clName+": deleting proc.result File:\n"+outFile );
+
+ fs.unlink( outFile, (err) => {
+ if( err) {
+ console.log(clName+
+ ": Error while deleting "+outFile+"\n "+err.message+"]\n");
+ }
+ });
+
+ timeStamp = new Date().toISOString();
+ console.log(clName+": timeStamp:["+timeStamp+"]\n");
+
+ var parmFile= parmFilePfx+ this.taskId+".txt";
+ console.log(clName+": deleting parameters File:\n"+parmFile+"]\n");
+
+ fs.unlink( parmFile, (err) => {
+ if( err) {
+ console.log(clName+
+ ": Error while deleting "+parmFile+"\n "+err.message+"]\n");
+ }
+ });
+
+ timeStamp = new Date().toISOString();
+ console.log(clName+": timeStamp:["+timeStamp+"]\n");
+
+ console.log(clName+": finish.");
diff --git a/src/app/ndserver.js b/src/app/ndserver.js
new file mode 100644
index 0000000..0826740
--- /dev/null
+++ b/src/app/ndserver.js
@@ -0,0 +1,253 @@
+/*
+============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============================================ */
+var express = require('express');
+var app = express();
+var https = require('https');
+var fs = require('fs');
+
+const options = {
+ key: fs.readFileSync(process.env.HTTPS_KEY_FILE),
+ cert: fs.readFileSync(process.env.HTTPS_CERT_FILE)
+};
+
+var bodyParser = require('body-parser');
+var textParser = bodyParser.text({ type: 'text/*' });
+
+const path = require('path');
+
+const PORT = process.env.PORT || 8080;
+const CDT_HOME= process.env.CDT_HOME;
+const LOG_DIR= process.env.LOG_DIR;
+const MaxLogSize= process.env.MaxLogSize || 3000000;
+//const DIST_FOLDER = path.join(process.cwd(), 'dist');
+//const DIST_FOLDER = path.join( CDT_HOME, 'dist');
+const LogF = path.join( LOG_DIR, 'ndserver.log' );
+
+var chproc = require("child_process");
+
+//var serverDataSvc = require('./dist/server-data-svc');
+var serverDataSvc = require('./server-data-svc');
+var logger = require('./srvlogger');
+
+app.get('/getUserRole*', (req, res) => {
+ console.log(`get: Start: /getUserRole/* route...`);
+ logger.addLog("get: Start: /getUserRole/* route...\n",LogF);
+ if( CDT_HOME != null ) {
+ logger.addLog("get: CDT_HOME:["+CDT_HOME+"]\n",LogF);
+ };
+ var respData= serverDataSvc.getUserRoles( req.url );
+ logger.addLog("get: /getUserRole/*: typeof response:["+
+ (typeof respData)+"]\n",LogF);
+
+ logger.addLog("get: /getUserRole/*: stringify respData:["+
+ JSON.stringify(respData).substr(0,300)+"...]\n",LogF);
+ if( respData.length != null && respData.length != undefined ) {
+ logger.addLog("get: /getUserRole/*: respData.length="+
+ respData.length+"\n",LogF);
+ } else {
+ logger.addLog("get: /getUserRole/*: respData.length not defined !\n",LogF);
+ };
+ res.status(200).send( respData );
+ let timeStamp = new Date().toISOString();
+ logger.addLog("get: done: timeStamp:["+timeStamp+"]\n",LogF);
+});
+
+app.get('/api/*', (req, res) => {
+ console.log(`get: Start: /api/* route...`);
+ logger.addLog("get: Start: /api/* route...\n",LogF);
+ if( req.url == null ) {
+ console.log("get: /api/*: req.url is null !");
+ logger.addLog("get: /api/*: req.url is null !\n",LogF);
+ }
+ else {
+ // console.log("get: /api/*: req.url:["+ req.url+"]");
+ logger.addLog("get: /api/*: req.url:["+ req.url+"]\n",LogF);
+ };
+ if( req.hostname == null ) {
+ console.log("get: /api/*: req.hostname is null !");
+ logger.addLog("get: /api/*: req.hostname is null !\n",LogF);
+ }
+ else {
+ // console.log("get: /api/*: req.hostname:["+ req.hostname+"]");
+ logger.addLog("get: /api/*: req.hostname:["+ req.hostname+"]\n",LogF);
+ };
+ if( req.params != null ) {
+ // console.log("get: /api/*: Have req.params ...");
+ logger.addLog("get: /api/*: Have req.params ...\n",LogF);
+ if( req.params.length != null ) {
+ // console.log("get: /api/*: req.params.length="+req.params.length );
+ logger.addLog("get: /api/*: req.params.length="+req.params.length+"\n",LogF);
+ }
+ };
+ if( req.socket != null ) {
+ // console.log("get: /api/*: Have req.socket ...");
+ logger.addLog("get: /api/*: Have req.socket ...\n",LogF);
+ if( req.socket.remoteAddress != null ) {
+ // console.log("get: /api/*: remoteAddress:["+ req.socket.remoteAddress+"]");
+ logger.addLog(
+ "get: /api/*: remoteAddress:["+ req.socket.remoteAddress+"]\n",LogF);
+ }
+ else {
+ console.log("get: /api/*: req.socket.remoteAddress is null !");
+ logger.addLog("get: /api/*: req.socket.remoteAddress is null !\n",LogF);
+ }
+ };
+ if( CDT_HOME != null ) {
+ logger.addLog("get: CDT_HOME:["+CDT_HOME+"]\n",LogF);
+ };
+ var respData= serverDataSvc.getData( req.url );
+ logger.addLog("get: /api/*: typeof response:["+(typeof respData)+"]\n",LogF);
+ if( typeof respData == "string" ) {
+ logger.addLog("get: /api/*: respData:length="+respData.length+"\n",LogF);
+ };
+ logger.addLog("get: /api/*: stringify respData:["+
+ JSON.stringify(respData).substr(0,300)+"...]\n",LogF);
+ if( respData.length != null && respData.length != undefined ) {
+ logger.addLog("get: /api/*: respData.length="+respData.length+"\n",LogF);
+ } else {
+ logger.addLog("get: /api/*: respData.length not defined !\n",LogF);
+ };
+ res.status(200).send( respData );
+ let timeStamp = new Date().toISOString();
+ logger.addLog("get: /api/* done: timeStamp:["+timeStamp+"]\n\n",LogF);
+});
+
+app.post('/api/*', textParser, (req, res) => {
+ console.log(`post: Start: /api/* route...`);
+ logger.addLog("post: Start: /api/* route...\n",LogF);
+ let timeStamp = new Date().toISOString();
+ logger.addLog("post: /api/*: timeStamp:["+timeStamp+"]\n\n",LogF);
+ if( req.url == null ) {
+ console.log("post: /api/*: req.url is null !");
+ logger.addLog("post: /api/*: req.url is null !\n",LogF);
+ }
+ else {
+ console.log("post: /api/*: req.url:["+ req.url+"]");
+ logger.addLog("post: /api/*: req.url:["+ req.url+"]\n",LogF);
+ };
+ if( req.body == null ) {
+ console.log("post: /api/*: req.body is null !");
+ }
+ else {
+ console.log("post: /api/*: req.body.length="+req.body.length );
+ };
+ if( req.headers != null ) {
+ console.log("post: /api/*: req.headers.length="+ req.headers.length );
+ };
+ var remAddr= '';
+ if( req.socket != null ) {
+ console.log("post: /api/*: Have req.socket ...");
+ logger.addLog("post: /api/*: Have req.socket ...\n",LogF);
+ if( req.socket.remoteAddress != null ) {
+ logger.addLog(
+ "post: /api/*: remoteAddress:["+ req.socket.remoteAddress+"]\n",LogF);
+ remAddr= req.socket.remoteAddress;
+ }
+ else {
+ console.log("post: /api/*: req.socket.remoteAddress is null !");
+ logger.addLog("post: /api/*: req.socket.remoteAddress is null !\n",LogF);
+ }
+ };
+ logger.addLog(
+ "post: /api/*: req.params:["+JSON.stringify(req.params)+"]\n",LogF);
+ //.. checking url
+ var rexpLR= new RegExp(/\/api\/post_logrec/);
+ var matchLR= rexpLR.exec( req.url );
+ var rspData= 'r_undef';
+ if( matchLR ) {
+ //.. posting server-side log record
+ logger.addLog("post: /api/*: start postLog: remAddr:["+remAddr+"]\n",LogF);
+ rspData= serverDataSvc.postSrvLogRec( req.url, req.body, remAddr );
+ logger.addLog("post: /api/*: to send: response:["+rspData+"]\n",LogF);
+ }
+ else { //.. process data request
+ logger.addLog("post: /api/*: start procReq: remAddr:["+remAddr+"]\n",LogF);
+ rspData= serverDataSvc.procReq( req.url, req.body, remAddr );
+ logger.addLog("post: /api/*: to send: response:["+rspData+"]\n",LogF);
+ var rspObj= JSON.parse(rspData);
+ if( rspObj.respStr != null && rspObj.respStr != undefined ) {
+ var respStrLen= rspObj.respStr.length;
+ logger.addLog("post: /api/*: respStr length="+respStrLen+"\n",LogF);
+ if( respStrLen < 60 ) {
+ logger.addLog("post: /api/*: rspObj.respStr:["+rspObj.respStr+"]\n",LogF);
+ } else {
+ logger.addLog("post: /api/*: rspObj.respStr(part):["+
+ rspObj.respStr.substr(0,60)+"]\n",LogF);
+ }
+ }
+ }
+ res.status(200).send( rspData );
+ timeStamp = new Date().toISOString();
+ logger.addLog("post: done: timeStamp:["+timeStamp+"]\n\n",LogF);
+});
+
+//.. express.static to serve static files from /browser
+//app.get('*.*', express.static(DIST_FOLDER) );
+app.get('*.*', express.static(CDT_HOME) );
+
+// All regular routes use the Universal engine
+app.get('*', (req, res) => {
+ console.log(`get: Start: regular route...`);
+ logger.addLog("get: * Start: regular route...\n",LogF);
+ if( req.url == null ) {
+ console.log("get: req.url is null !");
+ logger.addLog("get: * regular route req.url is null !\n",LogF);
+ }
+ else {
+ console.log("get: req.url:["+ req.url+"]");
+ logger.addLog("get: * regular route: req.url:["+ req.url+"]\n",LogF);
+ };
+ if( CDT_HOME != null ) {
+ logger.addLog("get: * CDT_HOME:["+CDT_HOME+"]\n",LogF);
+ };
+ if( req.socket != null ) {
+ logger.addLog("get: * Have req.socket ...\n",LogF);
+ if( req.socket.remoteAddress != null ) {
+ logger.addLog(
+ "get: *: remoteAddress:["+ req.socket.remoteAddress+"]\n",LogF);
+ }
+ else {
+ logger.addLog("get: *: req.socket.remoteAddress is null !\n",LogF);
+ }
+ };
+ var respData= serverDataSvc.getData( req.url );
+ logger.addLog("get: *: typeof response:["+(typeof respData)+"]\n",LogF);
+ if( typeof respData == "string" ) {
+ logger.addLog("get: *: respData:length="+respData.length+"\n",LogF);
+ };
+ // logger.addLog("get: *: respData:["+JSON.stringify(respData)+"]\n",LogF);
+ res.status(200).send( respData );
+ let timeStamp = new Date().toISOString();
+ logger.addLog("get: * done: timeStamp:["+timeStamp+"]\n\n",LogF);
+});
+
+// Start up the Node server
+https.createServer(options,app).listen(PORT, () => {
+ console.log(`Node server: CDT_HOME:[${CDT_HOME}]`);
+ console.log(`Node server: LOG_DIR:[${LOG_DIR}]`);
+ console.log(`Node server: opening Log in the file:[${LogF}]`);
+ console.log(`Node server listening on http://localhost:${PORT}`);
+ // console.log(" DIST_FOLDER:["+DIST_FOLDER+"]");
+ logger.setMaxLogSize( MaxLogSize );
+ logger.addLog("\n Node server: start: CDT_HOME:["+CDT_HOME+"]\n",LogF);
+ serverDataSvc.setHomeDir( CDT_HOME, LOG_DIR );
+});
+
diff --git a/src/app/server-data-svc.js b/src/app/server-data-svc.js
new file mode 100644
index 0000000..cb62f52
--- /dev/null
+++ b/src/app/server-data-svc.js
@@ -0,0 +1,656 @@
+/*
+============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============================================ */
+//.. processing on server side
+'use strict';
+
+const fs = require('fs');
+//var spawn = require("child_process").spawn;
+var Chproc = require("child_process");
+var logger = require('./srvlogger');
+
+var clName= "ServerDataSvc";
+//const DIST_FLDR = join(process.cwd(), 'dist');
+//var DIST_FLDR = "dist";
+var cdt_home = ".";
+var LOG_DIR = "/tmp";
+var LogF = "ndserver.log";
+var SubProcScript= "/app/subnproc.js";
+//var HTML_ROOT_FLDR= DIST_FLDR;
+//var DelScript= DIST_FLDR +"/app/deleteOldData.js";
+//var inputFilePfx = DIST_FLDR +"/posted_data_";
+var fsAvSpaceKB= -1;
+var rsfname= "";
+var remAddr= ""; //.. remote client address
+var taskId= "";
+var fdI;
+var fdRsf;
+var fDelim= "&";
+
+ //.. to be called by server at initialization
+exports.setHomeDir = function( homeDir, logDir ) {
+ this.cdt_home= homeDir;
+ this.LOG_DIR= logDir;
+ // this.DIST_FLDR= this.cdt_home+"/dist";
+ this.LogF= this.LOG_DIR+"/ndserver.log";
+ console.log( clName+": setHomeDir: cdt_home:["+this.cdt_home+"]");
+ console.log( clName+": setHomeDir: LogF:["+this.LogF+"]");
+};
+
+ //.. to be called by server on receiving GET /getUserRole request
+ // (simulation only)
+exports.getUserRoles = function( requrl ) {
+ var methName= "getUserRoles";
+ logger.addLog( clName+": "+methName+
+ ": start: url:["+ requrl+"]\n cdt_home:["+this.cdt_home+"]\n",this.LogF);
+ let timeStamp = new Date().toISOString();
+ logger.addLog( clName+": "+methName+": timeStamp:["+timeStamp+"]\n",this.LogF);
+ var resp= '{\"respStr\":\"notfoundResp\"}';
+ this.urolfname= this.cdt_home+"/userRoles.json";
+ resp= this.readResultFile( this.urolfname );
+ logger.addLog( clName+": "+methName+
+ ": result length="+resp.length+"\n",this.LogF);
+ return resp;
+};
+
+ //.. to be called by server on receiving GET /api/* request
+exports.getData = function( requrl ) {
+ var methName= "getData";
+ //console.log(clName+": getData: start: url:["+ requrl+"]\n cdt_home:["+
+ // this.cdt_home+"]");
+ logger.addLog( clName+": "+methName+
+ ": start: url:["+ requrl+"]\n cdt_home:["+this.cdt_home+"]\n",this.LogF);
+ let timeStamp = new Date().toISOString();
+ logger.addLog( clName+": "+methName+": timeStamp:["+timeStamp+"]\n",this.LogF);
+ var resp= '{\"respStr\":\"notfoundResp\"}';
+ var taskStr= "taskId=";
+ //... Regular Expressions for different requests ...
+ //.. to get processing result
+ var rexpGRESUL= new RegExp(/\/api\/get_result/);
+ //.. to get progress percentage of the processing
+ var rexpGPROGR= new RegExp(/\/api\/get_progress/);
+ //.. to get parameters calculated via the processing
+ var rexpGPRMS= new RegExp(/\/api\/get_params/);
+ //.. to get parameters format-error file
+ var rexpPFMTERR= new RegExp(/\/api\/get_pfmterr/);
+ //.. to get Available space in server-side file-system
+ var rexpGFSAVSP= new RegExp(/\/api\/get_fsAvSpace/);
+ //.. to check for ACE-editor resource files
+ var rexpACERES= new RegExp(/\/node_modules\/ace-builds\/src-min/);
+ //
+ //... checking which url is matching ...
+ if( requrl == '/' ) {
+ // console.log(clName+": getData: this is a ROOT request ...");
+ logger.addLog( clName+": getData: this is a ROOT request ...\n",this.LogF);
+ return this.getRoot();
+ };
+ //.. non-root, api url
+ var match1= null;
+ if( (match1= rexpGRESUL.exec(requrl)) != null ) {
+ logger.addLog( clName+": "+methName+": URL match /api/get_result\n",this.LogF);
+ //.. assuming: /api/get_result?taskId=f7be82e43e34cb4e960b45d35e8d9596
+ var indT= requrl.indexOf( taskStr, 0);
+ if( indT < 0 ) {
+ var errMsg=
+ clName+": "+methName+": Error: No taskId found in the URL !\n";
+ logger.addLog( errMsg,this.LogF);
+ resp= '{\"Error\":\"'+errMsg+'\"}';
+ }
+ else { //.. indT > -1 - have taskId in URL
+ this.taskId= requrl.substr( indT+ taskStr.length );
+ logger.addLog( clName+": "+methName+
+ ": extracted from URL: taskId:["+this.taskId+"]\n",this.LogF);
+ this.rsfname= this.cdt_home+"/sync_template_res_"+this.taskId+".txt";
+ resp= this.readResultFile( this.rsfname );
+ logger.addLog( clName+": "+methName+
+ ": result length="+resp.length+"\n",this.LogF);
+ logger.addLog( clName+": "+methName+
+ ": got result -Start data cleanup...\n",this.LogF);
+ this.deleteOldFiles( this.taskId );
+ };
+ }
+ else
+ if( (match1= rexpGPROGR.exec(requrl)) != null ) {
+ logger.addLog( clName+": "+methName+
+ ": URL match /api/get_progress\n",this.LogF);
+ //.. assuming: /api/get_progress?taskId=f7be82e43e34cb4e960b45d35e8d9596
+ var indT= requrl.indexOf( taskStr, 0);
+ if( indT < 0 ) {
+ var errMsg=
+ clName+": "+methName+": Error: No taskId found in the URL !\n";
+ logger.addLog( errMsg,this.LogF);
+ resp= '{\"Error\":\"'+errMsg+'\"}';
+ }
+ else { //.. indT > -1 - have taskId in URL
+ this.taskId= requrl.substr( indT+ taskStr.length );
+ logger.addLog( clName+": "+methName+
+ ": extracted from URL: taskId:["+this.taskId+"]\n",this.LogF);
+ this.pgfname= this.cdt_home+"/proc_status_"+this.taskId+".json";
+ // resp= '{\"percentage\":\"3\"}';
+ resp= this.readResultFile( this.pgfname );
+ }
+ logger.addLog( clName+": "+methName+
+ ": result length="+resp.length+"\n",this.LogF);
+ logger.addLog( clName+": "+methName+": progress:["+resp+"]\n",this.LogF);
+ }
+ else
+ if( (match1= rexpGPRMS.exec(requrl)) != null ) {
+ logger.addLog( clName+": "+methName+
+ ": URL match /api/get_params\n",this.LogF);
+ //.. assuming: /api/get_params?taskId=f7be82e43e34cb4e960b45d35e8d9596
+ var indT= requrl.indexOf( taskStr, 0);
+ if( indT < 0 ) {
+ var errMsg=
+ clName+": "+methName+": Error: No taskId found in the URL !\n";
+ logger.addLog( errMsg,this.LogF);
+ resp= '{\"Error\":\"'+errMsg+'\"}';
+ }
+ else { //.. indT > -1 - have taskId in URL
+ this.taskId= requrl.substr( indT+ taskStr.length );
+ logger.addLog( clName+": "+methName+
+ ": extracted from URL: taskId:["+this.taskId+"]\n",this.LogF);
+ var prmfname= this.cdt_home+"/template_params_"+this.taskId+".txt";
+ resp= this.readResultFile( prmfname );
+ }
+ logger.addLog( clName+": "+methName+
+ ": params length="+resp.length+"\n",this.LogF);
+ }
+ else
+ if( (match1= rexpPFMTERR.exec(requrl)) != null ) {
+ //.. parameter format error file
+ logger.addLog( clName+": "+methName+
+ ": URL match /api/get_pfmterr\n",this.LogF);
+ //.. assuming: /api/get_pfmterr?taskId=f7be82e43e34cb4e960b45d35e8d9596
+ var indT= requrl.indexOf( taskStr, 0);
+ if( indT < 0 ) {
+ var errMsg=
+ clName+": "+methName+": Error: No taskId found in the URL !\n";
+ logger.addLog( errMsg,this.LogF);
+ resp= '{\"Error\":\"'+errMsg+'\"}';
+ }
+ else { //.. indT > -1 - have taskId in URL
+ this.taskId= requrl.substr( indT+ taskStr.length );
+ logger.addLog( clName+": "+methName+
+ ": extracted from URL: taskId:["+this.taskId+"]\n",this.LogF);
+ var errfname= this.cdt_home+"/sync_template_err_"+this.taskId+".txt";
+ resp= this.readResultFile( errfname );
+ }
+ logger.addLog( clName+": "+methName+
+ ": params length="+resp.length+"\n",this.LogF);
+ }
+ else
+ if( (match1= rexpGFSAVSP.exec(requrl)) != null ) {
+ //.. Available Space in Server-side file-system
+ logger.addLog( clName+": "+methName+
+ ": URL match /api/get_fsAvSpace \n",this.LogF);
+ var errMsg= this.getFsAvailSpace( this.cdt_home );
+ if( errMsg.length > 0 ) {
+ //.. return non-empty Error message
+ resp= '{\"Error\":\"'+errMsg+'\"}';
+ }else{
+ resp= fsAvSpaceKB; //.. empty return means no error
+ };
+ }
+ else
+ if( (match1= rexpACERES.exec(requrl)) != null ) {
+ //.. (simulated env.) ACE-editor resource files
+ logger.addLog( clName+": "+methName+
+ ": URL match /node_modules/ace-builds...\n",this.LogF);
+ var acebldStr= "src-min\/";
+ var indAB= requrl.indexOf( acebldStr, 0);
+ if( indAB < 0 ) {
+ logger.addLog( clName+": "+methName+
+ ": Warn: No URL match("+acebldStr+").\n",this.LogF);
+ }
+ else { //.. indAB > -1 -got acebldStr
+ var acefname= requrl.substr( indAB +acebldStr.length );
+ logger.addLog( clName+": "+methName+
+ ": req.file name:["+acefname+"]\n",this.LogF);
+ // if( acefname == "mode-velocity.js" || acefname == "theme-chrome.js" )
+ if( acefname == "mode-velocity.js" )
+ {
+ var aresfname= this.cdt_home+"/app/"+acefname;
+ resp= this.readResultFile( aresfname );
+ }
+ else {
+ logger.addLog( clName+": "+methName+
+ ": Warn: No ace URL match("+acebldStr+"...js).\n",this.LogF);
+ }
+ }
+ }
+ else { //..
+ logger.addLog( clName+": "+methName+
+ ": Warn: No URL match - nothing to do !\n",this.LogF);
+ };
+ logger.addLog( clName+": "+methName+
+ ": resp.length="+resp.length+"\n finish.\n",this.LogF);
+ return resp;
+};
+
+exports.deleteOldFiles = function( ctaskId ) {
+ var methName= "deleteOldFiles";
+ logger.addLog( clName+": "+methName+
+ ": start. the complete task Id:["+ctaskId+"]\n",this.LogF);
+ var cp_args= new Array( 0 );
+ cp_args.push( ctaskId ); //.. give it taskId in args
+ cp_args.push( cdt_home );
+ cp_args.push( LOG_DIR );
+ var DelScript= this.cdt_home +"/app/deleteOldData.js";
+ var chprocI= Chproc.fork( DelScript, cp_args );
+ logger.addLog( clName+": "+methName+
+ ": DelScript started ...\n",this.LogF);
+ let timeStamp = new Date().toISOString();
+ logger.addLog( clName+": "+methName+": timeStamp:["+timeStamp+"]\n",this.LogF);
+};
+
+exports.getRoot = function() {
+ var methName= "getRoot";
+ logger.addLog( clName+": "+methName+": start. ROOT URL match \n",this.LogF);
+ logger.addLog( clName+": "+methName+
+ ": cdt_home:["+this.cdt_home+"]\n",this.LogF);
+ var HTML_ROOT_FLDR= this.cdt_home;
+ this.rsfname= HTML_ROOT_FLDR+"/index.html";
+ var resp= this.readResultFile( this.rsfname );
+ logger.addLog( clName+": "+methName+
+ ": result length="+resp.length+"\n",this.LogF);
+ logger.addLog( clName+": "+methName+": resp:["+resp+"]\n",this.LogF);
+ return resp;
+};
+
+exports.readResultFile = function( rfname ) {
+ var methName= "readResultFile";
+ //.. read processing result from file and send back to the client
+ logger.addLog( clName+": "+methName+
+ ": start. rfname:["+rfname+"]\n",this.LogF);
+ var rdata= "";
+ try {
+ rdata= fs.readFileSync( rfname, 'utf8');
+ }
+ catch( err ) {
+ logger.addLog( clName+": "+methName+
+ ": result-file read: Error: code="+err.code+"\n",this.LogF);
+ throw err;
+ }
+ logger.addLog( clName+": "+methName+
+ ": result-file content length="+rdata.length+"\n",this.LogF);
+ return rdata;
+};
+
+exports.postSrvLogRec = function ( requrl, inpdata, remaddr ) {
+ //.. to be called by server on receiving POST /api/post_logrec request
+ var methName= "postSrvLogRec";
+ logger.addLog( clName+": "+methName+
+ ": start: url:["+ requrl+"]\n",this.LogF);
+ let timeStamp = new Date().toISOString();
+ logger.addLog( clName+": "+methName+": timeStamp:["+timeStamp+"]\n",this.LogF);
+ logger.addLog( clName+": "+methName+
+ ": cdt_home:\n["+cdt_home+"]\n",this.LogF);
+ logger.addLog( clName+": "+methName+
+ ": client: remaddr:["+ remaddr+"]\n",this.LogF);
+ if( remaddr != null && remaddr != undefined ) {
+ this.remAddr= remaddr;
+ };
+ logger.addLog( clName+": "+methName+
+ ": Log Record:\n-["+inpdata+"]-\n",this.LogF);
+ var resp= '{\"respStr\":\"OK\"}';
+ logger.addLog( clName+": "+methName+": done: resp:["+resp+"]\n",this.LogF);
+ return( resp );
+};
+
+exports.procReq = function ( requrl, inpdata, remaddr ) {
+ //.. to be called by server on receiving POST /api/* request
+ // receive input data, save into a file and start server-side processing task
+ var methName= "procReq";
+ logger.addLog( clName+": "+methName+
+ ": start: url:["+ requrl+"]\n",this.LogF);
+ let timeStamp = new Date().toISOString();
+ logger.addLog( clName+": "+methName+": timeStamp:["+timeStamp+"]\n",this.LogF);
+ logger.addLog( clName+": "+methName+
+ ": cdt_home:\n["+cdt_home+"]\n",this.LogF);
+ logger.addLog( clName+": "+methName+
+ ": client: remaddr:["+ remaddr+"]\n",this.LogF);
+ if( remaddr != null && remaddr != undefined ) {
+ this.remAddr= remaddr;
+ };
+ logger.addLog( clName+": "+methName+
+ ": remAddr:["+ this.remAddr+"]\n",this.LogF);
+ var inpdLen= inpdata.length;
+ logger.addLog( clName+": "+methName+": inpdata length="+inpdLen+"\n",this.LogF);
+ if( inpdLen > 300 ) {
+ logger.addLog( clName+": "+methName+
+ ": inpdata:\n["+inpdata.substr(0,299)+"...]\n",this.LogF);
+ }else{
+ logger.addLog( clName+": "+methName+
+ ": inpdata:\n["+inpdata+"]\n",this.LogF);
+ };
+ var resp= '{\"respStr\":\"postNotFoundResp\"}';
+ var taskStr= "taskId=";
+ var rexp2= new RegExp(/\/api\/proc_cont/);
+ var match2= rexp2.exec( requrl );
+ if( match2 ) {
+ logger.addLog( clName+": "+methName+
+ ": URL match: proc_cont - processing content...\n",this.LogF);
+ //.. check available space before server-side processiong
+ var emsg= this.getFsAvailSpace( this.cdt_home );
+ var doAdd= ''; //.. false
+ var doProc= ''; //.. false
+ //.. assuming format:
+ // url: /api/proc_cont?taskId=1fcf9ebb05cec21caeb71ebac7e34b2c&part=2of2
+ var indT= requrl.indexOf( taskStr, 0);
+ if( indT < 0 ) {
+ logger.addLog( clName+": "+methName+
+ ": Warn: No taskId found in the URL - New Task !\n",this.LogF);
+ this.calcTaskId();
+ logger.addLog( clName+": "+methName+
+ ": calculated New taskId:["+this.taskId+"]\n", this.LogF);
+ resp= '{\"respStr\":\"proc_start\",\"taskId\":\"'+this.taskId+'\"}';
+ }
+ else { //.. indT > -1 - have taskId in URL
+ var indTV= indT+ taskStr.length;
+ var indDL= requrl.indexOf( fDelim, indTV );
+ if( indDL < 0 ) {
+ logger.addLog( clName+": "+methName+
+ ": no more fields after taskId.\n",this.LogF);
+ this.taskId= requrl.substr( indTV );
+ }else{ //.. found delimiter
+ this.taskId= requrl.substring( indTV, indDL );
+ };
+ logger.addLog( clName+": "+methName+
+ ": extracted from URL: taskId:["+this.taskId+"]\n", this.LogF);
+ doAdd= "true"; //.. will add to old content
+ resp= '{\"respStr\":\"proc_upload\"}'; //.. no return of old taskId
+ }
+ var inputFilePfx = this.cdt_home +"/posted_data_";
+ var infname= inputFilePfx +this.taskId +".txt";
+ logger.addLog( clName+": "+methName+
+ ": got input file name:["+infname+"]\n",this.LogF);
+ //.. extracting parts info, e.g.: "...&part=2of2"
+ var rexp2p= new RegExp(/part=(\d+)of(\d+)/);
+ var match2p= rexp2p.exec( requrl );
+ if( match2p == null ) {
+ logger.addLog( clName+": "+methName+
+ ": Warn: No part number found in the URL "+
+ "-cant determine the last part !\n",this.LogF);
+ }
+ else { //.. match2p != null
+ logger.addLog( clName+": "+methName+
+ ": match2p: length="+match2p.length+"\n",this.LogF);
+ for( var i1=0; i1 < match2p.length; i1++ ) {
+ logger.addLog( clName+": "+methName+
+ ": match2p:["+match2p[i1]+"]\n",this.LogF);
+ };
+ var partNum= match2p[ 1];
+ var partCnt= match2p[ 2];
+ logger.addLog( clName+": "+methName+
+ ": partNum:["+partNum+"] partCnt:["+partCnt+"]\n",this.LogF);
+ if( partNum == partCnt ) {
+ logger.addLog( clName+": "+methName+
+ ": this is the last part -need doProc\n",this.LogF);
+ doProc= "true";
+ };
+ };
+ //.. write data into the file and start processing right after the close
+ var errW= this.writeInp2File( infname, inpdata, doAdd, doProc );
+ if( errW.length > 0 ) {
+ resp= errW;
+ };
+ }
+ else { //.. no match2
+ logger.addLog( clName+": "+methName+": Warn: No URL match.\n",this.LogF);
+ }
+ logger.addLog( clName+": "+methName+": done: resp:["+resp+"]\n",this.LogF);
+ return( resp );
+};
+
+exports.getFsAvailSpace = function ( fspath ) {
+ var methName= "getFsAvailSpace";
+ //.. get available space (kB) in filesystem where the fspath is mounted
+ logger.addLog( clName+": "+methName+
+ ": start: fspath:\n["+fspath+"]\n",this.LogF);
+ var timeStampI = Date.now();
+ logger.addLog( clName+": "+methName+": timeStampI="+timeStampI+"\n",this.LogF);
+ var timeStamp = new Date( timeStampI ).toISOString();
+ logger.addLog( clName+": "+methName+": timeStamp:["+timeStamp+"]\n",this.LogF);
+ if( fspath.length < 1 ) {
+ var errMsg= methName+": Error: the filesystem directory path is empty !";
+ logger.addLog( clName+ errMsg+"\n", this.LogF);
+ return errMsg;
+ };
+ // var carg= "-k "+fspath;
+ // var mopts= { input: carg, timeout: 4000 };
+ //var moutObj= Chproc.spawnSync('df',[],mopts);
+ var c_args= new Array( 0 );
+ c_args.push( '-k' );
+ c_args.push( fspath );
+ var mopts= { timeout: 4000 };
+ logger.addLog( clName+": "+methName+
+ ": mopts:["+JSON.stringify(mopts)+"]\n",this.LogF);
+ //.. start
+ var moutObj= Chproc.spawnSync('df', c_args, mopts);
+ logger.addLog( clName+": "+methName+
+ ": df done: moutObj: status:["+moutObj.status+"](0 means Ok)\n",this.LogF);
+ var timeStampI = Date.now();
+ logger.addLog( clName+": "+methName+": timeStampI="+timeStampI+"\n",this.LogF);
+ if( moutObj.error != null ) {
+ var errMsg= clName+": "+methName+
+ ": spawn df: Error:["+JSON.stringify(moutObj.error)+"]";
+ logger.addLog( errMsg+"\n", this.LogF);
+ return errMsg;
+ };
+ logger.addLog( clName+": "+methName+
+ ": df moutObj.output: length="+moutObj.output.length+"\n",this.LogF);
+ if( moutObj.output.length > 0 ) {
+ for( var i0=0; i0 < moutObj.output.length; i0++ ) {
+ logger.addLog( clName+": "+methName+
+ ": moutObj.output["+i0+"]:["+moutObj.output[i0]+"]\n",this.LogF);
+ }; //.. loop
+ //.. output[1]: should contain 2 lines:
+ // [Filesystem 1K-blocks Used Available Use% Mounted on\n
+ // /dev/dm-0 37383720 8933604 26528068 26% /\n]
+ var out1= moutObj.output[1];
+ logger.addLog( clName+": "+methName+": to parse out1:["+out1+"]\n",this.LogF);
+ var rexp1= new RegExp(/\s+(\d+)\s+(\d+)\s+(\d+)\s+/);
+ logger.addLog( clName+": "+methName+": rexp1:["+rexp1+"]\n",this.LogF);
+ var matchArr= rexp1.exec( out1 );
+ if( matchArr == null ) {
+ var errMsg= clName+": "+methName+
+ ": spawn: Error: No digitals (bytes counts) found in the output !";
+ logger.addLog( errMsg+"\n", this.LogF);
+ return errMsg;
+ };
+ if( matchArr[3] == null || matchArr[3] == undefined ) {
+ var errMsg= clName+": "+methName+
+ ": parsed: Error: The 3-rd byte count is empty (no Available Kbytes) !";
+ logger.addLog( errMsg+"\n", this.LogF);
+ return errMsg;
+ };
+ fsAvSpaceKB= matchArr[3];
+ logger.addLog( clName+": "+methName+
+ ": extracted fsAvSpaceKB="+fsAvSpaceKB+"\n",this.LogF);
+ }else{
+ var errMsg= clName+": "+methName+
+ ": spawn: Error: Empty df-command output array !";
+ logger.addLog( errMsg+"\n", this.LogF);
+ return errMsg;
+ }
+ logger.addLog( clName+": "+methName+": finished.\n",this.LogF);
+ return '';
+};
+
+exports.calcTaskId = function () {
+ var methName= "calcTaskId";
+ //.. calculate taskId
+ logger.addLog( clName+": "+methName+": start:\n",this.LogF);
+ var timeStampI = Date.now();
+ logger.addLog( clName+": "+methName+": timeStampI="+timeStampI+"\n",this.LogF);
+ var timeStamp = new Date( timeStampI ).toISOString();
+ logger.addLog( clName+": "+methName+": timeStamp:["+timeStamp+"]\n",this.LogF);
+
+ var rawId = String( this.remAddr+'-'+timeStampI );
+ logger.addLog( clName+": "+methName+": rawId:["+rawId+"]\n",this.LogF);
+
+ var mopts= { input: rawId, timeout: 4000 };
+ logger.addLog( clName+": "+methName+
+ ": mopts:["+JSON.stringify(mopts)+"]\n",this.LogF);
+
+ var moutObj= Chproc.spawnSync('md5sum',[],mopts);
+ logger.addLog( clName+": "+methName+
+ ": moutObj: status:["+moutObj.status+"]\n",this.LogF);
+ if( moutObj.error != null ) {
+ logger.addLog( clName+": "+methName+
+ ": moutObj calc.: Error:["+JSON.stringify(moutObj.error)+"]\n",this.LogF);
+ throw moutObj.error;
+ }
+ else { //.. no errors
+ logger.addLog( clName+": "+methName+
+ ": moutObj: output: length="+moutObj.output.length+"\n",this.LogF);
+ if( moutObj.output.length > 0 ) {
+ for( var i0=0; i0 < moutObj.output.length; i0++ ) {
+ logger.addLog( clName+": "+methName+
+ ": moutObj: output:["+moutObj.output[i0]+"]\n",this.LogF);
+ }
+ }
+ var out1= moutObj.output[ 1 ];
+ logger.addLog( clName+": "+methName+": out1:["+out1+"]\n",this.LogF);
+ var rexp1= new RegExp(/\w+/); //.. alphanumeric
+ logger.addLog( clName+": "+methName+": rexp1:["+rexp1+"]\n",this.LogF);
+ var match1= rexp1.exec( out1 );
+ if( match1 == null ) {
+ logger.addLog( clName+": "+methName+
+ ": Warn.: No Match of rexp1 in the cmd output (No taskId) !\n",this.LogF);
+ }
+ else {
+ logger.addLog( clName+": "+methName+
+ ": match1:["+match1[0]+"] length="+match1.length+"\n",this.LogF);
+ this.taskId= match1[0];
+ };
+ };
+ logger.addLog( clName+": "+methName+
+ ": done: calculated taskId:["+this.taskId+"]\n",this.LogF);
+};
+
+exports.writeInp2File = function ( fname, inpd, doAdd, doProc ) {
+ var methName= "writeInp2File";
+ //.. write input data to the file
+ logger.addLog( clName+": "+methName+
+ ": Start: file:["+fname+"]\n",this.LogF);
+ let timeStamp = new Date().toISOString();
+ logger.addLog( clName+": "+methName+": timeStamp:["+timeStamp+"]\n",this.LogF);
+ var inpdLen= inpd.length;
+ logger.addLog( clName+": "+methName+": inpd length="+ inpdLen+"\n",this.LogF);
+ if( inpdLen < 1 ) {
+ logger.addLog( clName+": "+methName+
+ ": Warn.: Empty input - nothing to do !\n",this.LogF);
+ return ''; //.. not an error
+ };
+ if( inpdLen > 300 ) {
+ logger.addLog( clName+": "+methName+
+ ": inpd(begin):["+ inpd.substr(0,299)+"...]\n",this.LogF);
+ }
+ else {
+ logger.addLog( clName+": "+methName+": inpd:["+ inpd+"]\n",this.LogF);
+ };
+ logger.addLog( clName+": "+methName+
+ ": doAdd:["+doAdd+"] doProc:["+doProc+"]\n",this.LogF);
+ if( ! doAdd ) {
+ logger.addLog( clName+": "+methName+
+ ": Dont doAdd - need new content.\n",this.LogF);
+ //.. removing old file if is there with the same name (async is Not OK !)
+ var fname_o= fname+".save";
+ try {
+ fs.renameSync( fname, fname_o );
+ }
+ catch( err ) {
+ var errMsg= clName+": "+methName+
+ ": Warn.: Failed to rename old file:["+fname+"]"+
+ " err.code="+err.code+"\n";
+ logger.addLog( errMsg, this.LogF );
+ };
+ };
+ logger.addLog( clName+": "+methName+": opening file:["+fname+"]\n",this.LogF);
+ try {
+ this.fdI= fs.openSync( fname, 'a' );
+ }
+ catch( err ) {
+ var errMsg= clName+": "+methName+
+ ": Error: Failed to open file:["+fname+"]"+
+ " err.code="+err.code+"\n";
+ logger.addLog( errMsg, this.LogF );
+ return( errMsg );
+ };
+ logger.addLog( clName+": "+methName+
+ ": writing data into the file: fdI="+ this.fdI+"\n",this.LogF);
+ try {
+ fs.appendFileSync( this.fdI, inpd, 'utf8' );
+ }
+ catch( err ) {
+ var errMsg= clName+": "+methName+
+ ": Error: Failed to append input data to file: err.code="+err.code+"\n";
+ logger.addLog( errMsg, this.LogF );
+ return( errMsg );
+ };
+ logger.addLog( clName+": "+methName+
+ ": closing input data file...\n",this.LogF);
+ try {
+ fs.closeSync( this.fdI );
+ }
+ catch( err ) {
+ var errMsg= clName+": "+methName+
+ ": Error: Failed to close input data file: err.code="+err.code+"\n";
+ logger.addLog( errMsg, this.LogF );
+ return( errMsg );
+ };
+ logger.addLog( clName+": "+methName+
+ ": input file was written and closed successfully.\n",this.LogF);
+ timeStamp = new Date().toISOString();
+ logger.addLog( clName+": "+methName+": timeStamp:["+timeStamp+"]\n",this.LogF);
+ if( doProc ) {
+ logger.addLog( clName+": "+methName+
+ ": starting processing...\n",this.LogF);
+ this.startProcFile();
+ };
+ return ''; //.. no error
+};
+
+exports.startProcFile = function () {
+ var methName= "startProcFile";
+ //.. start processing of the input file in external sub-process
+ logger.addLog( clName+": "+methName+
+ ": Start: taskId:["+this.taskId+"]\n",this.LogF);
+ let timeStamp = new Date().toISOString();
+ logger.addLog( clName+": "+methName+
+ ": timeStamp:["+timeStamp+"]\n",this.LogF);
+ console.log(methName+": cdt_home:["+this.cdt_home+"]");
+ var SubProcScriptP= this.cdt_home + SubProcScript;
+ logger.addLog( clName+": "+methName+
+ ": run SubProcScript:\n["+SubProcScriptP+"]\n",this.LogF);
+ var cp_args= new Array( 0 );
+ cp_args.push( this.taskId ); //.. give it taskId in args
+ cp_args.push( this.cdt_home );
+ cp_args.push( this.LOG_DIR );
+ var chprocI= Chproc.fork( SubProcScriptP, cp_args );
+
+ // chprocI.on('message', (msg) => {
+ // console.log(methName+": chprocI got msgJ:["+JSON.stringify(msg)+"]");
+ // });
+ // console.log("startProcFile: sending a message to child.");
+ // chprocI.send({ hello: 'world' });
+ logger.addLog( clName+": "+methName+" done submit.\n",this.LogF);
+};
diff --git a/src/app/srvlogger.js b/src/app/srvlogger.js
new file mode 100755
index 0000000..22c6d83
--- /dev/null
+++ b/src/app/srvlogger.js
@@ -0,0 +1,96 @@
+/*
+============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============================================ */
+//.. srvlogger.js -logging in file system
+const fs = require('fs');
+
+const clName= "srvlogger";
+
+var MaxLogSize= 5000000;
+var LogFileNm;
+var fdL;
+
+exports.addLog = function( logStr, fileNm ) {
+
+ this.LogFileNm= fileNm
+ this.fdL= fs.openSync( this.LogFileNm, 'a' );
+ // console.log(clName+": log opened. fdL="+this.fdL);
+
+ var lfStats= fs.fstatSync( this.fdL );
+ if( lfStats.size + logStr.length >= MaxLogSize )
+ {
+ this.changeLogFile();
+ };
+
+ try {
+ fs.appendFileSync( this.fdL, logStr, 'utf8' );
+ }
+ catch( err ) {
+ console.log(clName+": log append: error:"+err.message );
+ throw err;
+ };
+ fs.closeSync( this.fdL );
+}
+
+exports.changeLogFile = function() {
+
+ var msgO= "\n=== The Log reached max size. Changing the file. ===\n";
+ try {
+ fs.appendFileSync( this.fdL, msgO, 'utf8' );
+ }
+ catch( err ) {
+ console.log(clName+": log append: error:"+err.message );
+ throw err;
+ };
+ fs.closeSync( this.fdL );
+
+ var LogFileNm_o= this.LogFileNm +".old";
+ try {
+ fs.renameSync( this.LogFileNm, LogFileNm_o );
+ }
+ catch( err ) {
+ throw err;
+ };
+
+ try {
+ this.fdL= fs.openSync( this.LogFileNm, 'a' );
+ }
+ catch( err ) {
+ console.log(clName+": New Log file open: error:["+err.message+"]\n");
+ throw err;
+ }
+ console.log( clName+": New Log file opened: fdL="+this.fdL+"\n");
+
+ var msgN= "\n=== New Log file ===\n";
+ try {
+ fs.appendFileSync( this.fdL, msgN, 'utf8' );
+ }
+ catch( err ) {
+ console.log( clName+": new log append: error:"+err.message );
+ throw err;
+ };
+}
+
+exports.setMaxLogSize = function( newMaxLogSize ) {
+ if( newMaxLogSize > 0 )
+ MaxLogSize= newMaxLogSize;
+ else
+ console.log(clName+": Wrong arg: newMaxLogSize <= 0 !");
+}
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"); }
+};