#!/usr/bin/python3 import configobj import xml.etree.ElementTree as ET import base64 import zlib import io import os from itertools import islice import mmap import shlex import psutil import time import datetime ''' This is a trisurf instance manager written in python Invoke with: tsmgr [-t tape | -r snapshot.vtu] [-s subdirectory] If tape is specified, the trisurf wilt start from tape with initial distribution, if snapshot is specified the trisurf will be restored from given snapshot file and simulation will continue. ''' class FileContent: def __init__(self,filename): self.filename=filename self.data="" self.readfile() def readfile(self): try: with open (self.filename, "r") as myfile: self.data=myfile.read().replace('\n', '') except: pass def writefile(self, data, mode='w'): with open (self.filename, mode) as myfile: myfile.write(data) def getText(self): return self.data def __str__(self): return self.getText() class Tape: '''Has all the info on the tape''' def __init__(self): return def readTape(self, tape='tape'): try: self.config=configobj.ConfigObj(tape) except: print("Error reading or parsing tape file!\n") exit(1) def setTape(self, string): self.config=configobj.ConfigObj(io.StringIO(string)) return def getValue(self,key): return self.config[key] def __str__(self): retval="" for key,val in self.config.iteritems(): retval=retval+str(key)+" = "+str(val)+"\n" return retval class Directory: def __init__(self, maindir=".", simdir=""): self.maindir=maindir self.simdir=simdir return def fullpath(self): return os.path.join(self.maindir,self.simdir) def exists(self): path=self.fullpath() if(os.path.exists(path)): return 1 else: return 0 def make(self): try: os.makedirs(self.fullpath()) except: print("Cannot make directory "+self.fullpath()+"\n") exit(1) return def makeifnotexist(self): if(self.exists()==0): self.make() return def remove(self): if(self.exists()): try: os.rmdir(self.fullpath()) except: print("Cannot remove directory "+self.fullpath()+ "\n") exit(1) return def goto(self): try: os.chdir(self.fullpath()) except: print("Cannot go to directory "+self.fullpath()+"\n") return class Statistics: def __init__(self,path,filename="statistics.csv"): self.path=path self.filename=filename self.fullname=os.path.join(path,filename) self.fileOK=self.read() return def exists(self): if(os.path.isfile(self.fullname)): return True else: return False def mapcount(self): f = open(self.fullname, "r+") buf = mmap.mmap(f.fileno(), 0) lines = 0 readline = buf.readline while readline(): lines += 1 return lines def read(self): if(self.exists()): nlines=self.mapcount() try: with open(self.fullname, "r+") as fin: i=0; for line in fin: if(i==1): #print (line) fields=shlex.split(line) epoch1=fields[0] n1=fields[1] if(i==nlines-1): fields=shlex.split(line) epoch2=fields[0] n2=fields[1] i=i+1 except: #print("Cannot read statistics file in "+self.fullname+"\n") return(False) else: #print("File "+self.fullname+" does not exists.\n") return(False) self.dT=(int(epoch2)-int(epoch1))/(int(n2)-int(n1)) self.last=n2 self.startDate=epoch1 return(True) def __str__(self): return(str(self.fullname)) class Runner: ''' Class Runner consists of a single running or terminated instance of the trisurf ''' def __init__(self, subdir='run0', tape='', snapshot=''): self.subdir=subdir if(tape!=''): self.initFromTape(tape) if(snapshot!=''): self.initFromSnapshot(snapshot) return def initFromTape(self, tape): self.tape=Tape() self.tape.readTape(tape) def initFromSnapshot(self, snapshotfile): try: tree = ET.parse(snapshotfile) except: print("Error reading snapshot file") exit(1) root = tree.getroot() tapetxt=root.find('tape') version=root.find('trisurfversion') self.tape=Tape() self.tape.setTape(tapetxt.text) def getPID(self): self.Dir=Directory(maindir=self.maindir,simdir=self.subdir) self.Dir.makeifnotexist() try: fp = open(os.path.join(self.Dir.fullpath(),'.lock')) except IOError as e: return 0 #file probably does not exist. e==2?? pid=fp.readline() fp.close() return pid def getStatus(self): pid=self.getPID() if(pid==0): return 0 if(psutil.pid_exists(int(pid))): if psutil.Process(int(pid)).name=="trisurf": return 1 else: return 0 else: return 0 def start(self): if(self.getStatus()==0): self.Dir=Directory(maindir=self.maindir,simdir=self.subdir) self.Dir.makeifnotexist() # self.Dir.goto() print("Starting trisurf-ng executable at "+self.Dir.fullpath()+"\n") else: print("Process already running. Not starting\n") return def stop(self): pass def setMaindir(self,prefix,variables): maindir="./" for p,v in zip(prefix,variables): if(v=="xk0"): tv=str(round(float(self.tape.config[v]))) else: tv=self.tape.config[v] maindir=maindir+p+tv self.maindir=maindir return def setSubdir(self, subdir="run0"): self.subdir=subdir return def getStatistics(self, statfile="statistics.csv"): self.Dir=Directory(maindir=self.maindir,simdir=self.subdir) self.statistics=Statistics(self.Dir.fullpath(), statfile) self.Comment=FileContent(os.path.join(self.Dir.fullpath(),".comment")) pid=self.getPID(); if(self.getStatus()): statustxt="Running" else: statustxt="Stopped" pid="" if(self.statistics.fileOK): # report=time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(int(self.statistics.startDate)))+"\t"+str(datetime.timedelta(microseconds=(int(self.tape.config['iterations'])-int(self.statistics.last))*self.statistics.dT)*1000)+" ETA\t"+"STATUS" report=[time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(int(self.statistics.startDate))),str(datetime.timedelta(microseconds=(int(self.tape.config['iterations'])-int(self.statistics.last))*self.statistics.dT)*1000), statustxt, pid, str(self.Dir.fullpath()), self.Comment.getText()] else: report=["N/A","N/A\t",statustxt, pid, str(self.Dir.fullpath()), self.Comment.getText()] return report def writeComment(self, data): self.Dir=Directory(maindir=self.maindir,simdir=self.subdir) self.Comment=FileContent(os.path.join(self.Dir.fullpath(),".comment")) self.Comment.writefile(data,mode='w') def __str__(self): if(self.getStatus()==0): str=" not running." else: str=" running." return(self.Dir.fullpath()+str)