#!/usr/bin/env python
"""
Moab-Condor compatibility layer

condor_wait: emulate the tool of the same name in the Condor distribution by 
taking a condor or moab log file and waiting untill all jobs listed therein are
done.

Usage
  condor_wait OPTIONS logfile [job id]

Options
  -num <number>     Wait for this many jobs to end (default is all jobs)
  -wait <seconds>   Wait no more than this time (default is unlimited)
"""
import os
import time
import MOPS.Torque as Torque




# Constants
POLLING_INTERVAL = 0.5                  # seconds


def waitForJob(log, wait=None, num=None, job=None):
    """
    Emulate condor_wait.
    """
    # We have two strategies here. If we have a job id, then we simpy monitor
    # that one. If not, we monitor jobs submitted by the calling user and
    # present in the input log file.
#     if(job != None):
#         return(_waitForNamedJob(job, wait))
#     else:
#         return(_waitForNumJobs(log, num, wait))
    # <-- end if

    # In reality, let's get the name of all jobs whose name is in the form
    # $MOPS_DBINSTANCE.N and wait on those.
    jobIds = Torque.getJobIds(name_root=os.environ.get('MOPS_DBINSTANCE',
                                        '%s_MOPS' %(os.environ['USER'])),
                              owner=os.environ['USER'])
    while(jobIds):
        time.sleep(POLLING_INTERVAL)
        jobIds = Torque.getJobIds(name_root=os.environ.get('MOPS_DBINSTANCE',
                                        '%s_MOPS' %(os.environ['USER'])),
                                  owner=os.environ['USER'])
    # <-- end while
    return


def _waitForNamedJob(job, wait):
    """
    Wait for up to wait seconds for job to finish. If wait=None, then wait
    forever.
    """
    if(wait != None):
        # Wait for the given number of seconds.
        return(_waitForNamedJobWithTimeout(job, wait))
    return(_waitForNamedJobForever(job))


def _waitForNamedJobForever(job, pollingTime=POLLING_INTERVAL):
    done = Torque.hasCompleted(jobId=job, log=None)
    while(not done):
        time.sleep(pollingTime)
        done = Torque.hasCompleted(jobId=job, log=None)
    # <-- end while
    return


def _waitForNamedJobWithTimeout(job, timeout, pollingTime=POLLING_INTERVAL):
    done = Torque.hasCompleted(jobId=job, log=None)
    t0 = time.time()
    
    while(not done and (time.time() - t0) <= timeout):
        time.sleep(pollingTime)
        done = Torque.hasCompleted(jobId=job, log=None)
    # <-- end while
    return



def _waitForNumJobs(log, num=None, wait=None):
    """
    Wait for up to wait seconds for num jobs to complete. If wait=None, then
    wait forever. If num=None, then wait for all jobs to complete.

    Only monitor jobs submitted by the current user and defined in log.
    """
    # Grab username form the environment. Portable????
    user = os.environ['USER']

    
    
    





if(__name__ == '__main__'):
    import optparse
    import sys
    


    # Constants
    USAGE = """Usage
  condor_wait OPTIONS logfile [job id]

Options
  -num <number>     Wait for this many jobs to end (default is all jobs)
  -wait <seconds>   Wait no more than this time (default is unlimited)
"""


    # Hack. we want to support the condor_wait -wait and -num options, which
    # optparse does not support.
    for i in range(len(sys.argv[1:])):
        if(sys.argv[i+1][0] == '-' and
           sys.argv[i+1][1] != '-' and
           len(sys.argv[i+1]) > 1):
            sys.argv[i+1] = '-' + sys.argv[i+1]
        # <-- end if
    # <-- end for

    # Parse the command line input.
    parser = optparse.OptionParser(USAGE)
    parser.add_option('--wait',
                      dest='wait',
                      type='int',
                      default=None,
                      help='Wait no more than this time (default is unlimited)')
    parser.add_option('--num',
                      dest='num',
                      type='int',
                      default=None,
                      help='Wait for <num> jobs to end (default is all jobs)')
    (options, args) = parser.parse_args()
    args.reverse()
    try:
        logFileName = args.pop()
    except:
        parser.error('logfile has to be specified.')
    # <-- end try/except
    try:
        jobId = args.pop()
    except:
        jobId = None
    # <-- end try/except

    sys.exit(waitForJob(log=logFileName,
                        wait=options.wait,
                        num=options.num,
                        job=jobId))
# <-- end if
