
import skytools

def handler_allows_copy(table_attrs):
    """Decide if table is copyable based on attrs."""
    if not table_attrs:
        return True
    attrs = skytools.db_urldecode(table_attrs)
    hstr = attrs['handler']
    p = londiste.handler.build_handler('unused.string', hstr, None)
    return p.needs_table()

def find_copy_source(queue_name, node_name, node_location, table_list):
    need = {}
    for tbl in table_list:
        need[tbl] = 1

    while 1:
        src_db = skytools.connect_database(node_location)
        src_db.set_isolation_level(skytools.I_AUTOCOMMIT)
        src_curs = src_db.cursor()

        q = "select * from pgq_node.get_node_info(%s)"
        src_curs.execute(q, [queue_name])
        info = src_curs.fetchone()
        if info['ret_code'] >= 400:
            raise UsageError("Node does not exists")

        self.log.info("Checking if %s can be used for copy", info['node_name'])

        q = "select table_name, local, table_attrs from londiste.get_table_list(%s)"
        src_curs.execute(q, [queue_name])
        got = {}
        for row in src_curs.fetchall():
            tbl = row['table_name']
            if tbl not in need:
                continue
            if not row['local']:
                self.log.debug("Problem: %s is not local", tbl)
                continue
            if not self.handler_allows_copy(row['table_attrs']):
                self.log.debug("Problem: %s handler does not store data [%s]", tbl, row['table_attrs'])
                continue
            self.log.debug("Good: %s is usable", tbl)
            got = True
            break
        
        src_db.close()

        if got:
            self.log.info("Node %s seems good source, using it", info['node_name'])
            return node_name, node_location

        if info['node_type'] == 'root':
            raise skytools.UsageError("Found root and no source found")

        # walk upwards
        node_name = info['provider_node']
        node_location = info['provider_location']

