# $CVSHeader: pal8e/src/StrideRun.py,v 1.2 2005/02/15 01:10:26 indraneel Rel $

import os
import sys
import ConfigParser

from Log import LogFH

class Error(Exception):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return self.value

class Runner:
    def __init__(self, conf_fname):
        self.conf_fname = conf_fname

    def _get_filelist(self, config):
        if config.has_option('Input', 'pdbdir'):
            pdbdir = config.get('Input', 'pdbdir')
            config.remove_option('Input', 'pdbdir')
        else: pdbdir = ''

        lfd = None
        if config.has_option('Input', 'listfiledir'):
            lfd = config.get('Input', 'listfiledir')
            config.remove_option('Input', 'listfiledir')
        if config.has_option('Input', 'listfile'):
            lfn = config.get('Input','listfile')
            config.remove_option('Input', 'listfile')
        else:    
            lfn = os.getenv('HOSTNAME')
        lf = None
        if lfd:
            lfn = lfd + lfn
            lf = file(lfn)
        if lf:
            filelist = lf.readlines()
            lf.close()
            if pdbdir:
                for i in range(len(filelist)):
                    if filelist[i][:5] == 'break': break
                    filelist[i] = pdbdir+filelist[i][:-1]
        elif pdbdir:
            filelist = os.listdir(pdbdir)
            for i in range(len(filelist)):
                filelist[i] = pdbdir+filelist[i]
        else:
            return []
        return filelist

    def _get_filedict(self, config):
        filelist = self._get_filelist(config)

        if config.has_option('Input', 'filename_prefilter'):
            filename_prefilter = config.get('Input', 'filename_prefilter')
            prefil_len = len(filename_prefilter)
        else: filename_prefilter = None
        if config.has_option('Input', 'filename_postfilter'):
            filename_postfilter = config.get('Input', 'filename_postfilter')
            postfil_len = len(filename_postfilter)
        else: filename_postfilter = None

        filedict = {}
        for fname in filelist:
            if fname[:5] == 'break': break
            structureID = os.path.basename(fname)
            if filename_prefilter:
                if filename_prefilter != structureID[:prefil_len]:
                    continue
                structureID = structureID[prefil_len:]
            if filename_postfilter:
                if filename_postfilter != structureID[-postfil_len:]:
                    continue
                structureID = structureID[:-postfil_len]
            if len(structureID) == 0: continue
            filedict[structureID] = fname
        return filedict

    def _multiprocess_fork(self):
        config = self.config
        structureID = config.get('Input', 'structureID')
        fname = config.get('Input', 'fname')
        exepath = config.get('Executable', 'path')
        exeargs = ' '+fname
        exeargs += ' '+config.get('Executable', 'args')
        exeargs += config.get('Output', 'dir')
        exeargs += structureID+config.get('Output','posttag')
        
        if len(self.children.keys()) >= self.multiprocess:
            pid,stat = os.wait()
            del self.children[pid]
            
        newpid = os.fork()
        if newpid == 0:
            os.system(exepath+exeargs)
            os._exit(0)
        else:
            self.logger.log(structureID+' '+fname+' (cid: '+str(newpid)+')')
            self.children[newpid] = True

    def run(self):
        config = ConfigParser.ConfigParser()
        config.read(self.conf_fname)
        self.config = config

        logfname = config.get('Debug','dbgdir')+config.get('Debug','logfile')
        compression = config.getint('Output', 'compression')
        self.logger = LogFH(logfname, compress=compression)
        config.remove_option('Debug', 'logfile')            

        filedict = self._get_filedict(config)
        if not filedict:
            self.logger.log('Empty filedict')
            return

        method = None
        if config.has_option('Process', 'children'):
            self.multiprocess = config.getint('Process', 'children')
        if self.multiprocess:
            self.children = {}
            method = self._multiprocess_fork
        
        for structureID, fname in filedict.items():
            config.set('Input', 'structureID', structureID)
            config.set('Input', 'fname', fname)

            if method:
                method()
            else:
                self.logger.log(structureID+' '+fname)
                exepath = config.get('Executable', 'path')
                exeargs = ' '+fname
                exeargs += ' '+config.get('Executable', 'args')
                exeargs += config.get('Output', 'dir')
                exeargs += structureID+config.get('Output','posttag')
                os.system(exepath+exeargs)
                    
        if self.multiprocess:
            while len(self.children.keys()):
                if method == self._multiprocess_fork:
                    pid,stat = os.wait()
                    del self.children[pid]
        self.logger.close()

if __name__ == '__main__':
    if not os.environ.has_key('StrideCONF'):
        os.environ['StrideCONF'] = os.path.expanduser('~/.strideconf')

    conf_fname = os.getenv('StrideCONF')
    runner = Runner(conf_fname)
    runner.run()
