<commit_before>#include <iostream>

#include "vtrc-client-base/vtrc-client.h"
#include "vtrc-common/vtrc-pool-pair.h"
#include "vtrc-common/vtrc-exception.h"

#include "protocol/calculator.pb.h"
#include "calculator-iface.h"

#include "vtrc-condition-variable.h"
#include "vtrc-bind.h"
#include "vtrc-ref.h"
#include "vtrc-thread.h"
#include "vtrc-chrono.h"

using namespace vtrc::client;
using namespace vtrc::common;

void usage(  )
{
    std::cout
          << "Usage: \n\tcalculator_client <server ip> <server port>\n"
          << "or:\n\tcalculator_client <localname>\n"
          << "examples:\n"
          << "\tfor tcp: calculator_client 127.0.0.1 55555\n"
          << "\tfor unix: calculator_client /tmp/calculator.sock\n"
          << "\tfor win pipe: calculator_client \\\\.\\pipe\\calculator_pipe\n";
}

struct work_time {
    typedef vtrc::chrono::high_resolution_clock::time_point time_point;
    time_point start_;
    work_time( )
        :start_(vtrc::chrono::high_resolution_clock::now( ))
    {}
    ~work_time( )
    {
        time_point::duration stop(
                    vtrc::chrono::high_resolution_clock::now( ) - start_);
        std::cout << "Call time: " << stop << "\n";
    }
};

class variable_pool: public vtrc_example::variable_pool {

    std::map<std::string, double> variables_;
    unsigned server_calback_count_;

    void set_variable(::google::protobuf::RpcController* controller,
                 const ::vtrc_example::number* request,
                 ::vtrc_example::number* response,
                 ::google::protobuf::Closure* done)
    {
        ++server_calback_count_;

        closure_holder done_holder(done);
        std::string n(request->name( ));

        std::cout << "Server sets variable: '" << n << "'"
                  << " = " <<  request->value( )
                  << " thread id: " << vtrc::this_thread::get_id( ) << "\n";

        variables_[n] = request->value( );
    }

    void get_variable(::google::protobuf::RpcController* controller,
                 const ::vtrc_example::number* request,
                 ::vtrc_example::number* response,
                 ::google::protobuf::Closure* done)
    {
        ++server_calback_count_;
        closure_holder done_holder(done);
        std::string n(request->name( ));

        std::cout << "Server wants variable: '" << n << "'"
                  << "; thread id: " << vtrc::this_thread::get_id( ) << "\n";

        std::map<std::string, double>::const_iterator f(variables_.find(n));
        if( f == variables_.end( ) ) {
            std::cout << "Client sends exception to server...\n";
            std::ostringstream oss;
            oss << "Variable is not found: '" << n << "'";
            throw std::runtime_error( oss.str( ) );
        }
        response->set_value( f->second );
    }

public:

    variable_pool( )
        :server_calback_count_(0)
    {}

    unsigned calls_count( ) const
    {
        return server_calback_count_;
    }

    void set( std::string const &name, double value )
    {
        /// don't need lock this calls;
        variables_[name] = value;
    }

};

void tests( vtrc::shared_ptr<vtrc_client> client,
            vtrc::shared_ptr<variable_pool> vars )
{

    work_time wt;
    /// create calculator client interface
    vtrc::unique_ptr<interfaces::calculator>
                            calc(interfaces::create_calculator( client ));

    std::string test_name;
    /// first: simple sum, mul, div, pow

    std::string splitter( 80, '=' );
    splitter += "\n";

    std::cout << "My thread id: " << vtrc::this_thread::get_id( ) << "\n";

    /**
     * ======================== FIRST ==================================
    **/
    test_name = "first";
    std::cout << splitter << test_name << ":\n";
    try {

        double res = calc->mul( "pi", "e" );
        std::cout << "\tpi * e = " << res << "\n";
        vars->set( test_name, res ); /// now we can use old result

    } catch( const vtrc::common::exception& ex ) {
        std::cout << "call '"<< test_name << "' failed: " << ex.what( ) << "; "
                  << ex.additional( ) << "\n";
    }

    /**
     * ======================== SECOND =================================
    **/
    test_name = "second";
    std::cout << splitter << test_name << ":\n";
    try {

        double res = calc->sum( 17, calc->mul( 3, 5 ));
        std::cout << "\t17 + 3 * 5 = " << res << "\n";
        vars->set( test_name, res );

    } catch( const vtrc::common::exception& ex ) {
        std::cout << "call '"<< test_name << "' failed: " << ex.what( ) << "; "
                  << ex.additional( ) << "\n";
    }

    /**
     * ======================== THRID ==================================
    **/
    test_name = "third";
    std::cout << splitter << test_name << ":\n";
    try {
        std::cout << "\tnow we take first and seconds results "
                  << "and make pow(firts, second)\n";
        double res = calc->pow( "first", "second" );
        std::cout << "\tpow(first, second) = " << res << "\n";
        vars->set( test_name, res );

    } catch( const vtrc::common::exception& ex ) {
        std::cout << "call '"<< test_name << "' failed: " << ex.what( ) << "; "
                  << ex.additional( ) << "\n";
    }

    /**
     * ======================== THE TEST THAT FAILED ===================
    **/
    test_name = "failed";
    std::cout << splitter << test_name << ":\n";
    try {
        std::cout << "\tDivision by zero\n";
        double res = calc->div( "first", 0);
        std::cout << "\tfirst/0 = " << res << "\n"; /// we don't see this out
        vars->set( test_name, res );

    } catch( const vtrc::common::exception& ex ) { /// but see this
        std::cout << "call '"<< test_name << "' failed: " << ex.what( ) << "; "
                  << ex.additional( ) << "\n";
    }

    /**
     * ======================== THE TEST THAT FAILED 2 =================
    **/
    test_name = "failed2";
    std::cout << splitter << test_name << ":\n";
    try {
        std::cout << "\tRequesting invalid variabe 'invalid'"
                  << " and make 'invalid' * 1\n";
        double res = calc->mul( "invalid", 1 );
        std::cout << "\t'invalid' * 1 = "
                  << res << "\n"; /// we don't see this out
        vars->set( test_name, res );

    } catch( const vtrc::common::exception& ex ) { /// but see this
        std::cout << "call '"<< test_name << "' failed: " << ex.what( ) << "; "
                  << ex.additional( ) << "\n";
    }

    std::cout << splitter;

    std::cout << "Total RPC was made: " << calc->calls_count( ) << "\n";

}

void on_client_ready( vtrc::condition_variable &cond )
{
    cond.notify_all( );
}

int main( int argc, char **argv ) try
{

    if( argc < 2 ) {<commit_msg>examples<commit_after>#include <iostream>

#include "vtrc-client-base/vtrc-client.h"
#include "vtrc-common/vtrc-pool-pair.h"
#include "vtrc-common/vtrc-exception.h"

#include "protocol/calculator.pb.h"
#include "calculator-iface.h"

#include "vtrc-condition-variable.h"
#include "vtrc-bind.h"
#include "vtrc-ref.h"
#include "vtrc-thread.h"
#include "vtrc-chrono.h"

using namespace vtrc::client;
using namespace vtrc::common;

void usage(  )
{
    std::cout
          << "Usage: \n\tcalculator_client <server ip> <server port>\n"
          << "or:\n\tcalculator_client <localname>\n"
          << "examples:\n"
          << "\tfor tcp: calculator_client 127.0.0.1 55555\n"
          << "\tfor unix: calculator_client /tmp/calculator.sock\n"
          << "\tfor win pipe: calculator_client \\\\.\\pipe\\calculator_pipe\n";
}

struct work_time {
    typedef vtrc::chrono::high_resolution_clock::time_point time_point;
    time_point start_;
    work_time( )
        :start_(vtrc::chrono::high_resolution_clock::now( ))
    {}
    ~work_time( )
    {
        time_point::duration stop(
                    vtrc::chrono::high_resolution_clock::now( ) - start_);
        std::cout << "Call time: " << stop << "\n";
    }
};

class variable_pool: public vtrc_example::variable_pool {

    std::map<std::string, double> variables_;
    unsigned server_calback_count_;

    void set_variable(::google::protobuf::RpcController* controller,
                 const ::vtrc_example::number* request,
                 ::vtrc_example::number* response,
                 ::google::protobuf::Closure* done)
    {
        ++server_calback_count_;

        closure_holder done_holder(done);
        std::string n(request->name( ));

        std::cout << "Server sets variable: '" << n << "'"
                  << " = " <<  request->value( )
                  << " thread id: " << vtrc::this_thread::get_id( ) << "\n";

        variables_[n] = request->value( );
    }

    void get_variable(::google::protobuf::RpcController* controller,
                 const ::vtrc_example::number* request,
                 ::vtrc_example::number* response,
                 ::google::protobuf::Closure* done)
    {
        ++server_calback_count_;
        closure_holder done_holder(done);
        std::string n(request->name( ));

        std::cout << "Server wants variable: '" << n << "'"
                  << "; thread id: " << vtrc::this_thread::get_id( ) << "\n";

        std::map<std::string, double>::const_iterator f(variables_.find(n));
        if( f == variables_.end( ) ) {
            std::cout << "Client sends exception to server...\n";
            std::ostringstream oss;
            oss << "Variable is not found: '" << n << "'";
            throw std::runtime_error( oss.str( ) );
        }
        response->set_value( f->second );
    }

public:

    variable_pool( )
        :server_calback_count_(0)
    {}

    unsigned calls_count( ) const
    {
        return server_calback_count_;
    }

    void set( std::string const &name, double value )
    {
        /// don't need lock this calls;
        variables_[name] = value;
    }

};

void tests( vtrc::shared_ptr<vtrc_client> client,
            vtrc::shared_ptr<variable_pool> vars )
{

    work_time wt;
    /// create calculator client interface
    vtrc::unique_ptr<interfaces::calculator>
                            calc(interfaces::create_calculator( client ));

    std::string test_name;
    /// first: simple sum, mul, div, pow

    std::string splitter( 80, '=' );
    splitter += "\n";

    std::cout << "My thread id: " << vtrc::this_thread::get_id( ) << "\n";

    /**
     * ======================== FIRST ==================================
    **/
    test_name = "first";
    std::cout << splitter << test_name << ":\n";
    try {

        double res = calc->mul( "pi", "e" ); /// CALL

        std::cout << "\tpi * e = " << res << "\n";
        vars->set( test_name, res ); /// now we can use old result

    } catch( const vtrc::common::exception& ex ) {
        std::cout << "call '"<< test_name << "' failed: " << ex.what( ) << "; "
                  << ex.additional( ) << "\n";
    }

    /**
     * ======================== SECOND =================================
    **/
    test_name = "second";
    std::cout << splitter << test_name << ":\n";
    try {

        double res = calc->sum( 17, calc->mul( 3, 5 )); /// CALL

        std::cout << "\t17 + 3 * 5 = " << res << "\n";
        vars->set( test_name, res );

    } catch( const vtrc::common::exception& ex ) {
        std::cout << "call '"<< test_name << "' failed: " << ex.what( ) << "; "
                  << ex.additional( ) << "\n";
    }

    /**
     * ======================== THRID ==================================
    **/
    test_name = "third";
    std::cout << splitter << test_name << ":\n";
    try {
        std::cout << "\tnow we take first and seconds results "
                  << "and make pow(firts, second)\n";

        double res = calc->pow( "first", "second" ); /// CALL

        std::cout << "\tpow(first, second) = " << res << "\n";
        vars->set( test_name, res );

    } catch( const vtrc::common::exception& ex ) {
        std::cout << "call '"<< test_name << "' failed: " << ex.what( ) << "; "
                  << ex.additional( ) << "\n";
    }

    /**
     * ======================== THE TEST THAT FAILED ===================
    **/
    test_name = "failed";
    std::cout << splitter << test_name << ":\n";
    try {
        std::cout << "\tDivision by zero\n";

        double res = calc->div( "first", 0); /// CALL

        std::cout << "\tfirst/0 = " << res << "\n"; /// we don't see this out
        vars->set( test_name, res );

    } catch( const vtrc::common::exception& ex ) { /// but see this
        std::cout << "call '"<< test_name << "' failed: " << ex.what( ) << "; "
                  << ex.additional( ) << "\n";
    }

    /**
     * ======================== THE TEST THAT FAILED 2 =================
    **/
    test_name = "failed2";
    std::cout << splitter << test_name << ":\n";
    try {
        std::cout << "\tRequesting invalid variabe 'invalid'"
                  << " and make 'invalid' * 1\n";

        double res = calc->mul( "invalid", 1 ); /// CALL

        std::cout << "\t'invalid' * 1 = "
                  << res << "\n"; /// we don't see this out
        vars->set( test_name, res );

    } catch( const vtrc::common::exception& ex ) { /// but see this
        std::cout << "call '"<< test_name << "' failed: " << ex.what( ) << "; "
                  << ex.additional( ) << "\n";
    }

    std::cout << splitter;

    std::cout << "Total RPC was made: " << calc->calls_count( ) << "\n";

}

void on_client_ready( vtrc::condition_variable &cond )
{
    cond.notify_all( );
}

int main( int argc, char **argv ) try
{

    if( argc < 2 ) {
{'fraction_non_alphanumeric': 0.21514440697844892, 'fraction_numerical': 0.004398182084738308, 'mean_word_length': 2.243699476937708, 'pattern_counts': {'":': 10, '<': 439, '<?xml version=': 0, '>': 57, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, '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': '505541', 'n_tokens_mistral': 4513, 'n_tokens_neox': 4274, 'n_words': 913}