#!/usr/bin/env python

##
## CreateBenchmarksArchive.py
##      -
##

# $Id: CreateBenchmarksArchive.py,v 1.6 2007/01/14 21:53:39 jarda Exp $


# import of required modules {{{
import os
import re
import sys
import zipfile
import time

import Database
from BenchConfig import BenchConfig
# }}}


def main():
    # DOC {{{
    """Detaches from the caller, creates the files and makes a clean-up.
    """
    # }}}

    # CODE {{{
    if (not sys.argv[1:]):
        print "Usage %s baseFileName" % (sys.argv[0],)
        sys.exit(1)
    
    forkIt()

    createFiles()

    cleanUp()
    # }}}


# XXX: implementation missing - delete all tmp files older than 3 days!
def cleanUp():
    # DOC {{{
    """Cleans up the directory.
    """
    # }}}

    # CODE {{{
    pass
    # }}}


def createFiles():
    # DOC {{{
    """Creates the archive and then the existence file.
    """
    # }}}

    # CODE {{{
    baseFileName = sys.argv[1]

    wholeFileName = "%s/%s.zip" % (BenchConfig.tmpDirectory, baseFileName,)
    
    createdZip = zipfile.ZipFile(wholeFileName, "w")

    for row in getRowGenerator(baseFileName):
        if ((not row['setname']) or (not row['filename'])):
            continue

        wholeFileName = "%s/%s/%s" % (BenchConfig.benchmarkFilesDirectory, row['setname'], row['filename'],)

        createdZip.write(wholeFileName, "%s/%s" % (row['setname'], row['filename'],))

    createdZip.close()

    wholeFileName = "%s/%s.existence" % (BenchConfig.tmpDirectory, baseFileName,)

    file = open(wholeFileName, "w")
    file.close()
    # }}}


def getRowGenerator(baseFileName):
    # DOC {{{
    """Returns generator that yields database rows containing file names used
    in creation of the benchmark archive.
    
    Parameters

        baseFileName -- base file name (without an extension)
    """
    # }}}

    # CODE {{{
    wholeFileName = "%s/%s.query" % (BenchConfig.tmpDirectory, baseFileName,)
    
    query = prepareQuery(open(wholeFileName).read())

    db = Database.getDatabaseConnection()

    recordSet = db.Execute(query)

    return Database.assocGen(recordSet)
    # }}}


def prepareQuery(query):
    # DOC {{{
    """Prepares the query.

    Parameters

        query -- an original query
    """
    # }}}

    # CODE {{{
    return re.sub(r"\\'", "'", query.strip())
    # }}}


def forkIt():
    # DOC {{{
    """Forks the process, sets new session ID and closes all open files to
    detach from the calling PHP script.
    """
    # }}}

    # CODE {{{
    pid = os.fork() 

    if pid > 0:
        # exit first parent
        sys.exit(0)     

    os.setsid()

    pid = os.fork() 

    if pid > 0:
        # exit second parent
        sys.exit(0)     

    try:
        sys.stdin.close()
    except:
        pass

    try:
        sys.stdout.close()
    except:
        pass

    try:
        sys.stderr.close()
    except:
        pass

    import resource		# Resource usage information.
    maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
    if (maxfd == resource.RLIM_INFINITY):
        maxfd = 1024
  
    # Iterate through and close all file descriptors.
    for fd in xrange(0, maxfd):
        try:
            os.close(fd)
        except OSError:	# ERROR, fd wasn't open to begin with (ignored)
            pass
    # }}}


if (__name__ == '__main__'):
    main()
