<commit_before>// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <vespa/fnet/frt/supervisor.h>
#include <vespa/fnet/frt/target.h>
#include <vespa/config/config.h>
#include <vespa/config/frt/frtconfigrequestfactory.h>
#include <vespa/config/frt/frtconnection.h>
#include <vespa/config/common/payload_converter.h>
#include <vespa/fastos/app.h>

#include <string>
#include <sstream>
#include <fstream>

#include <vespa/log/log.h>
LOG_SETUP("vespa-get-config");

using namespace config;

class GetConfig : public FastOS_Application
{
private:
    std::unique_ptr<fnet::frt::StandaloneFRT> _server;
    FRT_Target     *_target;

    GetConfig(const GetConfig &);
    GetConfig &operator=(const GetConfig &);

public:
    GetConfig() : _server(), _target(nullptr) {}
    ~GetConfig() override;
    int usage();
    void initRPC(const char *spec);
    void finiRPC();
    int Main() override;
};


GetConfig::~GetConfig()
{
    LOG_ASSERT( ! _server);
    LOG_ASSERT(_target == nullptr);
}


int
GetConfig::usage()
{
    fprintf(stderr, "usage: %s -n name -i configId\n", _argv[0]);
    fprintf(stderr, "-n name           (config name, including namespace, on the form <namespace>.<name>)\n");
    fprintf(stderr, "-i configId       (config id, optional)\n");
    fprintf(stderr, "-j                (output config as json, optional)\n");
    fprintf(stderr, "-l                (output config in legacy cfg format, optional)\n");
    fprintf(stderr, "-g generation     (config generation, optional)\n");
    fprintf(stderr, "-a schema         (config def schema file, optional)\n");
    fprintf(stderr, "-v defVersion     (config definition version, optional, deprecated)\n");
    fprintf(stderr, "-m defMd5         (definition md5sum, optional)\n");
    fprintf(stderr, "-t serverTimeout  (server timeout in seconds, default 3)\n");
    fprintf(stderr, "-w timeout        (timeout in seconds, default 10)\n");
    fprintf(stderr, "-s server         (server hostname, default localhost)\n");
    fprintf(stderr, "-p port           (proxy/server port number, default 19090)\n");
    fprintf(stderr, "-r traceLevel     (tracelevel to use in request, default 0\n");
    fprintf(stderr, "-V vespaVersion   (vespa version to use in request, optional\n");
    fprintf(stderr, "-d                (debug mode)\n");
    fprintf(stderr, "-h                (This help text)\n");
    return 1;
}


void
GetConfig::initRPC(const char *spec)
{
    _server = std::make_unique<fnet::frt::StandaloneFRT>();
    _target     = _server->supervisor().GetTarget(spec);
}


void
GetConfig::finiRPC()
{
    if (_target != nullptr) {
        _target->SubRef();
        _target = nullptr;
    }
    _server.reset();
}


int
GetConfig::Main()
{
    bool debugging = false;
    int c = -1;

    std::vector<vespalib::string> defSchema;
    const char *schema = nullptr;
    const char *defName = nullptr;
    const char *defMD5 = "";
    std::string defNamespace("config");
    const char *serverHost = "localhost";
    const char *configId = getenv("VESPA_CONFIG_ID");
    bool printAsJson = false;
    int traceLevel = config::protocol::readTraceLevel();
    const char *vespaVersionString = nullptr;
    int64_t generation = 0;

    if (configId == nullptr) {
        configId = "";
    }
    const char *configXxhash64 = "";
    int serverTimeout = 3;
    int clientTimeout = 10;

    int serverPort = 19090;

    const char *optArg = nullptr;
    int optInd = 0;
    while ((c = GetOpt("a:n:v:g:i:jlm:c:t:V:w:r:s:p:dh", optArg, optInd)) != -1) {
        int retval = 1;
        switch (c) {
        case 'a':
            schema = optArg;
            break;
        case 'n':
            defName = optArg;
            break;
        case 'v':
            break;
        case 'g':
            generation = atoll(optArg);
            break;
        case 'i':
            configId = optArg;
            break;
        case 'j':
            printAsJson = true;
            break;
        case 'l':
            printAsJson = false;
            break;
        case 'm':
            defMD5 = optArg;
            break;
        case 't':
            serverTimeout = atoi(optArg);
            break;
        case 'w':
            clientTimeout = atoi(optArg);
            break;
        case 'r':
            traceLevel = atoi(optArg);
            break;
        case 'V':
            vespaVersionString = optArg;
            break;
        case 's':
            serverHost = optArg;
            break;
        case 'p':
            serverPort = atoi(optArg);
            break;
        case 'd':
            debugging = true;
            break;
        case 'h':
            retval = 0;
            [[fallthrough]];
        case '?':
        default:
            usage();
            return retval;
        }
    }

    if (defName == nullptr || serverPort == 0) {
        usage();
        return 1;
    }

    if (strchr(defName, '.') != nullptr) {
        const char *tmp = defName;
        defName = strrchr(defName, '.');
        defName++;
        defNamespace = std::string(tmp, defName - tmp - 1);
    }

    if (schema != nullptr) {
        std::ifstream is;
        is.open(schema);
        std::string item;
        while (std::getline(is, item)) {
            if (item.find("namespace=") == std::string::npos) {
                defSchema.push_back(item);
            }
        }
        is.close();
    }
    std::ostringstream tmp;
    tmp << "tcp/";
    tmp << serverHost;
    tmp << ":";
    tmp << serverPort;
    std::string sspec = tmp.str();
    const char *spec = sspec.c_str();
    if (debugging) {
        printf("connecting to '%s'\n", spec);
    }
    initRPC(spec);

    auto vespaVersion = VespaVersion::getCurrentVersion();
    if (vespaVersionString != nullptr) {
        vespaVersion = VespaVersion::fromString(vespaVersionString);<commit_msg>Use installed config schema if none is given as option<commit_after>// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <vespa/fnet/frt/supervisor.h>
#include <vespa/fnet/frt/target.h>
#include <vespa/config/config.h>
#include <vespa/config/frt/frtconfigrequestfactory.h>
#include <vespa/config/frt/frtconnection.h>
#include <vespa/config/common/payload_converter.h>
#include <vespa/fastos/app.h>

#include <string>
#include <sstream>
#include <fstream>

#include <vespa/log/log.h>
LOG_SETUP("vespa-get-config");

using namespace config;

class GetConfig : public FastOS_Application
{
private:
    std::unique_ptr<fnet::frt::StandaloneFRT> _server;
    FRT_Target     *_target;

    GetConfig(const GetConfig &);
    GetConfig &operator=(const GetConfig &);

public:
    GetConfig() : _server(), _target(nullptr) {}
    ~GetConfig() override;
    int usage();
    void initRPC(const char *spec);
    void finiRPC();
    int Main() override;
};


GetConfig::~GetConfig()
{
    LOG_ASSERT( ! _server);
    LOG_ASSERT(_target == nullptr);
}


int
GetConfig::usage()
{
    fprintf(stderr, "usage: %s -n name -i configId\n", _argv[0]);
    fprintf(stderr, "-n name           (config name, including namespace, on the form <namespace>.<name>)\n");
    fprintf(stderr, "-i configId       (config id, optional)\n");
    fprintf(stderr, "-j                (output config as json, optional)\n");
    fprintf(stderr, "-l                (output config in legacy cfg format, optional)\n");
    fprintf(stderr, "-g generation     (config generation, optional)\n");
    fprintf(stderr, "-a schema         (config def schema file, optional)\n");
    fprintf(stderr, "-v defVersion     (config definition version, optional, deprecated)\n");
    fprintf(stderr, "-m defMd5         (definition md5sum, optional)\n");
    fprintf(stderr, "-t serverTimeout  (server timeout in seconds, default 3)\n");
    fprintf(stderr, "-w timeout        (timeout in seconds, default 10)\n");
    fprintf(stderr, "-s server         (server hostname, default localhost)\n");
    fprintf(stderr, "-p port           (proxy/server port number, default 19090)\n");
    fprintf(stderr, "-r traceLevel     (tracelevel to use in request, default 0\n");
    fprintf(stderr, "-V vespaVersion   (vespa version to use in request, optional\n");
    fprintf(stderr, "-d                (debug mode)\n");
    fprintf(stderr, "-h                (This help text)\n");
    return 1;
}


void
GetConfig::initRPC(const char *spec)
{
    _server = std::make_unique<fnet::frt::StandaloneFRT>();
    _target     = _server->supervisor().GetTarget(spec);
}


void
GetConfig::finiRPC()
{
    if (_target != nullptr) {
        _target->SubRef();
        _target = nullptr;
    }
    _server.reset();
}


int
GetConfig::Main()
{
    bool debugging = false;
    int c = -1;

    std::vector<vespalib::string> defSchema;
    const char *schemaString = nullptr;
    const char *defName = nullptr;
    const char *defMD5 = "";
    std::string defNamespace("config");
    const char *serverHost = "localhost";
    const char *configId = getenv("VESPA_CONFIG_ID");
    bool printAsJson = false;
    int traceLevel = config::protocol::readTraceLevel();
    const char *vespaVersionString = nullptr;
    int64_t generation = 0;

    if (configId == nullptr) {
        configId = "";
    }
    const char *configXxhash64 = "";
    int serverTimeout = 3;
    int clientTimeout = 10;

    int serverPort = 19090;

    const char *optArg = nullptr;
    int optInd = 0;
    while ((c = GetOpt("a:n:v:g:i:jlm:c:t:V:w:r:s:p:dh", optArg, optInd)) != -1) {
        int retval = 1;
        switch (c) {
        case 'a':
            schemaString = optArg;
            break;
        case 'n':
            defName = optArg;
            break;
        case 'v':
            break;
        case 'g':
            generation = atoll(optArg);
            break;
        case 'i':
            configId = optArg;
            break;
        case 'j':
            printAsJson = true;
            break;
        case 'l':
            printAsJson = false;
            break;
        case 'm':
            defMD5 = optArg;
            break;
        case 't':
            serverTimeout = atoi(optArg);
            break;
        case 'w':
            clientTimeout = atoi(optArg);
            break;
        case 'r':
            traceLevel = atoi(optArg);
            break;
        case 'V':
            vespaVersionString = optArg;
            break;
        case 's':
            serverHost = optArg;
            break;
        case 'p':
            serverPort = atoi(optArg);
            break;
        case 'd':
            debugging = true;
            break;
        case 'h':
            retval = 0;
            [[fallthrough]];
        case '?':
        default:
            usage();
            return retval;
        }
    }

    if (defName == nullptr || serverPort == 0) {
        usage();
        return 1;
    }

    if (strchr(defName, '.') != nullptr) {
        const char *tmp = defName;
        defName = strrchr(defName, '.');
        defName++;
        defNamespace = std::string(tmp, defName - tmp - 1);
    }

    std::string schema;
    if (schemaString == nullptr) {
      std::ostringstream tmp;
      tmp << getenv("VESPA_HOME");
      tmp << "/share/vespa/configdefinitions/";
      tmp << defName;
      tmp << ".def";
      schema = tmp.str();
    } else {
      schema = schemaString;
    }
    if (debugging) {
      printf("Using schema in %s\n", schema.c_str());
    }
    std::ifstream is;
    is.open(schema);
    std::string item;
    while (std::getline(is, item)) {
      if (item.find("namespace=") == std::string::npos) {
        defSchema.push_back(item);
      }
    }
    is.close();

    std::ostringstream tmp;
    tmp << "tcp/";
    tmp << serverHost;
    tmp << ":";
    tmp << serverPort;
    std::string sspec = tmp.str();
    const char *spec = sspec.c_str();
    if (debugging) {
        printf("connecting to '%s'\n", spec);
    }
    initRPC(spec);

    auto vespaVersion = VespaVersion::getCurrentVersion();
    if (vespaVersionString != nullptr) {
        vespaVersion = VespaVersion::fromString(vespaVersionString);
{'fraction_non_alphanumeric': 0.13751338881107358, 'fraction_numerical': 0.006261843948257395, 'mean_word_length': 2.1849908160587774, 'pattern_counts': {'":': 2, '<': 59, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7580871', 'n_tokens_mistral': 3810, 'n_tokens_neox': 3749, 'n_words': 956}