static bool parse_failover_property_list()

in src/router_node.c [1411:1541]


static bool parse_failover_property_list(qd_router_t *router, qd_connection_t *conn, pn_data_t *props)
{
    bool found_failover = false;

    if (pn_data_type(props) != PN_LIST)
        return false;

    size_t list_num_items = pn_data_get_list(props);

    if (list_num_items > 0) {

        save_original_and_current_conn_info(conn);

        pn_data_enter(props); // enter list

        for (int i=0; i < list_num_items; i++) {
            pn_data_next(props);// this is the first element of the list, a map.
            if (props && pn_data_type(props) == PN_MAP) {

                size_t map_num_items = pn_data_get_map(props);
                pn_data_enter(props);

                qd_failover_item_t *item = NEW(qd_failover_item_t);
                ZERO(item);

                // We have found a map with the connection information. Step thru the map contents and create qd_failover_item_t

                for (int j=0; j < map_num_items/2; j++) {

                    pn_data_next(props);
                    if (pn_data_type(props) == PN_SYMBOL) {
                        pn_bytes_t sym = pn_data_get_symbol(props);
                        if (sym.size == strlen(QD_CONNECTION_PROPERTY_FAILOVER_NETHOST_KEY) &&
                            strcmp(sym.start, QD_CONNECTION_PROPERTY_FAILOVER_NETHOST_KEY) == 0) {
                            pn_data_next(props);
                            if (pn_data_type(props) == PN_STRING) {
                                item->host = strdup(pn_data_get_string(props).start);
                            }
                        }
                        else if (sym.size == strlen(QD_CONNECTION_PROPERTY_FAILOVER_PORT_KEY) &&
                                 strcmp(sym.start, QD_CONNECTION_PROPERTY_FAILOVER_PORT_KEY) == 0) {
                            pn_data_next(props);
                            item->port = qdpn_data_as_string(props);

                        }
                        else if (sym.size == strlen(QD_CONNECTION_PROPERTY_FAILOVER_SCHEME_KEY) &&
                                 strcmp(sym.start, QD_CONNECTION_PROPERTY_FAILOVER_SCHEME_KEY) == 0) {
                            pn_data_next(props);
                            if (pn_data_type(props) == PN_STRING) {
                                item->scheme = strdup(pn_data_get_string(props).start);
                            }

                        }
                        else if (sym.size == strlen(QD_CONNECTION_PROPERTY_FAILOVER_HOSTNAME_KEY) &&
                                 strcmp(sym.start, QD_CONNECTION_PROPERTY_FAILOVER_HOSTNAME_KEY) == 0) {
                            pn_data_next(props);
                            if (pn_data_type(props) == PN_STRING) {
                                item->hostname = strdup(pn_data_get_string(props).start);
                            }
                        }
                    }
                }

                int host_length = strlen(item->host);
                //
                // We will not even bother inserting the item if there is no host available.
                //
                if (host_length != 0) {
                    if (item->scheme == 0)
                        item->scheme = strdup("amqp");
                    if (item->port == 0)
                        item->port = strdup("5672");

                    int hplen = strlen(item->host) + strlen(item->port) + 2;
                    item->host_port = malloc(hplen);
                    snprintf(item->host_port, hplen, "%s:%s", item->host, item->port);

                    //
                    // Iterate through failover list items and sets insert_tail to true
                    // when list has just original connector's host and port or when new
                    // reported host and port is not yet part of the current list.
                    //
                    bool insert_tail = false;
                    if ( DEQ_SIZE(conn->connector->conn_info_list) == 1 ) {
                        insert_tail = true;
                    } else {
                        qd_failover_item_t *conn_item = DEQ_HEAD(conn->connector->conn_info_list);
                        insert_tail = true;
                        while ( conn_item ) {
                            if ( !strcmp(conn_item->host_port, item->host_port) ) {
                                insert_tail = false;
                                break;
                            }
                            conn_item = DEQ_NEXT(conn_item);
                        }
                    }

                    // Only inserts if not yet part of failover list
                    if ( insert_tail ) {
                        DEQ_INSERT_TAIL(conn->connector->conn_info_list, item);
                        qd_log(router->log_source, QD_LOG_DEBUG, "Added %s as backup host", item->host_port);
                        found_failover = true;
                    }
                    else {
                        free(item->scheme);
                        free(item->host);
                        free(item->port);
                        free(item->hostname);
                        free(item->host_port);
                        free(item);
                    }

                }
                else {
                    free(item->scheme);
                    free(item->host);
                    free(item->port);
                    free(item->hostname);
                    free(item->host_port);
                    free(item);
                }
            }
            pn_data_exit(props);
        }
    } // list_num_items > 0
    else {
        save_original_and_current_conn_info(conn);
    }

    return found_failover;
}