<commit_before>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2015
Raffaello D. Di Napoli

This file is part of Abaclade.

Abaclade is free software: you can redistribute it and/or modify it under the terms of the GNU
General Public License as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

Abaclade is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.

You should have received a copy of the GNU General Public License along with Abaclade. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#ifndef _ABACLADE_LIST_HXX
#define _ABACLADE_LIST_HXX

#ifndef _ABACLADE_HXX
   #error "Please #include <abaclade.hxx> before this file"
#endif
#ifdef ABC_CXX_PRAGMA_ONCE
   #pragma once
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::detail::list_impl

namespace abc {
namespace detail {

//! Non-template implementation class for abc::list.
class ABACLADE_SYM list_impl {
public:
   /*! Constructor.

   @param l
      Source object.
   */
   list_impl() :
      m_pnFirst(nullptr),
      m_pnLast(nullptr),
      m_cNodes(0) {
   }
   list_impl(list_impl && l) :
      m_pnFirst(l.m_pnFirst),
      m_pnLast(l.m_pnLast),
      m_cNodes(l.m_cNodes) {
      l.m_pnFirst = nullptr;
      l.m_pnLast = nullptr;
      l.m_cNodes = 0;
   }

   //! Destructor.
   ~list_impl() {
   }

   /*! Assignment operator.

   @param l
      Source object.
   */
   list_impl & operator=(list_impl && l);

   /*! Returns the count of elements in the list.

   @return
      Count of elements.
   */
   std::size_t size() const {
      return m_cNodes;
   }

protected:
   /*! Inserts a node to the end of the list.

   @param pn
      Pointer to the node to become the first in the list.
   */
   void link_back(xor_list_node_impl * pn);

   /*! Inserts a node to the start of the list.

   @param pn
      Pointer to the node to become the last in the list.
   */
   void link_front(xor_list_node_impl * pn);

   /*! Unlinks and returns the first node in the list.

   @return
      Former first node.
   */
   xor_list_node_impl * unlink_back();

   /*! Unlinks and returns the first node in the list.

   @return
      Former first node.
   */
   xor_list_node_impl * unlink_front();

protected:
   //! Pointer to the first node.
   xor_list_node_impl * m_pnFirst;
   //! Pointer to the last node.
   xor_list_node_impl * m_pnLast;
   //! Count of nodes.
   std::size_t m_cNodes;
};

} //namespace detail
} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::list

namespace abc {

//! Doubly-linked list.
template <typename T>
class list : public detail::list_impl {
private:
   typedef detail::xor_list_node_impl node_impl;

protected:
   //! List node.
   class node : public node_impl {
   public:
      //! Constructor.
      node(T t) :
         m_t(std::move(t)) {
      }

      //! See detail::xor_list_node_impl::get_next().
      node * get_next(node * pnPrev) {
         return static_cast<node *>(node_impl::get_next(static_cast<xor_list_node_impl *>(pnPrev)));
      }

      //! See detail::xor_list_node_impl::get_prev().
      node * get_prev(node * pnNext) {
         return static_cast<node *>(node_impl::get_prev(static_cast<xor_list_node_impl *>(pnNext)));
      }

      /*! Returns a pointer to the contained T.

      @return
         Pointer to the contained value.
      */
      T * value_ptr() {
         return &m_t;
      }
      T const * value_ptr() const {
         return &m_t;
      }

   public:
      //! Element contained within the node.
      T m_t;
   };

   //! Iterator for list::node subclasses.
   template <typename TValue>
   class iterator_impl :
      public detail::xor_list_iterator_impl<iterator_impl<TValue>, node, TValue> {
   public:
      //! See detail::xor_list_iterator_impl::xor_list_iterator_impl().
      iterator_impl(node * pnPrev, node * pnCurr, node * pnNext) :
         detail::xor_list_iterator_impl<iterator_impl<TValue>, node, TValue>(
            pnPrev, pnCurr, pnNext
         ) {
      }
   };

public:
   typedef iterator_impl<T> iterator;
   typedef iterator_impl<T const> const_iterator;
   typedef std::reverse_iterator<iterator> reverse_iterator;
   typedef std::reverse_iterator<const_iterator> const_reverse_iterator;

public:
   /*! Constructor.

   @param l
      Source object.
   */
   list() {
   }
   list(list && l) :
      detail::list_impl(std::move(l)) {
   }

   //! Destructor.
   ~list() {
      destruct_list(static_cast<node *>(m_pnFirst));
   }

   /*! Assignment operator.

   @param l
      Source object.
   */
   list & operator=(list && l) {
      node * pnFirst = m_pnFirst;
      detail::list_impl::operator=(std::move(l));
      // Now that the *this has been successfully overwritten, destruct the old nodes.
      destruct_list(pnFirst);
      return *this;
   }

   /*! Returns a forward iterator to the start of the list.

   @return
      Iterator to the first node in the list.
   */
   iterator begin() {
      return iterator(nullptr, m_pnFirst, m_pnFirst ? m_pnFirst->get_next(nullptr) : nullptr);
   }

   //! Removes all elements from the list.
   void clear() {
      ABC_TRACE_FUNC(this);

      destruct_list(static_cast<node *>(m_pnFirst));
      m_cNodes = 0;
   }

   /*! Returns a forward iterator to the end of the list.

   @return
      Iterator to the beyond the last node in the list.
   */
   iterator end() {
      return iterator(m_pnLast, nullptr, nullptr);
   }

   /*! Removes and returns the last element in the list.

   @return
      Former last element in the list.
   */
   T pop_back() {
      ABC_TRACE_FUNC(this);

      std::unique_ptr<node> pn(static_cast<node *>(unlink_back()));
      return std::move(pn->m_t);
   }

   /*! Removes the first element in the list.

   @return
      Former first element in the list.
   */
   T pop_front() {
      ABC_TRACE_FUNC(this);

      std::unique_ptr<node> pn(static_cast<node *>(unlink_front()));
      return std::move(pn->m_t);
   }

   /*! Adds an element to the start of the list.

   @param t
      Element to add.
   */
   void push_front(T t) {
      ABC_TRACE_FUNC(this/*, t*/);

      /* Memory management must happen here instead of link_back() because the unique_ptr must be of
      node, since node_impl doesn’t have a virtual destructor. */
      std::unique_ptr<node> pn(new node(std::move(t)));
      link_front(pn.get());
      // No exceptions, so the node is managed as part of the list.
      pn.release();
   }

   /*! Adds an element to the end of the list.

   @param t
      Element to add.
   */
   void push_back(T t) {
      ABC_TRACE_FUNC(this/*, t*/);

      /* Memory management must happen here instead of link_back() because the unique_ptr must be of
      node, since node_impl doesn’t have a virtual destructor. */
      std::unique_ptr<node> pn(new node(std::move(t)));
      link_back(pn.get());
      // No exceptions, so the node is managed as part of the list.
      pn.release();
   }

   /*! Returns a reverse iterator to the end of the list.

   @return
      Reverse Iterator to the last node in the list.
   */
   reverse_iterator rbegin() {
      return reverse_iterator(end());
   }

   //! Removes the last element in the list.
   void remove_back() {
      ABC_TRACE_FUNC(this);

      delete static_cast<node *>(unlink_back());
   }

   //! Removes the first element in the list.
   void remove_front() {
      ABC_TRACE_FUNC(this);

      delete static_cast<node *>(unlink_front());
   }

   /*! Returns a reverse iterator to the start of the list.

   @return
      Reverse iterator to the before the first node in the list.
   */
   reverse_iterator rend() {
      return reverse_iterator(begin());
   }

private:
   /*! Removes all elements from a list, given its first node.

   @param pnFirst
      Pointer to the first node to destruct.
   */
   void destruct_list(node * pnFirst) {
      ABC_TRACE_FUNC(this);

      for (node * pnPrev = nullptr, * pnCurr = pnFirst; pnCurr; ) {
         node * pnNext = pnCurr->get_next(pnPrev);
         delete pnCurr;
         pnPrev = pnCurr;
         pnCurr = pnNext;
      }
      m_cNodes = 0;
   }
};

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////

#endif //ifndef _ABACLADE_LIST_HXX
<commit_msg>Avoid overriding node_impl methods in abc::list::node<commit_after>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2015
Raffaello D. Di Napoli

This file is part of Abaclade.

Abaclade is free software: you can redistribute it and/or modify it under the terms of the GNU
General Public License as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

Abaclade is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.

You should have received a copy of the GNU General Public License along with Abaclade. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#ifndef _ABACLADE_LIST_HXX
#define _ABACLADE_LIST_HXX

#ifndef _ABACLADE_HXX
   #error "Please #include <abaclade.hxx> before this file"
#endif
#ifdef ABC_CXX_PRAGMA_ONCE
   #pragma once
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::detail::list_impl

namespace abc {
namespace detail {

//! Non-template implementation class for abc::list.
class ABACLADE_SYM list_impl {
public:
   /*! Constructor.

   @param l
      Source object.
   */
   list_impl() :
      m_pnFirst(nullptr),
      m_pnLast(nullptr),
      m_cNodes(0) {
   }
   list_impl(list_impl && l) :
      m_pnFirst(l.m_pnFirst),
      m_pnLast(l.m_pnLast),
      m_cNodes(l.m_cNodes) {
      l.m_pnFirst = nullptr;
      l.m_pnLast = nullptr;
      l.m_cNodes = 0;
   }

   //! Destructor.
   ~list_impl() {
   }

   /*! Assignment operator.

   @param l
      Source object.
   */
   list_impl & operator=(list_impl && l);

   /*! Returns the count of elements in the list.

   @return
      Count of elements.
   */
   std::size_t size() const {
      return m_cNodes;
   }

protected:
   /*! Inserts a node to the end of the list.

   @param pn
      Pointer to the node to become the first in the list.
   */
   void link_back(xor_list_node_impl * pn);

   /*! Inserts a node to the start of the list.

   @param pn
      Pointer to the node to become the last in the list.
   */
   void link_front(xor_list_node_impl * pn);

   /*! Unlinks and returns the first node in the list.

   @return
      Former first node.
   */
   xor_list_node_impl * unlink_back();

   /*! Unlinks and returns the first node in the list.

   @return
      Former first node.
   */
   xor_list_node_impl * unlink_front();

protected:
   //! Pointer to the first node.
   xor_list_node_impl * m_pnFirst;
   //! Pointer to the last node.
   xor_list_node_impl * m_pnLast;
   //! Count of nodes.
   std::size_t m_cNodes;
};

} //namespace detail
} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::list

namespace abc {

//! Doubly-linked list.
template <typename T>
class list : public detail::list_impl {
private:
   typedef detail::xor_list_node_impl node_impl;

protected:
   //! List node.
   class node : public node_impl {
   public:
      //! Constructor.
      node(T t) :
         m_t(std::move(t)) {
      }

      /*! Returns a pointer to the contained T.

      @return
         Pointer to the contained value.
      */
      T * value_ptr() {
         return &m_t;
      }
      T const * value_ptr() const {
         return &m_t;
      }

   public:
      //! Element contained within the node.
      T m_t;
   };

   //! Nodes iterator.
   template <typename TValue>
   class iterator_impl :
      public detail::xor_list_iterator_impl<iterator_impl<TValue>, node, TValue> {
   public:
      //! See detail::xor_list_iterator_impl::xor_list_iterator_impl().
      iterator_impl(node * pnPrev, node * pnCurr, node * pnNext) :
         detail::xor_list_iterator_impl<iterator_impl<TValue>, node, TValue>(
            pnPrev, pnCurr, pnNext
         ) {
      }
   };

public:
   typedef iterator_impl<T> iterator;
   typedef iterator_impl<T const> const_iterator;
   typedef std::reverse_iterator<iterator> reverse_iterator;
   typedef std::reverse_iterator<const_iterator> const_reverse_iterator;

public:
   /*! Constructor.

   @param l
      Source object.
   */
   list() {
   }
   list(list && l) :
      detail::list_impl(std::move(l)) {
   }

   //! Destructor.
   ~list() {
      destruct_list(static_cast<node *>(m_pnFirst));
   }

   /*! Assignment operator.

   @param l
      Source object.
   */
   list & operator=(list && l) {
      node * pnFirst = m_pnFirst;
      detail::list_impl::operator=(std::move(l));
      // Now that the *this has been successfully overwritten, destruct the old nodes.
      destruct_list(pnFirst);
      return *this;
   }

   /*! Returns a forward iterator to the start of the list.

   @return
      Iterator to the first node in the list.
   */
   iterator begin() {
      return iterator(nullptr, m_pnFirst, m_pnFirst ? m_pnFirst->get_next(nullptr) : nullptr);
   }

   //! Removes all elements from the list.
   void clear() {
      ABC_TRACE_FUNC(this);

      destruct_list(static_cast<node *>(m_pnFirst));
      m_cNodes = 0;
   }

   /*! Returns a forward iterator to the end of the list.

   @return
      Iterator to the beyond the last node in the list.
   */
   iterator end() {
      return iterator(m_pnLast, nullptr, nullptr);
   }

   /*! Removes and returns the last element in the list.

   @return
      Former last element in the list.
   */
   T pop_back() {
      ABC_TRACE_FUNC(this);

      std::unique_ptr<node> pn(static_cast<node *>(unlink_back()));
      return std::move(pn->m_t);
   }

   /*! Removes the first element in the list.

   @return
      Former first element in the list.
   */
   T pop_front() {
      ABC_TRACE_FUNC(this);

      std::unique_ptr<node> pn(static_cast<node *>(unlink_front()));
      return std::move(pn->m_t);
   }

   /*! Adds an element to the start of the list.

   @param t
      Element to add.
   */
   void push_front(T t) {
      ABC_TRACE_FUNC(this/*, t*/);

      /* Memory management must happen here instead of link_back() because the unique_ptr must be of
      node, since node_impl doesn’t have a virtual destructor. */
      std::unique_ptr<node> pn(new node(std::move(t)));
      link_front(pn.get());
      // No exceptions, so the node is managed as part of the list.
      pn.release();
   }

   /*! Adds an element to the end of the list.

   @param t
      Element to add.
   */
   void push_back(T t) {
      ABC_TRACE_FUNC(this/*, t*/);

      /* Memory management must happen here instead of link_back() because the unique_ptr must be of
      node, since node_impl doesn’t have a virtual destructor. */
      std::unique_ptr<node> pn(new node(std::move(t)));
      link_back(pn.get());
      // No exceptions, so the node is managed as part of the list.
      pn.release();
   }

   /*! Returns a reverse iterator to the end of the list.

   @return
      Reverse Iterator to the last node in the list.
   */
   reverse_iterator rbegin() {
      return reverse_iterator(end());
   }

   //! Removes the last element in the list.
   void remove_back() {
      ABC_TRACE_FUNC(this);

      delete static_cast<node *>(unlink_back());
   }

   //! Removes the first element in the list.
   void remove_front() {
      ABC_TRACE_FUNC(this);

      delete static_cast<node *>(unlink_front());
   }

   /*! Returns a reverse iterator to the start of the list.

   @return
      Reverse iterator to the before the first node in the list.
   */
   reverse_iterator rend() {
      return reverse_iterator(begin());
   }

private:
   /*! Removes all elements from a list, given its first node.

   @param pnFirst
      Pointer to the first node to destruct.
   */
   void destruct_list(node * pnFirst) {
      ABC_TRACE_FUNC(this);

      for (node_impl * pnPrev = nullptr, * pnCurr = pnFirst; pnCurr; ) {
         node_impl * pnNext = pnCurr->get_next(pnPrev);
         delete static_cast<node *>(pnCurr);
         pnPrev = pnCurr;
         pnCurr = pnNext;
      }
      m_cNodes = 0;
   }
};

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////

#endif //ifndef _ABACLADE_LIST_HXX
<|endoftext|>


<commit_before>#include <iostream>
#include <boost/asio.hpp>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/service.h>

#include "vtrc-common/vtrc-pool-pair.h"

#include "vtrc-common/vtrc-connection-iface.h"
#include "vtrc-common/vtrc-call-context.h"
#include "vtrc-common/vtrc-exception.h"
#include "vtrc-common/vtrc-protocol-layer.h"

#include "vtrc-client-base/vtrc-client.h"
#include "protocol/vtrc-rpc-lowlevel.pb.h"
#include "protocol/vtrc-service.pb.h"
#include "protocol/vtrc-errors.pb.h"

#include <boost/random.hpp>
#include <boost/random/random_device.hpp>

#include "vtrc-thread.h"
#include "vtrc-chrono.h"

using namespace vtrc;

void on_connect( const boost::system::error_code &err )
{
    std::cout << "connected "
              << err.value( ) << " "
              << err.message( ) << "\n";
}

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

class ping_impl: public vtrc_service::internal {

    client::vtrc_client *c_;

public:

    ping_impl( client::vtrc_client *c )
        :c_( c )
    {}

    void ping(::google::protobuf::RpcController* controller,
                         const ::vtrc_service::ping_req* request,
                         ::vtrc_service::pong_res* response,
                         ::google::protobuf::Closure* done)
    {
        common::closure_holder chold(done);
        std::cout << "ping event rcvd "
                  << c_->connection( )
                     ->get_protocol( ).get_call_context( )
                     ->get_lowlevel_message( )->id( )
                  << " " << vtrc::this_thread::get_id( ) << " "
                  //<< vtrc::chrono::high_resolution_clock::now( )
                  << "\n";

        //return;

        const vtrc::common::call_context *cc =
                    vtrc::common::call_context::get( c_->connection( ) );

        vtrc::shared_ptr<google::protobuf::RpcChannel>
                            ch(c_->create_channel( false, true ));

        vtrc_rpc_lowlevel::message_info mi;
        vtrc_service::test_rpc::Stub s( ch.get( ) );

        s.test2( NULL, &mi, &mi, NULL );

        //if( done ) done->Run( );
    }
};

class test_ev: public vtrc_service::test_events
{
    vtrc::common::connection_iface *c_;
public:
    test_ev( vtrc::common::connection_iface *c )
        :c_( c )
    {}

    void test(::google::protobuf::RpcController* controller,
                         const ::vtrc_rpc_lowlevel::message_info* request,
                         ::vtrc_rpc_lowlevel::message_info* response,
                         ::google::protobuf::Closure* done)
    {
        common::closure_holder ch(done);
        std::cout << "test event rcvd "
                  << c_->get_protocol( ).get_call_context( )->get_lowlevel_message( )->id( )
                  << " " << vtrc::this_thread::get_id( ) << " "
                  << "\n";
    }

};

void run_client( vtrc::shared_ptr<client::vtrc_client> cl, bool wait)
{
    vtrc::shared_ptr<google::protobuf::RpcChannel>
            ch(cl->create_channel( wait, false ));
    vtrc_service::test_rpc::Stub s( ch.get( ) );

    vtrc_rpc_lowlevel::message_info mi;

    size_t last = 0;

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

    for( int i=0; i<29999999999; ++i ) {
        try {

            if( wait )
                vtrc::this_thread::sleep_for( vtrc::chrono::milliseconds(1) );
            work_time wt;
            s.test( NULL, &mi, &mi, NULL );
            last = mi.message_type( );
            std::cout << "response: " << last << "\n";
            //cl.reset( );
        } catch( const vtrc::common::exception &ex ) {
            std::cout << "call error: "
                      << " code (" << ex.code( ) << ")"
                      << " category (" << ex.category( ) << ")"
                      << " what: " << ex.what( )
                      << " (" << ex.additional( ) << ")"
                      << "\n";
            //if( i % 100 == 0 )
            std::cout << i << "\n";
            if( ex.category( ) == vtrc_errors::CATEGORY_SYSTEM ) break;
            if( ex.code( ) == vtrc_errors::ERR_COMM ) break;
        } catch( const std::exception &ex ) {
            //std::cout << "call error: " << ex.what( ) << "\n";
        }
    }
}

int main( )
{

    common::pool_pair pp(2, 2);
    vtrc::shared_ptr<client::vtrc_client> cl(client::vtrc_client::create(pp));

    cl->connect( "/tmp/test" );
    //cl->connect( "192.168.56.101", "44667" );
    cl->connect( "127.0.0.1", "44667" );
    //cl->connect( "::1", "44668" );
    ///cl->async_connect( "127.0.0.1", "44667", on_connect );

    cl->advise_handler( vtrc::shared_ptr<test_ev>(new test_ev(cl->connection( ).get( ))) );
    cl->advise_handler( vtrc::shared_ptr<ping_impl>(new ping_impl(cl.get( ))) );

    vtrc::this_thread::sleep_for( vtrc::chrono::milliseconds(2000) );

    //vtrc::thread( run_client, cl, true ).detach( );
    vtrc::thread( run_client, cl, false ).detach( );
    vtrc::thread( run_client, cl, false ).join( );

    pp.stop_all( );
    pp.join_all( );

    return 0;

}
<commit_msg>protocol<commit_after>#include <iostream>
#include <boost/asio.hpp>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/service.h>

#include "vtrc-common/vtrc-pool-pair.h"

#include "vtrc-common/vtrc-connection-iface.h"
#include "vtrc-common/vtrc-call-context.h"
#include "vtrc-common/vtrc-exception.h"
#include "vtrc-common/vtrc-protocol-layer.h"

#include "vtrc-client-base/vtrc-client.h"
#include "protocol/vtrc-rpc-lowlevel.pb.h"
#include "protocol/vtrc-service.pb.h"
#include "protocol/vtrc-errors.pb.h"

#include <boost/random.hpp>
#include <boost/random/random_device.hpp>

#include "vtrc-thread.h"
#include "vtrc-chrono.h"

using namespace vtrc;

void on_connect( const boost::system::error_code &err )
{
    std::cout << "connected "
              << err.value( ) << " "
              << err.message( ) << "\n";
}

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

class ping_impl: public vtrc_service::internal {

    client::vtrc_client *c_;

public:

    ping_impl( client::vtrc_client *c )
        :c_( c )
    {}

    void ping(::google::protobuf::RpcController* controller,
                         const ::vtrc_service::ping_req* request,
                         ::vtrc_service::pong_res* response,
                         ::google::protobuf::Closure* done)
    {
        common::closure_holder chold(done);
        std::cout << "ping event rcvd "
                  << c_->connection( )
                     ->get_protocol( ).get_call_context( )
                     ->get_lowlevel_message( )->id( )
                  << " " << vtrc::this_thread::get_id( ) << " "
                  //<< vtrc::chrono::high_resolution_clock::now( )
                  << "\n";

        //return;

        const vtrc::common::call_context *cc =
                    vtrc::common::call_context::get( c_->connection( ) );

        vtrc::shared_ptr<google::protobuf::RpcChannel>
                            ch(c_->create_channel( false, true ));

        vtrc_rpc_lowlevel::message_info mi;
        vtrc_service::test_rpc::Stub s( ch.get( ) );

        s.test2( NULL, &mi, &mi, NULL );

        //if( done ) done->Run( );
    }
};

class test_ev: public vtrc_service::test_events
{
    vtrc::common::connection_iface *c_;
public:
    test_ev( vtrc::common::connection_iface *c )
        :c_( c )
    {}

    void test(::google::protobuf::RpcController* controller,
                         const ::vtrc_rpc_lowlevel::message_info* request,
                         ::vtrc_rpc_lowlevel::message_info* response,
                         ::google::protobuf::Closure* done)
    {
        common::closure_holder ch(done);
        std::cout << "test event rcvd "
                  << c_->get_protocol( ).get_call_context( )->get_lowlevel_message( )->id( )
                  << " " << vtrc::this_thread::get_id( ) << " "
                  << "\n";
    }

};

void run_client( vtrc::shared_ptr<client::vtrc_client> cl, bool wait)
{
    vtrc::shared_ptr<google::protobuf::RpcChannel>
            ch(cl->create_channel( wait, false ));
    vtrc_service::test_rpc::Stub s( ch.get( ) );

    vtrc_rpc_lowlevel::message_info mi;

    size_t last = 0;

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

    for( int i=0; i<29999999999; ++i ) {
        try {

            if( wait )
                vtrc::this_thread::sleep_for( vtrc::chrono::milliseconds(1) );
            work_time wt;
            s.test( NULL, &mi, &mi, NULL );
            last = mi.message_type( );
            std::cout << "response: " << last << "\n";
            //cl.reset( );
        } catch( const vtrc::common::exception &ex ) {
            std::cout << "call error: "
                      << " code (" << ex.code( ) << ")"
                      << " category (" << ex.category( ) << ")"
                      << " what: " << ex.what( )
                      << " (" << ex.additional( ) << ")"
                      << "\n";
            //if( i % 100 == 0 )
            std::cout << i << "\n";
            if( ex.category( ) == vtrc_errors::CATEGORY_SYSTEM ) break;
            if( ex.code( ) == vtrc_errors::ERR_COMM ) break;
        } catch( const std::exception &ex ) {
            //std::cout << "call error: " << ex.what( ) << "\n";
        }
    }
}

int main( )
{

    common::pool_pair pp(2, 2);
    vtrc::shared_ptr<client::vtrc_client> cl(client::vtrc_client::create(pp));

    cl->connect( "/tmp/test" );
    //cl->connect( "192.168.56.101", "44667" );
    cl->connect( "127.0.0.1", "44667" );
    //cl->connect( "::1", "44668" );
    ///cl->async_connect( "127.0.0.1", "44667", on_connect );

    cl->advise_handler( vtrc::shared_ptr<test_ev>(new test_ev(cl->connection( ).get( ))) );
    cl->advise_handler( vtrc::shared_ptr<ping_impl>(new ping_impl(cl.get( ))) );

    vtrc::this_thread::sleep_for( vtrc::chrono::milliseconds(2000) );

    //vtrc::thread( run_client, cl, true ).detach( );
    //vtrc::thread( run_client, cl, false ).detach( );
    vtrc::thread( run_client, cl, false ).join( );

    pp.stop_all( );
    pp.join_all( );

    return 0;

}
<|endoftext|>


<commit_before>// Copyright 2020, 2021, 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "elisp/binary.h"

#include <string>
#include <vector>

#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "gmock/gmock.h"  // IWYU pragma: keep
#include "gtest/gtest.h"  // IWYU pragma: keep
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif

#include "elisp/process.h"

// IWYU pragma: no_include "gtest/gtest_pred_impl.h"
// IWYU pragma: no_include <gmock/gmock-matchers.h>
// IWYU pragma: no_include <gtest/gtest-matchers.h>
// IWYU pragma: no_include <gtest/gtest-message.h>
// IWYU pragma: no_include <gtest/gtest-test-part.h>

namespace phst_rules_elisp {
namespace {

using ::testing::Eq;

TEST(Executor, RunBinaryWrap) {
  const absl::StatusOr<Runfiles> runfiles = Runfiles::CreateForTest();
  ASSERT_TRUE(runfiles.ok()) << runfiles.status();
  NativeString wrapper =
      PHST_RULES_ELISP_NATIVE_LITERAL("phst_rules_elisp/tests/wrap/wrap");
#ifdef PHST_RULES_ELISP_WINDOWS
  wrapper += L".exe";
#endif
  const NativeString argv0 = PHST_RULES_ELISP_NATIVE_LITERAL("unused");
  const absl::StatusOr<NativeString> input_file =
      runfiles->Resolve("phst_rules_elisp/elisp/binary.cc");
  ASSERT_TRUE(input_file.ok()) << input_file.status();
  const std::vector<NativeString> args = {
      PHST_RULES_ELISP_NATIVE_LITERAL("--wrapper=") + wrapper,
      PHST_RULES_ELISP_NATIVE_LITERAL("--mode=wrap"),
      PHST_RULES_ELISP_NATIVE_LITERAL("--rule-tag=local"),
      PHST_RULES_ELISP_NATIVE_LITERAL("--rule-tag=mytag"),
      PHST_RULES_ELISP_NATIVE_LITERAL("--load-directory=phst_rules_elisp"),
      PHST_RULES_ELISP_NATIVE_LITERAL(
          "--data-file=phst_rules_elisp/elisp/binary.h"),
      PHST_RULES_ELISP_NATIVE_LITERAL("--input-arg=2"),
      PHST_RULES_ELISP_NATIVE_LITERAL("--output-arg=-1"),
      PHST_RULES_ELISP_NATIVE_LITERAL("--"),
      argv0,
      PHST_RULES_ELISP_NATIVE_LITERAL("--option"),
      *input_file,
      PHST_RULES_ELISP_NATIVE_LITERAL(" \t\n\r\f äα𝐴🐈'\\\""),
#ifdef PHST_RULES_ELISP_WINDOWS
      L"/:C:\\Temp\\output.dat",
#else
      "/:/tmp/output.dat",
#endif
  };
  EXPECT_THAT(RunBinary(argv0, args), Eq(0));
}

}  // namespace
}  // namespace phst_rules_elisp
<commit_msg>Suppress warnings under Visual C++<commit_after>// Copyright 2020, 2021, 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "elisp/binary.h"

#include <string>
#include <vector>

#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
#ifdef _MSC_VER
#pragma warning(push, 3)
#endif
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "gmock/gmock.h"  // IWYU pragma: keep
#include "gtest/gtest.h"  // IWYU pragma: keep
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "elisp/process.h"

// IWYU pragma: no_include "gtest/gtest_pred_impl.h"
// IWYU pragma: no_include <gmock/gmock-matchers.h>
// IWYU pragma: no_include <gtest/gtest-matchers.h>
// IWYU pragma: no_include <gtest/gtest-message.h>
// IWYU pragma: no_include <gtest/gtest-test-part.h>

namespace phst_rules_elisp {
namespace {

using ::testing::Eq;

TEST(Executor, RunBinaryWrap) {
  const absl::StatusOr<Runfiles> runfiles = Runfiles::CreateForTest();
  ASSERT_TRUE(runfiles.ok()) << runfiles.status();
  NativeString wrapper =
      PHST_RULES_ELISP_NATIVE_LITERAL("phst_rules_elisp/tests/wrap/wrap");
#ifdef PHST_RULES_ELISP_WINDOWS
  wrapper += L".exe";
#endif
  const NativeString argv0 = PHST_RULES_ELISP_NATIVE_LITERAL("unused");
  const absl::StatusOr<NativeString> input_file =
      runfiles->Resolve("phst_rules_elisp/elisp/binary.cc");
  ASSERT_TRUE(input_file.ok()) << input_file.status();
  const std::vector<NativeString> args = {
      PHST_RULES_ELISP_NATIVE_LITERAL("--wrapper=") + wrapper,
      PHST_RULES_ELISP_NATIVE_LITERAL("--mode=wrap"),
      PHST_RULES_ELISP_NATIVE_LITERAL("--rule-tag=local"),
      PHST_RULES_ELISP_NATIVE_LITERAL("--rule-tag=mytag"),
      PHST_RULES_ELISP_NATIVE_LITERAL("--load-directory=phst_rules_elisp"),
      PHST_RULES_ELISP_NATIVE_LITERAL(
          "--data-file=phst_rules_elisp/elisp/binary.h"),
      PHST_RULES_ELISP_NATIVE_LITERAL("--input-arg=2"),
      PHST_RULES_ELISP_NATIVE_LITERAL("--output-arg=-1"),
      PHST_RULES_ELISP_NATIVE_LITERAL("--"),
      argv0,
      PHST_RULES_ELISP_NATIVE_LITERAL("--option"),
      *input_file,
      PHST_RULES_ELISP_NATIVE_LITERAL(" \t\n\r\f äα𝐴🐈'\\\""),
#ifdef PHST_RULES_ELISP_WINDOWS
      L"/:C:\\Temp\\output.dat",
#else
      "/:/tmp/output.dat",
#endif
  };
  EXPECT_THAT(RunBinary(argv0, args), Eq(0));
}

}  // namespace
}  // namespace phst_rules_elisp
<|endoftext|>


<commit_before>#include "net.hpp"

#include <gtest/gtest.h>

TEST(FeedForward_Network, resize) {
  FeedForward_Network<> f(10, 20, 30);
  f.resize_activation(12);
  ASSERT_EQ(f.activation_input.n_rows, 12);
  ASSERT_EQ(f.activation_hidden.n_rows, 12);
  ASSERT_EQ(f.activation_output.n_rows, 12);

  ASSERT_EQ(f.activation_input.n_cols, 10);
  ASSERT_EQ(f.activation_hidden.n_cols, 20);
  ASSERT_EQ(f.activation_output.n_cols, 30);
}
<commit_msg>removed floating net.cpp<commit_after><|endoftext|>


<commit_before>/**
 * Copyright (C) 2015 Dato, Inc.
 * All rights reserved.
 *
 * This software may be modified and distributed under the terms
 * of the BSD license. See the LICENSE file for details.
 */
#include <lambda/pylambda.hpp>
#include <lambda/python_api.hpp>
#include <lambda/python_import_modules.hpp>
#include <lambda/python_thread_guard.hpp>
#include <lambda/pyflexible_type.hpp>
#include <sframe/sarray.hpp>
#include <sframe/sframe.hpp>
#include <sframe/sframe_rows.hpp>
#include <fileio/fs_utils.hpp>
#include <util/cityhash_gl.hpp>
#include <shmipc/shmipc.hpp>

namespace graphlab {

namespace lambda {

  namespace python = boost::python;

  pylambda_evaluator::~pylambda_evaluator() {
    if (m_shared_memory_listener.active()) {
      m_shared_memory_thread_terminating = true;
      m_shared_memory_listener.join();
    }
  }

  size_t pylambda_evaluator::make_lambda(const std::string& pylambda_str) {
    python_thread_guard py_thread_guard;
    auto status = fileio::get_file_status(pylambda_str);
    if (status == fileio::file_status::DIRECTORY) {
      try {
        // Does python::object(python::handle<>(lambda_filename)) decref this?
        PyObject* lambda_filename =
            PyString_FromStringAndSize(pylambda_str.c_str(), pylambda_str.size());
        size_t hash_key = hash64(pylambda_str.c_str(), pylambda_str.size());
        auto unpickler = py_gl_pickle.attr("GLUnpickler")(python::object(python::handle<>(lambda_filename)));
        m_lambda_hash[hash_key] = new python::object(unpickler.attr("load")());
        return hash_key;
      } catch (python::error_already_set const& e) {
        std::string error_string = parse_python_error();
        throw(error_string);
      }
    } else {
      try {
        PyObject* lambda_bytes = PyByteArray_FromStringAndSize(pylambda_str.c_str(), pylambda_str.size());
        size_t hash_key = hash64(pylambda_str.c_str(), pylambda_str.size());
        m_lambda_hash[hash_key] = new python::object((py_pickle.attr("loads")(python::object(python::handle<>(lambda_bytes)))));
        logstream(LOG_DEBUG) << "make lambda" << hash_key << std::endl;
        return hash_key;
      } catch (python::error_already_set const& e) {
        std::string error_string = parse_python_error();
        throw(error_string);
      }
    }
  }

  void pylambda_evaluator::release_lambda(size_t lambda_hash) {
    python_thread_guard py_thread_guard;
    logstream(LOG_DEBUG) << "release lambda" << lambda_hash << std::endl;
    auto lambda_obj = m_lambda_hash.find(lambda_hash);

    if (lambda_obj == m_lambda_hash.end()) {
      throw("Cannot find the lambda hash to release " + std::to_string(lambda_hash));
    }

    if (m_current_lambda_hash == lambda_hash) {
      m_current_lambda_hash = (size_t)(-1);
      m_current_lambda = NULL;
    }

    m_lambda_hash.erase(lambda_hash);
    delete m_lambda_hash[lambda_hash];

    // run gc to reclaim heap
    py_gc.attr("collect")();
  }

  flexible_type pylambda_evaluator::eval(size_t lambda_hash, const flexible_type& arg) {
    set_lambda(lambda_hash);
    try {
        python::object input = PyObject_FromFlex(arg);
        python::object output = m_current_lambda->operator()(input);
        return PyObject_AsFlex(output);
    } catch (python::error_already_set const& e) {
      std::string error_string = parse_python_error();
      throw(error_string);
    } catch (std::exception& e) {
      throw(std::string(e.what()));
    } catch (...) {
      throw("Unknown exception from python lambda evaluation.");
    }
  }

  /**
   * Bulk version of eval.
   */
  std::vector<flexible_type> pylambda_evaluator::bulk_eval(
    size_t lambda_hash,
    const std::vector<flexible_type>& args,
    bool skip_undefined,
    int seed) {

    python_thread_guard py_thread_guard;

    set_lambda(lambda_hash);

    py_set_random_seed(seed);

    std::vector<flexible_type> ret(args.size());
    size_t i = 0;
    for (const auto& x : args) {
      if (skip_undefined && x == FLEX_UNDEFINED) {
        ret[i++] = FLEX_UNDEFINED;
      } else {
        ret[i++] = eval(lambda_hash, x);
      }
    }
    return ret;
  }

  std::vector<flexible_type> pylambda_evaluator::bulk_eval_rows(
    size_t lambda_hash,
    const sframe_rows& rows,
    bool skip_undefined,
    int seed) {

    python_thread_guard py_thread_guard;

    set_lambda(lambda_hash);

    py_set_random_seed(seed);

    std::vector<flexible_type> ret(rows.num_rows());
    size_t i = 0;
    for (const auto& x : rows) {
      if (skip_undefined && x[0] == FLEX_UNDEFINED) {
        ret[i++] = FLEX_UNDEFINED;
      } else {
        ret[i++] = eval(lambda_hash, x[0]);
      }
    }
    return ret;
  }

  /**
   * Bulk version of eval_dict.
   */
  std::vector<flexible_type> pylambda_evaluator::bulk_eval_dict(
    size_t lambda_hash,
    const std::vector<std::string>& keys,
    const std::vector<std::vector<flexible_type>>& values,
    bool skip_undefined,
    int seed) {

    python_thread_guard py_thread_guard;

    set_lambda(lambda_hash);
    py_set_random_seed(seed);
    std::vector<flexible_type> ret(values.size());
    python::dict input;
    size_t cnt = 0;
    try {
        for (const auto& val: values) {
          PyDict_UpdateFromFlex(input, keys, val);
          python::object output = m_current_lambda->operator()(input);
          PyObject_AsFlex(output, ret[cnt]);
          cnt++;
        }
    } catch (python::error_already_set const& e) {
      std::string error_string = parse_python_error();
      throw(error_string);
    } catch (std::exception& e) {
      throw(std::string(e.what()));
    } catch (...) {
      throw("Unknown exception from python lambda evaluation.");
    }
    return ret;
  }

  std::vector<flexible_type> pylambda_evaluator::bulk_eval_dict_rows(
    size_t lambda_hash,
    const std::vector<std::string>& keys,
    const sframe_rows& rows,
    bool skip_undefined,
    int seed) {

    python_thread_guard py_thread_guard;

    set_lambda(lambda_hash);
    py_set_random_seed(seed);
    std::vector<flexible_type> ret(rows.num_rows());
    python::dict input;
    size_t cnt = 0;
    try {
      std::vector<flexible_type> row(rows.num_columns());
      for (const auto& row_iter: rows) {
        for (size_t j = 0; j < row.size(); ++j)
          row[j] = row_iter[j];
        PyDict_UpdateFromFlex(input, keys, row);
        python::object output = m_current_lambda->operator()(input);
        PyObject_AsFlex(output, ret[cnt]);
        cnt++;
      }
    } catch (python::error_already_set const& e) {
      std::string error_string = parse_python_error();
      throw(error_string);
    } catch (std::exception& e) {
      throw(std::string(e.what()));
    } catch (...) {
      throw("Unknown exception from python lambda evaluation.");
    }
    return ret;
  }

  void pylambda_evaluator::set_lambda(size_t lambda_hash) {
    if (m_current_lambda_hash == lambda_hash) return;

    auto lambda_obj = m_lambda_hash.find(lambda_hash);
    if (lambda_obj == m_lambda_hash.end()) {
      throw("Cannot find a lambda handle that is value " + std::to_string(lambda_hash));
    }

    m_current_lambda = m_lambda_hash[lambda_hash];
    m_current_lambda_hash = lambda_hash;
  }

  std::vector<flexible_type>
  pylambda_evaluator::bulk_eval_rows_serialized(const char* ptr, size_t len) {
    iarchive iarc(ptr, len);
    char c;
    iarc >> c;
    if (c == (char)bulk_eval_serialized_tag::BULK_EVAL_ROWS) {
      size_t lambda_hash;
      sframe_rows rows;
      bool skip_undefined;
      int seed;
      iarc >> lambda_hash >> rows >> skip_undefined >> seed;
      return bulk_eval_rows(lambda_hash, rows, skip_undefined, seed);
    } else if (c == (char)bulk_eval_serialized_tag::BULK_EVAL_DICT_ROWS) {
      size_t lambda_hash;
      std::vector<std::string> keys;
      sframe_rows values;
      bool skip_undefined;
      int seed;
      iarc >> lambda_hash >> keys >> values >> skip_undefined >> seed;
      return bulk_eval_dict_rows(lambda_hash, keys, values, skip_undefined, seed);
    } else {
      logstream(LOG_FATAL) << "Invalid serialized result" << std::endl;
    }
  }

  std::string pylambda_evaluator::initialize_shared_memory_comm() {
    if (m_shared_memory_server) {
      if (!m_shared_memory_listener.active()) {
        m_shared_memory_listener.launch(
            [=]() {
            while(!m_shared_memory_server->wait_for_connect(3)) {
              if (m_shared_memory_thread_terminating) return;
            }
            char* receive_buffer = nullptr;
            size_t receive_buffer_length = 0;
            size_t message_length = 0;
            char* send_buffer = nullptr;
            size_t send_buffer_length= 0 ;
            while(1) {
              bool has_data =
                  shmipc::large_receive(*m_shared_memory_server,
                                        &receive_buffer,
                                        &receive_buffer_length,
                                        message_length,
                                        3 /* timeout */);
              if (!has_data) {
                if (m_shared_memory_thread_terminating) break;
                else continue;
              } else {
                oarchive oarc;
                oarc.buf = send_buffer;
                oarc.len = send_buffer_length;
                try {
                  auto ret = bulk_eval_rows_serialized(receive_buffer, message_length);
                  oarc << (char)(1) << ret;
                } catch (std::string& s) {
                  oarc << (char)(0) << s;
                } catch (const char* s) {
                  oarc << (char)(0) << std::string(s);
                } catch (...) {
                  oarc << (char)(0) << std::string("Unknown Runtime Exception");
                }
                shmipc::large_send(*m_shared_memory_server,
                                   oarc.buf,
                                   oarc.off);
                send_buffer = oarc.buf;
                send_buffer_length = oarc.len;
              }
            }
            if (receive_buffer) free(receive_buffer);
            if (send_buffer) free(send_buffer);
            });
      }
      return m_shared_memory_server->get_shared_memory_name();
    } else {
      return "";
    }
  }
} // end of namespace lambda
} // end of namespace graphlab
<commit_msg>fix a memory leak in lambda worker<commit_after>/**
 * Copyright (C) 2015 Dato, Inc.
 * All rights reserved.
 *
 * This software may be modified and distributed under the terms
 * of the BSD license. See the LICENSE file for details.
 */
#include <lambda/pylambda.hpp>
#include <lambda/python_api.hpp>
#include <lambda/python_import_modules.hpp>
#include <lambda/python_thread_guard.hpp>
#include <lambda/pyflexible_type.hpp>
#include <sframe/sarray.hpp>
#include <sframe/sframe.hpp>
#include <sframe/sframe_rows.hpp>
#include <fileio/fs_utils.hpp>
#include <util/cityhash_gl.hpp>
#include <shmipc/shmipc.hpp>

namespace graphlab {

namespace lambda {

  namespace python = boost::python;

  pylambda_evaluator::~pylambda_evaluator() {
    if (m_shared_memory_listener.active()) {
      m_shared_memory_thread_terminating = true;
      m_shared_memory_listener.join();
    }
  }

  size_t pylambda_evaluator::make_lambda(const std::string& pylambda_str) {
    python_thread_guard py_thread_guard;
    auto status = fileio::get_file_status(pylambda_str);
    if (status == fileio::file_status::DIRECTORY) {
      try {
        // Does python::object(python::handle<>(lambda_filename)) decref this?
        PyObject* lambda_filename =
            PyString_FromStringAndSize(pylambda_str.c_str(), pylambda_str.size());
        size_t hash_key = hash64(pylambda_str.c_str(), pylambda_str.size());
        auto unpickler = py_gl_pickle.attr("GLUnpickler")(python::object(python::handle<>(lambda_filename)));
        m_lambda_hash[hash_key] = new python::object(unpickler.attr("load")());
        return hash_key;
      } catch (python::error_already_set const& e) {
        std::string error_string = parse_python_error();
        throw(error_string);
      }
    } else {
      try {
        PyObject* lambda_bytes = PyByteArray_FromStringAndSize(pylambda_str.c_str(), pylambda_str.size());
        size_t hash_key = hash64(pylambda_str.c_str(), pylambda_str.size());
        m_lambda_hash[hash_key] = new python::object((py_pickle.attr("loads")(python::object(python::handle<>(lambda_bytes)))));
        logstream(LOG_DEBUG) << "make lambda" << hash_key << std::endl;
        return hash_key;
      } catch (python::error_already_set const& e) {
        std::string error_string = parse_python_error();
        throw(error_string);
      }
    }
  }

  void pylambda_evaluator::release_lambda(size_t lambda_hash) {
    python_thread_guard py_thread_guard;
    logstream(LOG_DEBUG) << "release lambda" << lambda_hash << std::endl;
    auto lambda_obj = m_lambda_hash.find(lambda_hash);

    if (lambda_obj == m_lambda_hash.end()) {
      throw("Cannot find the lambda hash to release " + std::to_string(lambda_hash));
    }

    if (m_current_lambda_hash == lambda_hash) {
      m_current_lambda_hash = (size_t)(-1);
      m_current_lambda = NULL;
    }

    delete m_lambda_hash[lambda_hash];
    m_lambda_hash.erase(lambda_hash);

    // run gc to reclaim heap
    py_gc.attr("collect")();
  }

  flexible_type pylambda_evaluator::eval(size_t lambda_hash, const flexible_type& arg) {
    set_lambda(lambda_hash);
    try {
        python::object input = PyObject_FromFlex(arg);
        python::object output = m_current_lambda->operator()(input);
        return PyObject_AsFlex(output);
    } catch (python::error_already_set const& e) {
      std::string error_string = parse_python_error();
      throw(error_string);
    } catch (std::exception& e) {
      throw(std::string(e.what()));
    } catch (...) {
      throw("Unknown exception from python lambda evaluation.");
    }
  }

  /**
   * Bulk version of eval.
   */
  std::vector<flexible_type> pylambda_evaluator::bulk_eval(
    size_t lambda_hash,
    const std::vector<flexible_type>& args,
    bool skip_undefined,
    int seed) {

    python_thread_guard py_thread_guard;

    set_lambda(lambda_hash);

    py_set_random_seed(seed);

    std::vector<flexible_type> ret(args.size());
    size_t i = 0;
    for (const auto& x : args) {
      if (skip_undefined && x == FLEX_UNDEFINED) {
        ret[i++] = FLEX_UNDEFINED;
      } else {
        ret[i++] = eval(lambda_hash, x);
      }
    }
    return ret;
  }

  std::vector<flexible_type> pylambda_evaluator::bulk_eval_rows(
    size_t lambda_hash,
    const sframe_rows& rows,
    bool skip_undefined,
    int seed) {

    python_thread_guard py_thread_guard;

    set_lambda(lambda_hash);

    py_set_random_seed(seed);

    std::vector<flexible_type> ret(rows.num_rows());
    size_t i = 0;
    for (const auto& x : rows) {
      if (skip_undefined && x[0] == FLEX_UNDEFINED) {
        ret[i++] = FLEX_UNDEFINED;
      } else {
        ret[i++] = eval(lambda_hash, x[0]);
      }
    }
    return ret;
  }

  /**
   * Bulk version of eval_dict.
   */
  std::vector<flexible_type> pylambda_evaluator::bulk_eval_dict(
    size_t lambda_hash,
    const std::vector<std::string>& keys,
    const std::vector<std::vector<flexible_type>>& values,
    bool skip_undefined,
    int seed) {

    python_thread_guard py_thread_guard;

    set_lambda(lambda_hash);
    py_set_random_seed(seed);
    std::vector<flexible_type> ret(values.size());
    python::dict input;
    size_t cnt = 0;
    try {
        for (const auto& val: values) {
          PyDict_UpdateFromFlex(input, keys, val);
          python::object output = m_current_lambda->operator()(input);
          PyObject_AsFlex(output, ret[cnt]);
          cnt++;
        }
    } catch (python::error_already_set const& e) {
      std::string error_string = parse_python_error();
      throw(error_string);
    } catch (std::exception& e) {
      throw(std::string(e.what()));
    } catch (...) {
      throw("Unknown exception from python lambda evaluation.");
    }
    return ret;
  }

  std::vector<flexible_type> pylambda_evaluator::bulk_eval_dict_rows(
    size_t lambda_hash,
    const std::vector<std::string>& keys,
    const sframe_rows& rows,
    bool skip_undefined,
    int seed) {

    python_thread_guard py_thread_guard;

    set_lambda(lambda_hash);
    py_set_random_seed(seed);
    std::vector<flexible_type> ret(rows.num_rows());
    python::dict input;
    size_t cnt = 0;
    try {
      std::vector<flexible_type> row(rows.num_columns());
      for (const auto& row_iter: rows) {
        for (size_t j = 0; j < row.size(); ++j)
          row[j] = row_iter[j];
        PyDict_UpdateFromFlex(input, keys, row);
        python::object output = m_current_lambda->operator()(input);
        PyObject_AsFlex(output, ret[cnt]);
        cnt++;
      }
    } catch (python::error_already_set const& e) {
      std::string error_string = parse_python_error();
      throw(error_string);
    } catch (std::exception& e) {
      throw(std::string(e.what()));
    } catch (...) {
      throw("Unknown exception from python lambda evaluation.");
    }
    return ret;
  }

  void pylambda_evaluator::set_lambda(size_t lambda_hash) {
    if (m_current_lambda_hash == lambda_hash) return;

    auto lambda_obj = m_lambda_hash.find(lambda_hash);
    if (lambda_obj == m_lambda_hash.end()) {
      throw("Cannot find a lambda handle that is value " + std::to_string(lambda_hash));
    }

    m_current_lambda = m_lambda_hash[lambda_hash];
    m_current_lambda_hash = lambda_hash;
  }

  std::vector<flexible_type>
  pylambda_evaluator::bulk_eval_rows_serialized(const char* ptr, size_t len) {
    iarchive iarc(ptr, len);
    char c;
    iarc >> c;
    if (c == (char)bulk_eval_serialized_tag::BULK_EVAL_ROWS) {
      size_t lambda_hash;
      sframe_rows rows;
      bool skip_undefined;
      int seed;
      iarc >> lambda_hash >> rows >> skip_undefined >> seed;
      return bulk_eval_rows(lambda_hash, rows, skip_undefined, seed);
    } else if (c == (char)bulk_eval_serialized_tag::BULK_EVAL_DICT_ROWS) {
      size_t lambda_hash;
      std::vector<std::string> keys;
      sframe_rows values;
      bool skip_undefined;
      int seed;
      iarc >> lambda_hash >> keys >> values >> skip_undefined >> seed;
      return bulk_eval_dict_rows(lambda_hash, keys, values, skip_undefined, seed);
    } else {
      logstream(LOG_FATAL) << "Invalid serialized result" << std::endl;
    }
  }

  std::string pylambda_evaluator::initialize_shared_memory_comm() {
    if (m_shared_memory_server) {
      if (!m_shared_memory_listener.active()) {
        m_shared_memory_listener.launch(
            [=]() {
            while(!m_shared_memory_server->wait_for_connect(3)) {
              if (m_shared_memory_thread_terminating) return;
            }
            char* receive_buffer = nullptr;
            size_t receive_buffer_length = 0;
            size_t message_length = 0;
            char* send_buffer = nullptr;
            size_t send_buffer_length= 0 ;
            while(1) {
              bool has_data =
                  shmipc::large_receive(*m_shared_memory_server,
                                        &receive_buffer,
                                        &receive_buffer_length,
                                        message_length,
                                        3 /* timeout */);
              if (!has_data) {
                if (m_shared_memory_thread_terminating) break;
                else continue;
              } else {
                oarchive oarc;
                oarc.buf = send_buffer;
                oarc.len = send_buffer_length;
                try {
                  auto ret = bulk_eval_rows_serialized(receive_buffer, message_length);
                  oarc << (char)(1) << ret;
                } catch (std::string& s) {
                  oarc << (char)(0) << s;
                } catch (const char* s) {
                  oarc << (char)(0) << std::string(s);
                } catch (...) {
                  oarc << (char)(0) << std::string("Unknown Runtime Exception");
                }
                shmipc::large_send(*m_shared_memory_server,
                                   oarc.buf,
                                   oarc.off);
                send_buffer = oarc.buf;
                send_buffer_length = oarc.len;
              }
            }
            if (receive_buffer) free(receive_buffer);
            if (send_buffer) free(send_buffer);
            });
      }
      return m_shared_memory_server->get_shared_memory_name();
    } else {
      return "";
    }
  }
} // end of namespace lambda
} // end of namespace graphlab
<|endoftext|>


<commit_before>#include "Config.hpp"
#include "Exception.hpp"
#include "Utility.hpp"
#include <fstream>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QEventLoop>
#include <QUrl>
#include <FAST/Visualization/Window.hpp>
#include <QElapsedTimer>
#include <QStandardPaths>
#include <QDir>
#include <zip/zip.h>

// Includes needed to get path of dynamic library
#ifdef _WIN32
#include <windows.h>
#else
#define __USE_GNU 1
#include <dlfcn.h>
#endif

namespace fast {

		namespace {
			// Initialize global variables, put in anonymous namespace to hide them
			bool mConfigurationLoaded = false;
			std::string mConfigFilename = "";
			std::string mBasePath = "";
			std::string mTestDataPath;
			std::string mKernelSourcePath;
			std::string mKernelBinaryPath;
			std::string mDocumentationPath;
			std::string mPipelinePath;
			std::string mLibraryPath;
			std::string mQtPluginsPath;
			StreamingMode m_streamingMode = STREAMING_MODE_PROCESS_ALL_FRAMES;
		}

		std::string Config::getPath() {
			if (mBasePath != "")
				return mBasePath;
			std::string path = "";
			std::string slash = "/";
			// Find path of the FAST dynamic library
			// The fast_configuration.txt file should lie in the folder below
#ifdef _WIN32
			// http://stackoverflow.com/questions/6924195/get-dll-path-at-runtime
			HMODULE hm = NULL;

			if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
				GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
				(LPCSTR)&getPath,
				&hm)) {
				int ret = GetLastError();
				throw Exception("Error reading dyanmic library address in getPath()");
			}
			char dlpath[MAX_PATH];
			GetModuleFileNameA(hm, dlpath, sizeof(dlpath));
			path = std::string(dlpath);
			path = replace(path, "\\", "/"); // Replace windows \ with /
			path = replace(path, "/FAST.dll", "");
#else
			// http://stackoverflow.com/questions/1681060/library-path-when-dynamically-loaded
			Dl_info dl_info;
			int ret = dladdr((void *)&getPath, &dl_info);
			if (ret == 0)
				throw Exception("Error reading dynamic library address in getPath()");
			const char* dlpath = dl_info.dli_fname;
			path = std::string(dlpath);
			// Remove lib name and lib folder
			int libPos = path.rfind(slash + "lib" + slash);
			path = path.substr(0, libPos) + slash + "bin";
#endif

			path = path + slash; // Make sure there is a slash at the end
			return path;
		}

		void Config::loadConfiguration() {
			if (mConfigurationLoaded)
				return;

			// Set default paths
			// Check if data is located in the FAST folder and if so use that
			if(fileExists(getPath() + "../../data/LICENSE.md")) {
				mTestDataPath = getPath() + "../../data/";
			} else {
#ifdef WIN32
				mTestDataPath = "C:/ProgramData/FAST/data/";
#else
				mTestDataPath = QDir::homePath().toStdString() + "/.FAST/data/";
#endif
			}
#ifdef WIN32
			mKernelBinaryPath = "C:/ProgramData/FAST/kernel_binaries/";
			mPipelinePath = "C:/ProgramData/FAST/pipelines/";
			std::string writeablePath = "C:/ProgramData/FAST/";
			mLibraryPath = getPath();
#else
			mKernelBinaryPath = QDir::homePath().toStdString() + "/.FAST/kernel_binaries/";
			mPipelinePath = QDir::homePath().toStdString() + "/.FAST/pipelines/";
			std::string writeablePath = QDir::homePath().toStdString() + "/.FAST/";
			mLibraryPath = getPath() + "/../lib/";
#endif
			mKernelSourcePath = getPath() + "../../source/FAST/";
			mDocumentationPath = getPath() + "../../doc/";
			mQtPluginsPath = getPath() + "../plugins/";

			createDirectories(mTestDataPath);

			// Copy pipelines (first time only)
			for(auto&& pipeline : getDirectoryList(mPipelinePath)) {
				if(!fileExists(mPipelinePath)) {
					// Copy file from source folder
					std::ifstream  src(mPipelinePath + pipeline, std::ios::binary);
					std::ofstream  dst(writeablePath + "pipelines/" + pipeline, std::ios::binary);

					dst << src.rdbuf();
				}
			}

			// Read and parse configuration file
			// It should reside in the build folder when compiling, and in the root folder when using release
			std::string filename;
			if(mConfigFilename == "") {
				filename = getPath() + "fast_configuration.txt";
			}
			else {
				filename = mConfigFilename;
			}
			std::ifstream file(filename);
			if (!file.is_open()) {
				Reporter::warning() << "Unable to open the configuration file " << filename << ". Using defaults instead." << Reporter::end();
				mConfigurationLoaded = true;
				return;
			}
			Reporter::info() << "Loaded configuration file: " << filename << Reporter::end();

			do {
				std::string line;
				std::getline(file, line);
				trim(line);
				if (line[0] == '#' || line.size() == 0) {
					// Comment or empty line, skip
					continue;
				}
				std::vector<std::string> list = split(line, "=");
				if (list.size() != 2) {
					throw Exception("Error parsing configuration file. Expected key = value pair, got: " + line);
				}

				std::string key = list[0];
				std::string value = list[1];
				trim(key);
				trim(value);

				if (key == "TestDataPath") {
					value = replace(value, "@ROOT@", getPath() + "/../");
					mTestDataPath = value;
				}
				else if (key == "KernelSourcePath") {
					value = replace(value, "@ROOT@", getPath() + "/../");
					mKernelSourcePath = value;
				}
				else if (key == "KernelBinaryPath") {
					value = replace(value, "@ROOT@", writeablePath);
					mKernelBinaryPath = value;
				}
				else if (key == "DocumentationPath") {
					value = replace(value, "@ROOT@", getPath() + "/../");
					mDocumentationPath = value;
				}
				else if (key == "PipelinePath") {
					value = replace(value, "@ROOT@", writeablePath);
					mPipelinePath = value;
				}
				else if (key == "QtPluginsPath") {
					value = replace(value, "@ROOT@", getPath() + "/../");
					mQtPluginsPath = value;
				}
				else if (key == "LibraryPath") {
					value = replace(value, "@ROOT@", getPath() + "/../");
					mLibraryPath = value;
				}
				else {
					throw Exception("Error parsing configuration file. Unrecognized key: " + key);
				}
			} while (!file.eof());
			file.close();

			Reporter::info() << "Test data path: " << mTestDataPath << Reporter::end();
			Reporter::info() << "Kernel source path: " << mKernelSourcePath << Reporter::end();
			Reporter::info() << "Kernel binary path: " << mKernelBinaryPath << Reporter::end();
			Reporter::info() << "Documentation path: " << mDocumentationPath << Reporter::end();
			Reporter::info() << "Pipeline path: " << mPipelinePath << Reporter::end();
			Reporter::info() << "Qt plugins path: " << mQtPluginsPath << Reporter::end();
            Reporter::info() << "Library path: " << mLibraryPath << Reporter::end();

			mConfigurationLoaded = true;
		}

		std::string Config::getTestDataPath() {
			loadConfiguration();
			return mTestDataPath;
		}

		std::string Config::getKernelSourcePath() {
			loadConfiguration();
			return mKernelSourcePath;
		}

		std::string Config::getKernelBinaryPath() {
			loadConfiguration();
			return mKernelBinaryPath;
		}

		std::string Config::getDocumentationPath() {
			loadConfiguration();
			return mDocumentationPath;
		}

		std::string Config::getPipelinePath() {
			loadConfiguration();
			return mPipelinePath;
		}

		std::string Config::getLibraryPath() {
		    loadConfiguration();
		    return mLibraryPath;
		}

		std::string Config::getQtPluginsPath() {
			loadConfiguration();
			return mQtPluginsPath;
		}

		void Config::setConfigFilename(std::string filename) {
			mConfigFilename = filename;
			loadConfiguration();
		}

		void Config::setBasePath(std::string path) {
			mBasePath = path;
			if (mBasePath[mBasePath.size() - 1] != '/')
				mBasePath += "/";
			mTestDataPath = getPath() + "../data/";
			mKernelSourcePath = getPath() + "../source/FAST/";
			mKernelBinaryPath = getPath() + "kernel_binaries/";
			mDocumentationPath = getPath() + "../doc/";
			mPipelinePath = getPath() + "../pipelines/";
			mQtPluginsPath = getPath() + "../plugins/";
#ifdef WIN32
            mLibraryPath = getPath() + "../bin/";
#else
            mLibraryPath = getPath() + "../lib/";
#endif
			loadConfiguration();
		}

		void Config::setTestDataPath(std::string path) {
			mTestDataPath = path;
		}

		void Config::setKernelSourcePath(std::string path) {
			mKernelSourcePath = path;
		}

		void Config::setKernelBinaryPath(std::string path) {
			mKernelBinaryPath = path;
		}

		void Config::setDocumentationPath(std::string path) {
			mDocumentationPath = path;
		}

		void Config::setPipelinePath(std::string path) {
			mPipelinePath = path;
		}

		void Config::setStreamingMode(StreamingMode mode) {
		    m_streamingMode = mode;
		}

		StreamingMode Config::getStreamingMode() {
		    return m_streamingMode;
		}

		void downloadTestDataIfNotExists(std::string destination, bool force) {
			if(destination.empty())
				destination = Config::getTestDataPath();
			if(!force && fileExists(destination + "/LICENSE.md"))
				return;
			std::cout << "Downloading test data (~2GB) to " << destination << std::endl;
			createDirectories(destination);
			std::cout << "Progress: " << std::endl;
			Window::initializeQtApp();
			QNetworkAccessManager manager;
			QUrl url("http://fast.eriksmistad.no/download/FAST_Test_Data_install.zip");
			QNetworkRequest request(url);
			auto timer = new QElapsedTimer;
			timer->start();
			auto reply = manager.get(request);
			int step = 5;
			int progress = step;
			QObject::connect(reply, &QNetworkReply::downloadProgress, [&progress, timer, step](quint64 current, quint64 max) {
				int percent = ((float)current / max) * 100;
				float speed = ((float)timer->elapsed() / 1000.0f)/percent;
				uint64_t remaining = speed * (100 - percent);
				if(percent >= progress) {
					std::cout << percent << "% - ETA ~" << (int)std::ceil((float)remaining / 60) << " minutes. " << std::endl;;
					progress += step;
				}
			});
			auto tempLocation = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
			QFile file(tempLocation + "FAST_Test_Data.zip");
			if(!file.open(QIODevice::WriteOnly)) {
				throw Exception("Could not write to " + tempLocation.toStdString());
			}
			QObject::connect(reply, &QNetworkReply::readyRead, [&reply, &file]() {
				file.write(reply->read(reply->bytesAvailable()));
			});
			QObject::connect(&manager, &QNetworkAccessManager::finished, [reply, &file, destination]() {
				std::cout << "Finished downloading file. Processing.." << std::endl;
				file.close();
				std::cout << "Unzipping the data file.." << std::endl;
				zip_extract(file.fileName().toStdString().c_str(), (destination + "/../../").c_str(), nullptr, nullptr);
				file.remove();
				std::cout << "Done." << std::endl;
			});

			auto eventLoop = new QEventLoop(&manager);

			// Make sure to quit the event loop when download is finished
			QObject::connect(&manager, &QNetworkAccessManager::finished, eventLoop, &QEventLoop::quit);

			// Wait for it to finish
			eventLoop->exec();

		}

}; // end namespace fast
<commit_msg>fixed pipeline directory not exist error and downloadTestData for linux<commit_after>#include "Config.hpp"
#include "Exception.hpp"
#include "Utility.hpp"
#include <fstream>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QEventLoop>
#include <QUrl>
#include <FAST/Visualization/Window.hpp>
#include <QElapsedTimer>
#include <QStandardPaths>
#include <QDir>
#include <zip/zip.h>

// Includes needed to get path of dynamic library
#ifdef _WIN32
#include <windows.h>
#else
#define __USE_GNU 1
#include <dlfcn.h>
#endif

namespace fast {

		namespace {
			// Initialize global variables, put in anonymous namespace to hide them
			bool mConfigurationLoaded = false;
			std::string mConfigFilename = "";
			std::string mBasePath = "";
			std::string mTestDataPath;
			std::string mKernelSourcePath;
			std::string mKernelBinaryPath;
			std::string mDocumentationPath;
			std::string mPipelinePath;
			std::string mLibraryPath;
			std::string mQtPluginsPath;
			StreamingMode m_streamingMode = STREAMING_MODE_PROCESS_ALL_FRAMES;
		}

		std::string Config::getPath() {
			if (mBasePath != "")
				return mBasePath;
			std::string path = "";
			std::string slash = "/";
			// Find path of the FAST dynamic library
			// The fast_configuration.txt file should lie in the folder below
#ifdef _WIN32
			// http://stackoverflow.com/questions/6924195/get-dll-path-at-runtime
			HMODULE hm = NULL;

			if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
				GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
				(LPCSTR)&getPath,
				&hm)) {
				int ret = GetLastError();
				throw Exception("Error reading dyanmic library address in getPath()");
			}
			char dlpath[MAX_PATH];
			GetModuleFileNameA(hm, dlpath, sizeof(dlpath));
			path = std::string(dlpath);
			path = replace(path, "\\", "/"); // Replace windows \ with /
			path = replace(path, "/FAST.dll", "");
#else
			// http://stackoverflow.com/questions/1681060/library-path-when-dynamically-loaded
			Dl_info dl_info;
			int ret = dladdr((void *)&getPath, &dl_info);
			if (ret == 0)
				throw Exception("Error reading dynamic library address in getPath()");
			const char* dlpath = dl_info.dli_fname;
			path = std::string(dlpath);
			// Remove lib name and lib folder
			int libPos = path.rfind(slash + "lib" + slash);
			path = path.substr(0, libPos) + slash + "bin";
#endif

			path = path + slash; // Make sure there is a slash at the end
			return path;
		}

		void Config::loadConfiguration() {
			if (mConfigurationLoaded)
				return;

			// Set default paths
			// Check if data is located in the FAST folder and if so use that
			if(fileExists(getPath() + "../../data/LICENSE.md")) {
				mTestDataPath = getPath() + "../../data/";
			} else {
#ifdef WIN32
				mTestDataPath = "C:/ProgramData/FAST/data/";
#else
				mTestDataPath = QDir::homePath().toStdString() + "/.FAST/data/";
#endif
			}
#ifdef WIN32
			mKernelBinaryPath = "C:/ProgramData/FAST/kernel_binaries/";
			mPipelinePath = "C:/ProgramData/FAST/pipelines/";
			std::string writeablePath = "C:/ProgramData/FAST/";
			mLibraryPath = getPath();
#else
			mKernelBinaryPath = QDir::homePath().toStdString() + "/.FAST/kernel_binaries/";
			mPipelinePath = QDir::homePath().toStdString() + "/.FAST/pipelines/";
			std::string writeablePath = QDir::homePath().toStdString() + "/.FAST/";
			mLibraryPath = getPath() + "/../lib/";
#endif
			mKernelSourcePath = getPath() + "../../source/FAST/";
			mDocumentationPath = getPath() + "../../doc/";
			mQtPluginsPath = getPath() + "../plugins/";

			createDirectories(mTestDataPath);

			/*
			// Copy pipelines (first time only)
			for(auto&& pipeline : getDirectoryList(mPipelinePath)) {
				if(!fileExists(mPipelinePath)) {
					// Copy file from source folder
					std::ifstream  src(mPipelinePath + pipeline, std::ios::binary);
					std::ofstream  dst(writeablePath + "pipelines/" + pipeline, std::ios::binary);

					dst << src.rdbuf();
				}
			}
			*/

			// Read and parse configuration file
			// It should reside in the build folder when compiling, and in the root folder when using release
			std::string filename;
			if(mConfigFilename == "") {
				filename = getPath() + "fast_configuration.txt";
			}
			else {
				filename = mConfigFilename;
			}
			std::ifstream file(filename);
			if (!file.is_open()) {
				Reporter::warning() << "Unable to open the configuration file " << filename << ". Using defaults instead." << Reporter::end();
				mConfigurationLoaded = true;
				return;
			}
			Reporter::info() << "Loaded configuration file: " << filename << Reporter::end();

			do {
				std::string line;
				std::getline(file, line);
				trim(line);
				if (line[0] == '#' || line.size() == 0) {
					// Comment or empty line, skip
					continue;
				}
				std::vector<std::string> list = split(line, "=");
				if (list.size() != 2) {
					throw Exception("Error parsing configuration file. Expected key = value pair, got: " + line);
				}

				std::string key = list[0];
				std::string value = list[1];
				trim(key);
				trim(value);

				if (key == "TestDataPath") {
					value = replace(value, "@ROOT@", getPath() + "/../");
					mTestDataPath = value;
				}
				else if (key == "KernelSourcePath") {
					value = replace(value, "@ROOT@", getPath() + "/../");
					mKernelSourcePath = value;
				}
				else if (key == "KernelBinaryPath") {
					value = replace(value, "@ROOT@", writeablePath);
					mKernelBinaryPath = value;
				}
				else if (key == "DocumentationPath") {
					value = replace(value, "@ROOT@", getPath() + "/../");
					mDocumentationPath = value;
				}
				else if (key == "PipelinePath") {
					value = replace(value, "@ROOT@", writeablePath);
					mPipelinePath = value;
				}
				else if (key == "QtPluginsPath") {
					value = replace(value, "@ROOT@", getPath() + "/../");
					mQtPluginsPath = value;
				}
				else if (key == "LibraryPath") {
					value = replace(value, "@ROOT@", getPath() + "/../");
					mLibraryPath = value;
				}
				else {
					throw Exception("Error parsing configuration file. Unrecognized key: " + key);
				}
			} while (!file.eof());
			file.close();

			Reporter::info() << "Test data path: " << mTestDataPath << Reporter::end();
			Reporter::info() << "Kernel source path: " << mKernelSourcePath << Reporter::end();
			Reporter::info() << "Kernel binary path: " << mKernelBinaryPath << Reporter::end();
			Reporter::info() << "Documentation path: " << mDocumentationPath << Reporter::end();
			Reporter::info() << "Pipeline path: " << mPipelinePath << Reporter::end();
			Reporter::info() << "Qt plugins path: " << mQtPluginsPath << Reporter::end();
            Reporter::info() << "Library path: " << mLibraryPath << Reporter::end();

			mConfigurationLoaded = true;
		}

		std::string Config::getTestDataPath() {
			loadConfiguration();
			return mTestDataPath;
		}

		std::string Config::getKernelSourcePath() {
			loadConfiguration();
			return mKernelSourcePath;
		}

		std::string Config::getKernelBinaryPath() {
			loadConfiguration();
			return mKernelBinaryPath;
		}

		std::string Config::getDocumentationPath() {
			loadConfiguration();
			return mDocumentationPath;
		}

		std::string Config::getPipelinePath() {
			loadConfiguration();
			return mPipelinePath;
		}

		std::string Config::getLibraryPath() {
		    loadConfiguration();
		    return mLibraryPath;
		}

		std::string Config::getQtPluginsPath() {
			loadConfiguration();
			return mQtPluginsPath;
		}

		void Config::setConfigFilename(std::string filename) {
			mConfigFilename = filename;
			loadConfiguration();
		}

		void Config::setBasePath(std::string path) {
			mBasePath = path;
			if (mBasePath[mBasePath.size() - 1] != '/')
				mBasePath += "/";
			mTestDataPath = getPath() + "../data/";
			mKernelSourcePath = getPath() + "../source/FAST/";
			mKernelBinaryPath = getPath() + "kernel_binaries/";
			mDocumentationPath = getPath() + "../doc/";
			mPipelinePath = getPath() + "../pipelines/";
			mQtPluginsPath = getPath() + "../plugins/";
#ifdef WIN32
            mLibraryPath = getPath() + "../bin/";
#else
            mLibraryPath = getPath() + "../lib/";
#endif
			loadConfiguration();
		}

		void Config::setTestDataPath(std::string path) {
			mTestDataPath = path;
		}

		void Config::setKernelSourcePath(std::string path) {
			mKernelSourcePath = path;
		}

		void Config::setKernelBinaryPath(std::string path) {
			mKernelBinaryPath = path;
		}

		void Config::setDocumentationPath(std::string path) {
			mDocumentationPath = path;
		}

		void Config::setPipelinePath(std::string path) {
			mPipelinePath = path;
		}

		void Config::setStreamingMode(StreamingMode mode) {
		    m_streamingMode = mode;
		}

		StreamingMode Config::getStreamingMode() {
		    return m_streamingMode;
		}

		void downloadTestDataIfNotExists(std::string destination, bool force) {
			if(destination.empty())
				destination = Config::getTestDataPath();
			if(!force && fileExists(destination + "/LICENSE.md"))
				return;
			std::cout << "Downloading test data (~2GB) to " << destination << std::endl;
			createDirectories(destination);
			std::cout << "Progress: " << std::endl;
			Window::initializeQtApp();
			QNetworkAccessManager manager;
			QUrl url("http://fast.eriksmistad.no/download/FAST_Test_Data.zip");
			QNetworkRequest request(url);
			auto timer = new QElapsedTimer;
			timer->start();
			auto reply = manager.get(request);
			int step = 5;
			int progress = step;
			QObject::connect(reply, &QNetworkReply::downloadProgress, [&progress, timer, step](quint64 current, quint64 max) {
				int percent = ((float)current / max) * 100;
				float speed = ((float)timer->elapsed() / 1000.0f)/percent;
				uint64_t remaining = speed * (100 - percent);
				if(percent >= progress) {
					std::cout << percent << "% - ETA ~" << (int)std::ceil((float)remaining / 60) << " minutes. " << std::endl;;
					progress += step;
				}
			});
			auto tempLocation = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
			QFile file(tempLocation + "/FAST_Test_Data.zip");
			if(!file.open(QIODevice::WriteOnly)) {
				throw Exception("Could not write to " + tempLocation.toStdString());
			}
			QObject::connect(reply, &QNetworkReply::readyRead, [&reply, &file]() {
				file.write(reply->read(reply->bytesAvailable()));
			});
			QObject::connect(&manager, &QNetworkAccessManager::finished, [reply, &file, destination]() {
				std::cout << "Finished downloading file. Processing.." << std::endl;
				file.close();
				std::cout << "Unzipping the data file ..." << std::endl;
				zip_extract(file.fileName().toStdString().c_str(), (destination + "/../").c_str(), nullptr, nullptr);
				file.remove();
				std::cout << "Done." << std::endl;
			});

			auto eventLoop = new QEventLoop(&manager);

			// Make sure to quit the event loop when download is finished
			QObject::connect(&manager, &QNetworkAccessManager::finished, eventLoop, &QEventLoop::quit);

			// Wait for it to finish
			eventLoop->exec();

		}

}; // end namespace fast
<|endoftext|>


<commit_before>
#include <iostream>
#include <stdlib.h>

#include <vector>
#include <queue>

#include "google/protobuf/descriptor.h"

#include "boost/asio.hpp"
#include "boost/chrono.hpp"

#include "boost/thread.hpp"
#include "boost/thread/shared_mutex.hpp"

#include "boost/thread/condition_variable.hpp"

#include "vtrc-server/vtrc-application.h"
#include "vtrc-server/vtrc-listener.h"
#include "vtrc-server/vtrc-listener-tcp.h"
#include "vtrc-server/vtrc-listener-local.h"

#include "vtrc-common/vtrc-connection-iface.h"
#include "vtrc-common/vtrc-pool-pair.h"
#include "vtrc-common/vtrc-sizepack-policy.h"
#include "vtrc-common/vtrc-exception.h"

#include "vtrc-common/vtrc-hash-iface.h"

#include "vtrc-common/vtrc-data-queue.h"
#include "vtrc-common/vtrc-condition-queues.h"
#include "vtrc-common/vtrc-rpc-service-wrapper.h"
#include "vtrc-common/vtrc-protocol-layer.h"
#include "vtrc-common/vtrc-call-context.h"
#include "vtrc-common/vtrc-closure-holder.h"
#include "vtrc-common/vtrc-connection-iface.h"
#include "vtrc-common/vtrc-delayed-call.h"
#include "vtrc-common/vtrc-call-keeper.h"

#include "protocol/vtrc-errors.pb.h"
#include "protocol/vtrc-auth.pb.h"
#include "protocol/vtrc-rpc-lowlevel.pb.h"
#include "protocol/vtrc-service.pb.h"

#include "vtrc-memory.h"
#include "vtrc-chrono.h"
#include "vtrc-thread.h"

#include "vtrc-server/vtrc-channels.h"

namespace ba = boost::asio;

using namespace vtrc;

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

void test_send( common::connection_iface *connection,
                vtrc::server::application &app, int count )
{
    common::connection_iface_sptr s(connection->shared_from_this());
    vtrc::shared_ptr<google::protobuf::RpcChannel> ev(
                vtrc::server
                ::channels::unicast
                ::create_event_channel( s, true ));

    if(common::call_context::get( s ))
        const vtrc_rpc::lowlevel_unit *pllu =
            common::call_context::get( s )->get_lowlevel_message( );

//    vtrc_rpc_lowlevel::lowlevel_unit llu;
//    s->get_protocol( ).send_message( llu );

    vtrc_service::internal::Stub ping( ev.get( ));
    vtrc_service::ping_req preq;
    vtrc_service::pong_res pres;

//    for( int i=0; i<100; ++i )
//        ping.ping( NULL, &preq, &pres, NULL );

    try {
        //for( ;; )
        {
//            std::cout << "ping 2 " << vtrc::this_thread::get_id( ) << "\n";
            while( count-- )
                ping.ping( NULL, &preq, &pres, NULL );
        }
    } catch( std::exception const &ex ) {
//        std::cout << "png error " << ex.what( ) << "\n";
    }

}

void call_delayed_test( const boost::system::error_code &err,
                        ::google::protobuf::RpcController* controller,
                        const ::vtrc_rpc::message_info* request,
                        ::vtrc_rpc::message_info* response,
                        ::google::protobuf::Closure* done,
                        unsigned id,
                        common::connection_iface *c_,
                        vtrc::server::application &app_)
{

    common::closure_holder ch(done);
    response->set_message_type( id );

    test_send(c_, app_, 1);
}

void test_keeper_call( const boost::system::error_code &ecode,
                        common::call_keeper_sptr ck,
                       ::vtrc_service::test_message* response,
                       uint64_t id,
                       common::connection_iface *c,
                       vtrc::server::application &app)
{
    response->set_id( id );
    test_send(c, app, 1);
}

class test_impl: public vtrc_service::test_rpc {

    common::connection_iface *c_;
    vtrc::server::application &app_;
    unsigned id_;
    common::delayed_call dc_;

public:

    test_impl( common::connection_iface *c, vtrc::server::application &app )
        :c_(c)
        ,app_(app)
        ,id_(0)
        ,dc_(app_.get_rpc_service( ))
    { }

    void test(::google::protobuf::RpcController* controller,
              const ::vtrc_service::test_message* request,
              ::vtrc_service::test_message* response,
              ::google::protobuf::Closure* done)
    {
//        c_->impersonate( );
//        c_->revert( );

        {
            //common::call_keeper_sptr ck(common::call_keeper::create(c_));
            common::closure_holder ch(done);

            if( (id_++ % 100) == 0 )
                throw std::runtime_error( "oops 10 =)" );

//            dc_.call_from_now( vtrc::bind( test_keeper_call, _1,
//                                ck,
//                                response, id_,
//                                c_, vtrc::ref(app_)),
//                               boost::posix_time::milliseconds( 0 ));

          response->set_id( id_ );
          //std::cout << id_ << "\n";
//        connection_->get_io_service( ).dispatch(
//                    vtrc::bind(test_send, connection_));
//        boost::thread(test_send, connection_).detach( );
          test_send(c_, app_, 5);
        }
    }

    virtual void test2(::google::protobuf::RpcController* controller,
                         const ::vtrc_service::test_message* request,
                         ::vtrc_service::test_message* response,
                         ::google::protobuf::Closure* done)
    {
        common::closure_holder ch(done);

        const vtrc::common::call_context *cc =
                    vtrc::common::call_context::get( c_ );

//        std::cout << "test 2 " << vtrc::this_thread::get_id( ) << "\n\n";

//        std::cout << std::setw(8) << id_ << " stack: ";
//        while (cc) {
//            std::cout << cc->get_lowlevel_message( )->call( ).method_id( )
//                      << " <- ";
//            cc = cc->next( );
//        }
//        std::cout << "\n";
    }
};

class main_app: public vtrc::server::application
{

public:

    main_app( common::pool_pair &pp )
        :application(pp)
    { }

    void attach_listener( vtrc::shared_ptr<server::listener> nl )
    {
        nl->get_on_start( ).connect(
                vtrc::bind(&main_app::on_endpoint_started, this, nl.get( )));
        nl->get_on_stop( ).connect(
                vtrc::bind(&main_app::on_endpoint_stopped, this, nl.get( )));

        nl->get_on_new_connection( ).connect(
                vtrc::bind(&main_app::on_new_connection, this, _1, nl.get( )));

        nl->get_on_stop_connection( ).connect(
                vtrc::bind(&main_app::on_stop_connection, this, _1, nl.get( )));
    }

private:

    void on_new_connection( const common::connection_iface *c,
                            vtrc::server::listener *ep)
    {
        std::cout << "new connection: ep = " << ep->name( )
                  << "; count: "  << ep->clients_count( )
                  << "; c = " << c->name( ) << "\n";
    }

    void on_stop_connection( const common::connection_iface *c,
                             vtrc::server::listener *ep )
    {
        std::cout << "stop connection: ep = " << ep->name( )
                  << "; count: "  << ep->clients_count( )
                  << "; c = " << c->name( ) << "\n";
    }

    void on_endpoint_started( vtrc::server::listener *ep )
    {
        std::cout << "Start endpoint: " << ep->name( ) << "\n";
    }

    void on_endpoint_stopped( vtrc::server::listener *ep )
    {
        std::cout << "Stop endpoint: " << ep->name( ) << "\n";
    }

    std::string get_session_key( vtrc::common::connection_iface *connection,
                                 const std::string &id)
    {
        return "1234";
    }

    vtrc::common::rpc_service_wrapper_sptr get_service_by_name(
                                    vtrc::common::connection_iface *connection,
                                    const std::string &service_name)
    {
        if( service_name == test_impl::descriptor( )->full_name( ) ) {
            return common::rpc_service_wrapper_sptr(
                        new common::rpc_service_wrapper(
                                new test_impl(connection, *this) ) );
        }

        return common::rpc_service_wrapper_sptr( );
    }

};

int main( ) try {

    common::pool_pair pp(1, 1);
    main_app app(pp);

    vtrc::shared_ptr<vtrc::server::listener> tcp4_ep
            (vtrc::server::listeners::tcp::create(app, "0.0.0.0", 44667, true ));

    vtrc::shared_ptr<vtrc::server::listener> tcp6_ep
            (vtrc::server::listeners::tcp::create(app, "::", 44668, true));

#ifndef _WIN32

    std::string file_name("/tmp/test.socket");

    ::unlink( file_name.c_str( ) );
#else
    std::string file_name("\\\\.\\pipe\\test_pipe");

#endif

    vtrc::shared_ptr<vtrc::server::listener> local_listen
            (vtrc::server::listeners::local::create(app, file_name));

    ::chmod(file_name.c_str( ), 0xFFFFFF );

    app.attach_listener( tcp4_ep );
    app.attach_listener( tcp6_ep );
    app.attach_listener( local_listen );

    local_listen->start( );
    tcp4_ep->start( );
    tcp6_ep->start( );

    vtrc::this_thread::sleep_for( vtrc::chrono::seconds( 10999999 ) );

    std::cout << "Stoppped. Wait ... \n";

    local_listen->stop( );
    tcp4_ep->stop( );
    tcp6_ep->stop( );

    app.stop_all_clients( );

    std::cout << "Stoppped. Wait ... \n";

    pp.stop_all( );
    pp.join_all( );

    google::protobuf::ShutdownProtobufLibrary( );

    return 0;

} catch( const std::exception &ex ) {

    google::protobuf::ShutdownProtobufLibrary( );
    std::cout << "general error: " << ex.what( ) << "\n";
    return 0;
}

//////////

<commit_msg>local listener<commit_after>
#include <iostream>
#include <stdlib.h>

#include <vector>
#include <queue>

#include "google/protobuf/descriptor.h"

#include "boost/asio.hpp"
#include "boost/chrono.hpp"

#include "boost/thread.hpp"
#include "boost/thread/shared_mutex.hpp"

#include "boost/thread/condition_variable.hpp"

#include "vtrc-server/vtrc-application.h"
#include "vtrc-server/vtrc-listener.h"
#include "vtrc-server/vtrc-listener-tcp.h"
#include "vtrc-server/vtrc-listener-local.h"

#include "vtrc-common/vtrc-connection-iface.h"
#include "vtrc-common/vtrc-pool-pair.h"
#include "vtrc-common/vtrc-sizepack-policy.h"
#include "vtrc-common/vtrc-exception.h"

#include "vtrc-common/vtrc-hash-iface.h"

#include "vtrc-common/vtrc-data-queue.h"
#include "vtrc-common/vtrc-condition-queues.h"
#include "vtrc-common/vtrc-rpc-service-wrapper.h"
#include "vtrc-common/vtrc-protocol-layer.h"
#include "vtrc-common/vtrc-call-context.h"
#include "vtrc-common/vtrc-closure-holder.h"
#include "vtrc-common/vtrc-connection-iface.h"
#include "vtrc-common/vtrc-delayed-call.h"
#include "vtrc-common/vtrc-call-keeper.h"

#include "protocol/vtrc-errors.pb.h"
#include "protocol/vtrc-auth.pb.h"
#include "protocol/vtrc-rpc-lowlevel.pb.h"
#include "protocol/vtrc-service.pb.h"

#include "vtrc-memory.h"
#include "vtrc-chrono.h"
#include "vtrc-thread.h"

#include "vtrc-server/vtrc-channels.h"

namespace ba = boost::asio;

using namespace vtrc;

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

void test_send( common::connection_iface *connection,
                vtrc::server::application &app, int count )
{
    common::connection_iface_sptr s(connection->shared_from_this());
    vtrc::shared_ptr<google::protobuf::RpcChannel> ev(
                vtrc::server
                ::channels::unicast
                ::create_event_channel( s, true ));

    if(common::call_context::get( s ))
        const vtrc_rpc::lowlevel_unit *pllu =
            common::call_context::get( s )->get_lowlevel_message( );

//    vtrc_rpc_lowlevel::lowlevel_unit llu;
//    s->get_protocol( ).send_message( llu );

    vtrc_service::internal::Stub ping( ev.get( ));
    vtrc_service::ping_req preq;
    vtrc_service::pong_res pres;

//    for( int i=0; i<100; ++i )
//        ping.ping( NULL, &preq, &pres, NULL );

    try {
        //for( ;; )
        {
//            std::cout << "ping 2 " << vtrc::this_thread::get_id( ) << "\n";
            while( count-- )
                ping.ping( NULL, &preq, &pres, NULL );
        }
    } catch( std::exception const &ex ) {
//        std::cout << "png error " << ex.what( ) << "\n";
    }

}

void call_delayed_test( const boost::system::error_code &err,
                        ::google::protobuf::RpcController* controller,
                        const ::vtrc_rpc::message_info* request,
                        ::vtrc_rpc::message_info* response,
                        ::google::protobuf::Closure* done,
                        unsigned id,
                        common::connection_iface *c_,
                        vtrc::server::application &app_)
{

    common::closure_holder ch(done);
    response->set_message_type( id );

    test_send(c_, app_, 1);
}

void test_keeper_call( const boost::system::error_code &ecode,
                        common::call_keeper_sptr ck,
                       ::vtrc_service::test_message* response,
                       uint64_t id,
                       common::connection_iface *c,
                       vtrc::server::application &app)
{
    response->set_id( id );
    test_send(c, app, 1);
}

class test_impl: public vtrc_service::test_rpc {

    common::connection_iface *c_;
    vtrc::server::application &app_;
    unsigned id_;
    common::delayed_call dc_;

public:

    test_impl( common::connection_iface *c, vtrc::server::application &app )
        :c_(c)
        ,app_(app)
        ,id_(0)
        ,dc_(app_.get_rpc_service( ))
    { }

    void test(::google::protobuf::RpcController* controller,
              const ::vtrc_service::test_message* request,
              ::vtrc_service::test_message* response,
              ::google::protobuf::Closure* done)
    {
//        c_->impersonate( );
//        c_->revert( );

        {
            //common::call_keeper_sptr ck(common::call_keeper::create(c_));
            common::closure_holder ch(done);

            if( (id_++ % 100) == 0 )
                throw std::runtime_error( "oops 10 =)" );

//            dc_.call_from_now( vtrc::bind( test_keeper_call, _1,
//                                ck,
//                                response, id_,
//                                c_, vtrc::ref(app_)),
//                               boost::posix_time::milliseconds( 0 ));

          response->set_id( id_ );
          //std::cout << id_ << "\n";
//        connection_->get_io_service( ).dispatch(
//                    vtrc::bind(test_send, connection_));
//        boost::thread(test_send, connection_).detach( );
          test_send(c_, app_, 5);
        }
    }

    virtual void test2(::google::protobuf::RpcController* controller,
                         const ::vtrc_service::test_message* request,
                         ::vtrc_service::test_message* response,
                         ::google::protobuf::Closure* done)
    {
        common::closure_holder ch(done);

        const vtrc::common::call_context *cc =
                    vtrc::common::call_context::get( c_ );

//        std::cout << "test 2 " << vtrc::this_thread::get_id( ) << "\n\n";

//        std::cout << std::setw(8) << id_ << " stack: ";
//        while (cc) {
//            std::cout << cc->get_lowlevel_message( )->call( ).method_id( )
//                      << " <- ";
//            cc = cc->next( );
//        }
//        std::cout << "\n";
    }
};

class main_app: public vtrc::server::application
{

public:

    main_app( common::pool_pair &pp )
        :application(pp)
    { }

    void attach_listener( vtrc::shared_ptr<server::listener> nl )
    {
        nl->get_on_start( ).connect(
                vtrc::bind(&main_app::on_endpoint_started, this, nl.get( )));
        nl->get_on_stop( ).connect(
                vtrc::bind(&main_app::on_endpoint_stopped, this, nl.get( )));

        nl->get_on_new_connection( ).connect(
                vtrc::bind(&main_app::on_new_connection, this, _1, nl.get( )));

        nl->get_on_stop_connection( ).connect(
                vtrc::bind(&main_app::on_stop_connection, this, _1, nl.get( )));
    }

private:

    void on_new_connection( const common::connection_iface *c,
                            vtrc::server::listener *ep)
    {
        std::cout << "new connection: ep = " << ep->name( )
                  << "; count: "  << ep->clients_count( )
                  << "; c = " << c->name( ) << "\n";
    }

    void on_stop_connection( const common::connection_iface *c,
                             vtrc::server::listener *ep )
    {
        std::cout << "stop connection: ep = " << ep->name( )
                  << "; count: "  << ep->clients_count( )
                  << "; c = " << c->name( ) << "\n";
    }

    void on_endpoint_started( vtrc::server::listener *ep )
    {
        std::cout << "Start endpoint: " << ep->name( ) << "\n";
    }

    void on_endpoint_stopped( vtrc::server::listener *ep )
    {
        std::cout << "Stop endpoint: " << ep->name( ) << "\n";
    }

    std::string get_session_key( vtrc::common::connection_iface *connection,
                                 const std::string &id)
    {
        return "1234";
    }

    vtrc::common::rpc_service_wrapper_sptr get_service_by_name(
                                    vtrc::common::connection_iface *connection,
                                    const std::string &service_name)
    {
        if( service_name == test_impl::descriptor( )->full_name( ) ) {
            return common::rpc_service_wrapper_sptr(
                        new common::rpc_service_wrapper(
                                new test_impl(connection, *this) ) );
        }

        return common::rpc_service_wrapper_sptr( );
    }

};

int main( ) try {

    common::pool_pair pp(1, 1);
    main_app app(pp);

    vtrc::shared_ptr<vtrc::server::listener> tcp4_ep
            (vtrc::server::listeners::tcp::create(app, "0.0.0.0", 44667, true ));

    vtrc::shared_ptr<vtrc::server::listener> tcp6_ep
            (vtrc::server::listeners::tcp::create(app, "::", 44668, true));

#ifndef _WIN32

    std::string file_name("/tmp/test.socket");

    ::unlink( file_name.c_str( ) );
#else
    std::string file_name("\\\\.\\pipe\\test_pipe");

#endif

    vtrc::shared_ptr<vtrc::server::listener> local_listen
            (vtrc::server::listeners::local::create(app, file_name));

    app.attach_listener( tcp4_ep );
    app.attach_listener( tcp6_ep );
    app.attach_listener( local_listen );

    local_listen->start( );
    tcp4_ep->start( );
    tcp6_ep->start( );

    vtrc::this_thread::sleep_for( vtrc::chrono::seconds( 10999999 ) );

    std::cout << "Stoppped. Wait ... \n";

    local_listen->stop( );
    tcp4_ep->stop( );
    tcp6_ep->stop( );

    app.stop_all_clients( );

    std::cout << "Stoppped. Wait ... \n";

    pp.stop_all( );
    pp.join_all( );

    google::protobuf::ShutdownProtobufLibrary( );

    return 0;

} catch( const std::exception &ex ) {

    google::protobuf::ShutdownProtobufLibrary( );
    std::cout << "general error: " << ex.what( ) << "\n";
    return 0;
}

//////////

<|endoftext|>