<commit_before>#include <puppet/runtime/values/value.hpp>
#include <puppet/cast.hpp>
#include <boost/functional/hash.hpp>

using namespace std;

namespace puppet { namespace runtime { namespace types {

    type::type(unique_ptr<values::type const> parameter) :
        _parameter(rvalue_cast(parameter))
    {
    }

    type::type(type const& other) :
        _parameter(other.parameter() ? new values::type(*other.parameter()) : nullptr)
    {
    }

    type& type::operator=(type const& other)
    {
        _parameter.reset(other.parameter() ? new values::type(*other.parameter()) : nullptr);
        return *this;
    }

    unique_ptr<values::type const> const& type::parameter() const
    {
        return _parameter;
    }

    char const* type::name()
    {
        return "Type";
    }

    bool type::is_instance(values::value const& value, recursion_guard& guard) const
    {
        auto ptr = value.as<values::type>();
        if (!ptr) {
            return false;
        }
        return !_parameter || _parameter->is_assignable(*ptr, guard);
    }

    bool type::is_assignable(values::type const& other, recursion_guard& guard) const
    {
        auto type = boost::get<types::type>(&other);
        if (!type) {
            return false;
        }
        if (!_parameter) {
            // Any type can be assigned to Type
            return true;
        }
        if (!type->_parameter) {
            // Type cannot assign to Type[T]
            return false;
        }
        return _parameter->is_assignable(*type->_parameter, guard);
    }

    void type::write(ostream& stream, bool expand) const
    {
        stream << types::type::name();
        if (!_parameter) {
            return;
        }
        stream << '[';
        _parameter->write(stream, false);
        stream << ']';
    }

    ostream& operator<<(ostream& os, types::type const& type)
    {
        type.write(os);
        return os;
    }

    bool operator==(type const& left, type const& right)
    {
        if (!left.parameter() && !right.parameter()) {
            return true;
        } else if (left.parameter() || right.parameter()) {
            return false;
        }
        return *left.parameter() == *right.parameter();
    }

    bool operator!=(type const& left, type const& right)
    {
        return !(left == right);
    }

    size_t hash_value(types::type const& type)
    {
        static const size_t name_hash = boost::hash_value(types::type::name());

        size_t seed = 0;
        boost::hash_combine(seed, name_hash);
        if (type.parameter()) {
            boost::hash_combine(seed, *type.parameter());
        }
        return seed;
    }

}}}  // namespace puppet::runtime::types
<commit_msg>(maint) Fix operator== for Type type.<commit_after>#include <puppet/runtime/values/value.hpp>
#include <puppet/cast.hpp>
#include <boost/functional/hash.hpp>

using namespace std;

namespace puppet { namespace runtime { namespace types {

    type::type(unique_ptr<values::type const> parameter) :
        _parameter(rvalue_cast(parameter))
    {
    }

    type::type(type const& other) :
        _parameter(other.parameter() ? new values::type(*other.parameter()) : nullptr)
    {
    }

    type& type::operator=(type const& other)
    {
        _parameter.reset(other.parameter() ? new values::type(*other.parameter()) : nullptr);
        return *this;
    }

    unique_ptr<values::type const> const& type::parameter() const
    {
        return _parameter;
    }

    char const* type::name()
    {
        return "Type";
    }

    bool type::is_instance(values::value const& value, recursion_guard& guard) const
    {
        auto ptr = value.as<values::type>();
        if (!ptr) {
            return false;
        }
        return !_parameter || _parameter->is_assignable(*ptr, guard);
    }

    bool type::is_assignable(values::type const& other, recursion_guard& guard) const
    {
        auto type = boost::get<types::type>(&other);
        if (!type) {
            return false;
        }
        if (!_parameter) {
            // Any type can be assigned to Type
            return true;
        }
        if (!type->_parameter) {
            // Type cannot assign to Type[T]
            return false;
        }
        return _parameter->is_assignable(*type->_parameter, guard);
    }

    void type::write(ostream& stream, bool expand) const
    {
        stream << types::type::name();
        if (!_parameter) {
            return;
        }
        stream << '[';
        _parameter->write(stream, false);
        stream << ']';
    }

    ostream& operator<<(ostream& os, types::type const& type)
    {
        type.write(os);
        return os;
    }

    bool operator==(type const& left, type const& right)
    {
        if (!left.parameter() && !right.parameter()) {
            return true;
        } else if (!left.parameter()) {
            return false;
        } else if (!right.parameter()) {
            return false;
        }
        return *left.parameter() == *right.parameter();
    }

    bool operator!=(type const& left, type const& right)
    {
        return !(left == right);
    }

    size_t hash_value(types::type const& type)
    {
        static const size_t name_hash = boost::hash_value(types::type::name());

        size_t seed = 0;
        boost::hash_combine(seed, name_hash);
        if (type.parameter()) {
            boost::hash_combine(seed, *type.parameter());
        }
        return seed;
    }

}}}  // namespace puppet::runtime::types
<|endoftext|>


<commit_before>#include "Destination.h"
#include "Identity.h"
#include "ClientContext.h"
#include "I2PService.h"
#include <boost/asio/error.hpp>

namespace i2p
{
namespace client
{
	static const i2p::data::SigningKeyType I2P_SERVICE_DEFAULT_KEY_TYPE = i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256;

	I2PService::I2PService (std::shared_ptr<ClientDestination> localDestination):
		m_LocalDestination (localDestination ? localDestination :
			i2p::client::context.CreateNewLocalDestination (false, I2P_SERVICE_DEFAULT_KEY_TYPE)),
			m_ReadyTimer(m_LocalDestination->GetService()),
			m_ReadyTimerTriggered(false),
			m_ConnectTimeout(0),
			isUpdated (true)
	{
		m_LocalDestination->Acquire ();
	}

	I2PService::I2PService (i2p::data::SigningKeyType kt):
		m_LocalDestination (i2p::client::context.CreateNewLocalDestination (false, kt)),
		m_ReadyTimer(m_LocalDestination->GetService()),
		m_ConnectTimeout(0),
		isUpdated (true)
	{
		m_LocalDestination->Acquire ();
	}

	I2PService::~I2PService ()
	{
		ClearHandlers ();
		if (m_LocalDestination) m_LocalDestination->Release ();
	}

	void I2PService::ClearHandlers ()
	{
		if(m_ConnectTimeout)
			m_ReadyTimer.cancel();
		std::unique_lock<std::mutex> l(m_HandlersMutex);
		for (auto it: m_Handlers)
			it->Terminate ();
		m_Handlers.clear();
	}

	void I2PService::SetConnectTimeout(uint32_t timeout)
	{
		m_ConnectTimeout = timeout;
	}

	void I2PService::AddReadyCallback(ReadyCallback cb)
	{
		uint32_t now = i2p::util::GetSecondsSinceEpoch();
		uint32_t tm = (m_ConnectTimeout) ? now + m_ConnectTimeout : NEVER_TIMES_OUT;

		LogPrint(eLogDebug, "I2PService::AddReadyCallback() ", tm, " ", now);
		m_ReadyCallbacks.push_back({cb, tm});
		if (!m_ReadyTimerTriggered) TriggerReadyCheckTimer();
	}

	void I2PService::TriggerReadyCheckTimer()
	{
		m_ReadyTimer.expires_from_now(boost::posix_time::seconds (1));
		m_ReadyTimer.async_wait(std::bind(&I2PService::HandleReadyCheckTimer, this, std::placeholders::_1));
		m_ReadyTimerTriggered = true;

	}

	void I2PService::HandleReadyCheckTimer(const boost::system::error_code &ec)
	{
		if(ec || m_LocalDestination->IsReady())
		{
			for(auto & itr : m_ReadyCallbacks)
				itr.first(ec);
			m_ReadyCallbacks.clear();
		}
		else if(!m_LocalDestination->IsReady())
		{
			// expire timed out requests
			uint32_t now = i2p::util::GetSecondsSinceEpoch ();
			auto itr = m_ReadyCallbacks.begin();
			while(itr != m_ReadyCallbacks.end())
			{
			    if(itr->second != NEVER_TIMES_OUT && now >= itr->second)
				{
					itr->first(boost::asio::error::timed_out);
					itr = m_ReadyCallbacks.erase(itr);
				}
				else
					++itr;
			}
		}
		if(!ec && m_ReadyCallbacks.size())
		    TriggerReadyCheckTimer();
		else
		    m_ReadyTimerTriggered = false;
	}

	void I2PService::CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, int port) {
		assert(streamRequestComplete);
		i2p::data::IdentHash identHash;
		if (i2p::client::context.GetAddressBook ().GetIdentHash (dest, identHash))
			CreateStream(streamRequestComplete, identHash, port);
		else
		{
			LogPrint (eLogWarning, "I2PService: Remote destination not found: ", dest);
			streamRequestComplete (nullptr);
		}
	}

	void I2PService::CreateStream(StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash & identHash, int port)
	{
		if(m_ConnectTimeout)
		{
			if(m_LocalDestination->IsReady())
				m_LocalDestination->CreateStream (streamRequestComplete, identHash, port);
			else
			{
				AddReadyCallback([this, streamRequestComplete, identHash, port] (const boost::system::error_code & ec) {
						if(ec)
						{
							LogPrint(eLogWarning, "I2PService::CeateStream() ", ec.message());
							streamRequestComplete(nullptr);
						}
						else
							this->m_LocalDestination->CreateStream(streamRequestComplete, identHash, port);
					});
			}
		}
		else
			m_LocalDestination->CreateStream(streamRequestComplete, identHash, port);
	}

	TCPIPPipe::TCPIPPipe(I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> upstream, std::shared_ptr<boost::asio::ip::tcp::socket> downstream) : I2PServiceHandler(owner), m_up(upstream), m_down(downstream)
	{
		boost::asio::socket_base::receive_buffer_size option(TCP_IP_PIPE_BUFFER_SIZE);
		upstream->set_option(option);
		downstream->set_option(option);
	}

	TCPIPPipe::~TCPIPPipe()
	{
		Terminate();
	}

	void TCPIPPipe::Start()
	{
		AsyncReceiveUpstream();
		AsyncReceiveDownstream();
	}

	void TCPIPPipe::Terminate()
	{
		if(Kill()) return;
		if (m_up)
		{
			if (m_up->is_open())
				m_up->close();
			m_up = nullptr;
		}
		if (m_down)
		{
			if (m_down->is_open())
				m_down->close();
			m_down = nullptr;
		}
		Done(shared_from_this());
	}

	void TCPIPPipe::AsyncReceiveUpstream()
	{
		if (m_up)
		{
			m_up->async_read_some(boost::asio::buffer(m_upstream_to_down_buf, TCP_IP_PIPE_BUFFER_SIZE),
				std::bind(&TCPIPPipe::HandleUpstreamReceived, shared_from_this(),
				std::placeholders::_1, std::placeholders::_2));
		}
		else
			LogPrint(eLogError, "TCPIPPipe: upstream receive: no socket");
	}

	void TCPIPPipe::AsyncReceiveDownstream()
	{
		if (m_down) {
			m_down->async_read_some(boost::asio::buffer(m_downstream_to_up_buf, TCP_IP_PIPE_BUFFER_SIZE),
				std::bind(&TCPIPPipe::HandleDownstreamReceived, shared_from_this(),
				std::placeholders::_1, std::placeholders::_2));
		}
		else
			LogPrint(eLogError, "TCPIPPipe: downstream receive: no socket");
	}

	void TCPIPPipe::UpstreamWrite(size_t len)
	{
		if (m_up)
		{
			LogPrint(eLogDebug, "TCPIPPipe: upstream: ", (int) len, " bytes written");
			boost::asio::async_write(*m_up, boost::asio::buffer(m_upstream_buf, len),
				boost::asio::transfer_all(),
				std::bind(&TCPIPPipe::HandleUpstreamWrite,
				shared_from_this(),
				std::placeholders::_1));
		}
		else
			LogPrint(eLogError, "TCPIPPipe: upstream write: no socket");
	}

	void TCPIPPipe::DownstreamWrite(size_t len)
	{
		if (m_down)
		{
			LogPrint(eLogDebug, "TCPIPPipe: downstream: ", (int) len, " bytes written");
			boost::asio::async_write(*m_down, boost::asio::buffer(m_downstream_buf, len),
				boost::asio::transfer_all(),
				std::bind(&TCPIPPipe::HandleDownstreamWrite,
				shared_from_this(),
				std::placeholders::_1));
		}
		else
			LogPrint(eLogError, "TCPIPPipe: downstream write: no socket");
	}

	void TCPIPPipe::HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered)
	{
		LogPrint(eLogDebug, "TCPIPPipe: downstream: ", (int) bytes_transfered, " bytes received");
		if (ecode)
		{
			LogPrint(eLogError, "TCPIPPipe: downstream read error:" , ecode.message());
			if (ecode != boost::asio::error::operation_aborted)
				Terminate();
		} else {
			if (bytes_transfered > 0 )
				memcpy(m_upstream_buf, m_downstream_to_up_buf, bytes_transfered);
			UpstreamWrite(bytes_transfered);
		}
	}

	void TCPIPPipe::HandleDownstreamWrite(const boost::system::error_code & ecode) {
		if (ecode)
		{
			LogPrint(eLogError, "TCPIPPipe: downstream write error:" , ecode.message());
			if (ecode != boost::asio::error::operation_aborted)
				Terminate();
		}
		else
			AsyncReceiveUpstream();
	}

	void TCPIPPipe::HandleUpstreamWrite(const boost::system::error_code & ecode) {
		if (ecode)
		{
			LogPrint(eLogError, "TCPIPPipe: upstream write error:" , ecode.message());
			if (ecode != boost::asio::error::operation_aborted)
				Terminate();
		}
		else
			AsyncReceiveDownstream();
	}

	void TCPIPPipe::HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered)
	{
		LogPrint(eLogDebug, "TCPIPPipe: upstream ", (int)bytes_transfered, " bytes received");
		if (ecode)
		{
			LogPrint(eLogError, "TCPIPPipe: upstream read error:" , ecode.message());
			if (ecode != boost::asio::error::operation_aborted)
				Terminate();
		} else {
			if (bytes_transfered > 0 )
				memcpy(m_downstream_buf, m_upstream_to_down_buf, bytes_transfered);
			DownstreamWrite(bytes_transfered);
		}
	}

	void TCPIPAcceptor::Start ()
	{
		m_Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService (), m_LocalEndpoint));
		//update the local end point in case port has been set zero and got updated now
		m_LocalEndpoint = m_Acceptor->local_endpoint();
		m_Acceptor->listen ();
		Accept ();
	}

	void TCPIPAcceptor::Stop ()
	{
		if (m_Acceptor)
		{
			m_Acceptor->close();
			m_Acceptor.reset (nullptr);
		}
		m_Timer.cancel ();
		ClearHandlers();
	}

	void TCPIPAcceptor::Accept ()
	{
		auto newSocket = std::make_shared<boost::asio::ip::tcp::socket> (GetService ());
		m_Acceptor->async_accept (*newSocket, std::bind (&TCPIPAcceptor::HandleAccept, this,
			std::placeholders::_1, newSocket));
	}

	void TCPIPAcceptor::HandleAccept (const boost::system::error_code& ecode, std::shared_ptr<boost::asio::ip::tcp::socket> socket)
	{
		if (!ecode)
		{
			LogPrint(eLogDebug, "I2PService: ", GetName(), " accepted");
			auto handler = CreateHandler(socket);
			if (handler)
			{
				AddHandler(handler);
				handler->Handle();
			}
			else
				socket->close();
			Accept();
		}
		else
		{
			if (ecode != boost::asio::error::operation_aborted)
				LogPrint (eLogError, "I2PService: ", GetName(), " closing socket on accept because: ", ecode.message ());
		}
	}
}
}
<commit_msg>EdDSA signatures by default<commit_after>#include "Destination.h"
#include "Identity.h"
#include "ClientContext.h"
#include "I2PService.h"
#include <boost/asio/error.hpp>

namespace i2p
{
namespace client
{
	static const i2p::data::SigningKeyType I2P_SERVICE_DEFAULT_KEY_TYPE = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519;

	I2PService::I2PService (std::shared_ptr<ClientDestination> localDestination):
		m_LocalDestination (localDestination ? localDestination :
			i2p::client::context.CreateNewLocalDestination (false, I2P_SERVICE_DEFAULT_KEY_TYPE)),
			m_ReadyTimer(m_LocalDestination->GetService()),
			m_ReadyTimerTriggered(false),
			m_ConnectTimeout(0),
			isUpdated (true)
	{
		m_LocalDestination->Acquire ();
	}

	I2PService::I2PService (i2p::data::SigningKeyType kt):
		m_LocalDestination (i2p::client::context.CreateNewLocalDestination (false, kt)),
		m_ReadyTimer(m_LocalDestination->GetService()),
		m_ConnectTimeout(0),
		isUpdated (true)
	{
		m_LocalDestination->Acquire ();
	}

	I2PService::~I2PService ()
	{
		ClearHandlers ();
		if (m_LocalDestination) m_LocalDestination->Release ();
	}

	void I2PService::ClearHandlers ()
	{
		if(m_ConnectTimeout)
			m_ReadyTimer.cancel();
		std::unique_lock<std::mutex> l(m_HandlersMutex);
		for (auto it: m_Handlers)
			it->Terminate ();
		m_Handlers.clear();
	}

	void I2PService::SetConnectTimeout(uint32_t timeout)
	{
		m_ConnectTimeout = timeout;
	}

	void I2PService::AddReadyCallback(ReadyCallback cb)
	{
		uint32_t now = i2p::util::GetSecondsSinceEpoch();
		uint32_t tm = (m_ConnectTimeout) ? now + m_ConnectTimeout : NEVER_TIMES_OUT;

		LogPrint(eLogDebug, "I2PService::AddReadyCallback() ", tm, " ", now);
		m_ReadyCallbacks.push_back({cb, tm});
		if (!m_ReadyTimerTriggered) TriggerReadyCheckTimer();
	}

	void I2PService::TriggerReadyCheckTimer()
	{
		m_ReadyTimer.expires_from_now(boost::posix_time::seconds (1));
		m_ReadyTimer.async_wait(std::bind(&I2PService::HandleReadyCheckTimer, this, std::placeholders::_1));
		m_ReadyTimerTriggered = true;

	}

	void I2PService::HandleReadyCheckTimer(const boost::system::error_code &ec)
	{
		if(ec || m_LocalDestination->IsReady())
		{
			for(auto & itr : m_ReadyCallbacks)
				itr.first(ec);
			m_ReadyCallbacks.clear();
		}
		else if(!m_LocalDestination->IsReady())
		{
			// expire timed out requests
			uint32_t now = i2p::util::GetSecondsSinceEpoch ();
			auto itr = m_ReadyCallbacks.begin();
			while(itr != m_ReadyCallbacks.end())
			{
			    if(itr->second != NEVER_TIMES_OUT && now >= itr->second)
				{
					itr->first(boost::asio::error::timed_out);
					itr = m_ReadyCallbacks.erase(itr);
				}
				else
					++itr;
			}
		}
		if(!ec && m_ReadyCallbacks.size())
		    TriggerReadyCheckTimer();
		else
		    m_ReadyTimerTriggered = false;
	}

	void I2PService::CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, int port) {
		assert(streamRequestComplete);
		i2p::data::IdentHash identHash;
		if (i2p::client::context.GetAddressBook ().GetIdentHash (dest, identHash))
			CreateStream(streamRequestComplete, identHash, port);
		else
		{
			LogPrint (eLogWarning, "I2PService: Remote destination not found: ", dest);
			streamRequestComplete (nullptr);
		}
	}

	void I2PService::CreateStream(StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash & identHash, int port)
	{
		if(m_ConnectTimeout)
		{
			if(m_LocalDestination->IsReady())
				m_LocalDestination->CreateStream (streamRequestComplete, identHash, port);
			else
			{
				AddReadyCallback([this, streamRequestComplete, identHash, port] (const boost::system::error_code & ec) {
						if(ec)
						{
							LogPrint(eLogWarning, "I2PService::CeateStream() ", ec.message());
							streamRequestComplete(nullptr);
						}
						else
							this->m_LocalDestination->CreateStream(streamRequestComplete, identHash, port);
					});
			}
		}
		else
			m_LocalDestination->CreateStream(streamRequestComplete, identHash, port);
	}

	TCPIPPipe::TCPIPPipe(I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> upstream, std::shared_ptr<boost::asio::ip::tcp::socket> downstream) : I2PServiceHandler(owner), m_up(upstream), m_down(downstream)
	{
		boost::asio::socket_base::receive_buffer_size option(TCP_IP_PIPE_BUFFER_SIZE);
		upstream->set_option(option);
		downstream->set_option(option);
	}

	TCPIPPipe::~TCPIPPipe()
	{
		Terminate();
	}

	void TCPIPPipe::Start()
	{
		AsyncReceiveUpstream();
		AsyncReceiveDownstream();
	}

	void TCPIPPipe::Terminate()
	{
		if(Kill()) return;
		if (m_up)
		{
			if (m_up->is_open())
				m_up->close();
			m_up = nullptr;
		}
		if (m_down)
		{
			if (m_down->is_open())
				m_down->close();
			m_down = nullptr;
		}
		Done(shared_from_this());
	}

	void TCPIPPipe::AsyncReceiveUpstream()
	{
		if (m_up)
		{
			m_up->async_read_some(boost::asio::buffer(m_upstream_to_down_buf, TCP_IP_PIPE_BUFFER_SIZE),
				std::bind(&TCPIPPipe::HandleUpstreamReceived, shared_from_this(),
				std::placeholders::_1, std::placeholders::_2));
		}
		else
			LogPrint(eLogError, "TCPIPPipe: upstream receive: no socket");
	}

	void TCPIPPipe::AsyncReceiveDownstream()
	{
		if (m_down) {
			m_down->async_read_some(boost::asio::buffer(m_downstream_to_up_buf, TCP_IP_PIPE_BUFFER_SIZE),
				std::bind(&TCPIPPipe::HandleDownstreamReceived, shared_from_this(),
				std::placeholders::_1, std::placeholders::_2));
		}
		else
			LogPrint(eLogError, "TCPIPPipe: downstream receive: no socket");
	}

	void TCPIPPipe::UpstreamWrite(size_t len)
	{
		if (m_up)
		{
			LogPrint(eLogDebug, "TCPIPPipe: upstream: ", (int) len, " bytes written");
			boost::asio::async_write(*m_up, boost::asio::buffer(m_upstream_buf, len),
				boost::asio::transfer_all(),
				std::bind(&TCPIPPipe::HandleUpstreamWrite,
				shared_from_this(),
				std::placeholders::_1));
		}
		else
			LogPrint(eLogError, "TCPIPPipe: upstream write: no socket");
	}

	void TCPIPPipe::DownstreamWrite(size_t len)
	{
		if (m_down)
		{
			LogPrint(eLogDebug, "TCPIPPipe: downstream: ", (int) len, " bytes written");
			boost::asio::async_write(*m_down, boost::asio::buffer(m_downstream_buf, len),
				boost::asio::transfer_all(),
				std::bind(&TCPIPPipe::HandleDownstreamWrite,
				shared_from_this(),
				std::placeholders::_1));
		}
		else
			LogPrint(eLogError, "TCPIPPipe: downstream write: no socket");
	}

	void TCPIPPipe::HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered)
	{
		LogPrint(eLogDebug, "TCPIPPipe: downstream: ", (int) bytes_transfered, " bytes received");
		if (ecode)
		{
			LogPrint(eLogError, "TCPIPPipe: downstream read error:" , ecode.message());
			if (ecode != boost::asio::error::operation_aborted)
				Terminate();
		} else {
			if (bytes_transfered > 0 )
				memcpy(m_upstream_buf, m_downstream_to_up_buf, bytes_transfered);
			UpstreamWrite(bytes_transfered);
		}
	}

	void TCPIPPipe::HandleDownstreamWrite(const boost::system::error_code & ecode) {
		if (ecode)
		{
			LogPrint(eLogError, "TCPIPPipe: downstream write error:" , ecode.message());
			if (ecode != boost::asio::error::operation_aborted)
				Terminate();
		}
		else
			AsyncReceiveUpstream();
	}

	void TCPIPPipe::HandleUpstreamWrite(const boost::system::error_code & ecode) {
		if (ecode)
		{
			LogPrint(eLogError, "TCPIPPipe: upstream write error:" , ecode.message());
			if (ecode != boost::asio::error::operation_aborted)
				Terminate();
		}
		else
			AsyncReceiveDownstream();
	}

	void TCPIPPipe::HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered)
	{
		LogPrint(eLogDebug, "TCPIPPipe: upstream ", (int)bytes_transfered, " bytes received");
		if (ecode)
		{
			LogPrint(eLogError, "TCPIPPipe: upstream read error:" , ecode.message());
			if (ecode != boost::asio::error::operation_aborted)
				Terminate();
		} else {
			if (bytes_transfered > 0 )
				memcpy(m_downstream_buf, m_upstream_to_down_buf, bytes_transfered);
			DownstreamWrite(bytes_transfered);
		}
	}

	void TCPIPAcceptor::Start ()
	{
		m_Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService (), m_LocalEndpoint));
		//update the local end point in case port has been set zero and got updated now
		m_LocalEndpoint = m_Acceptor->local_endpoint();
		m_Acceptor->listen ();
		Accept ();
	}

	void TCPIPAcceptor::Stop ()
	{
		if (m_Acceptor)
		{
			m_Acceptor->close();
			m_Acceptor.reset (nullptr);
		}
		m_Timer.cancel ();
		ClearHandlers();
	}

	void TCPIPAcceptor::Accept ()
	{
		auto newSocket = std::make_shared<boost::asio::ip::tcp::socket> (GetService ());
		m_Acceptor->async_accept (*newSocket, std::bind (&TCPIPAcceptor::HandleAccept, this,
			std::placeholders::_1, newSocket));
	}

	void TCPIPAcceptor::HandleAccept (const boost::system::error_code& ecode, std::shared_ptr<boost::asio::ip::tcp::socket> socket)
	{
		if (!ecode)
		{
			LogPrint(eLogDebug, "I2PService: ", GetName(), " accepted");
			auto handler = CreateHandler(socket);
			if (handler)
			{
				AddHandler(handler);
				handler->Handle();
			}
			else
				socket->close();
			Accept();
		}
		else
		{
			if (ecode != boost::asio::error::operation_aborted)
				LogPrint (eLogError, "I2PService: ", GetName(), " closing socket on accept because: ", ecode.message ());
		}
	}
}
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2018 Lubos Ilcik, and contributors.
 *
 * The MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include <graphene/app/config_util.hpp>
#include <graphene/chain/config.hpp>

#include <fc/reflect/variant.hpp>
#include <fc/string.hpp>
#include <fc/exception/exception.hpp>
#include <fc/log/console_appender.hpp>
#include <fc/log/file_appender.hpp>
#include <fc/log/logger_config.hpp>

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string.hpp>

#include <fstream>

namespace bpo = boost::program_options;

class deduplicator
{
public:
   deduplicator() : modifier(nullptr) {}

   deduplicator(const boost::shared_ptr<bpo::option_description> (*mod_fn)(const boost::shared_ptr<bpo::option_description>&))
   : modifier(mod_fn) {}

   const boost::shared_ptr<bpo::option_description> next(const boost::shared_ptr<bpo::option_description>& o)
   {
      const std::string name = o->long_name();
      if( seen.find( name ) != seen.end() )
         return nullptr;
      seen.insert(name);
      return modifier ? modifier(o) : o;
   }

private:
   boost::container::flat_set<std::string> seen;
   const boost::shared_ptr<bpo::option_description> (*modifier)(const boost::shared_ptr<bpo::option_description>&);
};

// Currently, you can only specify the filenames and logging levels, which
// are all most users would want to change.  At a later time, options can
// be added to control rotation intervals, compression, and other seldom-
// used features
static void write_default_logging_config_to_stream(std::ostream& out)
{
   out << "# declare an appender named \"stderr\" that writes messages to the console\n"
          "[log.console_appender.stderr]\n"
          "stream=std_error\n\n"
          "# declare an appender named \"default\" that writes messages to default.log\n"
          "[log.file_appender.default]\n"
          "# filename can be absolute or relative to this config file\n"
          "filename=logs/default/default.log\n"
          "# Rotate log every ? minutes, if leave out default to 60\n"
          "rotation_interval=60\n"
          "# how long will logs be kept (in days), if leave out default to 1\n"
          "rotation_limit=7\n\n"
          "# declare an appender named \"p2p\" that writes messages to p2p.log\n"
          "[log.file_appender.p2p]\n"
          "# filename can be absolute or relative to this config file\n"
          "filename=logs/p2p/p2p.log\n"
          "# Rotate log every ? minutes, if leave out default to 60\n"
          "rotation_interval=60\n"
          "# how long will logs be kept (in days), if leave out default to 1\n"
          "rotation_limit=7\n\n"
          "# declare an appender named \"rpc\" that writes messages to rpc.log\n"
          "[log.file_appender.rpc]\n"
          "# filename can be absolute or relative to this config file\n"
          "filename=logs/rpc/rpc.log\n"
          "# Rotate log every ? minutes, if leave out default to 60\n"
          "rotation_interval=60\n"
          "# how long will logs be kept (in days), if leave out default to 1\n"
          "rotation_limit=7\n\n"
          "# route any messages logged to the default logger to the \"stderr\" appender and\n"
          "# \"default\" appender we declared above, if they are info level or higher\n"
          "[logger.default]\n"
          "level=info\n"
          "appenders=stderr,default\n\n"
          "# route messages sent to the \"p2p\" logger to the \"p2p\" appender declared above\n"
          "[logger.p2p]\n"
          "level=warn\n"
          "appenders=p2p\n\n"
          "# route messages sent to the \"rpc\" logger to the \"rpc\" appender declared above\n"
          "[logger.rpc]\n"
          "level=error\n"
          "appenders=rpc\n\n";
}

// logging config is too complicated to be parsed by boost::program_options,
// so we do it by hand
static fc::optional<fc::logging_config> load_logging_config_from_ini_file(const fc::path& config_ini_filename)
{
   try
   {
      fc::logging_config logging_config;
      bool found_logging_config = false;

      boost::property_tree::ptree config_ini_tree;
      boost::property_tree::ini_parser::read_ini(config_ini_filename.preferred_string().c_str(), config_ini_tree);
      for (const auto& section : config_ini_tree)
      {
         const std::string& section_name = section.first;
         const boost::property_tree::ptree& section_tree = section.second;

         const std::string console_appender_section_prefix = "log.console_appender.";
         const std::string file_appender_section_prefix = "log.file_appender.";
         const std::string logger_section_prefix = "logger.";

         if (boost::starts_with(section_name, console_appender_section_prefix))
         {
            std::string console_appender_name = section_name.substr(console_appender_section_prefix.length());
            std::string stream_name = section_tree.get<std::string>("stream");

            // construct a default console appender config here
            // stdout/stderr will be taken from ini file, everything else hard-coded here
            fc::console_appender::config console_appender_config;
            console_appender_config.level_colors.emplace_back(
            fc::console_appender::level_color(fc::log_level::debug,
                                              fc::console_appender::color::green));
            console_appender_config.level_colors.emplace_back(
            fc::console_appender::level_color(fc::log_level::warn,
                                              fc::console_appender::color::brown));
            console_appender_config.level_colors.emplace_back(
            fc::console_appender::level_color(fc::log_level::error,
                                              fc::console_appender::color::cyan));
            console_appender_config.stream = fc::variant(stream_name).as<fc::console_appender::stream::type>(GRAPHENE_MAX_NESTED_OBJECTS);
            logging_config.appenders.push_back(fc::appender_config(console_appender_name, "console", fc::variant(console_appender_config, GRAPHENE_MAX_NESTED_OBJECTS)));
            found_logging_config = true;
         }
         else if (boost::starts_with(section_name, file_appender_section_prefix))
         {
            std::string file_appender_name = section_name.substr(file_appender_section_prefix.length());
            fc::path file_name = section_tree.get<std::string>("filename");
            if (file_name.is_relative())
               file_name = fc::absolute(config_ini_filename).parent_path() / file_name;

            int interval = section_tree.get_optional<int>("rotation_interval").get_value_or(60);
            int limit = section_tree.get_optional<int>("rotation_limit").get_value_or(1);

            // construct a default file appender config here
            // filename will be taken from ini file, everything else hard-coded here
            fc::file_appender::config file_appender_config;
            file_appender_config.filename = file_name;
            file_appender_config.flush = true;
            file_appender_config.rotate = true;
            file_appender_config.rotation_interval = fc::minutes(interval);
            file_appender_config.rotation_limit = fc::days(limit);
            logging_config.appenders.push_back(fc::appender_config(file_appender_name, "file", fc::variant(file_appender_config, GRAPHENE_MAX_NESTED_OBJECTS)));
            found_logging_config = true;
         }
         else if (boost::starts_with(section_name, logger_section_prefix))
         {
            std::string logger_name = section_name.substr(logger_section_prefix.length());
            std::string level_string = section_tree.get<std::string>("level");
            std::string appenders_string = section_tree.get<std::string>("appenders");
            fc::logger_config logger_config(logger_name);
            logger_config.level = fc::variant(level_string).as<fc::log_level>(5);
            boost::split(logger_config.appenders, appenders_string,
                         boost::is_any_of(" ,"),
                         boost::token_compress_on);
            logging_config.loggers.push_back(logger_config);
            found_logging_config = true;
         }
      }
      if (found_logging_config)
         return logging_config;
      else
         return fc::optional<fc::logging_config>();
   }
   FC_RETHROW_EXCEPTIONS(warn, "")
}

static const boost::shared_ptr<bpo::option_description> new_option_description( const std::string& name, const bpo::value_semantic* value, const std::string& description )
{
   bpo::options_description helper("");
   helper.add_options()( name.c_str(), value, description.c_str() );
   return helper.options()[0];
}

static void load_config_file(const fc::path& config_ini_path, const bpo::options_description& cfg_options,
                             bpo::variables_map& options )
{
   deduplicator dedup;
   bpo::options_description unique_options("Graphene Witness Node");
   for( const boost::shared_ptr<bpo::option_description> opt : cfg_options.options() )
   {
      const boost::shared_ptr<bpo::option_description> od = dedup.next(opt);
      if( !od ) continue;
      unique_options.add( od );
   }

   // get the basic options
   bpo::store(bpo::parse_config_file<char>(config_ini_path.preferred_string().c_str(),
                                           unique_options, true), options);
}

static bool load_logging_config_file(const fc::path& config_ini_path)
{
   // try to get logging options from the config file.
   try
   {
      fc::optional<fc::logging_config> logging_config = load_logging_config_from_ini_file(config_ini_path);
      if (logging_config)
      {
         fc::configure_logging(*logging_config);
         return true;
      }
   }
   catch (const fc::exception& ex)
   {
      wlog("Error parsing logging config from logging config file ${config}, using default config", ("config", config_ini_path.preferred_string()));
   }
   return false;
}

static void create_new_config_file(const fc::path& config_ini_path, const fc::path& data_dir,
                                   const bpo::options_description& cfg_options )
{
   ilog("Writing new config file at ${path}", ("path", config_ini_path));
   if( !fc::exists(data_dir) )
      fc::create_directories(data_dir);

   auto modify_option_defaults = [](const boost::shared_ptr<bpo::option_description>& o) -> const boost::shared_ptr<bpo::option_description> {
       const std::basic_string<char, std::char_traits<char>, std::allocator<char>> & name = o->long_name();
       if( name == "partial-operations" )
          return new_option_description(name, bpo::value<bool>()->default_value(true), o->description() );
       if( name == "max-ops-per-account" )
          return new_option_description(name, bpo::value<int>()->default_value(1000), o->description() );
       return o;
   };
   deduplicator dedup(modify_option_defaults);
   std::ofstream out_cfg(config_ini_path.preferred_string());
   for( const boost::shared_ptr<bpo::option_description> opt : cfg_options.options() )
   {
      const boost::shared_ptr<bpo::option_description> od = dedup.next(opt);
      if( !od ) continue;

      if( !od->description().empty() )
         out_cfg << "# " << od->description() << "\n";
      boost::any store;
      if( !od->semantic()->apply_default(store) )
         out_cfg << "# " << od->long_name() << " = \n";
      else {
         auto example = od->format_parameter();
         if( example.empty() )
            // This is a boolean switch
            out_cfg << od->long_name() << " = " << "false\n";
         else {
            // The string is formatted "arg (=<interesting part>)"
            example.erase(0, 6);
            example.erase(example.length()-1);
            out_cfg << od->long_name() << " = " << example << "\n";
         }
      }
      out_cfg << "\n";
   }

   out_cfg.close();
}

static void create_logging_config_file(const fc::path& config_ini_path, const fc::path& data_dir)
{
   ilog("Writing new config file at ${path}", ("path", config_ini_path));
   if (!exists(data_dir))
   {
      create_directories(data_dir);
   }

   std::ofstream out_cfg(config_ini_path.preferred_string());
   write_default_logging_config_to_stream(out_cfg);
   out_cfg.close();
}

namespace graphene { namespace app {

   void load_configuration_options(const fc::path& data_dir, const bpo::options_description& cfg_options, bpo::variables_map& options)
   {
      const auto config_ini_path = data_dir / "config.ini";
      const auto logging_ini_path = data_dir / "logging.ini";

      if(!exists(config_ini_path) && fc::exists(logging_ini_path))
      {
         // this is an uncommon case
         create_new_config_file(config_ini_path, data_dir, cfg_options);
      }
      else if(!exists(config_ini_path))
      {
         // create default config.ini and logging.ini
         create_new_config_file(config_ini_path, data_dir, cfg_options);
         create_logging_config_file(logging_ini_path, data_dir);
      }

      // load witness node configuration
      load_config_file(config_ini_path, cfg_options, options);

      // load logging configuration
      if (fc::exists(logging_ini_path))
      {
         load_logging_config_file(logging_ini_path);
      }
      else
      {
         // this is the legacy config.ini case
         load_logging_config_file(config_ini_path);
      }
   }

} } // graphene::app<commit_msg>std::basic_string replaced with std::string<commit_after>/*
 * Copyright (c) 2018 Lubos Ilcik, and contributors.
 *
 * The MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include <graphene/app/config_util.hpp>
#include <graphene/chain/config.hpp>

#include <fc/reflect/variant.hpp>
#include <fc/string.hpp>
#include <fc/exception/exception.hpp>
#include <fc/log/console_appender.hpp>
#include <fc/log/file_appender.hpp>
#include <fc/log/logger_config.hpp>

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string.hpp>

#include <fstream>

namespace bpo = boost::program_options;

class deduplicator
{
public:
   deduplicator() : modifier(nullptr) {}

   deduplicator(const boost::shared_ptr<bpo::option_description> (*mod_fn)(const boost::shared_ptr<bpo::option_description>&))
   : modifier(mod_fn) {}

   const boost::shared_ptr<bpo::option_description> next(const boost::shared_ptr<bpo::option_description>& o)
   {
      const std::string name = o->long_name();
      if( seen.find( name ) != seen.end() )
         return nullptr;
      seen.insert(name);
      return modifier ? modifier(o) : o;
   }

private:
   boost::container::flat_set<std::string> seen;
   const boost::shared_ptr<bpo::option_description> (*modifier)(const boost::shared_ptr<bpo::option_description>&);
};

// Currently, you can only specify the filenames and logging levels, which
// are all most users would want to change.  At a later time, options can
// be added to control rotation intervals, compression, and other seldom-
// used features
static void write_default_logging_config_to_stream(std::ostream& out)
{
   out << "# declare an appender named \"stderr\" that writes messages to the console\n"
          "[log.console_appender.stderr]\n"
          "stream=std_error\n\n"
          "# declare an appender named \"default\" that writes messages to default.log\n"
          "[log.file_appender.default]\n"
          "# filename can be absolute or relative to this config file\n"
          "filename=logs/default/default.log\n"
          "# Rotate log every ? minutes, if leave out default to 60\n"
          "rotation_interval=60\n"
          "# how long will logs be kept (in days), if leave out default to 1\n"
          "rotation_limit=7\n\n"
          "# declare an appender named \"p2p\" that writes messages to p2p.log\n"
          "[log.file_appender.p2p]\n"
          "# filename can be absolute or relative to this config file\n"
          "filename=logs/p2p/p2p.log\n"
          "# Rotate log every ? minutes, if leave out default to 60\n"
          "rotation_interval=60\n"
          "# how long will logs be kept (in days), if leave out default to 1\n"
          "rotation_limit=7\n\n"
          "# declare an appender named \"rpc\" that writes messages to rpc.log\n"
          "[log.file_appender.rpc]\n"
          "# filename can be absolute or relative to this config file\n"
          "filename=logs/rpc/rpc.log\n"
          "# Rotate log every ? minutes, if leave out default to 60\n"
          "rotation_interval=60\n"
          "# how long will logs be kept (in days), if leave out default to 1\n"
          "rotation_limit=7\n\n"
          "# route any messages logged to the default logger to the \"stderr\" appender and\n"
          "# \"default\" appender we declared above, if they are info level or higher\n"
          "[logger.default]\n"
          "level=info\n"
          "appenders=stderr,default\n\n"
          "# route messages sent to the \"p2p\" logger to the \"p2p\" appender declared above\n"
          "[logger.p2p]\n"
          "level=warn\n"
          "appenders=p2p\n\n"
          "# route messages sent to the \"rpc\" logger to the \"rpc\" appender declared above\n"
          "[logger.rpc]\n"
          "level=error\n"
          "appenders=rpc\n\n";
}

// logging config is too complicated to be parsed by boost::program_options,
// so we do it by hand
static fc::optional<fc::logging_config> load_logging_config_from_ini_file(const fc::path& config_ini_filename)
{
   try
   {
      fc::logging_config logging_config;
      bool found_logging_config = false;

      boost::property_tree::ptree config_ini_tree;
      boost::property_tree::ini_parser::read_ini(config_ini_filename.preferred_string().c_str(), config_ini_tree);
      for (const auto& section : config_ini_tree)
      {
         const std::string& section_name = section.first;
         const boost::property_tree::ptree& section_tree = section.second;

         const std::string console_appender_section_prefix = "log.console_appender.";
         const std::string file_appender_section_prefix = "log.file_appender.";
         const std::string logger_section_prefix = "logger.";

         if (boost::starts_with(section_name, console_appender_section_prefix))
         {
            std::string console_appender_name = section_name.substr(console_appender_section_prefix.length());
            std::string stream_name = section_tree.get<std::string>("stream");

            // construct a default console appender config here
            // stdout/stderr will be taken from ini file, everything else hard-coded here
            fc::console_appender::config console_appender_config;
            console_appender_config.level_colors.emplace_back(
            fc::console_appender::level_color(fc::log_level::debug,
                                              fc::console_appender::color::green));
            console_appender_config.level_colors.emplace_back(
            fc::console_appender::level_color(fc::log_level::warn,
                                              fc::console_appender::color::brown));
            console_appender_config.level_colors.emplace_back(
            fc::console_appender::level_color(fc::log_level::error,
                                              fc::console_appender::color::cyan));
            console_appender_config.stream = fc::variant(stream_name).as<fc::console_appender::stream::type>(GRAPHENE_MAX_NESTED_OBJECTS);
            logging_config.appenders.push_back(fc::appender_config(console_appender_name, "console", fc::variant(console_appender_config, GRAPHENE_MAX_NESTED_OBJECTS)));
            found_logging_config = true;
         }
         else if (boost::starts_with(section_name, file_appender_section_prefix))
         {
            std::string file_appender_name = section_name.substr(file_appender_section_prefix.length());
            fc::path file_name = section_tree.get<std::string>("filename");
            if (file_name.is_relative())
               file_name = fc::absolute(config_ini_filename).parent_path() / file_name;

            int interval = section_tree.get_optional<int>("rotation_interval").get_value_or(60);
            int limit = section_tree.get_optional<int>("rotation_limit").get_value_or(1);

            // construct a default file appender config here
            // filename will be taken from ini file, everything else hard-coded here
            fc::file_appender::config file_appender_config;
            file_appender_config.filename = file_name;
            file_appender_config.flush = true;
            file_appender_config.rotate = true;
            file_appender_config.rotation_interval = fc::minutes(interval);
            file_appender_config.rotation_limit = fc::days(limit);
            logging_config.appenders.push_back(fc::appender_config(file_appender_name, "file", fc::variant(file_appender_config, GRAPHENE_MAX_NESTED_OBJECTS)));
            found_logging_config = true;
         }
         else if (boost::starts_with(section_name, logger_section_prefix))
         {
            std::string logger_name = section_name.substr(logger_section_prefix.length());
            std::string level_string = section_tree.get<std::string>("level");
            std::string appenders_string = section_tree.get<std::string>("appenders");
            fc::logger_config logger_config(logger_name);
            logger_config.level = fc::variant(level_string).as<fc::log_level>(5);
            boost::split(logger_config.appenders, appenders_string,
                         boost::is_any_of(" ,"),
                         boost::token_compress_on);
            logging_config.loggers.push_back(logger_config);
            found_logging_config = true;
         }
      }
      if (found_logging_config)
         return logging_config;
      else
         return fc::optional<fc::logging_config>();
   }
   FC_RETHROW_EXCEPTIONS(warn, "")
}

static const boost::shared_ptr<bpo::option_description> new_option_description( const std::string& name, const bpo::value_semantic* value, const std::string& description )
{
   bpo::options_description helper("");
   helper.add_options()( name.c_str(), value, description.c_str() );
   return helper.options()[0];
}

static void load_config_file(const fc::path& config_ini_path, const bpo::options_description& cfg_options,
                             bpo::variables_map& options )
{
   deduplicator dedup;
   bpo::options_description unique_options("Graphene Witness Node");
   for( const boost::shared_ptr<bpo::option_description> opt : cfg_options.options() )
   {
      const boost::shared_ptr<bpo::option_description> od = dedup.next(opt);
      if( !od ) continue;
      unique_options.add( od );
   }

   // get the basic options
   bpo::store(bpo::parse_config_file<char>(config_ini_path.preferred_string().c_str(),
                                           unique_options, true), options);
}

static bool load_logging_config_file(const fc::path& config_ini_path)
{
   // try to get logging options from the config file.
   try
   {
      fc::optional<fc::logging_config> logging_config = load_logging_config_from_ini_file(config_ini_path);
      if (logging_config)
      {
         fc::configure_logging(*logging_config);
         return true;
      }
   }
   catch (const fc::exception& ex)
   {
      wlog("Error parsing logging config from logging config file ${config}, using default config", ("config", config_ini_path.preferred_string()));
   }
   return false;
}

static void create_new_config_file(const fc::path& config_ini_path, const fc::path& data_dir,
                                   const bpo::options_description& cfg_options )
{
   ilog("Writing new config file at ${path}", ("path", config_ini_path));
   if( !fc::exists(data_dir) )
      fc::create_directories(data_dir);

   auto modify_option_defaults = [](const boost::shared_ptr<bpo::option_description>& o) -> const boost::shared_ptr<bpo::option_description> {
       const std::string& name = o->long_name();
       if( name == "partial-operations" )
          return new_option_description(name, bpo::value<bool>()->default_value(true), o->description() );
       if( name == "max-ops-per-account" )
          return new_option_description(name, bpo::value<int>()->default_value(1000), o->description() );
       return o;
   };
   deduplicator dedup(modify_option_defaults);
   std::ofstream out_cfg(config_ini_path.preferred_string());
   for( const boost::shared_ptr<bpo::option_description> opt : cfg_options.options() )
   {
      const boost::shared_ptr<bpo::option_description> od = dedup.next(opt);
      if( !od ) continue;

      if( !od->description().empty() )
         out_cfg << "# " << od->description() << "\n";
      boost::any store;
      if( !od->semantic()->apply_default(store) )
         out_cfg << "# " << od->long_name() << " = \n";
      else {
         auto example = od->format_parameter();
         if( example.empty() )
            // This is a boolean switch
            out_cfg << od->long_name() << " = " << "false\n";
         else {
            // The string is formatted "arg (=<interesting part>)"
            example.erase(0, 6);
            example.erase(example.length()-1);
            out_cfg << od->long_name() << " = " << example << "\n";
         }
      }
      out_cfg << "\n";
   }

   out_cfg.close();
}

static void create_logging_config_file(const fc::path& config_ini_path, const fc::path& data_dir)
{
   ilog("Writing new config file at ${path}", ("path", config_ini_path));
   if (!exists(data_dir))
   {
      create_directories(data_dir);
   }

   std::ofstream out_cfg(config_ini_path.preferred_string());
   write_default_logging_config_to_stream(out_cfg);
   out_cfg.close();
}

namespace graphene { namespace app {

   void load_configuration_options(const fc::path& data_dir, const bpo::options_description& cfg_options, bpo::variables_map& options)
   {
      const auto config_ini_path = data_dir / "config.ini";
      const auto logging_ini_path = data_dir / "logging.ini";

      if(!exists(config_ini_path) && fc::exists(logging_ini_path))
      {
         // this is an uncommon case
         create_new_config_file(config_ini_path, data_dir, cfg_options);
      }
      else if(!exists(config_ini_path))
      {
         // create default config.ini and logging.ini
         create_new_config_file(config_ini_path, data_dir, cfg_options);
         create_logging_config_file(logging_ini_path, data_dir);
      }

      // load witness node configuration
      load_config_file(config_ini_path, cfg_options, options);

      // load logging configuration
      if (fc::exists(logging_ini_path))
      {
         load_logging_config_file(logging_ini_path);
      }
      else
      {
         // this is the legacy config.ini case
         load_logging_config_file(config_ini_path);
      }
   }

} } // graphene::app<|endoftext|>


<commit_before>#pragma once
#include <boost/iterator/indirect_iterator.hpp>
#include "type.hpp"

namespace backend {

class monotype_t :
    public type_t
{
private:
    const std::string m_name;
    std::vector<std::shared_ptr<type_t> > m_params;

public:
    monotype_t(const std::string &name)
        : type_t(*this),
          m_name(name)
        {}
    monotype_t(const std::string &name,
               std::vector<std::shared_ptr<type_t > > &&params)
        : type_t(*this),
          m_name(name),
          m_params(std::move(params))
        {}
    const std::string& name(void) const {
        return m_name;
    }
    typedef decltype(boost::make_indirect_iterator(m_params.cbegin())) const_iterator;
    const_iterator begin() const {
        return boost::make_indirect_iterator(m_params.cbegin());
    }

    const_iterator end() const {
        return boost::make_indirect_iterator(m_params.cend());
    }

};

template<const char *s>
struct concrete_t :
        public monotype_t
{
    concrete_t() : monotype_t(s) {}
};

char int32_s[]   =   "Int32";
char int64_s[]   =   "Int64";
char uint32_s[]  =  "Uint32";
char uint64_s[]  =  "Uint64";
char float32_s[] = "Float32";
char float64_s[] = "Float64";
char bool_s[]    =    "Bool";
char void_s[]    =    "Void";

typedef concrete_t<int32_s>     int32_mt;
typedef concrete_t<int64_s>     int64_mt;
typedef concrete_t<uint32_s>   uint32_mt;
typedef concrete_t<uint64_s>   uint64_mt;
typedef concrete_t<float32_s> float32_mt;
typedef concrete_t<float64_s> float64_mt;
typedef concrete_t<bool_s>       bool_mt;
typedef concrete_t<void_s>       void_mt;

class sequence_t :
        public monotype_t
{
public:
    inline sequence_t(const std::shared_ptr<type_t> &sub)
        : monotype_t("Seq", std::vector<std::shared_ptr<type_t>>{sub})
        {}
};

class tuple_t :
        public monotype_t
{
public:
    inline tuple_t(std::vector<std::shared_ptr<type_t> > && sub)
        : monotype_t("Tuple", std::move(sub))
        {}
};

class fn_t :
        public monotype_t
{
public:
    inline fn_t(const std::shared_ptr<tuple_t> args,
                const std::shared_ptr<type_t> result)
        : monotype_t("Fn", std::vector<std::shared_ptr<type_t>>{args, result})
        {}
};

}
<commit_msg>Fixed bug which only manifested on mac.<commit_after>#pragma once
#include <vector>
#include <boost/iterator/indirect_iterator.hpp>
#include "type.hpp"

namespace backend {

class monotype_t :
    public type_t
{
private:
    const std::string m_name;
    std::vector<std::shared_ptr<type_t> > m_params;

public:
    monotype_t(const std::string &name)
        : type_t(*this),
          m_name(name)
        {}
    monotype_t(const std::string &name,
               std::vector<std::shared_ptr<type_t > > &&params)
        : type_t(*this),
          m_name(name),
          m_params(std::move(params))
        {}
    const std::string& name(void) const {
        return m_name;
    }
    typedef decltype(boost::make_indirect_iterator(m_params.cbegin())) const_iterator;
    const_iterator begin() const {
        return boost::make_indirect_iterator(m_params.cbegin());
    }

    const_iterator end() const {
        return boost::make_indirect_iterator(m_params.cend());
    }

};

template<const char *s>
struct concrete_t :
        public monotype_t
{
    concrete_t() : monotype_t(s) {}
};

char int32_s[]   =   "Int32";
char int64_s[]   =   "Int64";
char uint32_s[]  =  "Uint32";
char uint64_s[]  =  "Uint64";
char float32_s[] = "Float32";
char float64_s[] = "Float64";
char bool_s[]    =    "Bool";
char void_s[]    =    "Void";

typedef concrete_t<int32_s>     int32_mt;
typedef concrete_t<int64_s>     int64_mt;
typedef concrete_t<uint32_s>   uint32_mt;
typedef concrete_t<uint64_s>   uint64_mt;
typedef concrete_t<float32_s> float32_mt;
typedef concrete_t<float64_s> float64_mt;
typedef concrete_t<bool_s>       bool_mt;
typedef concrete_t<void_s>       void_mt;

class sequence_t :
        public monotype_t
{
public:
    inline sequence_t(const std::shared_ptr<type_t> &sub)
        : monotype_t("Seq", std::vector<std::shared_ptr<type_t>>{sub})
        {}
};

class tuple_t :
        public monotype_t
{
public:
    inline tuple_t(std::vector<std::shared_ptr<type_t> > && sub)
        : monotype_t("Tuple", std::move(sub))
        {}
};

class fn_t :
        public monotype_t
{
public:
    inline fn_t(const std::shared_ptr<tuple_t> args,
                const std::shared_ptr<type_t> result)
        : monotype_t("Fn", std::vector<std::shared_ptr<type_t>>{args, result})
        {}
};

}
<|endoftext|>


<commit_before>
// -*- mode: c++; c-basic-offset:4 -*-

// This file is part of nc_handler, a data handler for the OPeNDAP data
// server.

// Copyright (c) 2002,2003 OPeNDAP, Inc.
// Author: James Gallagher <jgallagher@opendap.org>
//
// This is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License as published by the Free
// Software Foundation; either version 2.1 of the License, or (at your
// option) any later version.
//
// This software 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 Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.

// cdf_module.cc

#include <iostream>

using std::endl ;

#include "DODSInitList.h"
#include "DODSRequestHandlerList.h"
#include "NCRequestHandler.h"
#include "ContainerStorageList.h"
#include "ContainerStorageCatalog.h"
#include "DODSLog.h"
#include "DirectoryCatalog.h"
#include "CatalogList.h"

#define NC_NAME "nc"
#define NC_CATALOG_ROOT_KEY "Catalog.catalog.RootDirectory"

static bool
NCInit(int, char**)
{
    if( DODSLog::TheLog()->is_verbose() )
	(*DODSLog::TheLog()) << "Initializing NC:" << endl ;

    if( DODSLog::TheLog()->is_verbose() )
	(*DODSLog::TheLog()) << "    adding " << NC_NAME << " request handler"
		      << endl ;
    DODSRequestHandlerList::TheList()->add_handler( NC_NAME, new NCRequestHandler( NC_NAME ) ) ;

    if( DODSLog::TheLog()->is_verbose() )
	(*DODSLog::TheLog()) << "    adding " << NC_NAME << " catalog"
		      << endl ;
    CatalogList::TheCatalogList()->add_catalog( new DirectoryCatalog( NC_CATALOG_ROOT_KEY ) ) ;

    if( DODSLog::TheLog()->is_verbose() )
	(*DODSLog::TheLog()) << "Adding Catalog Container Storage" << endl;
    ContainerStorageCatalog *csc = new ContainerStorageCatalog( "catalog" ) ;
    ContainerStorageList::TheList()->add_persistence( csc ) ;

    return true ;
}

static bool
NCTerm(void)
{
    if( DODSLog::TheLog()->is_verbose() )
	(*DODSLog::TheLog()) << "Removing NC Handlers" << endl;
    DODSRequestHandler *rh = DODSRequestHandlerList::TheList()->remove_handler( NC_NAME ) ;
    if( rh ) delete rh ;

    if( DODSLog::TheLog()->is_verbose() )
	(*DODSLog::TheLog()) << "Removing catalog Container Storage" << endl;
    ContainerStorageList::TheList()->rem_persistence( "catalog" ) ;

    return true ;
}

FUNINITQUIT( NCInit, NCTerm, 3 ) ;

<commit_msg>different way of creating DirectoryCatalog<commit_after>
// -*- mode: c++; c-basic-offset:4 -*-

// This file is part of nc_handler, a data handler for the OPeNDAP data
// server.

// Copyright (c) 2002,2003 OPeNDAP, Inc.
// Author: James Gallagher <jgallagher@opendap.org>
//
// This is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License as published by the Free
// Software Foundation; either version 2.1 of the License, or (at your
// option) any later version.
//
// This software 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 Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.

// cdf_module.cc

#include <iostream>

using std::endl ;

#include "DODSInitList.h"
#include "DODSRequestHandlerList.h"
#include "NCRequestHandler.h"
#include "ContainerStorageList.h"
#include "ContainerStorageCatalog.h"
#include "DODSLog.h"
#include "DirectoryCatalog.h"
#include "CatalogList.h"

#define NC_NAME "nc"
#define NC_CATALOG "catalog"

static bool
NCInit(int, char**)
{
    if( DODSLog::TheLog()->is_verbose() )
	(*DODSLog::TheLog()) << "Initializing NC:" << endl ;

    if( DODSLog::TheLog()->is_verbose() )
	(*DODSLog::TheLog()) << "    adding " << NC_NAME << " request handler"
		      << endl ;
    DODSRequestHandlerList::TheList()->add_handler( NC_NAME, new NCRequestHandler( NC_NAME ) ) ;

    if( DODSLog::TheLog()->is_verbose() )
	(*DODSLog::TheLog()) << "    adding " << NC_NAME << " catalog"
		      << endl ;
    CatalogList::TheCatalogList()->add_catalog( new DirectoryCatalog( NC_CATALOG ) ) ;

    if( DODSLog::TheLog()->is_verbose() )
	(*DODSLog::TheLog()) << "Adding Catalog Container Storage" << endl;
    ContainerStorageCatalog *csc = new ContainerStorageCatalog( NC_CATALOG ) ;
    ContainerStorageList::TheList()->add_persistence( csc ) ;

    return true ;
}

static bool
NCTerm(void)
{
    if( DODSLog::TheLog()->is_verbose() )
	(*DODSLog::TheLog()) << "Removing NC Handlers" << endl;
    DODSRequestHandler *rh = DODSRequestHandlerList::TheList()->remove_handler( NC_NAME ) ;
    if( rh ) delete rh ;

    if( DODSLog::TheLog()->is_verbose() )
	(*DODSLog::TheLog()) << "Removing catalog Container Storage" << endl;
    ContainerStorageList::TheList()->rem_persistence( "catalog" ) ;

    return true ;
}

FUNINITQUIT( NCInit, NCTerm, 3 ) ;

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2000 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form under the terms of the GNU
 *    General Public License as published by the Free Software
 *    Foundation; either version 2 of the License, or (at your option)
 *    any later version.
 *
 *    This program 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 this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_scope.cc,v 1.38 2007/06/02 03:42:13 steve Exp $"
#endif

# include "config.h"
# include "compiler.h"

# include  "netlist.h"
# include  <cstring>
# include  <sstream>

/*
 * The NetScope class keeps a scope tree organized. Each node of the
 * scope tree points to its parent, its right sibling and its leftmost
 * child. The root node has no parent or siblings. The node stores the
 * name of the scope. The complete hierarchical name of the scope is
 * formed by appending the path of scopes from the root to the scope
 * in question.
 */

NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t)
: type_(t), up_(up), sib_(0), sub_(0)
{
      signals_ = 0;
      events_ = 0;
      lcounter_ = 0;

      if (up) {
	    time_unit_ = up->time_unit();
	    time_prec_ = up->time_precision();
	    sib_ = up_->sub_;
	    up_->sub_ = this;
      } else {
	    time_unit_ = 0;
	    time_prec_ = 0;
	    assert(t == MODULE);
      }

      switch (t) {
	  case NetScope::TASK:
	    task_ = 0;
	    break;
	  case NetScope::FUNC:
	    func_ = 0;
	    break;
	  case NetScope::MODULE:
	    module_name_ = perm_string();
	    break;
	  default:  /* BEGIN_END and FORK_JOIN, do nothing */
	    break;
      }
      name_ = n;
}

NetScope::~NetScope()
{
      assert(sib_ == 0);
      assert(sub_ == 0);
      lcounter_ = 0;

	/* name_ and module_name_ are perm-allocated. */
}

NetExpr* NetScope::set_parameter(perm_string key, NetExpr*expr,
				 NetExpr*msb, NetExpr*lsb, bool signed_flag)
{
      param_expr_t&ref = parameters[key];
      NetExpr* res = ref.expr;
      ref.expr = expr;
      ref.msb = msb;
      ref.lsb = lsb;
      ref.signed_flag = signed_flag;
      return res;
}

bool NetScope::auto_name(const char*prefix, char pad, const char* suffix)
{
      char tmp[32];
      int pad_pos = strlen(prefix);
      int max_pos = sizeof(tmp) - strlen(suffix) - 1;
      strncpy(tmp, prefix, sizeof(tmp));
      while (pad_pos <= max_pos) {
	    strcat(tmp + pad_pos, suffix);
	    hname_t new_name(lex_strings.make(tmp));
	    if (!up_->child(new_name)) {
		  name_ = new_name;
		  return true;
	    }
	    tmp[pad_pos++] = pad;
      }
      return false;
}

/*
 * Return false if this creates a new parameter.
 */
bool NetScope::replace_parameter(perm_string key, NetExpr*expr)
{
      bool flag = true;
      param_expr_t&ref = parameters[key];

      NetExpr* res = ref.expr;

      if (res) {
	    delete res;
      } else {
	    flag = false;
	    ref.msb = 0;
	    ref.lsb = 0;
	    ref.signed_flag = false;
      }

      ref.expr = expr;
      return flag;
}

NetExpr* NetScope::set_localparam(perm_string key, NetExpr*expr)
{
      param_expr_t&ref = localparams[key];
      NetExpr* res = ref.expr;
      ref.expr = expr;
      ref.msb = 0;
      ref.lsb = 0;
      ref.signed_flag = false;
      return res;
}

/*
 * NOTE: This method takes a const char* as a key to lookup a
 * parameter, because we don't save that pointer. However, due to the
 * way the map<> template works, we need to *cheat* and use the
 * perm_string::literal method to fake the compiler into doing the
 * compare without actually creating a perm_string.
 */
const NetExpr* NetScope::get_parameter(const char* key,
				       const NetExpr*&msb,
				       const NetExpr*&lsb) const
{
      map<perm_string,param_expr_t>::const_iterator idx;

      idx = parameters.find(perm_string::literal(key));
      if (idx != parameters.end()) {
	    msb = (*idx).second.msb;
	    lsb = (*idx).second.lsb;
	    return (*idx).second.expr;
      }

      idx = localparams.find(perm_string::literal(key));
      if (idx != localparams.end()) {
	    msb = (*idx).second.msb;
	    lsb = (*idx).second.lsb;
	    return (*idx).second.expr;
      }

      return 0;
}

NetScope::TYPE NetScope::type() const
{
      return type_;
}

void NetScope::set_task_def(NetTaskDef*def)
{
      assert( type_ == TASK );
      assert( task_ == 0 );
      task_ = def;
}

NetTaskDef* NetScope::task_def()
{
      assert( type_ == TASK );
      return task_;
}

const NetTaskDef* NetScope::task_def() const
{
      assert( type_ == TASK );
      return task_;
}

void NetScope::set_func_def(NetFuncDef*def)
{
      assert( type_ == FUNC );
      assert( func_ == 0 );
      func_ = def;
}

NetFuncDef* NetScope::func_def()
{
      assert( type_ == FUNC );
      return func_;
}
bool NetScope::in_func()
{
      return (type_ == FUNC) ? true : false;
}

const NetFuncDef* NetScope::func_def() const
{
      assert( type_ == FUNC );
      return func_;
}

void NetScope::set_module_name(perm_string n)
{
      assert(type_ == MODULE);
      module_name_ = n; /* NOTE: n mus have been permallocated. */
}

perm_string NetScope::module_name() const
{
      assert(type_ == MODULE);
      return module_name_;
}

void NetScope::time_unit(int val)
{
      time_unit_ = val;
}

void NetScope::time_precision(int val)
{
      time_prec_ = val;
}

int NetScope::time_unit() const
{
      return time_unit_;
}

int NetScope::time_precision() const
{
      return time_prec_;
}

void NetScope::default_nettype(NetNet::Type nt)
{
      default_nettype_ = nt;
}

NetNet::Type NetScope::default_nettype() const
{
      return default_nettype_;
}

perm_string NetScope::basename() const
{
      return name_.peek_name();
}

void NetScope::add_event(NetEvent*ev)
{
      assert(ev->scope_ == 0);
      ev->scope_ = this;
      ev->snext_ = events_;
      events_ = ev;
}

void NetScope::rem_event(NetEvent*ev)
{
      assert(ev->scope_ == this);
      ev->scope_ = 0;
      if (events_ == ev) {
	    events_ = ev->snext_;

      } else {
	    NetEvent*cur = events_;
	    while (cur->snext_ != ev) {
		  assert(cur->snext_);
		  cur = cur->snext_;
	    }
	    cur->snext_ = ev->snext_;
      }

      ev->snext_ = 0;
}

NetEvent* NetScope::find_event(perm_string name)
{
      for (NetEvent*cur = events_;  cur ;  cur = cur->snext_)
	    if (cur->name() == name)
		  return cur;

      return 0;
}

void NetScope::add_signal(NetNet*net)
{
      if (signals_ == 0) {
	    net->sig_next_ = net;
	    net->sig_prev_ = net;
      } else {
	    net->sig_next_ = signals_->sig_next_;
	    net->sig_prev_ = signals_;
	    net->sig_next_->sig_prev_ = net;
	    net->sig_prev_->sig_next_ = net;
      }
      signals_ = net;
}

void NetScope::rem_signal(NetNet*net)
{
      assert(net->scope() == this);
      if (signals_ == net)
	    signals_ = net->sig_prev_;

      if (signals_ == net) {
	    signals_ = 0;
      } else {
	    net->sig_prev_->sig_next_ = net->sig_next_;
	    net->sig_next_->sig_prev_ = net->sig_prev_;
      }
}

/*
 * This method looks for a signal within the current scope. The name
 * is assumed to be the base name of the signal, so no sub-scopes are
 * searched.
 */
NetNet* NetScope::find_signal(perm_string key)
{
      if (signals_ == 0)
	    return 0;

      NetNet*cur = signals_;
      do {
	    if (cur->name() == key)
		  return cur;
	    cur = cur->sig_prev_;
      } while (cur != signals_);
      return 0;
}

/*
 * This method locates a child scope by name. The name is the simple
 * name of the child, no hierarchy is searched.
 */
NetScope* NetScope::child(const hname_t&name)
{
      if (sub_ == 0) return 0;

      NetScope*cur = sub_;
      while (cur->name_ != name) {
	    if (cur->sib_ == 0) return 0;
	    cur = cur->sib_;
      }

      return cur;
}

const NetScope* NetScope::child(const hname_t&name) const
{
      if (sub_ == 0) return 0;

      NetScope*cur = sub_;
      while (cur->name_ != name) {
	    if (cur->sib_ == 0) return 0;
	    cur = cur->sib_;
      }

      return cur;
}

NetScope* NetScope::parent()
{
      return up_;
}

const NetScope* NetScope::parent() const
{
      return up_;
}

perm_string NetScope::local_symbol()
{
      ostringstream res;
      res << "_s" << (lcounter_++);
      return lex_strings.make(res.str());
}
#if 0
string NetScope::local_hsymbol()
{
      return string(name()) + "." + string(local_symbol());
}
#endif

<commit_msg>A NetScope will get a default nettype from a parent.<commit_after>/*
 * Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form under the terms of the GNU
 *    General Public License as published by the Free Software
 *    Foundation; either version 2 of the License, or (at your option)
 *    any later version.
 *
 *    This program 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 this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */

# include "config.h"
# include "compiler.h"

# include  "netlist.h"
# include  <cstring>
# include  <sstream>

/*
 * The NetScope class keeps a scope tree organized. Each node of the
 * scope tree points to its parent, its right sibling and its leftmost
 * child. The root node has no parent or siblings. The node stores the
 * name of the scope. The complete hierarchical name of the scope is
 * formed by appending the path of scopes from the root to the scope
 * in question.
 */

NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t)
: type_(t), up_(up), sib_(0), sub_(0)
{
      signals_ = 0;
      events_ = 0;
      lcounter_ = 0;

      if (up) {
	    default_nettype_ = up->default_nettype();
	    time_unit_ = up->time_unit();
	    time_prec_ = up->time_precision();
	    sib_ = up_->sub_;
	    up_->sub_ = this;
      } else {
	    default_nettype_ = NetNet::NONE;
	    time_unit_ = 0;
	    time_prec_ = 0;
	    assert(t == MODULE);
      }

      switch (t) {
	  case NetScope::TASK:
	    task_ = 0;
	    break;
	  case NetScope::FUNC:
	    func_ = 0;
	    break;
	  case NetScope::MODULE:
	    module_name_ = perm_string();
	    break;
	  default:  /* BEGIN_END and FORK_JOIN, do nothing */
	    break;
      }
      name_ = n;
}

NetScope::~NetScope()
{
      assert(sib_ == 0);
      assert(sub_ == 0);
      lcounter_ = 0;

	/* name_ and module_name_ are perm-allocated. */
}

NetExpr* NetScope::set_parameter(perm_string key, NetExpr*expr,
				 NetExpr*msb, NetExpr*lsb, bool signed_flag)
{
      param_expr_t&ref = parameters[key];
      NetExpr* res = ref.expr;
      ref.expr = expr;
      ref.msb = msb;
      ref.lsb = lsb;
      ref.signed_flag = signed_flag;
      return res;
}

bool NetScope::auto_name(const char*prefix, char pad, const char* suffix)
{
      char tmp[32];
      int pad_pos = strlen(prefix);
      int max_pos = sizeof(tmp) - strlen(suffix) - 1;
      strncpy(tmp, prefix, sizeof(tmp));
      while (pad_pos <= max_pos) {
	    strcat(tmp + pad_pos, suffix);
	    hname_t new_name(lex_strings.make(tmp));
	    if (!up_->child(new_name)) {
		  name_ = new_name;
		  return true;
	    }
	    tmp[pad_pos++] = pad;
      }
      return false;
}

/*
 * Return false if this creates a new parameter.
 */
bool NetScope::replace_parameter(perm_string key, NetExpr*expr)
{
      bool flag = true;
      param_expr_t&ref = parameters[key];

      NetExpr* res = ref.expr;

      if (res) {
	    delete res;
      } else {
	    flag = false;
	    ref.msb = 0;
	    ref.lsb = 0;
	    ref.signed_flag = false;
      }

      ref.expr = expr;
      return flag;
}

NetExpr* NetScope::set_localparam(perm_string key, NetExpr*expr)
{
      param_expr_t&ref = localparams[key];
      NetExpr* res = ref.expr;
      ref.expr = expr;
      ref.msb = 0;
      ref.lsb = 0;
      ref.signed_flag = false;
      return res;
}

/*
 * NOTE: This method takes a const char* as a key to lookup a
 * parameter, because we don't save that pointer. However, due to the
 * way the map<> template works, we need to *cheat* and use the
 * perm_string::literal method to fake the compiler into doing the
 * compare without actually creating a perm_string.
 */
const NetExpr* NetScope::get_parameter(const char* key,
				       const NetExpr*&msb,
				       const NetExpr*&lsb) const
{
      map<perm_string,param_expr_t>::const_iterator idx;

      idx = parameters.find(perm_string::literal(key));
      if (idx != parameters.end()) {
	    msb = (*idx).second.msb;
	    lsb = (*idx).second.lsb;
	    return (*idx).second.expr;
      }

      idx = localparams.find(perm_string::literal(key));
      if (idx != localparams.end()) {
	    msb = (*idx).second.msb;
	    lsb = (*idx).second.lsb;
	    return (*idx).second.expr;
      }

      return 0;
}

NetScope::TYPE NetScope::type() const
{
      return type_;
}

void NetScope::set_task_def(NetTaskDef*def)
{
      assert( type_ == TASK );
      assert( task_ == 0 );
      task_ = def;
}

NetTaskDef* NetScope::task_def()
{
      assert( type_ == TASK );
      return task_;
}

const NetTaskDef* NetScope::task_def() const
{
      assert( type_ == TASK );
      return task_;
}

void NetScope::set_func_def(NetFuncDef*def)
{
      assert( type_ == FUNC );
      assert( func_ == 0 );
      func_ = def;
}

NetFuncDef* NetScope::func_def()
{
      assert( type_ == FUNC );
      return func_;
}
bool NetScope::in_func()
{
      return (type_ == FUNC) ? true : false;
}

const NetFuncDef* NetScope::func_def() const
{
      assert( type_ == FUNC );
      return func_;
}

void NetScope::set_module_name(perm_string n)
{
      assert(type_ == MODULE);
      module_name_ = n; /* NOTE: n mus have been permallocated. */
}

perm_string NetScope::module_name() const
{
      assert(type_ == MODULE);
      return module_name_;
}

void NetScope::time_unit(int val)
{
      time_unit_ = val;
}

void NetScope::time_precision(int val)
{
      time_prec_ = val;
}

int NetScope::time_unit() const
{
      return time_unit_;
}

int NetScope::time_precision() const
{
      return time_prec_;
}

void NetScope::default_nettype(NetNet::Type nt)
{
      default_nettype_ = nt;
}

NetNet::Type NetScope::default_nettype() const
{
      return default_nettype_;
}

perm_string NetScope::basename() const
{
      return name_.peek_name();
}

void NetScope::add_event(NetEvent*ev)
{
      assert(ev->scope_ == 0);
      ev->scope_ = this;
      ev->snext_ = events_;
      events_ = ev;
}

void NetScope::rem_event(NetEvent*ev)
{
      assert(ev->scope_ == this);
      ev->scope_ = 0;
      if (events_ == ev) {
	    events_ = ev->snext_;

      } else {
	    NetEvent*cur = events_;
	    while (cur->snext_ != ev) {
		  assert(cur->snext_);
		  cur = cur->snext_;
	    }
	    cur->snext_ = ev->snext_;
      }

      ev->snext_ = 0;
}

NetEvent* NetScope::find_event(perm_string name)
{
      for (NetEvent*cur = events_;  cur ;  cur = cur->snext_)
	    if (cur->name() == name)
		  return cur;

      return 0;
}

void NetScope::add_signal(NetNet*net)
{
      if (signals_ == 0) {
	    net->sig_next_ = net;
	    net->sig_prev_ = net;
      } else {
	    net->sig_next_ = signals_->sig_next_;
	    net->sig_prev_ = signals_;
	    net->sig_next_->sig_prev_ = net;
	    net->sig_prev_->sig_next_ = net;
      }
      signals_ = net;
}

void NetScope::rem_signal(NetNet*net)
{
      assert(net->scope() == this);
      if (signals_ == net)
	    signals_ = net->sig_prev_;

      if (signals_ == net) {
	    signals_ = 0;
      } else {
	    net->sig_prev_->sig_next_ = net->sig_next_;
	    net->sig_next_->sig_prev_ = net->sig_prev_;
      }
}

/*
 * This method looks for a signal within the current scope. The name
 * is assumed to be the base name of the signal, so no sub-scopes are
 * searched.
 */
NetNet* NetScope::find_signal(perm_string key)
{
      if (signals_ == 0)
	    return 0;

      NetNet*cur = signals_;
      do {
	    if (cur->name() == key)
		  return cur;
	    cur = cur->sig_prev_;
      } while (cur != signals_);
      return 0;
}

/*
 * This method locates a child scope by name. The name is the simple
 * name of the child, no hierarchy is searched.
 */
NetScope* NetScope::child(const hname_t&name)
{
      if (sub_ == 0) return 0;

      NetScope*cur = sub_;
      while (cur->name_ != name) {
	    if (cur->sib_ == 0) return 0;
	    cur = cur->sib_;
      }

      return cur;
}

const NetScope* NetScope::child(const hname_t&name) const
{
      if (sub_ == 0) return 0;

      NetScope*cur = sub_;
      while (cur->name_ != name) {
	    if (cur->sib_ == 0) return 0;
	    cur = cur->sib_;
      }

      return cur;
}

NetScope* NetScope::parent()
{
      return up_;
}

const NetScope* NetScope::parent() const
{
      return up_;
}

perm_string NetScope::local_symbol()
{
      ostringstream res;
      res << "_s" << (lcounter_++);
      return lex_strings.make(res.str());
}
#if 0
string NetScope::local_hsymbol()
{
      return string(name()) + "." + string(local_symbol());
}
#endif
<|endoftext|>


<commit_before>//   Copyright 2015 Patrick Putnam
//
//   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
//
//       http://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.
#ifndef COMPUTE_CAPABILITIES_HPP_
#define COMPUTE_CAPABILITIES_HPP_

template < unsigned int V >
struct compute_capability;

template < >
struct compute_capability< 3 > {
    static const unsigned int WARP_SIZE = 32;
    static const unsigned int THREADS_PER_BLOCK = 1024;

    static const unsigned int THREAD_BLOCK_2D_X = WARP_SIZE;
    static const unsigned int THREAD_BLOCK_2D_Y = THREADS_PER_BLOCK / WARP_SIZE;

    static const unsigned int WARP_PER_BLOCK = THREADS_PER_BLOCK / WARP_SIZE;
};

#endif  // COMPUTE_CAPABILITIES_HPP_
<commit_msg>Refactored to compute_capability<commit_after><|endoftext|>


<commit_before>#include "decomm_inst.h"

using decomm::DecommInst;
enum buildtype_t { BUILD = 1, DECOMM = 2};

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
DecommInst::DecommInst(cyclus::Context* ctx)
    : cyclus::Institution(ctx) {};

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
DecommInst::~DecommInst() {}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DecommInst::Decommission(Agent* parent) {
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DecommInst::Build(Agent* parent) {
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int DecommInst::NToBuild(double avail) {
  // convert material availability to a number of facilities to build.
  int n = 0;
  if (DecisionLogic(avail)) {
    switch (buildtype) {
    case DECOMM :
      n -= 1;
      break;
    case BUILD :
      n += 1;
      break;
    default :
      throw cyclus::ValueError("Incorrect buildtype: "\
          "The options are 'decommission' or 'build'.");
    }
  }
  // need some logic to decrement avail.

  return n;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
double DecommInst::MaterialAvailable(cyclus::toolkit::Commodity commod){
  // use the commodityproducermanager to determine material available
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DecommInst::EnterNotify(){
  /// enter the simulation and register any children present
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DecommInst::BuildNotify(Agent* m){
  /// register a new child
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DecommInst::DecomNotify(Agent* m){
  /// unregister a decommissioned child
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Register_(cyclus::Agent* agent){
  /// register a child
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Unregister_(cyclus::Agent* agent){
/// unregister a child
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool DecisionLogic(double avail){
  bool d = false;
  return d;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
extern "C" cyclus::Agent* ConstructDecommInst(cyclus::Context* ctx) {
  return new DecommInst(ctx);
}
<commit_msg>comment logic builds, no warnings<commit_after>#include "decomm_inst.h"

using decomm::DecommInst;
enum buildtype_t { BUILD = 1, DECOMM = 2};

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
DecommInst::DecommInst(cyclus::Context* ctx)
    : cyclus::Institution(ctx) {};

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
DecommInst::~DecommInst() {}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DecommInst::Decommission(Agent* parent) {
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DecommInst::Build(Agent* parent) {
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int DecommInst::NToBuild(double avail) {
  // convert material availability to a number of facilities to build.
  int n = 0;
  if (DecisionLogic(avail)) {
    switch (buildtype) {
    case DECOMM :
      n -= 1;
      break;
    case BUILD :
      n += 1;
      break;
    default :
      throw cyclus::ValueError("Incorrect buildtype: "\
          "The options are 'decommission' or 'build'.");
      break;
    }
  }
  // need some logic to decrement avail.

  return n;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
double DecommInst::MaterialAvailable(cyclus::toolkit::Commodity commod){
  // use the commodityproducermanager to determine material available
  double n = 0;
  return n;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DecommInst::EnterNotify(){
  /// enter the simulation and register any children present
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DecommInst::BuildNotify(Agent* m){
  /// register a new child
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DecommInst::DecomNotify(Agent* m){
  /// unregister a decommissioned child
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DecommInst::Register_(cyclus::Agent* agent){
  /// register a child
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DecommInst::Unregister_(cyclus::Agent* agent){
/// unregister a child
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool DecommInst::DecisionLogic(double avail){
  bool d = false;
  return d;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
extern "C" cyclus::Agent* ConstructDecommInst(cyclus::Context* ctx) {
  return new DecommInst(ctx);
}
<|endoftext|>