12Module containing all functionality necessary to manage local metadata and payload 
   17from conditions_db 
import PayloadInformation
 
   22    Class to handle local sqlite dump of conditions database metadata 
   24    This class can create and read sqlite dumps of the central database in a format 
   25    compatible with the local metadata provider in basf2. 
   28    APPLICATION_ID = 0xb2cdb
 
   34        -- first drop all tables we care about 
   35        DROP VIEW IF EXISTS iov_payloads; 
   36        DROP INDEX IF EXISTS iov_index; 
   37        DROP TABLE IF EXISTS iovs; 
   38        DROP TABLE IF EXISTS globaltags; 
   39        DROP VIEW IF EXISTS full_payloads; 
   40        DROP TABLE IF EXISTS payloads; 
   41        DROP TABLE IF EXISTS payloadNames; 
   42        DROP TABLE IF EXISTS baseUrls; 
   44        -- table to store the base urls for normalization: Mostly we have the 
   45        -- same base url for all payloads but we only want to store the string 
   46        -- once so give it an id 
   47        CREATE TABLE baseUrls ( 
   48            baseUrlId INTEGER PRIMARY KEY, 
   52        -- table to store all distinct payload names only once 
   53        CREATE TABLE payloadNames ( 
   54            payloadNameId INTEGER PRIMARY KEY, 
   55            payloadName TEXT UNIQUE 
   58        -- Payload information for each payload. 
   59        -- payloadId, revision, checksum, payloadUrl are taken directly without 
   60        -- change from the central database. 
   61        -- payloadName and baseUrl are put into local tables defined above, 
   62        -- these ids are local to the file. 
   63        -- payloadUrl is taken from the database except if it follows the usual 
   64        -- `dbstore/{payloadName}/dbstore_{payloadName}_rev_{revision}.root` in 
   65        -- which case it is set to NULL and created on the fly from the pattern. 
   66        CREATE TABLE payloads ( 
   67            payloadId INTEGER PRIMARY KEY, 
   68            payloadNameId INTEGER NOT NULL, 
   69            revision INTEGER NOT NULL, 
   70            checksum text NOT NULL, 
   71            payloadUrl text DEFAULT NULL, 
   72            baseUrlId INTEGER NOT NULL, 
   73            CONSTRAINT name_rev UNIQUE (payloadNameId, revision), 
   74            FOREIGN KEY (payloadNameId) REFERENCES payloadNames (payloadNameId) 
   75                ON UPDATE CASCADE ON DELETE RESTRICT 
   76            FOREIGN KEY (baseUrlId) REFERENCES baseUrls (baseUrlId) 
   77                ON UPDATE CASCADE ON DELETE RESTRICT 
   80        -- Payload information with the local ids and the payloadUrl resolved 
   81        -- Information in this view is identical to the central server 
   82        CREATE VIEW full_payloads AS 
   83            SELECT payloadId, payloadName, revision, checksum, 
   84                ifnull(payloadUrl, 'dbstore/' || payloadName || '/dbstore_' || 
   85                       payloadName || '_rev_' || revision || '.root') 
   86                as payloadUrl, baseUrl 
   87            FROM payloads NATURAL JOIN payloadNames NATURAL JOIN baseUrls; 
   89        -- table for all globaltags in this file. All values taken directly from 
   91        CREATE TABLE globaltags ( 
   92            globalTagId INTEGER PRIMARY KEY, 
   93            globalTagName text UNIQUE, 
   94            globalTagStatus text NOT NULL 
   97        -- table for all iovs in all globaltags in this file, all values taken 
   98        -- directly from the central server 
  100            globalTagId INTEGER NOT NULL, 
  101            payloadId INTEGER NOT NULL, 
  102            firstExp INTEGER NOT NULL, 
  103            firstRun INTEGER NOT NULL, 
  104            finalExp INTEGER NOT NULL, 
  105            finalRun INTEGER NOT NULL, 
  106            FOREIGN KEY (globalTagId) REFERENCES globaltags (globalTagId) 
  107                ON UPDATE CASCADE ON DELETE CASCADE, 
  108            FOREIGN KEY (payloadId) REFERENCES payloads (payloadId) 
  109                ON UPDATE CASCADE ON DELETE RESTRICT 
  111        -- composite index on the iovs to exclude duplicates and allow 
  113        CREATE UNIQUE INDEX iov_index on iovs ( 
  114            globalTagId, firstExp, firstRun, finalExp, finalRun, payloadId 
  117        -- full view returning the full information on all iovs in all globaltags 
  118        CREATE VIEW iov_payloads AS 
  119            SELECT globalTagName, payloadId, payloadName, revision, checksum, 
  120                firstExp, firstRun, finalExp, finalRun, payloadUrl, baseUrl 
  121            FROM globaltags NATURAL JOIN iovs NATURAL JOIN full_payloads; 
  126        Open an sqlite database and make sure that the schema exists in the 
  127        correct version or create it if ``mode=overwrite`` 
  130          filename (str): name of the database file 
  131          readonly (str): how to open the file. Can be one of ``read`` to open 
  132            the file readonly, ``append` to append new data to an existing file 
  133            and ``overwrite`` to recreate all tables and overwrite the contents. 
  143            self.
_database = sqlite3.connect(f
"file:{filename}?mode=ro", uri=
True)
 
  144        elif mode 
in [
"append", 
"overwrite"]:
 
  145            self.
_database = sqlite3.connect(filename)
 
  147            raise RuntimeError(
"invalid mode: please supply one of 'read', 'append', 'overwrite'")
 
  149        if mode == 
"overwrite":
 
  153            self.
_database.execute(f
"PRAGMA application_id = {self.APPLICATION_ID}")
 
  154            self.
_database.execute(f
"PRAGMA user_version = {self.SCHEMA_VERSION}")
 
  158            application_id = self.
_database.execute(
"PRAGMA application_id").fetchone()[0]
 
  160                raise RuntimeError(
"Not a b2conditionsdb database file")
 
  161            schema_version = self.
_database.execute(
"PRAGMA user_version").fetchone()[0]
 
  163                raise RuntimeError(
"Cannot use sqlite file: different schema version, please recreate")
 
 
  166        """Get the number of distinct payloads known to this file""" 
  167        cursor = self.
_database.execute(
"SELECT count(*) from full_payloads")
 
  168        return cursor.fetchone()[0]
 
 
  172        Resolve the id for a named entity in the database file. 
  174        Create new entities on demand and cache all known entities 
  177          name (str): name to lookup 
  178          entity (str): type of the entity, currently ``baseUrl`` or ``payloadName`` 
  181        if entity 
not in self.
_cache:
 
  182            self.
_cache[entity] = {row[0]: row[1] 
for row 
in self.
_database.execute(f
"SELECT {entity}, {entity}Id from {entity}s")}
 
  184        cache = self.
_cache[entity]
 
  185        if name 
not in cache:
 
  186            cache[name] = len(cache) + 1
 
  187            self.
_database.execute(f
"INSERT INTO {entity}s ({entity}Id, {entity}) VALUES (?,?)", (cache[name], name))
 
 
  192        Add a globaltag to the database file. If the globaltag already exists in 
  193        the file its contents will be replaced. 
  195        Parameters: tag_id (str): id of the globaltag in the central database 
  196          name (str): name of the globaltag in the central database state (str): 
  197          state of the globaltag in the central database iovs 
  198          (list(PayloadInformation)): all iovs valid for this globaltag 
  200        self.
_database.execute(
"INSERT OR REPLACE INTO globaltags VALUES (?,?,?)", (tag_id, name, state))
 
  202        self.
_database.execute(
"DELETE from iovs WHERE globalTagId=?", (tag_id,))
 
  207            if p.payload_id 
not in all_payloads:
 
  211                if p.payload_url.lstrip(
'/') != f
"dbstore/{p.name}/dbstore_{p.name}_rev_{p.revision}.root":
 
  213                all_payloads[p.payload_id] = (p.payload_id, name, p.revision, p.checksum, url, base_url)
 
  214            all_iovs.append((tag_id, p.payload_id) + p.iov)
 
  216        self.
_database.executemany(
"INSERT OR REPLACE INTO payloads VALUES (?,?,?,?,?,?)", all_payloads.values())
 
  217        self.
_database.executemany(
"INSERT INTO iovs VALUES (?,?,?,?,?,?)", all_iovs)
 
 
  223        """Return the list of globaltags stored in the file 
  226          a list of (id, name, state) tuples for all globaltags 
  228        return [row 
for row 
in self.
_database.execute(
"SELECT globalTagId, globalTagName, globalTagStatus FROM globaltags " 
  229                                                      "ORDER by globalTagName")]
 
 
  232        """Get all payloads existing in this file 
  235          a sorted list of `PayloadInformation` objects for all payloads defined in this file with the iov set to None 
  238                           self.
_database.execute(
"SELECT payloadId, payloadName, revision, checksum, " 
  239                                                  "payloadUrl, baseUrl from full_payloads")])
 
 
  243        """Get all iovs for a given globaltag 
  246          globalTag (str): name of the globaltag 
  247          exp (int): experiment number to check (or None to return all iovs) 
  248          run (int): run number to check (or None to return all iovs) 
  249          message (str): ignored, just for compatibility with `ConditionsDB.get_all_iovs` 
  252          a sorted list of `PayloadInformation` objects 
  254        params = {
"globalTag": globalTag}
 
  257              payloadId, payloadName, revision, checksum, payloadUrl, baseUrl, 
  258              firstExp, firstRun, finalExp, finalRun 
  260            WHERE globalTagName=:globalTag""" 
  262            params.update({
"exp": exp, 
"run": run})
 
  264                ((firstExp==:exp AND firstRun<=:run) OR firstExp<:exp) AND 
  265                (finalExp<0 OR (finalRun<0 AND finalExp>=:exp) OR (finalExp>:exp) OR (finalExp==:exp AND finalRun>=:run))"""