diff options
Diffstat (limited to 'src/main/SendLog.py')
-rwxr-xr-x | src/main/SendLog.py | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/src/main/SendLog.py b/src/main/SendLog.py new file mode 100755 index 0000000..9f0af39 --- /dev/null +++ b/src/main/SendLog.py @@ -0,0 +1,206 @@ +## Hrishi Hiraskar +## 23 October 2016 + +import gevent +import time +import os +import threading +from gevent import monkey +from gevent.pywsgi import WSGIServer +from flask import Flask, request, Response, render_template, send_from_directory +from werkzeug import secure_filename + +monkey.patch_all(aggressive=False) + +import subprocess + +app = Flask(__name__, static_folder='webapp/') + +# This is the path to the upload directory +app.config['UPLOAD_FOLDER'] = 'uploads/' +# These are the extension that we are accepting to be uploaded +app.config['ALLOWED_EXTENSIONS'] = set(['zcos', 'xcos']) + +# Delay time to look for new line (in s) +LOOK_DELAY = 0.1 +# States of the line +INITIALIZATION = 0 +ENDING = 1 +DATA = 2 +NOLINE = -1 +# Scilab dir, can't run absolute paths +SCI = "../../../../scilab/scilab_master_old/scilab/" +# List to store figure IDs +figure_list = [] +# List to store filenames of files +xcos_file_list = [] + +class line_and_state: + # Class to store the line and its state + line = None + state = NOLINE + def __init__(self, line, state): + self.line = line + self.state = state + def set(self, line_state): + self.line = line_state[0] + self.state = line_state[1] + return False + def get_line(self): + return self.line + def get_state(self): + return self.state + +def parse_line(line): + # Function to parse the line + # Returns tuple of figure ID and state + # state = INITIALIZATION if new figure is created + # ENDING if current fig end + # DATA otherwise + line_words = line.split(' ') + if line_words[2] == "Initialization": + # New figure created + # Get fig id + figure_id = int(line_words[-1]) + return (figure_id, INITIALIZATION) + elif line_words[2] == "Ending": + # Current figure end + # Get fig id + figure_id = int(line_words[-1]) + return (figure_id, ENDING) + else: + # Current figure coordinates + figure_id = int(line_words[2]) + return (figure_id, DATA) + +def get_line_and_state(file): + # Function to get a new line from file + # This also parses the line and appends new figures to figure List + global figure_list + line = file.readline() + if not line: + return (None, NOLINE) + parse_result = parse_line(line) + figure_id = parse_result[0] + state = parse_result[1] + if state == INITIALIZATION: + # New figure created + # Add figure ID to list + figure_list.append(figure_id) + return (None, INITIALIZATION) + elif state == ENDING: + # End of figure + # Remove figure ID from list + figure_list.remove(figure_id) + return (None, ENDING) + return (line, DATA) + +def event_stream(xcos_file_id): + global figure_list + # If no id is sent, return + if(len(xcos_file_id)==0): + return + xcos_file_id = int(xcos_file_id) + xcos_file_dir = os.getcwd() + '/uploads/' + xcos_file_name = xcos_file_list[xcos_file_id] + # Get previously running scilab process IDs + proc = subprocess.Popen("pgrep scilab", stdout=subprocess.PIPE, shell=True) + # out will contain output of command, the list of process IDs of scilab + (out, err) = proc.communicate() + _l = len(out) + # Run xcos file + command = ["./"+SCI+"bin/scilab-adv-cli", "-nogui", "-noatomsautoload", "-nb", "-nw", "-e", "loadXcosLibs();importXcosDiagram('" + xcos_file_dir + xcos_file_name + "');xcos_simulate(scs_m,4);mode(2);quit()"] + scilab_proc = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=False); + # Wait till xcos is launched + while len(out) == _l: + # If length of out equals _l, + # it means scilab hasn't launched yet + # Wait + gevent.sleep(LOOK_DELAY) + # Get process IDs of scilab instances + proc = subprocess.Popen("pgrep scilab", stdout=subprocess.PIPE, shell=True) + # out will contain output of command, the list of process IDs of scilab + (out, err) = proc.communicate() + # out will contain output of command, the list of process IDs of scilab + # Get the latest process ID of scilab + pid = out.split()[-1] + # Define function to kill scilab(if still running) and remove files + def kill_scilab(): + # Kill scilab by it's pid + subprocess.Popen(["kill","-9",pid]) + # Remove log file + subprocess.Popen(["rm",log_dir+log_name]) + # Remove xcos file + subprocess.Popen(["rm",xcos_file_dir+xcos_file_name]) + # Log file directory + # As the scilab process is spawned by this script + # the log directory is same as that of this script + log_dir = "" + # Log file name + log_name = "scilab-log-"+pid+".txt" + # Open the log file + log_file = open(log_dir + log_name, "w+") + # Kill scilab-adv-cli, if running and get it's output + # If the simulation is error free, no output is generated + scilab_proc.kill() + (scilab_out, scilab_err) = scilab_proc.communicate(); + # Check for empty diagram + if "Empty diagram" in scilab_out: + yield "event: ERROR\ndata: Empty diagram\n\n" + kill_scilab(); + return + # Some other error + elif len(scilab_out) > 0: + yield "event: ERROR\ndata: " + scilab_out + "\n\n" + kill_scilab(); + return + # Start sending log + line = line_and_state(None, NOLINE) + while (line.set(get_line_and_state(log_file)) or line.get_state() != ENDING or len(figure_list) > 0): + # Get the line and loop until the state is ENDING and figure_list empty + if line.get_state() != DATA: + gevent.sleep(LOOK_DELAY) + else: + yield "event: log\ndata: "+line.get_line()+"\n\n" + # Reset line, so server won't send same line twice + line = line_and_state(None, NOLINE) + # Finished Sending Log + kill_scilab() + # Notify Client + yield "event: DONE\ndata: None\n\n" + +# Route that will process the file upload +@app.route('/upload', methods=['POST']) +def upload(): + # Get the file + file = request.files['file'] + # Check if the file is not null + if file: + # Make the filename safe, remove unsupported chars + client_id = len(xcos_file_list) + filename = str(client_id)+".xcos" + # Move the file form the temporal folder to + # the upload folder we setup + file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) + xcos_file_list.append(filename) + return str(client_id) + else: + return "error" + +@app.route('/SendLog') +def sse_request(): + # Set response method to event-stream + return Response(event_stream(request.args.get('id', '')), mimetype='text/event-stream') + +@app.route('/<path:path>') +def static_file(path): + return app.send_static_file(path) + +@app.route('/') +def page(): + return app.send_static_file('index.html') + +if __name__ == '__main__': + # Set server address 127.0.0.1:8001/ + http_server = WSGIServer(('127.0.0.1', 8001), app) + http_server.serve_forever()
\ No newline at end of file |