<commit_before>#
# Copyright (c) 2006-2007 rPath, Inc.  All Rights Reserved.
#
"""
SQL schema for the persistent DB store for rmake
"""
from rmake import errors

# NOTE: this schema is sqlite-specific

SCHEMA_VERSION = 11

def createJobs(db):
    cu = db.cursor()
    commit = False
    if "Jobs" not in db.tables:
        cu.execute("""
        CREATE TABLE Jobs (
            jobId          INTEGER PRIMARY KEY AUTOINCREMENT,
            pid            INTEGER NOT NULL DEFAULT 0,
            uuid           CHAR(32) NOT NULL DEFAULT '',
            state          INTEGER NOT NULL DEFAULT 0,
            status         STRING NOT NULL DEFAULT 'JobID entry created',
            owner          STRING NOT NULL DEFAULT '',
            start          STRING NOT NULL DEFAULT '0',
            finish         STRING NOT NULL DEFAULT '0',
            failureReason  STRING NOT NULL DEFAULT '',
            failureData    STRING NOT NULL DEFAULT ''
        )""")
        db.tables["Jobs"] = []
        commit = True
    if commit:
        db.commit()
        db.loadSchema()

def createJobConfig(db):
    cu = db.cursor()
    commit = False
    if "JobConfig" not in db.tables:
        cu.execute("""
        CREATE TABLE JobConfig (
            jobId       INTEGER NOT NULL,
            context     STRING NOT NULL DEFAULT "",
            key         STRING NOT NULL,
            ord         INTEGER NOT NULL,
            value       STRING NOT NULL
        )""")
        db.tables["JobConfig"] = []
    if db.createIndex("JobConfig", "JobConfigIdx", "jobId",
                      unique = False):
        commit = True
    if db.createIndex("JobConfig", "JobContextIdx", "jobId, context",
                      unique = False):
        commit = True
    if db.createIndex("JobConfig", "JobConfigContextKeyIdx",
                      "jobId, context, key", unique = False):
        commit = True
    if commit:
        db.commit()
        db.loadSchema()

def createTroveSettings(db):
    cu = db.cursor()
    commit = False
    if "TroveSettings" not in db.tables:
        cu.execute("""
        CREATE TABLE TroveSettings (
            jobId      INTEGER NOT NULL,
            troveId     INTEGER NOT NULL,
            key         STRING NOT NULL,
            ord         INTEGER NOT NULL,
            value       STRING NOT NULL
        )""")
        db.tables["TroveSettings"] = []
    if db.createIndex("TroveSettings", "TroveSettingsIdx", "jobId",
                      unique = False):
        commit = True
    if db.createIndex("TroveSettings", "TroveSettingsIdx2", "troveId",
                      unique = False):
        commit = True
    if commit:
        db.commit()
        db.loadSchema()

def createSubscriber(db):
    cu = db.cursor()
    commit = False
    if "Subscriber" not in db.tables:
        cu.execute("""
         CREATE TABLE Subscriber(
             subscriberId  INTEGER PRIMARY KEY AUTOINCREMENT,
             jobId         INTEGER NOT NULL,
             uri           STRING  NOT NULL
         )""")
        db.tables["Subscriber"] = []
        commit = True

    if db.createIndex("Subscriber", "SubscriberJobIdx", "jobId"):
        commit = True

    if "SubscriberEvents" not in db.tables:
        cu.execute("""
        CREATE TABLE SubscriberEvents (
            subscriberId  INTEGER NOT NULL,
            event         STRING  NOT NULL,
            subevent      STRING  NOT NULL
        )""")
        db.tables["SubscriberEvents"] = []
        commit = True

    if db.createIndex("SubscriberEvents", "SubscriberEventsIdx",
                      "subscriberId"):
        commit = True

    if db.createIndex("SubscriberEvents", "SubscriberEventsEventIdx",
                      "event,subevent"):
        commit = True

    if "SubscriberData" not in db.tables:
        cu.execute("""
        CREATE TABLE SubscriberData (
            subscriberId  STRING  NOT NULL,
            data          STRING  NOT NULL
        )""")
        db.tables["SubscriberData"] = []
        commit = True

    if db.createIndex("SubscriberData", "SubscriberDataIdx", "subscriberId"):
        commit = True

    if commit:
        db.commit()
        db.loadSchema()

def createBuildTroves(db):
    cu = db.cursor()
    commit = False
    if "BuildTroves" not in db.tables:
        # XXX: will normalize later
        cu.execute("""
        CREATE TABLE BuildTroves (
            troveId        INTEGER PRIMARY KEY AUTOINCREMENT,
            jobId          INTEGER NOT NULL,
            pid            INTEGER NOT NULL DEFAULT 0,
            troveName      STRING NOT NULL,
            troveType      STRING NOT NULL DEFAULT 'build',
            version        STRING NOT NULL,
            flavor         STRING NOT NULL,
            context        STRING NOT NULL DEFAULT '',
            state          INTEGER NOT NULL,
            status         STRING NOT NULL DEFAULT '',
            failureReason  STRING NOT NULL DEFAULT '',
            failureData    STRING NOT NULL DEFAULT '',
            start          STRING NOT NULL DEFAULT '0',
            finish         STRING NOT NULL DEFAULT '0',
            logPath        STRING NOT NULL DEFAULT '',
            recipeType     INTEGER NOT NULL DEFAULT 1,
            chrootId       INTEGER NOT NULL DEFAULT 0,
            buildType      INTEGER NOT NULL DEFAULT 0,
            CONSTRAINT BuildTroves_jobId_fk
                FOREIGN KEY(jobId) REFERENCES Jobs(jobId)
                ON DELETE CASCADE ON UPDATE RESTRICT
        )""")
        db.tables["BuildTroves"] = []
        commit = True
    if db.createIndex("BuildTroves", "BuildTrovesIdx",
                      "jobId, troveName, version, flavor",
                      unique = False):
        commit = True
    if db.createIndex("BuildTroves", "BuildTrovesContextIdx",
                      "jobId, troveName, version, flavor, context",
                      unique = True):
        commit = True
    if db.createIndex("BuildTroves", "BuildTroveJobIdIdx", "jobId",
                      unique = False):
        commit = True

    if db.createIndex("BuildTroves", "BuildTroveIdIdx", "troveId",
                      unique = False):
        commit = True
    if db.createIndex("BuildTroves", "BuildTrovesStateIdx", "jobId, state",
                      unique = False):
        commit = True

    if commit:
        db.commit()
        db.loadSchema()

def createBinaryTroves(db):
    cu = db.cursor()
    commit = False
    if "BinaryTroves" not in db.tables:
        cu.execute("""
        CREATE TABLE BinaryTroves (
            troveId     INTEGER NOT NULL,
            troveName   STRING,
            version     STRING,
            flavor      STRING,
            CONSTRAINT BinaryTroves_jobId_fk
                FOREIGN KEY(troveId) REFERENCES BuildTroves(troveId)
                ON DELETE CASCADE ON UPDATE RESTRICT
        )""")
        db.tables["BinaryTroves"] = []
        commit = True
    if db.createIndex("BinaryTroves", "BinaryTrovesIdx",
                      "troveId"):
        commit = True
    if commit:
        db.commit()
        db.loadSchema()

def createStateLogs(db):
    cu = db.cursor()
    commit = False
    if "StateLogs" not in db.tables:
        cu.execute("""
        CREATE TABLE StateLogs (
            logId    INTEGER PRIMARY KEY AUTOINCREMENT,
            jobId    INTEGER NOT NULL,
            troveId  INTEGER NOT NULL,
            message  STRING NOT NULL,
            args     STRING NOT NULL DEFAULT '',
            changed  STRING NOT NULL DEFAULT CURRENT_TIMESTAMP,
            CONSTRAINT StateLogsJob_fk
                FOREIGN KEY(jobId) REFERENCES Jobs(jobId)
                ON DELETE CASCADE ON UPDATE RESTRICT
        )""")
        db.tables["StateLogs"] = []
        commit = True
    if db.createIndex("StateLogs", "StateLogsJobTroveId", "jobId,troveId"):
        commit = True
    if commit:
        db.commit()
        db.loadSchema()

def createJobQueue(db):
    cu = db.cursor()
    commit = False
    if "JobQueue" not in db.tables:
        cu.execute("""
        CREATE TABLE JobQueue (
            jobId       INTEGER
        )""")
        db.tables["JobQueue"] = []
        commit = True
    if commit:
        db.commit()
        db.loadSchema()

def createChroots(db):
    cu = db.cursor()
    commit = False
    if "Chroots" not in db.tables:
        cu.execute("""
        CREATE TABLE Chroots (
            chrootId      INTEGER PRIMARY KEY AUTOINCREMENT,
            nodeName      VARCHAR,
            path          VARCHAR,
            troveId       INTEGER NOT NULL,
            active        INTEGER NOT NULL
        )""")
        db.tables["Chroots"] = []
        commit = True
    if db.createIndex("Chroots", "ChrootdsIdx", "troveId"):
        commit = True
    if commit:
        db.commit()
        db.loadSchema()

def createNodes(db):
    cu = db.cursor()
    commit = False
    if "Nodes" not in db.tables:
        cu.execute("""
        CREATE TABLE Nodes (
            nodeName     VARCHAR PRIMARY KEY NOT NULL,
            host         VARCHAR NOT NULL,
            slots        INTEGER NOT NULL,
            buildFlavors VARCHAR NOT NULL,
            active       INTEGER NOT NULL DEFAULT 0
        )""")
        db.tables["Nodes"] = []
        commit = True
    if commit:
        db.commit()
        db.loadSchema()

def createAuthCache(db):
    cu = db.cursor()
    commit = False
    if "AuthCache" not in db.tables:
        cu.execute("""
        CREATE TABLE AuthCache (
            sessionId    VARCHAR PRIMARY KEY NOT NULL,
            timeStamp    FLOAT NOT NULL
        )""")
        db.tables["AuthCache"] = []
        commit = True
    if commit:
        db.commit()
        db.loadSchema()

def createPluginVersionTable(db):
    cu = db.cursor()
    commit = False
    if "PluginVersion" not in db.tables:
        cu.execute("""
        CREATE TABLE PluginVersion (
            plugin      VARCHAR NOT NULL UNIQUE,
            version     INTEGER
        )""")
        db.tables["PluginVersion"] = []
        commit = True
    if commit:
        db.commit()
        db.loadSchema()

class AbstractSchemaManager(object):
    def __init__(self, db):
        self.db = db
        self.currentVersion = self.getLatestVersion()

    def loadSchema(self):
        db = self.db
        version = self.getVersion()

        if version == self.currentVersion:
            return version

        db.loadSchema()
        self.createTables()
        db.loadSchema()

        if version != self.currentVersion:
            return self.setVersion(self.currentVersion)

        return self.currentVersion

    def getVersion(self):
        return self.db.getVersion()

    def setVersion(self, version):
        self.db.setVersion(version)

    def loadAndMigrate(self):
        schemaVersion = self.getVersion()
        if schemaVersion > self.currentVersion:
            raise errors.DatabaseSchemaTooNew()
        if not schemaVersion:
            self.loadSchema()
            return self.currentVersion
        else:
            self.db.loadSchema()
            if schemaVersion != self.currentVersion:
                self.migrate(schemaVersion, self.currentVersion)
                self.loadSchema()
        return self.currentVersion

class AbstractMigrator(object):

    # FIXME: This migration code is susceptible to a sort of upgrade race
    # condition: if a table is created and migrated during the same run,
    # SQL that alters the table will fail. this only applies to rMake installs
    # that don't get upgraded very often. there are a few ways to accomodate
    # this, just be aware that nothing is yet implemented.

    def _addColumn(self, table, name, value):
        self.cu.execute('ALTER TABLE %s ADD COLUMN %s    %s' % (table, name,
                                                                value))

    def migrate(self, currentVersion, newVersion):
        if currentVersion < newVersion:
            while currentVersion < newVersion:
                # migration returns the schema that they migrated to.
                currentVersion = getattr(self, 'migrateFrom' + str(currentVersion))()
        self.schemaMgr.setVersion(newVersion)
        self.db.commit()

    def __init__(self, db, schemaMgr):
        self.db = db
        self.cu = db.cursor()
        self.schemaMgr = schemaMgr

class SchemaManager(AbstractSchemaManager):

    def createTables(self):
        db = self.db
        createJobs(db)
        createJobConfig(db)
        createTroveSettings(db)
        createBuildTroves(db)
        createBinaryTroves(db)
        createStateLogs(db)
        createSubscriber(db)
        createJobQueue(db)
        createChroots(db)
        createNodes(db)
        createPluginVersionTable(db)
        createAuthCache(db)

    def migrate(self, oldVersion, newVersion):
        Migrator(self.db, self).migrate(oldVersion, newVersion)

    def getLatestVersion(self):
        return SCHEMA_VERSION

class Migrator(AbstractMigrator):
    def migrateFrom1(self):
        self._addColumn('Jobs', "uuid", "CHAR(32) NOT NULL DEFAULT ''")

        return 2

    def migrateFrom2(self):
        self._addColumn('Jobs', "pid", "INTEGER NOT NULL DEFAULT 0")
        self._addColumn('BuildTroves', "pid", "INTEGER NOT NULL DEFAULT 0")
        return 3

    def migrateFrom3(self):
        self.cu.execute("UPDATE Jobs SET state = state + 1000")
        for iState, fState in [(999, 1), (1000, 0), (1001, 2), (1002, 3),
                               (1003, 4), (1099, 5), (1100, 6), (1101, 7)]:
            self.cu.execute("UPDATE Jobs SET state=? WHERE state=?",
                            fState, iState)
        return 4

    def migrateFrom4(self):
        self._addColumn('BuildTroves', "recipeType",
                        "INTEGER NOT NULL DEFAULT 0")
        return 5

    def migrateFrom5(self):
        self._addColumn('BuildTroves', "chrootId",
                        "INTEGER NOT NULL DEFAULT 0")
        createChroots(self.db)
        createNodes(self.db)
        createPluginVersionTable(self.db)
        return 6

    def migrateFrom6(self):
        self._addColumn('BuildTroves', "context",
                        "STRING NOT NULL DEFAULT ''")
        self._addColumn('JobConfig',  "context",
                        "STRING NOT NULL DEFAULT ''")
        self._addColumn('BuildTroves', "buildType",
                        "INTEGER NOT NULL DEFAULT 0")
        self.cu.execute("DROP INDEX BuildTrovesIdx") # this idx is no longer
                                                     # unique
        createJobConfig(self.db) # add index
        createBuildTroves(self.db) # add indexes
        return 8

    def migrateFrom7(self):
        self._addColumn('BuildTroves', "buildType",
                        "INTEGER NOT NULL DEFAULT 0")
        return 8

    def migrateFrom8(self):
        createAuthCache(self.db)
        return 9

    def migrateFrom9(self):
        self._addColumn("Jobs", "owner",
                        "STRING NOT NULL DEFAULT ''")
        return 10

    def migrateFrom10(self):
        sql, = self.db.cursor().execute('select sql from sqlite_master'
                                        ' where tbl_name="BuildTroves"').next()
        if 'troveType' in sql:
            return 11
        self._addColumn("BuildTroves", "troveType",
                        "troveType      STRING NOT NULL DEFAULT 'build'")
        return 11

class PluginSchemaManager(AbstractSchemaManager):
    """
        Not used at the moment but here's a way to add plugin-specific tables
        to rMake.
    """

    def getVersion(self):
        cu = self.db.cursor()
        rv = cu.execute('SELECT version from PluginVersion WHERE plugin=?',
                        self.name).fetchall()
        if rv:
            return rv[0][0]
        else:
            return None

    def getLatestVersion(self):
        return SCHEMA_VERSION

    def setVersion(self, version):
        if self.getVersion() is None:
            cu = self.db.cursor()
            rv = cu.execute('INSERT INTO PluginVersion VALUES (?, ?)',
                            self.name, version)
        else:
            cu = self.db.cursor()
            rv = cu.execute('UPDATE PluginVersion SET version=? WHERE'
                            'plugin=?', version, self.name)

<commit_msg>Finish migration (RMK-889)<commit_after>#
# Copyright (c) 2006-2007 rPath, Inc.  All Rights Reserved.
#
"""
SQL schema for the persistent DB store for rmake
"""
from rmake import errors

# NOTE: this schema is sqlite-specific

SCHEMA_VERSION = 11

def createJobs(db):
    cu = db.cursor()
    commit = False
    if "Jobs" not in db.tables:
        cu.execute("""
        CREATE TABLE Jobs (
            jobId          INTEGER PRIMARY KEY AUTOINCREMENT,
            pid            INTEGER NOT NULL DEFAULT 0,
            uuid           CHAR(32) NOT NULL DEFAULT '',
            state          INTEGER NOT NULL DEFAULT 0,
            status         STRING NOT NULL DEFAULT 'JobID entry created',
            owner          STRING NOT NULL DEFAULT '',
            start          STRING NOT NULL DEFAULT '0',
            finish         STRING NOT NULL DEFAULT '0',
            failureReason  STRING NOT NULL DEFAULT '',
            failureData    STRING NOT NULL DEFAULT ''
        )""")
        db.tables["Jobs"] = []
        commit = True
    if commit:
        db.commit()
        db.loadSchema()

def createJobConfig(db):
    cu = db.cursor()
    commit = False
    if "JobConfig" not in db.tables:
        cu.execute("""
        CREATE TABLE JobConfig (
            jobId       INTEGER NOT NULL,
            context     STRING NOT NULL DEFAULT "",
            key         STRING NOT NULL,
            ord         INTEGER NOT NULL,
            value       STRING NOT NULL
        )""")
        db.tables["JobConfig"] = []
    if db.createIndex("JobConfig", "JobConfigIdx", "jobId",
                      unique = False):
        commit = True
    if db.createIndex("JobConfig", "JobContextIdx", "jobId, context",
                      unique = False):
        commit = True
    if db.createIndex("JobConfig", "JobConfigContextKeyIdx",
                      "jobId, context, key", unique = False):
        commit = True
    if commit:
        db.commit()
        db.loadSchema()

def createTroveSettings(db):
    cu = db.cursor()
    commit = False
    if "TroveSettings" not in db.tables:
        cu.execute("""
        CREATE TABLE TroveSettings (
            jobId      INTEGER NOT NULL,
            troveId     INTEGER NOT NULL,
            key         STRING NOT NULL,
            ord         INTEGER NOT NULL,
            value       STRING NOT NULL
        )""")
        db.tables["TroveSettings"] = []
    if db.createIndex("TroveSettings", "TroveSettingsIdx", "jobId",
                      unique = False):
        commit = True
    if db.createIndex("TroveSettings", "TroveSettingsIdx2", "troveId",
                      unique = False):
        commit = True
    if commit:
        db.commit()
        db.loadSchema()

def createSubscriber(db):
    cu = db.cursor()
    commit = False
    if "Subscriber" not in db.tables:
        cu.execute("""
         CREATE TABLE Subscriber(
             subscriberId  INTEGER PRIMARY KEY AUTOINCREMENT,
             jobId         INTEGER NOT NULL,
             uri           STRING  NOT NULL
         )""")
        db.tables["Subscriber"] = []
        commit = True

    if db.createIndex("Subscriber", "SubscriberJobIdx", "jobId"):
        commit = True

    if "SubscriberEvents" not in db.tables:
        cu.execute("""
        CREATE TABLE SubscriberEvents (
            subscriberId  INTEGER NOT NULL,
            event         STRING  NOT NULL,
            subevent      STRING  NOT NULL
        )""")
        db.tables["SubscriberEvents"] = []
        commit = True

    if db.createIndex("SubscriberEvents", "SubscriberEventsIdx",
                      "subscriberId"):
        commit = True

    if db.createIndex("SubscriberEvents", "SubscriberEventsEventIdx",
                      "event,subevent"):
        commit = True

    if "SubscriberData" not in db.tables:
        cu.execute("""
        CREATE TABLE SubscriberData (
            subscriberId  STRING  NOT NULL,
            data          STRING  NOT NULL
        )""")
        db.tables["SubscriberData"] = []
        commit = True

    if db.createIndex("SubscriberData", "SubscriberDataIdx", "subscriberId"):
        commit = True

    if commit:
        db.commit()
        db.loadSchema()

def createBuildTroves(db):
    cu = db.cursor()
    commit = False
    if "BuildTroves" not in db.tables:
        # XXX: will normalize later
        cu.execute("""
        CREATE TABLE BuildTroves (
            troveId        INTEGER PRIMARY KEY AUTOINCREMENT,
            jobId          INTEGER NOT NULL,
            pid            INTEGER NOT NULL DEFAULT 0,
            troveName      STRING NOT NULL,
            troveType      STRING NOT NULL DEFAULT 'build',
            version        STRING NOT NULL,
            flavor         STRING NOT NULL,
            context        STRING NOT NULL DEFAULT '',
            state          INTEGER NOT NULL,
            status         STRING NOT NULL DEFAULT '',
            failureReason  STRING NOT NULL DEFAULT '',
            failureData    STRING NOT NULL DEFAULT '',
            start          STRING NOT NULL DEFAULT '0',
            finish         STRING NOT NULL DEFAULT '0',
            logPath        STRING NOT NULL DEFAULT '',
            recipeType     INTEGER NOT NULL DEFAULT 1,
            chrootId       INTEGER NOT NULL DEFAULT 0,
            buildType      INTEGER NOT NULL DEFAULT 0,
            CONSTRAINT BuildTroves_jobId_fk
                FOREIGN KEY(jobId) REFERENCES Jobs(jobId)
                ON DELETE CASCADE ON UPDATE RESTRICT
        )""")
        db.tables["BuildTroves"] = []
        commit = True
    if db.createIndex("BuildTroves", "BuildTrovesIdx",
                      "jobId, troveName, version, flavor",
                      unique = False):
        commit = True
    if db.createIndex("BuildTroves", "BuildTrovesContextIdx",
                      "jobId, troveName, version, flavor, context",
                      unique = True):
        commit = True
    if db.createIndex("BuildTroves", "BuildTroveJobIdIdx", "jobId",
                      unique = False):
        commit = True

    if db.createIndex("BuildTroves", "BuildTroveIdIdx", "troveId",
                      unique = False):
        commit = True
    if db.createIndex("BuildTroves", "BuildTrovesStateIdx", "jobId, state",
                      unique = False):
        commit = True

    if commit:
        db.commit()
        db.loadSchema()

def createBinaryTroves(db):
    cu = db.cursor()
    commit = False
    if "BinaryTroves" not in db.tables:
        cu.execute("""
        CREATE TABLE BinaryTroves (
            troveId     INTEGER NOT NULL,
            troveName   STRING,
            version     STRING,
            flavor      STRING,
            CONSTRAINT BinaryTroves_jobId_fk
                FOREIGN KEY(troveId) REFERENCES BuildTroves(troveId)
                ON DELETE CASCADE ON UPDATE RESTRICT
        )""")
        db.tables["BinaryTroves"] = []
        commit = True
    if db.createIndex("BinaryTroves", "BinaryTrovesIdx",
                      "troveId"):
        commit = True
    if commit:
        db.commit()
        db.loadSchema()

def createStateLogs(db):
    cu = db.cursor()
    commit = False
    if "StateLogs" not in db.tables:
        cu.execute("""
        CREATE TABLE StateLogs (
            logId    INTEGER PRIMARY KEY AUTOINCREMENT,
            jobId    INTEGER NOT NULL,
            troveId  INTEGER NOT NULL,
            message  STRING NOT NULL,
            args     STRING NOT NULL DEFAULT '',
            changed  STRING NOT NULL DEFAULT CURRENT_TIMESTAMP,
            CONSTRAINT StateLogsJob_fk
                FOREIGN KEY(jobId) REFERENCES Jobs(jobId)
                ON DELETE CASCADE ON UPDATE RESTRICT
        )""")
        db.tables["StateLogs"] = []
        commit = True
    if db.createIndex("StateLogs", "StateLogsJobTroveId", "jobId,troveId"):
        commit = True
    if commit:
        db.commit()
        db.loadSchema()

def createJobQueue(db):
    cu = db.cursor()
    commit = False
    if "JobQueue" not in db.tables:
        cu.execute("""
        CREATE TABLE JobQueue (
            jobId       INTEGER
        )""")
        db.tables["JobQueue"] = []
        commit = True
    if commit:
        db.commit()
        db.loadSchema()

def createChroots(db):
    cu = db.cursor()
    commit = False
    if "Chroots" not in db.tables:
        cu.execute("""
        CREATE TABLE Chroots (
            chrootId      INTEGER PRIMARY KEY AUTOINCREMENT,
            nodeName      VARCHAR,
            path          VARCHAR,
            troveId       INTEGER NOT NULL,
            active        INTEGER NOT NULL
        )""")
        db.tables["Chroots"] = []
        commit = True
    if db.createIndex("Chroots", "ChrootdsIdx", "troveId"):
        commit = True
    if commit:
        db.commit()
        db.loadSchema()

def createNodes(db):
    cu = db.cursor()
    commit = False
    if "Nodes" not in db.tables:
        cu.execute("""
        CREATE TABLE Nodes (
            nodeName     VARCHAR PRIMARY KEY NOT NULL,
            host         VARCHAR NOT NULL,
            slots        INTEGER NOT NULL,
            buildFlavors VARCHAR NOT NULL,
            active       INTEGER NOT NULL DEFAULT 0
        )""")
        db.tables["Nodes"] = []
        commit = True
    if commit:
        db.commit()
        db.loadSchema()

def createAuthCache(db):
    cu = db.cursor()
    commit = False
    if "AuthCache" not in db.tables:
        cu.execute("""
        CREATE TABLE AuthCache (
            sessionId    VARCHAR PRIMARY KEY NOT NULL,
            timeStamp    FLOAT NOT NULL
        )""")
        db.tables["AuthCache"] = []
        commit = True
    if commit:
        db.commit()
        db.loadSchema()

def createPluginVersionTable(db):
    cu = db.cursor()
    commit = False
    if "PluginVersion" not in db.tables:
        cu.execute("""
        CREATE TABLE PluginVersion (
            plugin      VARCHAR NOT NULL UNIQUE,
            version     INTEGER
        )""")
        db.tables["PluginVersion"] = []
        commit = True
    if commit:
        db.commit()
        db.loadSchema()

class AbstractSchemaManager(object):
    def __init__(self, db):
        self.db = db
        self.currentVersion = self.getLatestVersion()

    def loadSchema(self):
        db = self.db
        version = self.getVersion()

        if version == self.currentVersion:
            return version

        db.loadSchema()
        self.createTables()
        db.loadSchema()

        if version != self.currentVersion:
            return self.setVersion(self.currentVersion)

        return self.currentVersion

    def getVersion(self):
        return self.db.getVersion()

    def setVersion(self, version):
        self.db.setVersion(version)

    def loadAndMigrate(self):
        schemaVersion = self.getVersion()
        if schemaVersion > self.currentVersion:
            raise errors.DatabaseSchemaTooNew()
        if not schemaVersion:
            self.loadSchema()
            return self.currentVersion
        else:
            self.db.loadSchema()
            if schemaVersion != self.currentVersion:
                self.migrate(schemaVersion, self.currentVersion)
                self.loadSchema()
        return self.currentVersion

class AbstractMigrator(object):

    # FIXME: This migration code is susceptible to a sort of upgrade race
    # condition: if a table is created and migrated during the same run,
    # SQL that alters the table will fail. this only applies to rMake installs
    # that don't get upgraded very often. there are a few ways to accomodate
    # this, just be aware that nothing is yet implemented.

    def _addColumn(self, table, name, value):
        self.cu.execute('ALTER TABLE %s ADD COLUMN %s    %s' % (table, name,
                                                                value))

    def migrate(self, currentVersion, newVersion):
        if currentVersion < newVersion:
            while currentVersion < newVersion:
                # migration returns the schema that they migrated to.
                currentVersion = getattr(self, 'migrateFrom' + str(currentVersion))()
        self.schemaMgr.setVersion(newVersion)
        self.db.commit()

    def __init__(self, db, schemaMgr):
        self.db = db
        self.cu = db.cursor()
        self.schemaMgr = schemaMgr

class SchemaManager(AbstractSchemaManager):

    def createTables(self):
        db = self.db
        createJobs(db)
        createJobConfig(db)
        createTroveSettings(db)
        createBuildTroves(db)
        createBinaryTroves(db)
        createStateLogs(db)
        createSubscriber(db)
        createJobQueue(db)
        createChroots(db)
        createNodes(db)
        createPluginVersionTable(db)
        createAuthCache(db)

    def migrate(self, oldVersion, newVersion):
        Migrator(self.db, self).migrate(oldVersion, newVersion)

    def getLatestVersion(self):
        return SCHEMA_VERSION

class Migrator(AbstractMigrator):
    def migrateFrom1(self):
        self._addColumn('Jobs', "uuid", "CHAR(32) NOT NULL DEFAULT ''")

        return 2

    def migrateFrom2(self):
        self._addColumn('Jobs', "pid", "INTEGER NOT NULL DEFAULT 0")
        self._addColumn('BuildTroves', "pid", "INTEGER NOT NULL DEFAULT 0")
        return 3

    def migrateFrom3(self):
        self.cu.execute("UPDATE Jobs SET state = state + 1000")
        for iState, fState in [(999, 1), (1000, 0), (1001, 2), (1002, 3),
                               (1003, 4), (1099, 5), (1100, 6), (1101, 7)]:
            self.cu.execute("UPDATE Jobs SET state=? WHERE state=?",
                            fState, iState)
        return 4

    def migrateFrom4(self):
        self._addColumn('BuildTroves', "recipeType",
                        "INTEGER NOT NULL DEFAULT 0")
        return 5

    def migrateFrom5(self):
        self._addColumn('BuildTroves', "chrootId",
                        "INTEGER NOT NULL DEFAULT 0")
        createChroots(self.db)
        createNodes(self.db)
        createPluginVersionTable(self.db)
        return 6

    def migrateFrom6(self):
        self._addColumn('BuildTroves', "context",
                        "STRING NOT NULL DEFAULT ''")
        self._addColumn('JobConfig',  "context",
                        "STRING NOT NULL DEFAULT ''")
        self._addColumn('BuildTroves', "buildType",
                        "INTEGER NOT NULL DEFAULT 0")
        self.cu.execute("DROP INDEX BuildTrovesIdx") # this idx is no longer
                                                     # unique
        createJobConfig(self.db) # add index
        createBuildTroves(self.db) # add indexes
        return 8

    def migrateFrom7(self):
        self._addColumn('BuildTroves', "buildType",
                        "INTEGER NOT NULL DEFAULT 0")
        return 8

    def migrateFrom8(self):
        createAuthCache(self.db)
        return 9

    def migrateFrom9(self):
        self._addColumn("Jobs", "owner",
                        "STRING NOT NULL DEFAULT ''")
        return 10

    def migrateFrom10(self):
        sql, = self.db.cursor().execute('select sql from sqlite_master'
                                        ' where tbl_name="BuildTroves"').next()
        if 'troveType' in sql:
            return 11
        createTroveSettings(self.db)
        self._addColumn("BuildTroves", "troveType",
                        "troveType      STRING NOT NULL DEFAULT 'build'")
        return 11

class PluginSchemaManager(AbstractSchemaManager):
    """
        Not used at the moment but here's a way to add plugin-specific tables
        to rMake.
    """

    def getVersion(self):
        cu = self.db.cursor()
        rv = cu.execute('SELECT version from PluginVersion WHERE plugin=?',
                        self.name).fetchall()
        if rv:
            return rv[0][0]
        else:
            return None

    def getLatestVersion(self):
        return SCHEMA_VERSION

    def setVersion(self, version):
        if self.getVersion() is None:
            cu = self.db.cursor()
            rv = cu.execute('INSERT INTO PluginVersion VALUES (?, ?)',
                            self.name, version)
        else:
            cu = self.db.cursor()
            rv = cu.execute('UPDATE PluginVersion SET version=? WHERE'
                            'plugin=?', version, self.name)

<|endoftext|>


<commit_before>import unittest

from nymms import registry
from nymms.resources import Command, MonitoringGroup
from weakref import WeakValueDictionary

class TestRegistry(unittest.TestCase):
    def tearDown(self):
        # Ensure we have a fresh registry after every test
        Command.registry.clear()

    def test_empty_registry(self):
        self.assertEqual(Command.registry, WeakValueDictionary())

    def test_register_object(self):
        # First test it's empty
        self.assertEqual(Command.registry, WeakValueDictionary())
        # Add a command
        command = Command('test_command', '/bin/true')
        # verify that there is only a single command in the registry
        self.assertEqual(len(Command.registry), 1)
        # Verify that the registered command is the same as command
        self.assertIs(Command.registry[command.name], command)

    def test_duplicate_register(self):
        # add a command
        Command('test_command', '/bin/true')
        with self.assertRaises(registry.DuplicateEntryError):
            Command('test_command', '/bin/true')

    def test_invalid_resource_register(self):
        with self.assertRaises(TypeError):
            Command.registry['test'] = MonitoringGroup('test_group')
<commit_msg>Clear command registry BEFORE each test.<commit_after>import unittest

from nymms import registry
from nymms.resources import Command, MonitoringGroup
from weakref import WeakValueDictionary

class TestRegistry(unittest.TestCase):
    def setUp(self):
        # Ensure we have a fresh registry before every test
        Command.registry.clear()

    def test_empty_registry(self):
        self.assertEqual(Command.registry, WeakValueDictionary())

    def test_register_object(self):
        # First test it's empty
        self.assertEqual(Command.registry, WeakValueDictionary())
        # Add a command
        command = Command('test_command', '/bin/true')
        # verify that there is only a single command in the registry
        self.assertEqual(len(Command.registry), 1)
        # Verify that the registered command is the same as command
        self.assertIs(Command.registry[command.name], command)

    def test_duplicate_register(self):
        # add a command
        print Command.registry
        Command('test_command', '/bin/true')
        with self.assertRaises(registry.DuplicateEntryError):
            Command('test_command', '/bin/true')

    def test_invalid_resource_register(self):
        with self.assertRaises(TypeError):
            Command.registry['test'] = MonitoringGroup('test_group')
<|endoftext|>


<commit_before># Copyright (C) 2014-2015 Kate Cook
#
# This file is part of rnascan.
#
# rnascan is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# rnascan is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with rnascan.  If not, see <http://www.gnu.org/licenses/>.

import os,sys,csv
import rnascan.pfmutil as pfmutil
import numpy as np

NUM_STRUCT = 7 # number of secondary structure contexts

def pfm_likelihood_seq(pfm,subseq):
    """ calculates likelihood that a subsequence was generated from a pfm """
    score = 1.
    for subpos in range(0, len(subseq)):
        base = subseq[subpos]
        score = score * pfm[base][subpos]
    return score

def bg_likelihood_seq(bg_probs,subseq):
    """ calculates likelihood that a subsequence was generated from a background distribution """
    score = 1.
    for subpos in range(0, len(subseq)):
        base = subseq[subpos]
        score = score * bg_probs[base]
    return score

def pfm_likelihood_struct(pfm,substructure):
    """ calculates likelihood that a substructure was generated from a pfm """
    pfm_length = pfm.shape[1]
    score = 1.
    for i in range(0, pfm_length):
        pfm_column = pfm[:,i]
        substructure_column = substructure[:,i]
        d = np.dot(pfm_column,substructure_column)
        score = score * d
    return score

def pfm_compare_seq(pfm,subseq,bg_probs,prob_pfm,prob_bg):
    """ calculates probability of a sequence hit given prior probabilities """
    llhood = pfm_likelihood_seq(pfm,subseq)
    bg_llhod = bg_likelihood_seq(bg_probs,subseq)
    probability = llhood * prob_pfm / (llhood*prob_pfm + bg_llhod*prob_bg)
    return probability

def pfm_compare_struct(pfm,substructure,bg_pfm,prob_pfm,prob_bg):
    """ calculates probability of a structure hit given prior probabilities """
    llhood = pfm_likelihood_struct(pfm,substructure)
    bg_llhood = pfm_likelihood_struct(bg_pfm,substructure)
    probability = llhood * prob_pfm / (llhood*prob_pfm + bg_llhood*prob_bg)
    return probability

def sequence_scan(pfm,seq,bg_probs,prob_pfm,prob_bg):
    """ Scan a sequence with a sequence pfm, returning a list of hit probabilities """
    #score forward strand only
    alphabet = sorted(pfm.keys())
    pfm_length = len(pfm[alphabet[0]])

    pos = 0
    scores = []

    while pos < (len(seq) - pfm_length + 1):
            subseq = seq[pos:(pos + pfm_length)]
            score = pfm_compare_seq(pfm,subseq,bg_probs,prob_pfm,prob_bg)
            scores.append(score)
            pos = pos + 1
    return scores

def structure_scan(pwm,structure,bg_model,prob_pfm,prob_bg):
    """ scan a structure with a structure pfm, returning a list of hit probabilities """
    #score forward strand only
    alphabet = sorted(pwm.keys())
    alphabet_struct = sorted(structure.keys())

    assert alphabet == alphabet_struct

    pwm_length = len(pwm[alphabet[0]])
    sequence_length = len(structure[alphabet[0]])

    pwm_np = convert_pfm_to_numpy(pwm)
    structure_np = convert_pfm_to_numpy(structure)

    pos = 0
    scores = []

    bg_probs = [bg_model[x] for x in sorted(bg_model.keys())]
    bg_pwm = np.reshape(np.repeat(bg_probs,pwm_length),[NUM_STRUCT,pwm_length])

    while pos < (sequence_length - pwm_length + 1):
        substructure = structure_np[:,pos:(pos+pwm_length)]
        p_hit = pfm_compare_struct(pwm_np,substructure,bg_pwm,prob_pfm,prob_bg)
        scores.append(p_hit)
        pos = pos + 1

    return scores

def convert_pfm_to_numpy(pfm):
    """ helper function to convert a (structure) pfm to a numpy array format """
    alphabet = sorted(pfm.keys())
    pfm_length = len(pfm[alphabet[0]])

    pfm_array = np.empty([len(alphabet),pfm_length])
    for i,base in enumerate(alphabet):
        for j in range(0, pfm_length):
            pfm_array[i,j] = pfm[base][j]

    return pfm_array

<commit_msg>add error message for above<commit_after># Copyright (C) 2014-2015 Kate Cook
#
# This file is part of rnascan.
#
# rnascan is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# rnascan is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with rnascan.  If not, see <http://www.gnu.org/licenses/>.

import os,sys,csv
import rnascan.pfmutil as pfmutil
import numpy as np

NUM_STRUCT = 7 # number of secondary structure contexts

def pfm_likelihood_seq(pfm,subseq):
    """ calculates likelihood that a subsequence was generated from a pfm """
    score = 1.
    for subpos in range(0, len(subseq)):
        base = subseq[subpos]
        score = score * pfm[base][subpos]
    return score

def bg_likelihood_seq(bg_probs,subseq):
    """ calculates likelihood that a subsequence was generated from a background distribution """
    score = 1.
    for subpos in range(0, len(subseq)):
        base = subseq[subpos]
        score = score * bg_probs[base]
    return score

def pfm_likelihood_struct(pfm,substructure):
    """ calculates likelihood that a substructure was generated from a pfm """
    pfm_length = pfm.shape[1]
    score = 1.
    for i in range(0, pfm_length):
        pfm_column = pfm[:,i]
        substructure_column = substructure[:,i]
        d = np.dot(pfm_column,substructure_column)
        score = score * d
    return score

def pfm_compare_seq(pfm,subseq,bg_probs,prob_pfm,prob_bg):
    """ calculates probability of a sequence hit given prior probabilities """
    llhood = pfm_likelihood_seq(pfm,subseq)
    bg_llhod = bg_likelihood_seq(bg_probs,subseq)
    probability = llhood * prob_pfm / (llhood*prob_pfm + bg_llhod*prob_bg)
    return probability

def pfm_compare_struct(pfm,substructure,bg_pfm,prob_pfm,prob_bg):
    """ calculates probability of a structure hit given prior probabilities """
    llhood = pfm_likelihood_struct(pfm,substructure)
    bg_llhood = pfm_likelihood_struct(bg_pfm,substructure)
    probability = llhood * prob_pfm / (llhood*prob_pfm + bg_llhood*prob_bg)
    return probability

def sequence_scan(pfm,seq,bg_probs,prob_pfm,prob_bg):
    """ Scan a sequence with a sequence pfm, returning a list of hit probabilities """
    #score forward strand only
    alphabet = sorted(pfm.keys())
    pfm_length = len(pfm[alphabet[0]])

    pos = 0
    scores = []

    while pos < (len(seq) - pfm_length + 1):
            subseq = seq[pos:(pos + pfm_length)]
            score = pfm_compare_seq(pfm,subseq,bg_probs,prob_pfm,prob_bg)
            scores.append(score)
            pos = pos + 1
    return scores

def structure_scan(pwm,structure,bg_model,prob_pfm,prob_bg):
    """ scan a structure with a structure pfm, returning a list of hit probabilities """
    #score forward strand only
    alphabet = sorted(pwm.keys())
    alphabet_struct = sorted(structure.keys())

    assert alphabet == alphabet_struct, "pfm structure alphabet " + alphabet +\
    " not the same as sequence strucutre alphabet "+alphabet_struct

    pwm_length = len(pwm[alphabet[0]])
    sequence_length = len(structure[alphabet[0]])

    pwm_np = convert_pfm_to_numpy(pwm)
    structure_np = convert_pfm_to_numpy(structure)

    pos = 0
    scores = []

    bg_probs = [bg_model[x] for x in sorted(bg_model.keys())]
    bg_pwm = np.reshape(np.repeat(bg_probs,pwm_length),[NUM_STRUCT,pwm_length])

    while pos < (sequence_length - pwm_length + 1):
        substructure = structure_np[:,pos:(pos+pwm_length)]
        p_hit = pfm_compare_struct(pwm_np,substructure,bg_pwm,prob_pfm,prob_bg)
        scores.append(p_hit)
        pos = pos + 1

    return scores

def convert_pfm_to_numpy(pfm):
    """ helper function to convert a (structure) pfm to a numpy array format """
    alphabet = sorted(pfm.keys())
    pfm_length = len(pfm[alphabet[0]])

    pfm_array = np.empty([len(alphabet),pfm_length])
    for i,base in enumerate(alphabet):
        for j in range(0, pfm_length):
            pfm_array[i,j] = pfm[base][j]

    return pfm_array

<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

# This file is part of the Rocket Web Server
# Copyright (c) 2010 Timothy Farrell

# Import System Modules
import os
import socket
import logging
import traceback
from threading import Thread

try:
    import ssl
    from ssl import SSLError
    has_ssl = True
except ImportError:
    has_ssl = False
    class SSLError(socket.error):
        pass
# Import Package Modules
from . import IS_JYTHON, NullHandler, THREAD_STOP_CHECK_INTERVAL

class Listener(Thread):
    """The Listener class is a class responsible for accepting connections
    and queuing them to be processed by a worker thread."""

    def __init__(self, interface, queue_size, active_queue, *args, **kwargs):
        Thread.__init__(self, *args, **kwargs)

        # Instance variables
        self.active_queue = active_queue
        self.interface = interface
        self.addr = interface[0]
        self.port = interface[1]
        self.secure = len(interface) == 4 and \
                      os.path.exists(interface[2]) and \
                      os.path.exists(interface[3])
        self.thread = None
        self.ready = False

        # Error Log
        self.err_log = logging.getLogger('Rocket.Errors.Port%i' % self.port)
        self.err_log.addHandler(NullHandler())

        # Build the socket
        listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        if not listener:
            self.err_log.error("Failed to get socket.")
            return

        if self.secure:
            if not has_ssl:
                self.err_log.error("ssl module required to serve HTTPS.")
                return
            elif not os.path.exists(interface[2]):
                data = (interface[2], interface[0], interface[1])
                self.err_log.error("Cannot find key file "
                          "'%s'.  Cannot bind to %s:%s" % data)
                return
            elif not os.path.exists(interface[3]):
                data = (interface[3], interface[0], interface[1])
                self.err_log.error("Cannot find certificate file "
                          "'%s'.  Cannot bind to %s:%s" % data)
                return

        # Set socket options
        try:
            listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        except:
            msg = "Cannot share socket.  Using %s:%i exclusively."
            self.err_log.warning(msg % (self.addr, self.port))

        try:
            if not IS_JYTHON:
                listener.setsockopt(socket.IPPROTO_TCP,
                                    socket.TCP_NODELAY,
                                    1)
        except:
            msg = "Cannot set TCP_NODELAY, things might run a little slower"
            self.err_log.warning(msg)

        try:
            listener.bind((self.addr, self.port))
        except:
            msg = "Socket %s:%i in use by other process and it won't share."
            self.err_log.error(msg % (self.addr, self.port))
        else:
            # We want socket operations to timeout periodically so we can
            # check if the server is shutting down
            listener.settimeout(THREAD_STOP_CHECK_INTERVAL)
            # Listen for new connections allowing queue_size number of
            # connections to wait before rejecting a connection.
            listener.listen(queue_size)

            self.listener = listener

            self.ready = True

    def wrap_socket(self, sock):
        try:
            sock = ssl.wrap_socket(sock,
                                   keyfile = self.interface[2],
                                   certfile = self.interface[3],
                                   server_side = True,
                                   ssl_version = ssl.PROTOCOL_SSLv23)
        except SSLError:
            # Generally this happens when an HTTP request is received on a
            # secure socket. We don't do anything because it will be detected
            # by Worker and dealt with appropriately.
            pass

        return sock

    def start(self):
        if not self.ready:
            self.err_log.warning('Listener started when not ready.')
            return

        if self.thread is not None and self.thread.isAlive():
            self.err_log.warning('Listener already running.')
            return

        self.thread = Thread(target=self.listen, name="Port" + str(self.port))

        self.thread.start()

    def isAlive(self):
        if self.thread is None:
            return False

        return self.thread.isAlive()

    def join(self):
        if self.thread is None:
            return

        self.ready = False

        self.thread.join()

        del self.thread
        self.thread = None
        self.ready = True

    def listen(self):
        if __debug__:
            self.err_log.debug('Entering main loop.')
        while True:
            try:
                sock, addr = self.listener.accept()

                if self.secure:
                    sock = self.wrap_socket(sock)

                self.active_queue.put(((sock, addr),
                                       self.interface[1],
                                       self.secure))

            except socket.timeout:
                # socket.timeout will be raised every THREAD_STOP_CHECK_INTERVAL
                # seconds.  When that happens, we check if it's time to die.

                if not self.ready:
                    if __debug__:
                        self.err_log.debug('Listener exiting.')
                    return
                else:
                    continue
            except:
                self.err_log.error(str(traceback.format_exc()))
<commit_msg>Shut down socket on listener shutdown<commit_after># -*- coding: utf-8 -*-

# This file is part of the Rocket Web Server
# Copyright (c) 2010 Timothy Farrell

# Import System Modules
import os
import socket
import logging
import traceback
from threading import Thread

try:
    import ssl
    from ssl import SSLError
    has_ssl = True
except ImportError:
    has_ssl = False
    class SSLError(socket.error):
        pass
# Import Package Modules
from . import IS_JYTHON, NullHandler, THREAD_STOP_CHECK_INTERVAL

class Listener(Thread):
    """The Listener class is a class responsible for accepting connections
    and queuing them to be processed by a worker thread."""

    def __init__(self, interface, queue_size, active_queue, *args, **kwargs):
        Thread.__init__(self, *args, **kwargs)

        # Instance variables
        self.active_queue = active_queue
        self.interface = interface
        self.addr = interface[0]
        self.port = interface[1]
        self.secure = len(interface) == 4 and \
                      os.path.exists(interface[2]) and \
                      os.path.exists(interface[3])
        self.thread = None
        self.ready = False

        # Error Log
        self.err_log = logging.getLogger('Rocket.Errors.Port%i' % self.port)
        self.err_log.addHandler(NullHandler())

        # Build the socket
        listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        if not listener:
            self.err_log.error("Failed to get socket.")
            return

        if self.secure:
            if not has_ssl:
                self.err_log.error("ssl module required to serve HTTPS.")
                return
            elif not os.path.exists(interface[2]):
                data = (interface[2], interface[0], interface[1])
                self.err_log.error("Cannot find key file "
                          "'%s'.  Cannot bind to %s:%s" % data)
                return
            elif not os.path.exists(interface[3]):
                data = (interface[3], interface[0], interface[1])
                self.err_log.error("Cannot find certificate file "
                          "'%s'.  Cannot bind to %s:%s" % data)
                return

        # Set socket options
        try:
            listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        except:
            msg = "Cannot share socket.  Using %s:%i exclusively."
            self.err_log.warning(msg % (self.addr, self.port))

        try:
            if not IS_JYTHON:
                listener.setsockopt(socket.IPPROTO_TCP,
                                    socket.TCP_NODELAY,
                                    1)
        except:
            msg = "Cannot set TCP_NODELAY, things might run a little slower"
            self.err_log.warning(msg)

        try:
            listener.bind((self.addr, self.port))
        except:
            msg = "Socket %s:%i in use by other process and it won't share."
            self.err_log.error(msg % (self.addr, self.port))
        else:
            # We want socket operations to timeout periodically so we can
            # check if the server is shutting down
            listener.settimeout(THREAD_STOP_CHECK_INTERVAL)
            # Listen for new connections allowing queue_size number of
            # connections to wait before rejecting a connection.
            listener.listen(queue_size)

            self.listener = listener

            self.ready = True

    def wrap_socket(self, sock):
        try:
            sock = ssl.wrap_socket(sock,
                                   keyfile = self.interface[2],
                                   certfile = self.interface[3],
                                   server_side = True,
                                   ssl_version = ssl.PROTOCOL_SSLv23)
        except SSLError:
            # Generally this happens when an HTTP request is received on a
            # secure socket. We don't do anything because it will be detected
            # by Worker and dealt with appropriately.
            pass

        return sock

    def start(self):
        if not self.ready:
            self.err_log.warning('Listener started when not ready.')
            return

        if self.thread is not None and self.thread.isAlive():
            self.err_log.warning('Listener already running.')
            return

        self.thread = Thread(target=self.listen, name="Port" + str(self.port))

        self.thread.start()

    def isAlive(self):
        if self.thread is None:
            return False

        return self.thread.isAlive()

    def join(self):
        if self.thread is None:
            return

        self.ready = False

        self.thread.join()

        del self.thread
        self.thread = None
        self.ready = True

    def listen(self):
        if __debug__:
            self.err_log.debug('Entering main loop.')
        while True:
            try:
                sock, addr = self.listener.accept()

                if self.secure:
                    sock = self.wrap_socket(sock)

                self.active_queue.put(((sock, addr),
                                       self.interface[1],
                                       self.secure))

            except socket.timeout:
                # socket.timeout will be raised every THREAD_STOP_CHECK_INTERVAL
                # seconds.  When that happens, we check if it's time to die.

                if not self.ready:
                    if __debug__:
                        self.err_log.debug('Listener exiting.')
                    self.listener.shutdown(socket.SHUT_RDWR)
                    return
                else:
                    continue
            except:
                self.err_log.error(str(traceback.format_exc()))
<|endoftext|>


<commit_before>#!/usr/bin/env python

import click
import platform

from flask import Flask
from flask_restful import Api
from processes import Processes

def _get_os_props():
    distro, _, release = platform.linux_distribution(
        full_distribution_name=False)
    return distro.lower(), release.lower()

def get_meminfo():
    with open('/proc/meminfo', 'r') as f:
        for l in f.read():
            data = l.split(' ')
            print data

@click.command()
@click.option('-p', '--port', default=31337)
@click.option('--debug', default=False, is_flag=True)
@click.option('-r', '--run-command', type=str, required=False)
def main(port, debug, run_command):
    if run_command:
        if hasattr(globals(), run_command):
            getattr(globals(), run_command)
    else:
        app = Flask('roomservice')
        api = Api(app)

        api.add_resource(Processes, '/processes')

        app.run(port=port, debug=debug)

if __name__ == '__main__':
    main()
<commit_msg>cleanup<commit_after>#!/usr/bin/env python

import click
import platform

from flask import Flask
from flask_restful import Api
from processes import Processes

def _get_os_props():
    distro, _, release = platform.linux_distribution(
        full_distribution_name=False)
    return distro.lower(), release.lower()

@click.command()
@click.option('-p', '--port', default=31337)
@click.option('--debug', default=False, is_flag=True)
@click.option('-r', '--run-command', type=str, required=False)
def main(port, debug, run_command):
        app = Flask('roomservice')
        api = Api(app)

        api.add_resource(Processes, '/processes')

        app.run(port=port, debug=debug)

if __name__ == '__main__':
    main()
<|endoftext|>


<commit_before>"""
                 _
 _ __ ___   ___ | |_     _ __  _   _ _ __ ___  _ __  _   _
| '__/ _ \ / _ \| __|   | '_ \| | | | '_ ` _ \| '_ \| | | |
| | | (_) | (_) | |_    | | | | |_| | | | | | | |_) | |_| |
|_|  \___/ \___/ \__|___|_| |_|\__,_|_| |_| |_| .__/ \__, |  {0}
                   |_____|                    |_|    |___/
"""
__version__ = '3.3.1.dev'
__doc__ = __doc__.format(__version__)
<commit_msg>bump version to 3.4.0<commit_after>"""
                 _
 _ __ ___   ___ | |_     _ __  _   _ _ __ ___  _ __  _   _
| '__/ _ \ / _ \| __|   | '_ \| | | | '_ ` _ \| '_ \| | | |
| | | (_) | (_) | |_    | | | | |_| | | | | | | |_) | |_| |
|_|  \___/ \___/ \__|___|_| |_|\__,_|_| |_| |_| .__/ \__, |  {0}
                   |_____|                    |_|    |___/
"""
__version__ = '3.4.0.dev'
__doc__ = __doc__.format(__version__)
<|endoftext|>


<commit_before>
"""
Medtronic - openaps driver for Medtronic
"""
from openaps.uses.use import Use
from openaps.configurable import Configurable
import decocare
from decocare import stick, session, link, commands, history
from datetime import datetime
from dateutil import relativedelta
from dateutil.parser import parse

def configure_use_app (app, parser):
  pass
  # parser.add_argument('foobar', help="LOOK AT ME")

def configure_add_app (app, parser):
  parser.add_argument('serial')

def configure_app (app, parser):
  if app.parent.name == 'add':
    print "CONFIG INNER", app, app.parent.name, app.name
def configure_parser (parser):
  pass
def main (args, app):
  print "MEDTRONIC", args, app
  print "app commands", app.selected.name

__USES__ = { }
def use ( ):
  def decorator (cls):
    if cls.__name__ not in __USES__:
      __USES__[cls.__name__] = cls
    return cls
  return decorator

@use( )
class scan (Use):
  """ scan for usb stick """
  def configure_app (self, app, parser):
    pass
    # print "hahaha"
  def scanner (self):
    from decocare.scan import scan
    return scan( )
  def main (self, args, app):
    return self.scanner( )

class MedtronicTask (scan):
  requires_session = True
  save_session = True
  record_stats = True
  def before_main (self, args, app):
    self.setup_medtronic( )
    if self.requires_session:
      self.check_session(app)
    else:
      self.pump.setModel(number=self.device.fields.get('model', ''))
  def after_main (self, args, app):
    if self.save_session:
      self.device.store(app.config)
      app.config.save( )
  def get_session_info (self):
    expires = self.device.fields.get('expires', None)
    now = datetime.now( )
    out = dict(device=self.device.name
      , vendor=__name__
      , used=now
      )
    if expires is None or parse(expires) < now:
      fields = self.create_session( )
      self.device.add_option('expires', fields['expires'].isoformat( ))
      self.device.add_option('model', fields['model'])
      out['expires'] = fields['expires']
      out['model'] = fields['model']
    else:
      out['expires'] = parse(expires)
      out['model'] = self.get_model( )
    return out
  def create_session (self):
    minutes = int(self.device.fields.get('minutes', 10))
    self.pump.power_control(minutes=minutes)
    model = self.get_model( )
    now = datetime.now( )
    offset = relativedelta.relativedelta(minutes=minutes)
    out = dict(device=self.device.name
      , model=model
      , vendor=__name__
      , created_at=now
      , started=now
      , expires=now + offset
      )
    return out
  def check_session (self, app):
    self.session = self.get_session_info( )
    self.device.add_option('model', self.device.fields.get('model', self.get_model( )))
  def get_model (self):
    model = self.pump.read_model( ).getData( )
    return model
  def setup_medtronic (self):
    self.uart = stick.Stick(link.Link(self.scanner( )))
    self.uart.open( )
    serial = self.device.fields['serial']
    self.pump = session.Pump(self.uart, serial)
    stats = self.uart.interface_stats( )
  def main (self, args, app):
    return self.scanner( )

class Session (MedtronicTask):
  """ session for pump
  """
  def configure_parser (self, parser):
    parser.add_argument('--minutes', type=int, default='10')
  def setup_application (self):
    print self.parser, self
  def main (self, args, app):
    self.pump.power_control(minutes=args.minutes)
    model = self.pump.read_model( ).getData( )
    offset = relativedelta.relativedelta(minutes=args.minutes)
    created_at = datetime.now( )
    out = dict(device=self.device.name
      , model=model
      , vendor=__name__
      , created_at=created_at
      , started=created_at
      , expires=created_at + offset
      )
    return out

@use( )
class model (MedtronicTask):
  """ Get model number
  """
  def configure_app (self, app, parser):
    pass
  def main (self, args, app):
    model = self.pump.read_model( ).getData( )
    return model

@use( )
class status (MedtronicTask):
  """ Get pump status
  """
  def main (self, args, app):
    return self.pump.model.read_status( )

@use( )
class reservoir (MedtronicTask):
  """ Get pump remaining insulin
  """
  def main (self, args, app):
    return self.pump.model.read_reservoir( )

@use( )
class settings (MedtronicTask):
  """ Get pump remaining insulin
  """
  def main (self, args, app):
    return self.pump.model.read_settings( )

@use( )
class yyyxread_temp_basal (MedtronicTask):
  """ Get pump remaining insulin
  """
  def main (self, args, app):
    return self.pump.model.read_temp_basal( )

@use( )
class mytest (MedtronicTask):
  """ Get pump remaining insulin
  """
  requires_session = False
  def main (self, args, app):
    return self.pump.model.my_read_settings( )

@use( )
class read_clock (MedtronicTask):
  """ Get pump remaining insulin
  """
  def main (self, args, app):
    return self.pump.model.read_clock( )

class SameNameCommand (MedtronicTask):
  def main (self, args, app):
    name = self.__class__.__name__.split('.').pop( )
    return getattr(self.pump.model, name)( )

@use( )
class read_temp_basal (SameNameCommand):
  """ Read temporary basal rates. """

def set_config (args, device):
  device.add_option('serial', args.serial)

def display_device (device):
  return ''

known_uses = [
  Session,
]
def get_uses (device, config):
  return  known_uses[:] + __USES__.values( )

<commit_msg>tweak/cleanup<commit_after>
"""
Medtronic - openaps driver for Medtronic
"""
from openaps.uses.use import Use
from openaps.configurable import Configurable
import decocare
from decocare import stick, session, link, commands, history
from datetime import datetime
from dateutil import relativedelta
from dateutil.parser import parse

def configure_use_app (app, parser):
  pass
  # parser.add_argument('foobar', help="LOOK AT ME")

def configure_add_app (app, parser):
  parser.add_argument('serial')

def configure_app (app, parser):
  if app.parent.name == 'add':
    print "CONFIG INNER", app, app.parent.name, app.name
def configure_parser (parser):
  pass
def main (args, app):
  print "MEDTRONIC", args, app
  print "app commands", app.selected.name

__USES__ = { }
def use ( ):
  def decorator (cls):
    if cls.__name__ not in __USES__:
      __USES__[cls.__name__] = cls
    return cls
  return decorator

@use( )
class scan (Use):
  """ scan for usb stick """
  def configure_app (self, app, parser):
    pass
    # print "hahaha"
  def scanner (self):
    from decocare.scan import scan
    return scan( )
  def main (self, args, app):
    return self.scanner( )

class MedtronicTask (scan):
  requires_session = True
  save_session = True
  record_stats = True
  def before_main (self, args, app):
    self.setup_medtronic( )
    if self.requires_session:
      self.check_session(app)
    else:
      self.pump.setModel(number=self.device.fields.get('model', ''))
  def after_main (self, args, app):
    if self.save_session:
      self.device.store(app.config)
      app.config.save( )
  def get_session_info (self):
    expires = self.device.fields.get('expires', None)
    now = datetime.now( )
    out = dict(device=self.device.name
      , vendor=__name__
      , used=now
      )
    if expires is None or parse(expires) < now:
      fields = self.create_session( )
      self.device.add_option('expires', fields['expires'].isoformat( ))
      self.device.add_option('model', fields['model'])
      out['expires'] = fields['expires']
      out['model'] = fields['model']
    else:
      out['expires'] = parse(expires)
      out['model'] = self.get_model( )
    return out
  def create_session (self):
    minutes = int(self.device.fields.get('minutes', 10))
    self.pump.power_control(minutes=minutes)
    model = self.get_model( )
    now = datetime.now( )
    offset = relativedelta.relativedelta(minutes=minutes)
    out = dict(device=self.device.name
      , model=model
      , vendor=__name__
      , created_at=now
      , started=now
      , expires=now + offset
      )
    return out
  def check_session (self, app):
    self.session = self.get_session_info( )
    self.device.add_option('model', self.device.fields.get('model', self.get_model( )))
  def get_model (self):
    model = self.pump.read_model( ).getData( )
    return model
  def setup_medtronic (self):
    self.uart = stick.Stick(link.Link(self.scanner( )))
    self.uart.open( )
    serial = self.device.fields['serial']
    self.pump = session.Pump(self.uart, serial)
    stats = self.uart.interface_stats( )
  def main (self, args, app):
    return self.scanner( )

class Session (MedtronicTask):
  """ session for pump
  """
  def configure_parser (self, parser):
    parser.add_argument('--minutes', type=int, default='10')
  def setup_application (self):
    print self.parser, self
  def main (self, args, app):
    self.pump.power_control(minutes=args.minutes)
    model = self.pump.read_model( ).getData( )
    offset = relativedelta.relativedelta(minutes=args.minutes)
    created_at = datetime.now( )
    out = dict(device=self.device.name
      , model=model
      , vendor=__name__
      , created_at=created_at
      , started=created_at
      , expires=created_at + offset
      )
    return out

@use( )
class model (MedtronicTask):
  """ Get model number
  """
  def configure_app (self, app, parser):
    pass
  def main (self, args, app):
    model = self.pump.read_model( ).getData( )
    return model

@use( )
class status (MedtronicTask):
  """ Get pump status
  """
  def main (self, args, app):
    return self.pump.model.read_status( )

@use( )
class reservoir (MedtronicTask):
  """ Get pump remaining insulin
  """
  def main (self, args, app):
    return self.pump.model.read_reservoir( )

@use( )
class settings (MedtronicTask):
  """ Get pump settings
  """
  def main (self, args, app):
    return self.pump.model.read_settings( )

@use( )
class mytest (MedtronicTask):
  """ Testing read_settings
  """
  requires_session = False
  def main (self, args, app):
    return self.pump.model.my_read_settings( )

@use( )
class read_clock (MedtronicTask):
  """ Read date/time of pump
  """
  def main (self, args, app):
    return self.pump.model.read_clock( )

class SameNameCommand (MedtronicTask):
  def main (self, args, app):
    name = self.__class__.__name__.split('.').pop( )
    return getattr(self.pump.model, name)( )

@use( )
class read_temp_basal (SameNameCommand):
  """ Read temporary basal rates. """

@use( )
class read_settings (SameNameCommand):
  """ Read settings. """

def set_config (args, device):
  device.add_option('serial', args.serial)

def display_device (device):
  return ''

known_uses = [
  Session,
]
def get_uses (device, config):
  return  known_uses[:] + __USES__.values( )

<|endoftext|>