def initFromCatalog()

in automation/tinc/main/ext/qautils/gppylib/gparray.py [0:0]


    def initFromCatalog(dbURL, utility=False):
        """
        Factory method, initializes a GpArray from provided database URL
        """

        conn = dbconn.connect(dbURL, utility)

        # Get the version from the database:
        version_str = None
        for row in dbconn.execSQL(conn, "SELECT version()"):
            version_str = row[0]
        version = GpVersion(version_str)

        if version.getVersionRelease() in ("3.0", "3.1", "3.2", "3.3"):

            # In older releases we get the fault strategy using the 
            # gp_fault_action guc.
            strategy_rows = dbconn.execSQL(conn, "show gp_fault_action")

            # Note: Mode may not be "right", certainly 4.0 concepts of mirroring
            # mode do not apply to 3.x, so it depends on how the scripts are
            # making use of mode.  For now it is initialized to synchronized.
            #
            # Note: hostname is initialized to null since the catalog does not
            # contain this information.  Initializing a hostcache using the
            # resulting gparray will automatically fill in a value for hostname.
            #
            # Note: this should be kept in sync with the code in 
            # GpDB.InitFromString() code for initializing old catalog formats.
            config_rows = dbconn.execSQL(conn, '''
                SELECT dbid, content, 
                       case when isprimary then 'p' else 'm' end as role, 
                       case when definedprimary then 'p' else 'm' end as preferred_role,
                       's' as mode, 
                       case when valid then 'u' else 'd' end as status, 
                       null as hostname,
                       hostname as address, 
                       port, 
                       null as replication_port, 
                       %s as fsoid,
                       datadir as fselocation
                FROM pg_catalog.gp_configuration
                ORDER BY content, preferred_role DESC
            ''' % str(SYSTEM_FILESPACE))

            # No SAN support in these older releases.
            san_segs_rows = []
            san_rows = []

            # no filespace support in older releases.
            filespaceArr = []

        else:

            strategy_rows = dbconn.execSQL(conn, '''
                SELECT fault_strategy FROM gp_fault_strategy
            ''')

            config_rows = dbconn.execSQL(conn, '''
                SELECT dbid, content, role, preferred_role, mode, status, 
                       hostname, address, port, replication_port, fs.oid, 
                       fselocation
                FROM pg_catalog.gp_segment_configuration
                JOIN pg_catalog.pg_filespace_entry on (dbid = fsedbid)
                JOIN pg_catalog.pg_filespace fs on (fsefsoid = fs.oid)
                ORDER BY content, preferred_role DESC, fs.oid
            ''')

            san_segs_rows = dbconn.execSQL(conn, '''
                SELECT dbid, content, status, unnest(san_mounts)
                FROM pg_catalog.gp_segment_configuration
                WHERE content >= 0
                ORDER BY content, dbid
            ''')

            san_rows = dbconn.execSQL(conn, '''
                SELECT mountid, active_host, san_type,
                       primary_host, primary_mountpoint, primary_device,
                       mirror_host, mirror_mountpoint, mirror_device
                FROM pg_catalog.gp_san_configuration
                ORDER BY mountid
            ''')

            filespaceRows = dbconn.execSQL(conn, '''
                SELECT oid, fsname
                FROM pg_filespace
                ORDER BY fsname;
            ''')
            filespaceArr = [GpFilespaceObj(fsRow[0], fsRow[1]) for fsRow in filespaceRows]


        # Todo: add checks that all segments should have the same filespaces?
        recoveredSegmentDbids = []
        segments = []
        seg = None
        for row in config_rows:

            # Extract fields from the row
            (dbid, content, role, preferred_role, mode, status, hostname, 
             address, port, replicationPort, fsoid, fslocation) = row

            # If we have segments which have recovered, record them.
            if preferred_role != role and content >= 0:
                if mode == MODE_SYNCHRONIZED and status == STATUS_UP:
                    recoveredSegmentDbids.append(dbid)
            
            # The query returns all the filespaces for a segment on separate
            # rows.  If this row is the same dbid as the previous row simply
            # add this filespace to the existing list, otherwise create a
            # new segment.
            if seg and seg.getSegmentDbId() == dbid:
                seg.addSegmentFilespace(fsoid, fslocation)
            else:
                seg = GpDB(content, preferred_role, dbid, role, mode, status, 
                           hostname, address, port, fslocation, replicationPort)
                segments.append(seg)
        
        for seg in segments:
            datcatloc = dbconn.execSQL(conn, '''
                select fsloc.fselocation || '/' ||
                       case when db.dattablespace = 1663
                          then 'base'
                          else db.dattablespace::text
                       end || '/'||db.oid as catloc
                from pg_Database db, pg_tablespace ts,
                     (SELECT dbid, fs.oid, fselocation
                      FROM pg_catalog.gp_segment_configuration
                      JOIN pg_catalog.pg_filespace_entry on (dbid = fsedbid)
                      JOIN pg_catalog.pg_filespace fs on (fsefsoid = fs.oid)) fsloc
                      where db.dattablespace = ts.oid
                      and ts.spcfsoid = fsloc.oid
                      and fsloc.dbid = %d 
            ''' % seg.dbid)
            seg.catdirs = []
            for row in datcatloc:
                seg.catdirs.append(row[0])

        conn.close()
        
        origSegments = [seg.copy() for seg in segments]
        
        if strategy_rows.rowcount == 0:
            raise Exception("Database does not contain gp_fault_strategy entry")
        if strategy_rows.rowcount > 1:
            raise Exception("Database does too many gp_fault_strategy entries")
        strategy = strategy_rows.fetchone()[0]

        array = GpArray(segments, origSegments, strategy)
        array.__version = version
        array.recoveredSegmentDbids = recoveredSegmentDbids
        array.setFaultStrategy(strategy)
        array.setSanConfig(san_rows, san_segs_rows)
        array.setFilespaces(filespaceArr)
        
        return array