int SaiPlayer::replay()

in saiplayer/SaiPlayer.cpp [2615:2897]


int SaiPlayer::replay()
{
    //swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_DEBUG);

    SWSS_LOG_ENTER();

    if (m_commandLineOptions->m_files.size() == 0)
    {
        fprintf(stderr, "ERR: need to specify filename\n");

        return -1;
    }

    auto filename = m_commandLineOptions->m_files.at(0);

    SWSS_LOG_NOTICE("using file: %s", filename.c_str());

    m_infile = std::ifstream{filename};

    if (!m_infile.is_open())
    {
        SWSS_LOG_ERROR("failed to open file %s", filename.c_str());
        return -1;
    }

    std::string line;

    while (std::getline(m_infile, line))
    {
        // std::cout << "processing " << line << std::endl;

        sai_common_api_t api = SAI_COMMON_API_CREATE;

        auto p = line.find_first_of("|");

        char op = line[p+1];

        switch (op)
        {
            case 'a':
                {
                    std::string response;

                    do
                    {
                        // this line may be notification, we need to skip
                        if (!std::getline(m_infile, response))
                        {
                            SWSS_LOG_THROW("failed to read next file from file, previous: %s", line.c_str());
                        }
                    }
                    while (response[response.find_first_of("|") + 1] == 'n');

                    performNotifySyncd(line, response);
                }
                continue;

            case 'f':
                {
                    std::string response;

                    do
                    {
                        // this line may be notification, we need to skip
                        if (!std::getline(m_infile, response))
                        {
                            SWSS_LOG_THROW("failed to read next file from file, previous: %s", line.c_str());
                        }
                    }
                    while (response[response.find_first_of("|") + 1] == 'n');

                    performFdbFlush(line, response);
                }
                continue;

            case '@':
                performSleep(line);
                continue;
            case 'c':
                api = SAI_COMMON_API_CREATE;
                break;
            case 'r':
                api = SAI_COMMON_API_REMOVE;
                break;
            case 's':
                api = SAI_COMMON_API_SET;
                break;
            case 'B':
                processBulk(SAI_COMMON_API_BULK_GET, line);
                continue;
            case 'S':
                processBulk(SAI_COMMON_API_BULK_SET, line);
                continue;
            case 'C':
                processBulk(SAI_COMMON_API_BULK_CREATE, line);
                continue;
            case 'R':
                processBulk(SAI_COMMON_API_BULK_REMOVE, line);
                continue;
            case 'g':
                api = SAI_COMMON_API_GET;
                break;
            case 'q':
                // TODO: implement SAI player support for query commands
                continue;
            case 'p':
                // TODO: implement SAI player support for counter polling commands
                continue;
            case 'Q':
                continue; // skip over query responses
            case '#':
            case 'n':
                SWSS_LOG_INFO("skipping op %c line %s", op, line.c_str());
                continue; // skip comment and notification

            default:
                SWSS_LOG_THROW("unknown op %c on line %s", op, line.c_str());
        }

        // timestamp|action|objecttype:objectid|attrid=value,...
        auto fields = swss::tokenize(line, '|');

        // objecttype:objectid (object id may contain ':')
        auto start = fields[2].find_first_of(":");

        auto str_object_type = fields[2].substr(0, start);
        auto str_object_id  = fields[2].substr(start + 1);

        sai_object_type_t object_type = deserialize_object_type(str_object_type);

        auto values = get_values(fields);

        SaiAttributeList list(object_type, values, false);

        sai_attribute_t *attr_list = list.get_attr_list();

        uint32_t attr_count = list.get_attr_count();

        SWSS_LOG_DEBUG("attr count: %u", list.get_attr_count());

        if (api != SAI_COMMON_API_GET)
        {
            translate_local_to_redis(object_type, attr_count, attr_list);
        }

        sai_status_t status;

        auto info = sai_metadata_get_object_type_info(object_type);

        switch ((int)object_type)
        {
            case SAI_OBJECT_TYPE_FDB_ENTRY:
                status = handle_fdb(str_object_id, api, attr_count, attr_list);
                break;

            case SAI_OBJECT_TYPE_NEIGHBOR_ENTRY:
                status = handle_neighbor(str_object_id, api, attr_count, attr_list);
                break;

            case SAI_OBJECT_TYPE_ROUTE_ENTRY:
                status = handle_route(str_object_id, api, attr_count, attr_list);
                break;

            case SAI_OBJECT_TYPE_INSEG_ENTRY:
                status = handle_inseg(str_object_id, api, attr_count, attr_list);
                break;

            case SAI_OBJECT_TYPE_DIRECTION_LOOKUP_ENTRY:
                status = handle_dash_direction_lookup(str_object_id, api, attr_count, attr_list);
                break;

            case SAI_OBJECT_TYPE_ENI_ETHER_ADDRESS_MAP_ENTRY:
                status = handle_dash_eni_ether_address_map(str_object_id, api, attr_count, attr_list);
                break;

            case SAI_OBJECT_TYPE_VIP_ENTRY:
                status = handle_dash_vip(str_object_id, api, attr_count, attr_list);
                break;

            case SAI_OBJECT_TYPE_INBOUND_ROUTING_ENTRY:
                status = handle_dash_inbound_routing(str_object_id, api, attr_count, attr_list);
                break;

            case SAI_OBJECT_TYPE_PA_VALIDATION_ENTRY:
                status = handle_dash_pa_validation(str_object_id, api, attr_count, attr_list);
                break;

            case SAI_OBJECT_TYPE_OUTBOUND_ROUTING_ENTRY:
                status = handle_dash_outbound_routing(str_object_id, api, attr_count, attr_list);
                break;

            case SAI_OBJECT_TYPE_OUTBOUND_CA_TO_PA_ENTRY:
                status = handle_dash_outbound_ca_to_pa(str_object_id, api, attr_count, attr_list);
                break;

            default:

                if (info->isnonobjectid)
                {
                    SWSS_LOG_THROW("object %s:%s is non object id, but not handled, FIXME",
                            sai_serialize_object_type(object_type).c_str(),
                            str_object_id.c_str());
                }

                status = handle_generic(object_type, str_object_id, api, attr_count, attr_list);
                break;
        }

        if (status != SAI_STATUS_SUCCESS)
        {
            if (api == SAI_COMMON_API_GET)
            {
                // GET status is checked in handle response
            }
            else
                SWSS_LOG_THROW("failed to execute api: %c: %s", op, sai_serialize_status(status).c_str());
        }

        if (api == SAI_COMMON_API_GET)
        {
            std::string response;

            do
            {
                // this line may be notification, we need to skip
                std::getline(m_infile, response);
            }
            while (response[response.find_first_of("|") + 1] == 'n');

            try
            {
                handle_get_response(object_type, attr_count, attr_list, response, status);
            }
            catch (const std::exception &e)
            {
                SWSS_LOG_NOTICE("line: %s", line.c_str());
                SWSS_LOG_NOTICE("resp (expected): %s", response.c_str());
                SWSS_LOG_NOTICE("got: %s", sai_serialize_status(status).c_str());

                if (api == SAI_COMMON_API_GET && (status == SAI_STATUS_SUCCESS || status == SAI_STATUS_BUFFER_OVERFLOW))
                {
                    // log each get parameter
                    for (uint32_t i = 0; i < attr_count; ++i)
                    {
                        auto meta = sai_metadata_get_attr_metadata(object_type, attr_list[i].id);

                        auto val = sai_serialize_attr_value(*meta, attr_list[i]);

                        SWSS_LOG_NOTICE(" - %s:%s", meta->attridname, val.c_str());
                    }
                }

                exit(EXIT_FAILURE);
            }

            if (api == SAI_COMMON_API_GET && (status == SAI_STATUS_SUCCESS || status == SAI_STATUS_BUFFER_OVERFLOW))
            {
                // log each get parameter
                for (uint32_t i = 0; i < attr_count; ++i)
                {
                    auto meta = sai_metadata_get_attr_metadata(object_type, attr_list[i].id);

                    auto val = sai_serialize_attr_value(*meta, attr_list[i]);

                    SWSS_LOG_NOTICE(" - %s:%s", meta->attridname, val.c_str());
                }
            }
        }
    }

    m_infile.close();

    SWSS_LOG_NOTICE("finished replaying %s with SUCCESS", filename.c_str());

    if (m_commandLineOptions->m_sleep)
    {
        fprintf(stderr, "Reply SUCCESS, sleeping, watching for notifications\n");

        sleep(-1);
    }

    return 0;
}