text:
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/multi_index/tag.hpp>

#include <boost/program_options.hpp>

#include <bts/net/node.hpp>
#include <bts/client/messages.hpp>

#include <bts/blockchain/chain_database.hpp>
#include <bts/blockchain/config.hpp>
#include <fc/filesystem.hpp>
#include <fc/log/logger.hpp>
#include <fc/log/file_appender.hpp>
#include <fc/io/raw.hpp>
#include <fc/reflect/variant.hpp>
#include <fc/thread/thread.hpp>

#include <iostream>

using namespace bts::blockchain;
using namespace bts::net;
using namespace bts::client;

// Generate a fake starting block.
// This block has all elements default-initialized, except for the block
// number which is 1.  (chosen because we'll consider a signature valid if
// it is equal to the block number, and we treat a signature of 0 to mean
// no signature.
block_message generate_fake_genesis_block()
{
  block_message genesis_block;
  genesis_block.block.block_num = 1;
  genesis_block.block_id = genesis_block.block.id();
  (*(uint32_t*)&genesis_block.signature.at(0)) = 1;
  ilog("generated genesis block, its id is ${id}", ("id", genesis_block.block_id));
  return genesis_block;
}

using namespace boost::multi_index;

/////////////////////////////////////////////////////////////////////////////////////////////////////////
class blockchain_tied_message_cache
{
   private:
     static const uint32_t cache_duration_in_blocks = 2;

     struct message_hash_index{};
     struct block_clock_index{};
     struct message_info
     {
       message_hash_type message_hash;
       message           message_body;
       uint32_t          block_clock_when_received;
       message_info(const message_hash_type& message_hash,
                    const message&           message_body,
                    uint32_t                 block_clock_when_received) :
         message_hash(message_hash),
         message_body(message_body),
         block_clock_when_received (block_clock_when_received)
       {}
     };
     typedef boost::multi_index_container<message_info, indexed_by<ordered_unique<tag<message_hash_index>, member<message_info, message_hash_type, &message_info::message_hash> >,
                                                                   ordered_non_unique<tag<block_clock_index>, member<message_info, uint32_t, &message_info::block_clock_when_received> > > > message_cache_container;
     message_cache_container _message_cache;

     uint32_t block_clock; //
   public:
     blockchain_tied_message_cache() :
       block_clock(0)
     {}
     void block_accepted();
     void cache_message(const message& message_to_cache, const message_hash_type& hash_of_message_to_cache);
     message get_message(const message_hash_type& hash_of_message_to_lookup);
};

void blockchain_tied_message_cache::block_accepted()
{
  ++block_clock;
  if (block_clock > cache_duration_in_blocks)
    _message_cache.get<block_clock_index>().erase(_message_cache.get<block_clock_index>().begin(),
                                                 _message_cache.get<block_clock_index>().lower_bound(block_clock - cache_duration_in_blocks));
}

void blockchain_tied_message_cache::cache_message(const message& message_to_cache, const message_hash_type& hash_of_message_to_cache)
{
  _message_cache.insert(message_info(hash_of_message_to_cache, message_to_cache, block_clock));
}

message blockchain_tied_message_cache::get_message(const message_hash_type& hash_of_message_to_lookup)
{
  message_cache_container::index<message_hash_index>::type::const_iterator iter = _message_cache.get<message_hash_index>().find(hash_of_message_to_lookup);
  if (iter != _message_cache.get<message_hash_index>().end())
    return iter->message_body;
  FC_THROW_EXCEPTION(key_not_found_exception, "Requested message not in cache");
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
class simple_net_test_miner : public bts::net::node_delegate
{
   private:
     node _node;

     // cache of messages we've seen in the past few blocks
     blockchain_tied_message_cache _message_cache;

     // blockchain is a series of block_messages
     struct block_hash_index{};
     typedef boost::multi_index_container<block_message, indexed_by<random_access<>,
                                                                    ordered_unique<tag<block_hash_index>, member<block_message, block_id_type, &block_message::block_id> > > > ordered_blockchain_container;
     ordered_blockchain_container _blockchain;

     // the list of unsigned blocks we're considering adding to our chain
     typedef boost::multi_index_container<block_message, indexed_by<ordered_unique<member<block_message, block_id_type, &block_message::block_id> > > > block_container;
     block_container _unsigned_blocks;

     // the list of transactions we're considering adding to a new block if we mine one.
     // we expire these after a few blocks.  A real client would also expire them immediately
     // if it received a block containing the transaction
     struct transaction_hash_index{};
     struct chain_length_index{};
     struct transaction_with_timestamp
     {
       bts::blockchain::signed_transaction transaction;
       transaction_id_type                 transaction_id;
       uint32_t                            chain_length_when_received;
     };
     typedef boost::multi_index_container<transaction_with_timestamp, indexed_by<ordered_unique<tag<transaction_hash_index>, member<transaction_with_timestamp, transaction_id_type, &transaction_with_timestamp::transaction_id> >,
                                                                                ordered_non_unique<tag<chain_length_index>, member<transaction_with_timestamp, uint32_t, &transaction_with_timestamp::chain_length_when_received> > > > transaction_container;
     transaction_container _transactions;

     // the list of signatures we've seen but have been unable to pair with a block (maybe the unsigned block hasn't arrived yet).
     typedef boost::multi_index_container<signature_message, indexed_by<ordered_unique<member<signature_message, block_id_type, &signature_message::block_id> > > > signature_container;
     signature_container _signatures;

     bool _synchronized;
     uint32_t _remaining_items_to_sync;

     uint16_t _listening_port;
     fc::path _config_dir;

     void push_valid_signed_block(const block_message& block_to_push);
     bool is_block_valid(const block_message& block_to_check);
     void store_transaction(const trx_message& transaction_to_store);

   public:
     simple_net_test_miner();
     void set_port(uint16_t port);
     void set_config_dir(const std::string& config_dir);
     void connect_to(fc::ip::endpoint remote_endpoint);
     void start();
     void generate_signed_block();
     void run();

     /* Implement node_delegate */
     bool has_item(const item_id& id) override;
     void handle_message(const message&) override;
     std::vector<item_hash_t> get_item_ids(const item_id& from_id,
                                           uint32_t& remaining_item_count,
                                           uint32_t limit = 2000) override;
     message get_item(const item_id& id) override;
     void sync_status(uint32_t item_type, uint32_t item_count) override;
     void connection_count_changed(uint32_t c) override;
};

simple_net_test_miner::simple_net_test_miner() :
  _synchronized(false),
  _remaining_items_to_sync(0),
  _listening_port(6543)
{
  _node.set_node_delegate(this);
  _config_dir = fc::app_path() / "simple_net_test_miner";
  push_valid_signed_block(generate_fake_genesis_block());
}

void simple_net_test_miner::set_port(uint16_t port)
{
  _listening_port = port;
}

void simple_net_test_miner::set_config_dir(const std::string& config_dir)
{
  _config_dir = config_dir.c_str();
}

void simple_net_test_miner::start()
{
  FC_ASSERT(!_blockchain.empty());
  _synchronized = false;

  if (!fc::exists(_config_dir))
    fc::create_directories(_config_dir);

  fc::file_appender::config appender_config;
  appender_config.filename = _config_dir / "log.txt";
  appender_config.truncate = false;
  appender_config.flush = true;
  fc::logger::get().add_appender(fc::shared_ptr<fc::file_appender>(new fc::file_appender(fc::variant(appender_config))));

  _node.load_configuration(_config_dir);

  _node.sync_from(item_id(block_message_type, _blockchain.back().block_id));
  _node.listen_on_port(_listening_port);
  _node.connect_to_p2p_network();
}
void simple_net_test_miner::connect_to(fc::ip::endpoint remote_endpoint)
{
  _node.connect_to(remote_endpoint);
}

void simple_net_test_miner::generate_signed_block()
{
  // generate a block
  block_message new_block;
  int last_block_number = _blockchain.get<0>().back().block.block_num;
  ilog("mined block ${block_number}", ("block_number", last_block_number + 1));
  new_block.block.block_num = last_block_number + 1;
  new_block.block.prev = _blockchain.get<0>().back().block_id;
  new_block.block_id = new_block.block.id();
  (*(uint32_t*)&new_block.signature.at(0)) = last_block_number + 1;
  push_valid_signed_block(new_block);
  message new_block_message(new_block);
  _message_cache.cache_message(new_block_message, new_block_message.id());
  _node.broadcast(new_block_message);
}

void simple_net_test_miner::run()
{
  if (_listening_port == 6540)
    for (int i = 0; i < 410; ++i)
      generate_signed_block();

  srand((unsigned)time(NULL));
  for (;;)
  {
    // sleep for 10-20 seconds
    fc::usleep(fc::milliseconds(15000 + ((rand() % 10000) - 5000)));
    ilog("looping");
    if (_listening_port == 6540)
      generate_signed_block();
  }
}

void simple_net_test_miner::push_valid_signed_block(const block_message& block_to_push)
{
  auto push_result = _blockchain.push_back(block_to_push);
  FC_ASSERT(push_result.second); // assert that insert succeeded

  // any unsigned blocks we have are garbage
  _unsigned_blocks.clear();

  // prune list of cached messages
  _message_cache.block_accepted();

  // prune list of uncommitted _transactions
  unsigned cached_transaction_duration_in_blocks = 2;
  if (_blockchain.size() > cached_transaction_duration_in_blocks)
    _transactions.get<chain_length_index>().erase(_transactions.get<chain_length_index>().begin(),
                                                  _transactions.get<chain_length_index>().lower_bound(_blockchain.size() - cached_transaction_duration_in_blocks));

  if (!_synchronized)
  {
    --_remaining_items_to_sync;
    if (_remaining_items_to_sync == 0)
      _synchronized = true;
  }

  ilog("CLIENT: pushed block ${id}, blockchain is now ${count} blocks long", ("id", block_to_push.block_id)("count", _blockchain.size()));
}

bool simple_net_test_miner::is_block_valid(const block_message& block_to_check)
{
  FC_ASSERT(!_blockchain.empty()); // we should always start with the genesis block
  if (_blockchain.empty())
    return true; // no way of knowing
  //block_to_check.block.prev;
  ordered_blockchain_container::index<block_hash_index>::type::iterator iter = _blockchain.get<block_hash_index>().find(block_to_check.block.prev);
  if (iter != _blockchain.get<block_hash_index>().end())
    return true;
  wlog("Got invalid block ${block}.  It's prev hash is ${prev} so I'm calling it invalid",
       ("block",block_to_check.block_id)("prev",block_to_check.block.prev));
  wlog("Last block on the block chain is ${id}",("id", _blockchain.back().block_id));
  return false;
}

void simple_net_test_miner::store_transaction(const trx_message& transaction_to_store)
{
  transaction_with_timestamp transaction_info;
  transaction_info.transaction = transaction_to_store.trx;
  transaction_info.transaction_id = transaction_to_store.trx.id();
  transaction_info.chain_length_when_received = _blockchain.size();
  _transactions.insert(transaction_info);
}

bool simple_net_test_miner::has_item(const item_id& id)
{
  ilog("CLIENT: node asks if I have item type ${type} hash ${hash}",("type", id.item_type)("hash", id.item_hash));
  if (id.item_type == trx_message_type)
    return _transactions.get<transaction_hash_index>().find(id.item_hash) != _transactions.end();
  if (id.item_type == block_message_type)
  {
    ilog("CLIENT: ... I answer: ${have_it}",("have_it",_blockchain.get<block_hash_index>().find(id.item_hash) != _blockchain.get<block_hash_index>().end()));
    return _blockchain.get<block_hash_index>().find(id.item_hash) != _blockchain.get<block_hash_index>().end();
  }
  return false;
}

void simple_net_test_miner::handle_message(const message& message_to_handle)
{
  switch (message_to_handle.msg_type)
  {
  case block_message_type:
    {
      block_message block_message_to_handle(message_to_handle.as<block_message>());
      ilog("CLIENT: just received block ${id}", ("id", block_message_to_handle.block_id));
      if (!is_block_valid(block_message_to_handle))
        FC_THROW("Invalid block received, I want to disconnect from the peer that sent it");
      if (block_message_to_handle.signature != fc::ecc::compact_signature())
        push_valid_signed_block(block_message_to_handle);
      else
      {
        // do I have a signature for it?
        signature_container::iterator iter = _signatures.find(block_message_to_handle.block_id);
        if (iter != _signatures.end())
        {
          // it's signed!
          block_message_to_handle.signature = iter->signature;
          _signatures.erase(iter);
          push_valid_signed_block(block_message_to_handle);
        }
        else
          _unsigned_blocks.insert(block_message_to_handle);
      }
      break;
    }
  case trx_message_type:
    {
      trx_message trx_message_to_handle(message_to_handle.as<trx_message>());
      store_transaction(trx_message_to_handle);
      break;
    }
  case signature_message_type:
    {
      signature_message signature_message_to_handle(message_to_handle.as<signature_message>());
      // do we have a block for it?
      block_container::iterator iter = _unsigned_blocks.find(signature_message_to_handle.block_id);
      if (iter != _unsigned_blocks.end())
      {
        block_message signed_block_message = *iter;
        _unsigned_blocks.erase(iter);
        signed_block_message.signature = signature_message_to_handle.signature;
        push_valid_signed_block(signed_block_message);
      }
      else
        _signatures.insert(signature_message_to_handle);
      break;
    }
  }

  // only cache the message if it was valid (we didn't throw)
  _message_cache.cache_message(message_to_handle, message_to_handle.id());
}

std::vector<item_hash_t> simple_net_test_miner::get_item_ids(const item_id& from_id,
                                                             uint32_t& remaining_item_count,
                                                             uint32_t limit)
{
  // artificially limit to 50 ids per message during testing
  limit = 50;

  ordered_blockchain_container::index<block_hash_index>::type::iterator block_hash_iter = _blockchain.get<block_hash_index>().find(from_id.item_hash);
  if (block_hash_iter == _blockchain.get<block_hash_index>().end())
  {
    remaining_item_count = 0;
    return std::vector<item_hash_t>();
  }
  ordered_blockchain_container::nth_index<0>::type::iterator sequential_iter = _blockchain.project<0>(block_hash_iter);
  ++sequential_iter;
  remaining_item_count = _blockchain.get<0>().end() - sequential_iter;
  uint32_t items_to_get_this_iteration = std::min(limit, remaining_item_count);
  std::vector<item_hash_t> hashes_to_return;
  hashes_to_return.reserve(items_to_get_this_iteration);
  for (uint32_t i = 0; i < items_to_get_this_iteration; ++i)
  {
    hashes_to_return.push_back(sequential_iter->block_id);
    ++sequential_iter;
  }
  remaining_item_count -= items_to_get_this_iteration;
  return hashes_to_return;
}

message simple_net_test_miner::get_item(const item_id& id)
{
  try
  {
    message result = _message_cache.get_message(id.item_hash);
    ilog("get_item() returning message from _message_cache (id: ${item_hash})", ("item_hash", result.id()));
    ilog("item's real hash is ${hash}", ("hash", fc::ripemd160::hash(&result.data[0], result.data.size())));
    return result;
  }
  catch (const fc::key_not_found_exception&)
  {
    // not in our cache.  Either it has already expired from our cache, or
    // it's a request for an actual block during synchronization.
  }

  if (id.item_type == block_message_type)
  {
    ordered_blockchain_container::index<block_hash_index>::type::iterator iter = _blockchain.get<block_hash_index>().find(id.item_hash);
    if (iter != _blockchain.get<block_hash_index>().end())
    {
      ilog("get_item() treating id as block_id, should only happen during sync");
      return *iter;
    }
  }

  FC_THROW_EXCEPTION(key_not_found_exception, "I don't have the item you're looking for");
}

void simple_net_test_miner::sync_status(uint32_t item_type, uint32_t item_count)
{
  _remaining_items_to_sync = item_count;
  _synchronized = _remaining_items_to_sync == 0;
  if (!item_count)
    ilog("TEST CLIENT: I am now in sync");
}

void simple_net_test_miner::connection_count_changed(uint32_t c)
{
  ilog("TEST CLIENT: I now have ${count} connections", ("count", c));
}

int main(int argc, char* argv[])
{
  boost::program_options::options_description option_config("Allowed options");
  option_config.add_options()("port", boost::program_options::value<uint16_t>(), "set port to listen on")
                             ("connect-to", boost::program_options::value<std::string>(), "set remote host to connect to")
                             ("config-dir", boost::program_options::value<std::string>(), "directory containing config files");
  boost::program_options::variables_map option_variables;
  boost::program_options::store(boost::program_options::parse_command_line(argc, argv, option_config), option_variables);
  boost::program_options::notify(option_variables);

  simple_net_test_miner miner;

  if (option_variables.count("config-dir"))
    miner.set_config_dir(option_variables["config-dir"].as<std::string>());

  if (option_variables.count("port"))
    miner.set_port(option_variables["port"].as<uint16_t>());

  miner.start();

  if (option_variables.count("connect-to"))
    miner.connect_to(fc::ip::endpoint::from_string(option_variables["connect-to"].as<std::string>()));

  miner.run();
  return 0;
}

max_stars_repo_name: emfrias/bitshares

max_issues_repo_name: denkhaus/bitsharesx

max_forks_repo_name: denkhaus/bitsharesx


text:
#pragma once

#include <boost/optional.hpp>

namespace m2d
{
namespace savanna
{
	template <typename Response>
	class result
	{
	public:
		boost::optional<Response> response;
		boost::optional<boost::system::system_error> error;

		result(Response response)
		    : response(response)
		    , error(boost::none)
		{
		}

		result(boost::system::system_error error)
		    : response(boost::none)
		    , error(error)
		{
		}
	};
}
}

ext: hpp

max_stars_repo_name: srchack/savanna

max_issues_repo_name: srchack/savanna

max_forks_repo_name: srchack/savanna


text:
#include <slas/util/detail/system.h>

#include <boost/log/trivial.hpp>

namespace util
{

namespace detail
{

FILE* System::fopen(const char *path, const char *mode) {
  BOOST_LOG_TRIVIAL(debug) << "libpatlms::util::detail::System::fopen: Function call with (path=" << path << "; mode=" << mode << ")";
  return ::fopen(path, mode);
}

size_t System::fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) {
  BOOST_LOG_TRIVIAL(debug) << "libpatlms::util::detail::System::fwrite: Function call with (ptr*; size=" << size << "; nmemb=" << nmemb << "; stream=*)";
  return ::fwrite(ptr, size, nmemb, stream);
}

int System::fclose(FILE *fp) {
  BOOST_LOG_TRIVIAL(debug) << "libpatlms::util::detail::System::fclose: Function call with (fp=*)";
  return ::fclose(fp);
}

pid_t System::getpid(void) {
  BOOST_LOG_TRIVIAL(debug) << "libpatlms::util::detail::System::getpid: Function call";
  return ::getpid();
}

int System::unlink(const char *pathname) {
  BOOST_LOG_TRIVIAL(debug) << "libpatlms::util::detail::System::getpid: Function call with (pathname=" << pathname << ")";
  return ::unlink(pathname);
}

int System::access(const char *pathname, int mode) {
  BOOST_LOG_TRIVIAL(debug) << "libpatlms::util::detail::System::stat: Function call with (pathname=" << pathname << "; buf=*)";
  return ::access(pathname, mode);
}

}

}

ext: cpp

max_stars_repo_name: chyla/slas

max_issues_repo_name: chyla/slas

max_forks_repo_name: chyla/slas


text:
/////////////////////////////////////////////////////////////////////////////
// Name:        src/system.cpp
// Purpose:     source for system managing class
// Author:      Akiva Miura <akiva.miura@gmail.com>
// Modified by:
// Created:     13/10/2011
// Copyright:   (C) 2010-2011 Akiva Miura
// Licence:     MIT License
/////////////////////////////////////////////////////////////////////////////

// pre-compiled header
#include "prec.h"

// declarations
#include "lev/system.hpp"

// dependencies
#include "lev/debug.hpp"
#include "lev/draw.hpp"
#include "lev/entry.hpp"
#include "lev/screen.hpp"
#include "lev/sound.hpp"
#include "lev/timer.hpp"
#include "lev/util.hpp"

// libraries
#include <boost/weak_ptr.hpp>
#include <map>
#include <luabind/luabind.hpp>
#include <luabind/raw_policy.hpp>
#include <SDL2/SDL.h>
#include <vector>

int luaopen_lev_system(lua_State *L)
{
  using namespace luabind;
  using namespace lev;

  open(L);
  // beginning to load
  globals(L)["package"]["loaded"]["lev.system"] = true;
  // pre-requirement
  globals(L)["require"]("lev.base");
  globals(L)["require"]("lev.image");
  globals(L)["require"]("lev.timer");
  globals(L)["require"]("lev.debug");

  module(L, "lev")
  [
    namespace_("system"),
    namespace_("classes")
    [
      class_<event, base, boost::shared_ptr<base> >("event")
        .property("button", &event::get_button)
        .property("clone", &event::clone)
        .def("copy", &event::clone)
        .property("dx", &event::get_dx)
        .property("dy", &event::get_dy)
        .property("id", &event::get_id)
        .property("is_pressed", &event::is_pressed)
        .property("is_released", &event::is_released)
        .property("key", &event::get_key)
        .property("keycode", &event::get_key_code)
        .property("key_code", &event::get_key_code)
        .property("left_is_down", &event::left_is_down)
        .property("middle_is_down", &event::middle_is_down)
        .property("pressed", &event::is_pressed)
        .property("released", &event::is_released)
        .property("right_is_down", &event::right_is_down)
        .property("scan_code", &event::get_scancode)
        .property("scancode", &event::get_scancode)
        .property("time", &event::get_timestamp)
        .property("timestamp", &event::get_timestamp)
        .property("x", &event::get_x)
        .property("xrel", &event::get_dx)
        .property("y", &event::get_y)
        .property("yrel", &event::get_dy),
      class_<lev::system, base, boost::shared_ptr<base> >("system")
        .def("close", &system::close)
        .def("create_mixer", &mixer::init)
        .property("dbg", &system::get_debugger)
        .property("debugger", &system::get_debugger)
        .def("delay", &system::delay)
        .def("do_event", &system::do_event)
        .def("do_events", &system::do_events)
        .def("done", &system::close)
        .property("elapsed", &system::get_elapsed)
        .property("is_debugging", &system::is_debugging)
        .property("is_running", &system::is_running, &system::set_running)
        .def("mixer", &mixer::init)
        .property("name", &system::get_name, &system::set_name)
        .property("on_button_down", &system::get_on_button_down, &system::set_on_button_down)
        .property("on_button_up", &system::get_on_button_up, &system::set_on_button_up)
        .property("on_idle", &system::get_on_idle, &system::set_on_idle)
        .property("on_key_down", &system::get_on_key_down, &system::set_on_key_down)
        .property("on_key_up", &system::get_on_key_up, &system::set_on_key_up)
        .property("on_left_down", &system::get_on_left_down, &system::set_on_left_down)
        .property("on_left_up", &system::get_on_left_up, &system::set_on_left_up)
        .property("on_middle_down", &system::get_on_middle_down, &system::set_on_middle_down)
        .property("on_middle_up", &system::get_on_middle_up, &system::set_on_middle_up)
        .property("on_motion", &system::get_on_motion, &system::set_on_motion)
        .property("on_quit", &system::get_on_quit, &system::set_on_quit)
        .property("on_right_down", &system::get_on_right_down, &system::set_on_right_down)
        .property("on_right_up", &system::get_on_right_up, &system::set_on_right_up)
        .def("quit", &system::quit)
        .def("quit", &system::quit0)
        .def("run", &system::run)
        .def("set_running", &system::set_running)
        .def("start_debug", &system::start_debug)
        .def("stop_debug", &system::stop_debug)
        .property("time", &system::get_elapsed)
        .scope
        [
          def("get", &system::get),
          def("init", &system::init, raw(_1))
        ]
    ]
  ];
  object lev = globals(L)["lev"];
  object classes = lev["classes"];
  lev["system"] = classes["system"]["init"];

  // post-requirement
  globals(L)["require"]("lev.screen");
  // end of loading
  globals(L)["package"]["loaded"]["lev.system"] = true;
  return 0;
}

namespace lev
{

  const char *input::to_keyname(long code)
  {
    static std::map<long, std::string> *keymap = NULL;

    if (keymap == NULL)
    {
      try {
        keymap = new std::map<long, std::string>;

        for (int i = 0; i <= 127; i++)
        {
          char ascii[2] = {tolower(i), 0};
          (*keymap)[tolower(i)] = ascii;
        }

        (*keymap)[SDLK_UNKNOWN]            = "(unknown)";
        (*keymap)[SDLK_AC_BACK]            = "ac_back";
        (*keymap)[SDLK_AC_BOOKMARKS]       = "ac_bookmarks";
        (*keymap)[SDLK_AC_FORWARD]         = "ac_forward";
        (*keymap)[SDLK_AC_HOME]            = "ac_home";
        (*keymap)[SDLK_AC_REFRESH]         = "ac_refresh";
        (*keymap)[SDLK_AC_SEARCH]          = "ac_search";
        (*keymap)[SDLK_AC_STOP]            = "ac_stop";
        (*keymap)[SDLK_AGAIN]              = "again";
        (*keymap)[SDLK_ALTERASE]           = "alterase";
        (*keymap)[SDLK_AMPERSAND]          = "ampersand";
        (*keymap)[SDLK_APPLICATION]        = "application";
        (*keymap)[SDLK_ASTERISK]           = "asterisk";
        (*keymap)[SDLK_AT]                 = "at";
        (*keymap)[SDLK_AUDIOMUTE]          = "audiomute";
        (*keymap)[SDLK_AUDIONEXT]          = "audionext";
        (*keymap)[SDLK_AUDIOPLAY]          = "audioplay";
        (*keymap)[SDLK_AUDIOPREV]          = "audioprev";
        (*keymap)[SDLK_AUDIOSTOP]          = "audiostop";
        (*keymap)[SDLK_BACKSLASH]          = "backslash";
        (*keymap)[SDLK_BACKSPACE]          = "backspace";
        (*keymap)[SDLK_BACKQUOTE]          = "backquote";
        (*keymap)[SDLK_BRIGHTNESSDOWN]     = "brightnessdown";
        (*keymap)[SDLK_BRIGHTNESSUP]       = "brightnessup";
        (*keymap)[SDLK_CALCULATOR]         = "calculator";
        (*keymap)[SDLK_CANCEL]             = "cancel";
        (*keymap)[SDLK_CAPSLOCK]           = "capslock";
        (*keymap)[SDLK_CARET]              = "caret";
        (*keymap)[SDLK_CLEAR]              = "clear";
        (*keymap)[SDLK_CLEARAGAIN]         = "clearagain";
        (*keymap)[SDLK_COLON]              = "colon";
        (*keymap)[SDLK_COMMA]              = "comma";
        (*keymap)[SDLK_COMPUTER]           = "computer";
        (*keymap)[SDLK_COPY]               = "copy";
        (*keymap)[SDLK_CRSEL]              = "crsel";
        (*keymap)[SDLK_CURRENCYUNIT]       = "currencyunit";
        (*keymap)[SDLK_CURRENCYSUBUNIT]    = "currencysubunit";
        (*keymap)[SDLK_CUT]                = "cut";
        (*keymap)[SDLK_DECIMALSEPARATOR]   = "decimalseparator";
        (*keymap)[SDLK_DELETE]             = "delete";
        (*keymap)[SDLK_DISPLAYSWITCH]      = "displayswitch";
        (*keymap)[SDLK_DOLLAR]             = "dollar";
        (*keymap)[SDLK_DOWN]               = "down";
        (*keymap)[SDLK_QUOTEDBL]           = "doublequote";
        (*keymap)[SDLK_EJECT]              = "eject";
        (*keymap)[SDLK_END]                = "end";
        (*keymap)[SDLK_EQUALS]             = "equals";
        (*keymap)[SDLK_ESCAPE]             = "escape";
        (*keymap)[SDLK_EXCLAIM]            = "exclaim";
        (*keymap)[SDLK_EXECUTE]            = "execute";
        (*keymap)[SDLK_EXSEL]              = "exsel";
        (*keymap)[SDLK_F1]                 = "f1";
        (*keymap)[SDLK_F2]                 = "f2";
        (*keymap)[SDLK_F3]                 = "f3";
        (*keymap)[SDLK_F4]                 = "f4";
        (*keymap)[SDLK_F5]                 = "f5";
        (*keymap)[SDLK_F6]                 = "f6";
        (*keymap)[SDLK_F7]                 = "f7";
        (*keymap)[SDLK_F8]                 = "f8";
        (*keymap)[SDLK_F9]                 = "f9";
        (*keymap)[SDLK_F10]                = "f10";
        (*keymap)[SDLK_F11]                = "f11";
        (*keymap)[SDLK_F12]                = "f12";
        (*keymap)[SDLK_F13]                = "f13";
        (*keymap)[SDLK_F14]                = "f14";
        (*keymap)[SDLK_F15]                = "f15";
        (*keymap)[SDLK_F16]                = "f16";
        (*keymap)[SDLK_F17]                = "f17";
        (*keymap)[SDLK_F18]                = "f18";
        (*keymap)[SDLK_F19]                = "f19";
        (*keymap)[SDLK_F20]                = "f20";
        (*keymap)[SDLK_F21]                = "f21";
        (*keymap)[SDLK_F22]                = "f22";
        (*keymap)[SDLK_F23]                = "f23";
        (*keymap)[SDLK_F24]                = "f24";
        (*keymap)[SDLK_FIND]               = "find";
        (*keymap)[SDLK_GREATER]            = "greater";
        (*keymap)[SDLK_HASH]               = "hash";
        (*keymap)[SDLK_HELP]               = "help";
        (*keymap)[SDLK_HOME]               = "home";
        (*keymap)[SDLK_INSERT]             = "insert";
        (*keymap)[SDLK_KBDILLUMDOWN]       = "kbdillumdown";
        (*keymap)[SDLK_KBDILLUMTOGGLE]     = "kbdillumtoggle";
        (*keymap)[SDLK_KBDILLUMUP]         = "kbdillumup";
        (*keymap)[SDLK_KP_0]               = "kp_0";
        (*keymap)[SDLK_KP_1]               = "kp_1";
        (*keymap)[SDLK_KP_2]               = "kp_2";
        (*keymap)[SDLK_KP_3]               = "kp_3";
        (*keymap)[SDLK_KP_4]               = "kp_4";
        (*keymap)[SDLK_KP_5]               = "kp_5";
        (*keymap)[SDLK_KP_6]               = "kp_6";
        (*keymap)[SDLK_KP_7]               = "kp_7";
        (*keymap)[SDLK_KP_8]               = "kp_8";
        (*keymap)[SDLK_KP_9]               = "kp_9";
        (*keymap)[SDLK_KP_00]              = "kp_00";
        (*keymap)[SDLK_KP_000]             = "kp_000";
        (*keymap)[SDLK_KP_A]               = "kp_a";
        (*keymap)[SDLK_KP_AMPERSAND]       = "kp_ampersand";
        (*keymap)[SDLK_KP_AT]              = "kp_at";
        (*keymap)[SDLK_KP_B]               = "kp_b";
        (*keymap)[SDLK_KP_BACKSPACE]       = "kp_backspace";
        (*keymap)[SDLK_KP_BINARY]          = "kp_binary";
        (*keymap)[SDLK_KP_C]               = "kp_c";
        (*keymap)[SDLK_KP_CLEAR]           = "kp_clear";
        (*keymap)[SDLK_KP_CLEARENTRY]      = "kp_clearentry";
        (*keymap)[SDLK_KP_COLON]           = "kp_colon";
        (*keymap)[SDLK_KP_COMMA]           = "kp_comma";
        (*keymap)[SDLK_KP_D]               = "kp_d";
        (*keymap)[SDLK_KP_DBLAMPERSAND]    = "kp_dblampersand";
        (*keymap)[SDLK_KP_DBLVERTICALBAR]  = "kp_dblverticalbar";
        (*keymap)[SDLK_KP_DECIMAL]         = "kp_decimal";
        (*keymap)[SDLK_KP_DIVIDE]          = "kp_divide";
        (*keymap)[SDLK_KP_E]               = "kp_e";
        (*keymap)[SDLK_KP_ENTER]           = "kp_enter";
        (*keymap)[SDLK_KP_EQUALS]          = "kp_equals";
        (*keymap)[SDLK_KP_EQUALSAS400]     = "kp_equalsas400";
        (*keymap)[SDLK_KP_EXCLAM]          = "kp_exclam";
        (*keymap)[SDLK_KP_F]               = "kp_f";
        (*keymap)[SDLK_KP_GREATER]         = "kp_greater";
        (*keymap)[SDLK_KP_HASH]            = "kp_hash";
        (*keymap)[SDLK_KP_HEXADECIMAL]     = "kp_hexadecimal";
        (*keymap)[SDLK_KP_LEFTBRACE]       = "kp_leftbrace";
        (*keymap)[SDLK_KP_LEFTPAREN]       = "kp_leftparen";
        (*keymap)[SDLK_KP_LESS]            = "kp_less";
        (*keymap)[SDLK_KP_MEMADD]          = "kp_memadd";
        (*keymap)[SDLK_KP_MEMCLEAR]        = "kp_memclear";
        (*keymap)[SDLK_KP_MEMDIVIDE]       = "kp_memdivide";
        (*keymap)[SDLK_KP_MEMMULTIPLY]     = "kp_memmultiply";
        (*keymap)[SDLK_KP_MEMRECALL]       = "kp_memrecall";
        (*keymap)[SDLK_KP_MEMSTORE]        = "kp_memstore";
        (*keymap)[SDLK_KP_MEMSUBTRACT]     = "kp_memsubtract";
        (*keymap)[SDLK_KP_MINUS]           = "kp_minus";
        (*keymap)[SDLK_KP_MULTIPLY]        = "kp_multiply";
        (*keymap)[SDLK_KP_OCTAL]           = "kp_octal";
        (*keymap)[SDLK_KP_PERCENT]         = "kp_percent";
        (*keymap)[SDLK_KP_PERIOD]          = "kp_period";
        (*keymap)[SDLK_KP_PLUS]            = "kp_plus";
        (*keymap)[SDLK_KP_PLUSMINUS]       = "kp_plusminus";
        (*keymap)[SDLK_KP_POWER]           = "kp_power";
        (*keymap)[SDLK_KP_RIGHTBRACE]      = "kp_rightbrace";
        (*keymap)[SDLK_KP_RIGHTPAREN]      = "kp_rightparen";
        (*keymap)[SDLK_KP_SPACE]           = "kp_space";
        (*keymap)[SDLK_KP_TAB]             = "kp_tab";
        (*keymap)[SDLK_KP_VERTICALBAR]     = "kp_verticalbar";
        (*keymap)[SDLK_KP_XOR]             = "kp_xor";
        (*keymap)[SDLK_LALT]               = "lalt";
        (*keymap)[SDLK_LCTRL]              = "lctrl";
        (*keymap)[SDLK_LEFT]               = "left";
        (*keymap)[SDLK_LEFTBRACKET]        = "leftbracket";
        (*keymap)[SDLK_LEFTPAREN]          = "leftparen";
        (*keymap)[SDLK_LESS]               = "less";
        (*keymap)[SDLK_LGUI]               = "lgui";
        (*keymap)[SDLK_LSHIFT]             = "lshift";
        (*keymap)[SDLK_MAIL]               = "mail";
        (*keymap)[SDLK_MEDIASELECT]        = "mediaselect";
        (*keymap)[SDLK_MENU]               = "menu";
        (*keymap)[SDLK_MINUS]              = "minus";
        (*keymap)[SDLK_MODE]               = "mode";
        (*keymap)[SDLK_MUTE]               = "mute";
        (*keymap)[SDLK_NUMLOCKCLEAR]       = "numlockclear";
        (*keymap)[SDLK_OPER]               = "oper";
        (*keymap)[SDLK_OUT]                = "out";
        (*keymap)[SDLK_PAGEDOWN]           = "pagedown";
        (*keymap)[SDLK_PAGEUP]             = "pageup";
        (*keymap)[SDLK_PASTE]              = "paste";
        (*keymap)[SDLK_PAUSE]              = "pause";
        (*keymap)[SDLK_PERCENT]            = "percent";
        (*keymap)[SDLK_PERIOD]             = "period";
        (*keymap)[SDLK_PLUS]               = "plus";
        (*keymap)[SDLK_POWER]              = "power";
        (*keymap)[SDLK_PRINTSCREEN]        = "printscreen";
        (*keymap)[SDLK_PRIOR]              = "prior";
        (*keymap)[SDLK_QUOTE]              = "quote";
        (*keymap)[SDLK_QUESTION]           = "question";
        (*keymap)[SDLK_RALT]               = "ralt";
        (*keymap)[SDLK_RCTRL]              = "rctrl";
        (*keymap)[SDLK_RETURN]             = "return";
        (*keymap)[SDLK_RETURN2]            = "return2";
        (*keymap)[SDLK_RGUI]               = "rgui";
        (*keymap)[SDLK_RIGHT]              = "right";
        (*keymap)[SDLK_RIGHTPAREN]         = "rightparen";
        (*keymap)[SDLK_RIGHTBRACKET]       = "rightbracket";
        (*keymap)[SDLK_RSHIFT]             = "rshift";
        (*keymap)[SDLK_SCROLLLOCK]         = "scrolllock";
        (*keymap)[SDLK_SELECT]             = "select";
        (*keymap)[SDLK_SEMICOLON]          = "semicolon";
        (*keymap)[SDLK_SEPARATOR]          = "separator";
        (*keymap)[SDLK_SLASH]              = "slash";
        (*keymap)[SDLK_SLEEP]              = "sleep";
        (*keymap)[SDLK_SPACE]              = "space";
        (*keymap)[SDLK_STOP]               = "stop";
        (*keymap)[SDLK_SYSREQ]             = "sysreq";
        (*keymap)[SDLK_TAB]                = "tab";
        (*keymap)[SDLK_THOUSANDSSEPARATOR] = "thousandsseparator";
        (*keymap)[SDLK_UNDERSCORE]         = "underscore";
        (*keymap)[SDLK_UNDO]               = "undo";
        (*keymap)[SDLK_UP]                 = "up";
        (*keymap)[SDLK_VOLUMEDOWN]         = "volumedown";
        (*keymap)[SDLK_VOLUMEUP]           = "volumeup";
        (*keymap)[SDLK_WWW]                = "www";
      }
      catch (...) {
        delete keymap;
        keymap = NULL;
        return "(error)";
      }
    }

    std::map<long, std::string>::iterator found;
    found = keymap->find(code);
    if (found == keymap->end()) { return "(undefined)"; }
    else { return found->second.c_str(); }
  }

  static luabind::object safe_call(luabind::object func)
  {
    using namespace luabind;
    lua_State *L = func.interpreter();
    func.push(L);
    if (lua_pcall(L, 0 /* nargs */, 1 /* nreturns */, 0 /* std errror */))
    {
      lev::debug_print(lua_tostring(L, -1));
    }
    luabind::object o(from_stack(L, -1));
    lua_pop(L, 1);
    return o;
  }
  static luabind::object safe_call(luabind::object func, luabind::object arg1)
  {
    using namespace luabind;
    lua_State *L = func.interpreter();
    func.push(L);
    arg1.push(L);
    if (lua_pcall(L, 1 /* nargs */, 1 /* nreturns */, 0 /* std errror */))
    {
      lev::debug_print(lua_tostring(L, -1));
    }
    luabind::object o(from_stack(L, -1));
    lua_pop(L, 1);
    return o;
  }

  // event class implementation
  class impl_event : public event
  {
    public:
      typedef boost::shared_ptr<impl_event> ptr;
    protected:
      impl_event() :
        event(),
        evt()
      { }
    public:
      virtual ~impl_event() { }

      virtual event::ptr clone()
      {
        impl_event::ptr e;
        try {
          e.reset(new impl_event);
          if (! e) { throw -1; }
          e->evt = evt;
        }
        catch (...) {
          e.reset();
          lev::debug_print("error on event instance cloning");
        }
        return e;
      }

      static impl_event::ptr create()
      {
        impl_event::ptr e;
        try {
          e.reset(new impl_event);
          if (! e) { throw -1; }
        }
        catch (...) {
          e.reset();
          lev::debug_print("error on event instance creation");
        }
        return e;
      }

      virtual std::string get_button() const
      {
        if (evt.type == SDL_MOUSEBUTTONDOWN || evt.type == SDL_MOUSEBUTTONUP)
        {
          switch (evt.button.button)
          {
            case SDL_BUTTON_LEFT:
              return "left";
            case SDL_BUTTON_MIDDLE:
              return "middle";
            case SDL_BUTTON_RIGHT:
              return "right";
            case SDL_BUTTON_X1:
              return "wheel_up";
            case SDL_BUTTON_X2:
              return "wheel_down";
            default:
              return "";
          }
        }
        return "";
      }

      virtual int get_dx() const
      {
        if (evt.type == SDL_MOUSEMOTION)
        {
          return evt.motion.xrel;
        }
        return 0;
      }

      virtual int get_dy() const
      {
        if (evt.type == SDL_MOUSEMOTION)
        {
          return evt.motion.yrel;
        }
        return 0;
      }

      virtual int get_id() const
      {
        return evt.window.windowID;
      }

      virtual std::string get_key() const
      {
        if (evt.type == SDL_KEYDOWN || evt.type == SDL_KEYUP)
        {
          return input::to_keyname(evt.key.keysym.sym);
        }
        return "";
      }

      virtual long get_key_code() const
      {
        if (evt.type == SDL_KEYDOWN || evt.type == SDL_KEYUP)
        {
          return evt.key.keysym.sym;
        }
        return -1;
      }

      virtual long get_scancode() const
      {
        if (evt.type == SDL_KEYDOWN || evt.type == SDL_KEYUP)
        {
          return evt.key.keysym.scancode;
        }
        return -1;
      }

      virtual double get_timestamp() const
      {
        return double(evt.window.timestamp) / 1000;
      }

      virtual int get_x() const
      {
        if (evt.type == SDL_MOUSEMOTION)
        {
          return evt.motion.x;
        }
        else if (evt.type == SDL_MOUSEBUTTONDOWN || evt.type == SDL_MOUSEBUTTONUP)
        {
          return evt.button.x;
        }
        else if (evt.type == SDL_MOUSEWHEEL)
        {
          return evt.wheel.x;
        }
        return -1;
      }

      virtual int get_y() const
      {
        if (evt.type == SDL_MOUSEMOTION)
        {
          return evt.motion.y;
        }
        else if (evt.type == SDL_MOUSEBUTTONDOWN || evt.type == SDL_MOUSEBUTTONUP)
        {
          return evt.button.y;
        }
        else if (evt.type == SDL_MOUSEWHEEL)
        {
          return evt.wheel.y;
        }
        return -1;
      }

      virtual bool is_pressed() const
      {
        if (evt.type == SDL_MOUSEBUTTONDOWN || evt.type == SDL_MOUSEBUTTONUP)
        {
          return evt.button.state == SDL_PRESSED;
        }
        return false;
      }

      virtual bool is_released() const
      {
        if (evt.type == SDL_MOUSEBUTTONDOWN || evt.type == SDL_MOUSEBUTTONUP)
        {
          return evt.button.state == SDL_RELEASED;
        }
        return false;
      }

      virtual bool left_is_down() const
      {
        if (evt.type == SDL_MOUSEMOTION)
        {
          return evt.motion.state & SDL_BUTTON_LMASK;
        }
        return false;
      }

      virtual bool middle_is_down() const
      {
        if (evt.type == SDL_MOUSEMOTION)
        {
          return evt.motion.state & SDL_BUTTON_MMASK;
        }
        return false;
      }

      virtual bool right_is_down() const
      {
        if (evt.type == SDL_MOUSEMOTION)
        {
          return evt.motion.state & SDL_BUTTON_RMASK;
        }
        return false;
      }

      SDL_Event evt;
  };

  class system_core
  {
    public:
      typedef boost::shared_ptr<system_core> ptr;
      static system_core::ptr singleton;
    protected:
      system_core(lua_State *L) :
        dbg(),
        funcs(), name("lev"), running(true),
        on_idle(),
        on_left_down(),   on_left_up(),
        on_middle_down(), on_middle_up(),
        on_right_down(),  on_right_up(),
        screens(),
        timers(),
        L(L)
      { }
    public:

      static system_core::ptr init(lua_State *L)
      {
        if (singleton) { return singleton; }
        try {
          singleton.reset(new system_core(L));
          if (! singleton) { throw -1; }
printf("INITTING!\n");
          if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { throw -2; }
//          if (SDL_Init(SDL_INIT_VIDEO) < 0) { throw -2; }
//printf("VIDEO INITTED!\n");
printf("INITTED!\n");

          // Fullscreen feature of SDL is not yet completed.
          //SDL_DisplayMode mode = { 0 };
          //SDL_SetFullscreenDisplayMode(&mode);

          SDL_GL_SetAttribute(SDL_GL_RED_SIZE,    8);
          SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,  8);
          SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,   8);
          SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE,  8);
          SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
          SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

          singleton->evt = impl_event::create();
          if (! singleton->evt) { throw -3; }
        }
        catch (...) {
          singleton.reset();
          lev::debug_print("error on system initialization");
        }
        return singleton;
      }

      virtual ~system_core()
      {
printf("QUITING1\n");
        dbg.reset();
//        if (mixer::get())
//        {
//          SDL_CloseAudio();
//        }
printf("QUITING2\n");
        SDL_Quit();
printf("QUITING3\n");
      }

      lua_State *L;
      debugger::ptr dbg;
      std::map<Uint32, luabind::object> funcs;
      std::string name;
      luabind::object on_idle;
      luabind::object on_left_down,   on_left_up;
      luabind::object on_middle_down, on_middle_up;
      luabind::object on_right_down,  on_right_up;
      std::map<Uint32, boost::weak_ptr<screen> > screens;
      std::vector<boost::weak_ptr<timer> > timers;
      impl_event::ptr evt;
      bool running;
  };
  system_core::ptr system_core::singleton;

  class impl_system : public system
  {
    public:
      typedef boost::shared_ptr<impl_system> ptr;
    protected:
      impl_system() : core() { }

    public:
      virtual ~impl_system()
      {
        close();
      }

      virtual bool attach(debugger::ptr d)
      {
        if (! core || ! d) { return false; }
        core->dbg = d;
        return true;
      }

      virtual bool attach(boost::shared_ptr<screen> s)
      {
        if (! core) { return false; }
        if (s->get_id() >= 0)
        {
          core->screens[s->get_id()] = s;
          return true;
        }
        return false;
      }

      virtual bool attach(boost::shared_ptr<timer> t)
      {
        if (! core) { return false; }
        if (! t) { return false; }
printf("ATTACH TIMER!\n");
        core->timers.push_back(t);
        return true;
      }

      virtual bool close()
      {
        if (! core) { return false; }
//printf("DONE CORE COUNT: %ld\n", system_core::singleton.use_count());
        core.reset();
//printf("RESETTED CORE COUNT: %ld\n", system_core::singleton.use_count());
        if (system_core::singleton.use_count() == 1)
        {
printf("SINGLETON CLEAR!\n");
          system_core::singleton.reset();
        }
        return true;
      }

      virtual bool delay(double seconds = 1)
      {
        if (! core) { return false; }
        SDL_Delay(seconds * 1000);
        return true;
      }

      virtual bool do_event()
      {
        if (! core) { return false; }

        std::vector<boost::weak_ptr<timer> >::iterator i = core->timers.begin();
        for ( ; i != core->timers.end(); i++)
        {
          if (boost::shared_ptr<timer> t = i->lock())
          {
//printf("PROVING!\n");
            t->probe();
          }
          else
          {
//printf("DETACHING TIMER!\n");
            core->timers.erase(i);
            break;
          }
        }

        SDL_Event &e = core->evt->evt;
        if (SDL_PollEvent(&e))
        {
          luabind::object f;

          if (e.type == SDL_KEYDOWN || e.type == SDL_KEYUP)
          {
            if (screen::ptr s = core->screens[e.key.windowID].lock())
            {
              if (e.type == SDL_KEYDOWN) { f = s->get_on_key_down(); }
              else { f = s->get_on_key_up(); }
            }
          }
          else if (e.type == SDL_MOUSEBUTTONDOWN ||
                   e.type == SDL_MOUSEBUTTONUP)
          {
            SDL_MouseButtonEvent &btn = e.button;
            if (screen::ptr s = core->screens[e.button.windowID].lock())
            {
              if (btn.button == SDL_BUTTON_LEFT)
              {
                if (btn.state == SDL_PRESSED)       { f = s->get_on_left_down(); }
                else if (btn.state == SDL_RELEASED) { f = s->get_on_left_up(); }
              }
              else if (btn.button == SDL_BUTTON_MIDDLE)
              {
                if (btn.state == SDL_PRESSED)       { f = s->get_on_middle_down(); }
                else if (btn.state == SDL_RELEASED) { f = s->get_on_middle_up(); }
              }
              else if (btn.button == SDL_BUTTON_RIGHT)
              {
                if (btn.state == SDL_PRESSED)       { f = s->get_on_right_down(); }
                else if (btn.state == SDL_RELEASED) { f = s->get_on_right_up(); }
              }
            }
            if (! f.is_valid())
            {
              if (btn.button == SDL_BUTTON_LEFT)
              {
                if (btn.state == SDL_PRESSED)       { f = core->on_left_down; }
                else if (btn.state == SDL_RELEASED) { f = core->on_left_up; }
              }
              if (btn.button == SDL_BUTTON_MIDDLE)
              {
                if (btn.state == SDL_PRESSED)       { f = core->on_middle_down; }
                else if (btn.state == SDL_RELEASED) { f = core->on_middle_up; }
              }
              if (btn.button == SDL_BUTTON_RIGHT)
              {
                if (btn.state == SDL_PRESSED)       { f = core->on_right_down; }
                else if (btn.state == SDL_RELEASED) { f = core->on_right_up; }
              }
            }
          }
          else if (e.type == SDL_MOUSEMOTION)
          {
            if (screen::ptr s = core->screens[e.motion.windowID].lock())
            {
              f = s->get_on_motion();
            }
          }
          else if (e.type == SDL_MOUSEWHEEL)
          {
            if (screen::ptr s = core->screens[e.wheel.windowID].lock())
            {
              f = s->get_on_wheel();
            }
          }
          else if (e.type == SDL_WINDOWEVENT)
          {
            if (screen::ptr s = core->screens[e.window.windowID].lock())
            {
              if (e.window.event == SDL_WINDOWEVENT_CLOSE)
              {
                f = s->get_on_close();
                if (! f.is_valid())
                {
                  if (core->dbg && s == core->dbg->get_screen())
                  {
                    // debug window
                    s->hide();
                  }
                  else
                  {
                    // normal window
                    s->close();
                  }
                }
              }
            }
          }
          else if (e.type == SDL_QUIT)
          {
            f = core->funcs[SDL_QUIT];
            if (! f.is_valid()) { set_running(false); }
          }
          else
          {
            // OTHERS
          }

          if (! f.is_valid())
          {
            f = core->funcs[e.type];
          }
          if (f.is_valid() && luabind::type(f) == LUA_TFUNCTION)
          {
            try {
              f(event::ptr(core->evt));
            }
            catch (...) {
              lev::debug_print(lua_tostring(core->L, -1));
              lev::debug_print("error on event processing\n");
            }
          }
          return true;
        }
        return false;
      }

      virtual bool do_events()
      {
        if (! core) { return false; }
        while (do_event()) { }
        return true;
      }

      static impl_system::ptr get()
      {
        impl_system::ptr sys;
        if (! system_core::singleton) { return sys; }
        try {
          sys.reset(new impl_system);
          if (! sys) { throw -1; }
          sys->core = system_core::singleton;
//printf("GET CORE COUNT: %ld\n", sys->core.use_count());
        }
        catch (...) {
          lev::debug_print("error on system instance cloning");
          sys.reset();
        }
        return sys;
      }

      virtual debugger::ptr get_debugger()
      {
        if (! core) { return debugger::ptr(); }
        return core->dbg;
      }

      virtual std::string get_name() const
      {
        if (! core) { return ""; }
        return core->name;
      }

      virtual luabind::object get_on_button_down()
      {
        if (! core) { return luabind::object(); }
        return core->funcs[SDL_MOUSEBUTTONDOWN];
      }

      virtual luabind::object get_on_button_up()
      {
        if (! core) { return luabind::object(); }
        return core->funcs[SDL_MOUSEBUTTONUP];
      }

      virtual luabind::object get_on_key_down()
      {
        if (! core) { return luabind::object(); }
        return core->funcs[SDL_KEYDOWN];
      }

      virtual luabind::object get_on_key_up()
      {
        if (! core) { return luabind::object(); }
        return core->funcs[SDL_KEYUP];
      }

      virtual luabind::object get_on_left_down()
      {
        if (! core) { return luabind::object(); }
        return core->on_left_down;
      }

      virtual luabind::object get_on_left_up()
      {
        if (! core) { return luabind::object(); }
        return core->on_left_up;
      }

      virtual luabind::object get_on_middle_down()
      {
        if (! core) { return luabind::object(); }
        return core->on_middle_down;
      }

      virtual luabind::object get_on_middle_up()
      {
        if (! core) { return luabind::object(); }
        return core->on_middle_up;
      }

      virtual luabind::object get_on_motion()
      {
        if (! core) { return luabind::object(); }
        return core->funcs[SDL_MOUSEMOTION];
      }

      virtual luabind::object get_on_quit()
      {
        if (! core) { return luabind::object(); }
        return core->funcs[SDL_QUIT];
      }

      virtual luabind::object get_on_right_down()
      {
        if (! core) { return luabind::object(); }
        return core->on_right_down;
      }

      virtual luabind::object get_on_right_up()
      {
        if (! core) { return luabind::object(); }
        return core->on_right_up;
      }

      virtual luabind::object get_on_idle()
      {
        if (! core) { return luabind::object(); }
        return core->on_idle;
      }

      virtual double get_elapsed() const
      {
        return double(SDL_GetPerformanceCounter()) / SDL_GetPerformanceFrequency();
      }

      static impl_system::ptr init(lua_State *L)
      {
        impl_system::ptr sys;
        if (! L) { return sys; }
        try {
          sys.reset(new impl_system);
          if (! sys) { throw -1; }
          sys->core = system_core::init(L);
          if (! sys->core) { throw -2; }
//printf("INIT CORE COUNT: %ld\n", sys->core.use_count());
        }
        catch (...) {
          lev::debug_print("error on system instance creation");
          sys.reset();
        }
        return sys;
      }

      virtual bool is_debugging() const
      {
        if (! core) { return false; }
        return core->dbg;
      }

      virtual bool is_running() const
      {
        if (! core) { return false; }
        return core->running;
      }

      virtual bool quit(bool force)
      {
        if (force)
        {
          set_running(false);
        }
        else
        {
          SDL_Event q;
          q.type = SDL_QUIT;
          SDL_PushEvent(&q);
        }
        return true;
      }

      virtual bool run()
      {
        if (! core) { return false; }
        core->running = true;
        while (is_running())
        {
          try {
            if (core->on_idle && luabind::type(core->on_idle) == LUA_TFUNCTION)
            {
              core->on_idle();
    //          safe_call(core->on_idle);
            }
            do_events();
          }
          catch (...) {
            lev::debug_print(lua_tostring(core->L, -1));
            lev::debug_print("error on system::run");
            return false;
          }
        }
        return true;
      }

      virtual bool set_name(const std::string &name)
      {
        if (! core) { return false; }
        core->name = name;
        return true;
      }

      virtual bool set_on_button_down(luabind::object func)
      {
        if (! core) { return false; }
        core->funcs[SDL_MOUSEBUTTONDOWN] = func;
        return true;
      }

      virtual bool set_on_button_up(luabind::object func)
      {
        if (! core) { return false; }
        core->funcs[SDL_MOUSEBUTTONUP] = func;
        return true;
      }

      virtual bool set_on_key_down(luabind::object func)
      {
        if (! core) { return false; }
        core->funcs[SDL_KEYDOWN] = func;
        return true;
      }

      virtual bool set_on_key_up(luabind::object func)
      {
        if (! core) { return false; }
        core->funcs[SDL_KEYUP] = func;
        return true;
      }

      virtual bool set_on_left_down(luabind::object func)
      {
        if (! core) { return false; }
        core->on_left_down = func;
        return true;
      }

      virtual bool set_on_left_up(luabind::object func)
      {
        if (! core) { return false; }
        core->on_left_up = func;
        return true;
      }

      virtual bool set_on_middle_down(luabind::object func)
      {
        if (! core) { return false; }
        core->on_middle_down = func;
        return true;
      }

      virtual bool set_on_middle_up(luabind::object func)
      {
        if (! core) { return false; }
        core->on_middle_up = func;
        return true;
      }

      virtual bool set_on_motion(luabind::object func)
      {
        if (! core) { return false; }
        core->funcs[SDL_MOUSEMOTION] = func;
        return true;
      }

      virtual bool set_on_quit(luabind::object func)
      {
        if (! core) { return false; }
        core->funcs[SDL_QUIT] = func;
        return true;
      }

      virtual bool set_on_right_down(luabind::object func)
      {
        if (! core) { return false; }
        core->on_right_down = func;
        return true;
      }

      virtual bool set_on_right_up(luabind::object func)
      {
        if (! core) { return false; }
        core->on_right_up = func;
        return true;
      }

      virtual bool set_on_idle(luabind::object func)
      {
        if (! core) { return false; }
        core->on_idle = func;
        return true;
      }

      virtual bool set_running(bool run)
      {
        if (! core) { return false; }
        core->running = run;
        return true;
      }

      virtual debugger::ptr start_debug()
      {
        return debugger::start();
      }

      virtual bool stop_debug()
      {
        if (! core) { return false; }
        if (! core->dbg) { return false; }
        core->dbg.reset();
        return true;
      }

      system_core::ptr core;
  };

  system::ptr system::get()
  {
    return impl_system::get();
  }

  system::ptr system::init(lua_State *L)
  {
    return impl_system::init(L);
  }

  lua_State *system::get_interpreter()
  {
    if (! system_core::singleton) { return NULL; }
    return system_core::singleton->L;
  }

}

max_stars_repo_name: akivajp/lev

max_issues_repo_name: akivajp/lev

max_forks_repo_name: akivajp/lev


text:
// This file is part of SWGANH which is released under the MIT license.
// See file LICENSE or go to http://swganh.com/LICENSE

#ifndef WIN32
#include <Python.h>
#endif

#include "character_create.h"

#include <boost/python.hpp>

#include "swganh/logger.h"

#include "swganh/app/swganh_kernel.h"
#include "swganh/service/service_manager.h"
#include "swganh/scripting/utilities.h"
#include "swganh/scripting/python_script.h"
#include "swganh_core/simulation/simulation_service.h"
#include "swganh_core/object/creature/creature.h"

namespace bp = boost::python;
using namespace swganh::character;
using namespace swganh::scripting;
using swganh::object::Creature;

PyCharacterCreate::PyCharacterCreate(swganh::app::SwganhKernel* kernel)
	: kernel_(kernel)
{
    simulation_ = kernel_->GetServiceManager()->GetService<swganh::simulation::SimulationService>("SimulationService");
}

uint64_t PyCharacterCreate::CreateCharacter(
	const std::wstring& full_name, const std::string& profession,
	const std::string& location, float height, const std::string& bio, const std::string& customization,
	const std::string& hair_iff, const std::string& hair_customization, const std::string& iff_template)
{
    uint64_t character_id = 0;
    std::vector<int> char_customization(customization.begin(), customization.end());
	std::vector<int> hair_custom(hair_customization.begin(), hair_customization.end());

    PythonScript script(kernel_->GetAppConfig().script_directory + "/character_create/create_starting_character.py");

    auto create_func = script.GetGlobal("CreateStartingCharacter");

    {
        ScopedGilLock lock;
        try
        {
            auto py_character = (*create_func)(bp::ptr(kernel_), height, iff_template, char_customization, full_name, profession, hair_iff, hair_custom, location);
            Creature* character = bp::extract<Creature*>(py_character);
            character_id = character->GetObjectId();

            simulation_->PersistRelatedObjects(character_id, true);
        }
        catch (bp::error_already_set&)
	    {
		    logPythonException();
	    }
    }

	return character_id;
}

ext: cc

max_stars_repo_name: apathyboy/swganh

max_issues_repo_name: apathyboy/swganh

max_forks_repo_name: apathyboy/swganh


text:
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.
//
// The following only applies to changes made to this file as part of YugaByte development.
//
// Portions Copyright (c) YugaByte, Inc.
//
// 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.
//

#include <algorithm>
#include <string>
#include <mutex>
#include <vector>

#include <boost/functional/hash.hpp>

#include <gflags/gflags.h>

#include "yb/gutil/strings/substitute.h"
#include "yb/gutil/walltime.h"

#include "yb/rpc/connection.h"
#include "yb/rpc/constants.h"
#include "yb/rpc/outbound_call.h"
#include "yb/rpc/rpc_controller.h"
#include "yb/rpc/rpc_introspection.pb.h"
#include "yb/rpc/rpc_metrics.h"
#include "yb/rpc/serialization.h"

#include "yb/util/flag_tags.h"
#include "yb/util/logging.h"
#include "yb/util/memory/memory.h"
#include "yb/util/pb_util.h"
#include "yb/util/thread_restrictions.h"
#include "yb/util/trace.h"
#include "yb/util/tsan_util.h"

METRIC_DEFINE_coarse_histogram(
    server, handler_latency_outbound_call_queue_time, "Time taken to queue the request ",
    yb::MetricUnit::kMicroseconds, "Microseconds spent to queue the request to the reactor");
METRIC_DEFINE_coarse_histogram(
    server, handler_latency_outbound_call_send_time, "Time taken to send the request ",
    yb::MetricUnit::kMicroseconds, "Microseconds spent to queue and write the request to the wire");
METRIC_DEFINE_coarse_histogram(
    server, handler_latency_outbound_call_time_to_response, "Time taken to get the response ",
    yb::MetricUnit::kMicroseconds,
    "Microseconds spent to send the request and get a response on the wire");

// 100M cycles should be about 50ms on a 2Ghz box. This should be high
// enough that involuntary context switches don't trigger it, but low enough
// that any serious blocking behavior on the reactor would.
DEFINE_int64(
    rpc_callback_max_cycles, 100 * 1000 * 1000 * yb::kTimeMultiplier,
    "The maximum number of cycles for which an RPC callback "
    "should be allowed to run without emitting a warning."
    " (Advanced debugging option)");
TAG_FLAG(rpc_callback_max_cycles, advanced);
TAG_FLAG(rpc_callback_max_cycles, runtime);
DECLARE_bool(rpc_dump_all_traces);

namespace yb {
namespace rpc {

using strings::Substitute;
using google::protobuf::Message;
using google::protobuf::io::CodedOutputStream;

OutboundCallMetrics::OutboundCallMetrics(const scoped_refptr<MetricEntity>& entity)
    : queue_time(METRIC_handler_latency_outbound_call_queue_time.Instantiate(entity)),
      send_time(METRIC_handler_latency_outbound_call_send_time.Instantiate(entity)),
      time_to_response(METRIC_handler_latency_outbound_call_time_to_response.Instantiate(entity)) {
}

namespace {

std::atomic<int32_t> call_id_ = {0};

int32_t NextCallId() {
  for (;;) {
    auto result = call_id_.fetch_add(1, std::memory_order_acquire);
    ++result;
    if (result > 0) {
      return result;
    }
    // When call id overflows, we reset it to zero.
    call_id_.compare_exchange_weak(result, 0);
  }
}

const std::string kEmptyString;

} // namespace

void InvokeCallbackTask::Run() {
  CHECK_NOTNULL(call_.get());
  call_->InvokeCallbackSync();
}

void InvokeCallbackTask::Done(const Status& status) {
  CHECK_NOTNULL(call_.get());
  if (!status.ok()) {
    LOG(WARNING) << Format(
        "Failed to schedule invoking callback on response for request $0 to $1: $2",
        call_->remote_method(), call_->hostname(), status);
    call_->SetThreadPoolFailure(status);
    // We are in the shutdown path, with the threadpool closing, so allow IO and wait.
    ThreadRestrictions::SetWaitAllowed(true);
    ThreadRestrictions::SetIOAllowed(true);
    call_->InvokeCallbackSync();
  }
  // Clear the call, since it holds OutboundCall object.
  call_ = nullptr;
}

///
/// OutboundCall
///

OutboundCall::OutboundCall(const RemoteMethod* remote_method,
                           const std::shared_ptr<OutboundCallMetrics>& outbound_call_metrics,
                           std::shared_ptr<const OutboundMethodMetrics> method_metrics,
                           google::protobuf::Message* response_storage,
                           RpcController* controller,
                           RpcMetrics* rpc_metrics,
                           ResponseCallback callback,
                           ThreadPool* callback_thread_pool)
    : hostname_(&kEmptyString),
      start_(CoarseMonoClock::Now()),
      controller_(DCHECK_NOTNULL(controller)),
      response_(DCHECK_NOTNULL(response_storage)),
      trace_(new Trace),
      call_id_(NextCallId()),
      remote_method_(remote_method),
      callback_(std::move(callback)),
      callback_thread_pool_(callback_thread_pool),
      outbound_call_metrics_(outbound_call_metrics),
      rpc_metrics_(rpc_metrics),
      method_metrics_(std::move(method_metrics)) {
  TRACE_TO_WITH_TIME(trace_, start_, "$0.", remote_method_->ToString());

  if (Trace::CurrentTrace()) {
    Trace::CurrentTrace()->AddChildTrace(trace_.get());
  }

  DVLOG(4) << "OutboundCall " << this << " constructed with state_: " << StateName(state_)
           << " and RPC timeout: "
           << (controller_->timeout().Initialized() ? controller_->timeout().ToString() : "none");

  IncrementCounter(rpc_metrics_->outbound_calls_created);
  IncrementGauge(rpc_metrics_->outbound_calls_alive);
}

OutboundCall::~OutboundCall() {
  DCHECK(IsFinished());
  DVLOG(4) << "OutboundCall " << this << " destroyed with state_: " << StateName(state_);

  if (PREDICT_FALSE(FLAGS_rpc_dump_all_traces)) {
    LOG(INFO) << ToString() << " took "
              << MonoDelta(CoarseMonoClock::Now() - start_).ToMicroseconds() << "us. Trace:";
    trace_->Dump(&LOG(INFO), true);
  }

  DecrementGauge(rpc_metrics_->outbound_calls_alive);
}

void OutboundCall::NotifyTransferred(const Status& status, Connection* conn) {
  if (status.ok()) {
    // Even when call is already finished (timed out) we should notify connection that it was sent
    // because it should expect response with appropriate id.
    conn->CallSent(shared_from(this));
  }

  if (IsFinished()) {
    LOG_IF_WITH_PREFIX(DFATAL, !IsTimedOut())
        << "Transferred call is in wrong state: " << state_.load(std::memory_order_acquire);
  } else if (status.ok()) {
    SetSent();
  } else {
    VLOG_WITH_PREFIX(1) << "Connection torn down: " << status;
    SetFailed(status);
  }
}

void OutboundCall::Serialize(boost::container::small_vector_base<RefCntBuffer>* output) {
  output->push_back(std::move(buffer_));
  buffer_consumption_ = ScopedTrackedConsumption();
}

Status OutboundCall::SetRequestParam(
    const Message& message, const MemTrackerPtr& mem_tracker) {
  using serialization::SerializeHeader;
  using serialization::SerializeMessage;

  size_t message_size = 0;
  auto status = SerializeMessage(message,
                                 /* param_buf */ nullptr,
                                 /* additional_size */ 0,
                                 /* use_cached_size */ false,
                                 /* offset */ 0,
                                 &message_size);
  if (!status.ok()) {
    return status;
  }

  using Output = google::protobuf::io::CodedOutputStream;
  auto timeout_ms = VERIFY_RESULT(TimeoutMs());
  size_t call_id_size = Output::VarintSize32(call_id_);
  size_t timeout_ms_size = Output::VarintSize32(timeout_ms);
  auto serialized_remote_method = remote_method_->serialized();

  size_t header_pb_len = 1 + call_id_size + serialized_remote_method.size() + 1 + timeout_ms_size;
  size_t header_size =
      kMsgLengthPrefixLength                            // Int prefix for the total length.
      + CodedOutputStream::VarintSize32(header_pb_len)  // Varint delimiter for header PB.
      + header_pb_len;                                  // Length for the header PB itself.
  size_t total_size = header_size + message_size;

  buffer_ = RefCntBuffer(total_size);
  uint8_t* dst = buffer_.udata();

  // 1. The length for the whole request, not including the 4-byte
  // length prefix.
  NetworkByteOrder::Store32(dst, total_size - kMsgLengthPrefixLength);
  dst += sizeof(uint32_t);

  // 2. The varint-prefixed RequestHeader PB
  dst = CodedOutputStream::WriteVarint32ToArray(header_pb_len, dst);
  dst = Output::WriteTagToArray(RequestHeader::kCallIdFieldNumber << 3, dst);
  dst = Output::WriteVarint32ToArray(call_id_, dst);
  memcpy(dst, serialized_remote_method.data(), serialized_remote_method.size());
  dst += serialized_remote_method.size();
  dst = CodedOutputStream::WriteTagToArray(RequestHeader::kTimeoutMillisFieldNumber << 3, dst);
  dst = Output::WriteVarint32ToArray(timeout_ms, dst);

  DCHECK_EQ(dst - buffer_.udata(), header_size);

  if (mem_tracker) {
    buffer_consumption_ = ScopedTrackedConsumption(mem_tracker, buffer_.size());
  }

  RETURN_NOT_OK(SerializeMessage(
      message, &buffer_, /* additional_size */ 0, /* use_cached_size */ true, header_size));
  if (method_metrics_) {
    IncrementCounterBy(method_metrics_->request_bytes, buffer_.size());
  }
  return Status::OK();
}

Status OutboundCall::status() const {
  std::lock_guard<simple_spinlock> l(lock_);
  return status_;
}

const ErrorStatusPB* OutboundCall::error_pb() const {
  std::lock_guard<simple_spinlock> l(lock_);
  return error_pb_.get();
}

string OutboundCall::StateName(State state) {
  return RpcCallState_Name(state);
}

OutboundCall::State OutboundCall::state() const {
  return state_.load(std::memory_order_acquire);
}

bool FinishedState(RpcCallState state) {
  switch (state) {
    case READY:
    case ON_OUTBOUND_QUEUE:
    case SENT:
      return false;
    case TIMED_OUT:
    case FINISHED_ERROR:
    case FINISHED_SUCCESS:
      return true;
  }
  LOG(FATAL) << "Unknown call state: " << state;
  return false;
}

bool ValidStateTransition(RpcCallState old_state, RpcCallState new_state) {
  switch (new_state) {
    case ON_OUTBOUND_QUEUE:
      return old_state == READY;
    case SENT:
      return old_state == ON_OUTBOUND_QUEUE;
    case TIMED_OUT:
      return old_state == SENT || old_state == ON_OUTBOUND_QUEUE;
    case FINISHED_SUCCESS:
      return old_state == SENT;
    case FINISHED_ERROR:
      return old_state == SENT || old_state == ON_OUTBOUND_QUEUE || old_state == READY;
    default:
      // No sanity checks for others.
      return true;
  }
}

bool OutboundCall::SetState(State new_state) {
  auto old_state = state_.load(std::memory_order_acquire);
  // Sanity check state transitions.
  DVLOG(3) << "OutboundCall " << this << " (" << ToString() << ") switching from " <<
    StateName(old_state) << " to " << StateName(new_state);
  for (;;) {
    if (FinishedState(old_state)) {
      VLOG(1) << "Call already finished: " << RpcCallState_Name(old_state) << ", new state: "
              << RpcCallState_Name(new_state);
      return false;
    }
    if (!ValidStateTransition(old_state, new_state)) {
      LOG(DFATAL)
          << "Invalid call state transition: " << RpcCallState_Name(old_state) << " => "
          << RpcCallState_Name(new_state);
      return false;
    }
    if (state_.compare_exchange_weak(old_state, new_state, std::memory_order_acq_rel)) {
      return true;
    }
  }
}

void OutboundCall::InvokeCallback() {
  if (callback_thread_pool_) {
    callback_task_.SetOutboundCall(shared_from(this));
    callback_thread_pool_->Enqueue(&callback_task_);
    TRACE_TO(trace_, "Callback will be called asynchronously.");
  } else {
    InvokeCallbackSync();
    TRACE_TO(trace_, "Callback called synchronously.");
  }
}

void OutboundCall::InvokeCallbackSync() {
  if (!callback_) {
    LOG(DFATAL) << "Callback has been already invoked.";
    return;
  }

  int64_t start_cycles = CycleClock::Now();
  callback_();
  // Clear the callback, since it may be holding onto reference counts
  // via bound parameters. We do this inside the timer because it's possible
  // the user has naughty destructors that block, and we want to account for that
  // time here if they happen to run on this thread.
  callback_ = nullptr;
  int64_t end_cycles = CycleClock::Now();
  int64_t wait_cycles = end_cycles - start_cycles;
  if (PREDICT_FALSE(wait_cycles > FLAGS_rpc_callback_max_cycles)) {
    auto time_spent = MonoDelta::FromSeconds(
        static_cast<double>(wait_cycles) / base::CyclesPerSecond());

    LOG(WARNING) << "RPC callback for " << ToString() << " took " << time_spent;
  }

  // Could be destroyed during callback. So reset it.
  controller_ = nullptr;
  response_ = nullptr;
}

void OutboundCall::SetResponse(CallResponse&& resp) {
  DCHECK(!IsFinished());

  auto now = CoarseMonoClock::Now();
  TRACE_TO_WITH_TIME(trace_, now, "Response received.");
  // Avoid expensive conn_id.ToString() in production.
  VTRACE_TO(1, trace_, "from $0", conn_id_.ToString());
  // Track time taken to be responded.

  if (outbound_call_metrics_) {
    outbound_call_metrics_->time_to_response->Increment(MonoDelta(now - start_).ToMicroseconds());
  }
  call_response_ = std::move(resp);
  Slice r(call_response_.serialized_response());

  if (method_metrics_) {
    IncrementCounterBy(method_metrics_->response_bytes, r.size());
  }

  if (call_response_.is_success()) {
    // TODO: here we're deserializing the call response within the reactor thread,
    // which isn't great, since it would block processing of other RPCs in parallel.
    // Should look into a way to avoid this.
    if (!pb_util::ParseFromArray(response_, r.data(), r.size()).IsOk()) {
      SetFailed(STATUS(IOError, "Invalid response, missing fields",
                                response_->InitializationErrorString()));
      return;
    }
    if (SetState(FINISHED_SUCCESS)) {
      InvokeCallback();
    } else {
      LOG(DFATAL) << "Success of already finished call: "
                  << RpcCallState_Name(state_.load(std::memory_order_acquire));
    }
  } else {
    // Error
    auto err = std::make_unique<ErrorStatusPB>();
    if (!pb_util::ParseFromArray(err.get(), r.data(), r.size()).IsOk()) {
      SetFailed(STATUS(IOError, "Was an RPC error but could not parse error response",
                                err->InitializationErrorString()));
      return;
    }
    auto status = STATUS(RemoteError, err->message());
    SetFailed(status, std::move(err));
  }
}

void OutboundCall::SetQueued() {
  auto end_time = CoarseMonoClock::Now();
  // Track time taken to be queued.
  if (outbound_call_metrics_) {
    outbound_call_metrics_->queue_time->Increment(MonoDelta(end_time - start_).ToMicroseconds());
  }
  SetState(ON_OUTBOUND_QUEUE);
  TRACE_TO_WITH_TIME(trace_, end_time, "Queued.");
}

void OutboundCall::SetSent() {
  auto end_time = CoarseMonoClock::Now();
  // Track time taken to be sent
  if (outbound_call_metrics_) {
    outbound_call_metrics_->send_time->Increment(MonoDelta(end_time - start_).ToMicroseconds());
  }
  SetState(SENT);
  TRACE_TO_WITH_TIME(trace_, end_time, "Call Sent.");
}

void OutboundCall::SetFinished() {
  DCHECK(!IsFinished());

  // Track time taken to be responded.
  if (outbound_call_metrics_) {
    outbound_call_metrics_->time_to_response->Increment(
        MonoDelta(CoarseMonoClock::Now() - start_).ToMicroseconds());
  }
  if (SetState(FINISHED_SUCCESS)) {
    InvokeCallback();
  }
}

void OutboundCall::SetFailed(const Status &status, std::unique_ptr<ErrorStatusPB> err_pb) {
  DCHECK(!IsFinished());

  TRACE_TO(trace_, "Call Failed.");
  bool invoke_callback;
  {
    std::lock_guard<simple_spinlock> l(lock_);
    status_ = status;
    if (status_.IsRemoteError()) {
      CHECK(err_pb);
      error_pb_ = std::move(err_pb);
    } else {
      CHECK(!err_pb);
    }
    invoke_callback = SetState(FINISHED_ERROR);
  }
  if (invoke_callback) {
    InvokeCallback();
  }
}

void OutboundCall::SetTimedOut() {
  DCHECK(!IsFinished());

  TRACE_TO(trace_, "Call TimedOut.");
  bool invoke_callback;
  {
    auto status = STATUS_FORMAT(
        TimedOut,
        "$0 RPC (request call id $3) to $1 timed out after $2",
        remote_method_->method_name(),
        conn_id_.remote(),
        controller_->timeout(),
        call_id_);
    std::lock_guard<simple_spinlock> l(lock_);
    status_ = std::move(status);
    invoke_callback = SetState(TIMED_OUT);
  }
  if (invoke_callback) {
    InvokeCallback();
  }
}

bool OutboundCall::IsTimedOut() const {
  return state_.load(std::memory_order_acquire) == TIMED_OUT;
}

bool OutboundCall::IsFinished() const {
  return FinishedState(state_.load(std::memory_order_acquire));
}

Result<Slice> OutboundCall::GetSidecar(int idx) const {
  return call_response_.GetSidecar(idx);
}

string OutboundCall::ToString() const {
  return Format("RPC call $0 -> $1 , state=$2.", *remote_method_, conn_id_, StateName(state_));
}

bool OutboundCall::DumpPB(const DumpRunningRpcsRequestPB& req,
                          RpcCallInProgressPB* resp) {
  std::lock_guard<simple_spinlock> l(lock_);
  auto state_value = state();
  if (!req.dump_timed_out() && state_value == RpcCallState::TIMED_OUT) {
    return false;
  }
  if (!InitHeader(resp->mutable_header()).ok() && !req.dump_timed_out()) {
    // Note that if we proceed here due to req.dump_timed_out() being true, then the
    // header.timeout_millis() will be inaccurate/not-set. This is ok because DumpPB
    // is only used for dumping the PB and not to send the RPC over the wire.
    return false;
  }
  resp->set_elapsed_millis(MonoDelta(CoarseMonoClock::Now() - start_).ToMilliseconds());
  resp->set_state(state_value);
  if (req.include_traces() && trace_) {
    resp->set_trace_buffer(trace_->DumpToString(true));
  }
  return true;
}

std::string OutboundCall::LogPrefix() const {
  return Format("{ OutboundCall@$0 } ", this);
}

Result<uint32_t> OutboundCall::TimeoutMs() const {
  MonoDelta timeout = controller_->timeout();
  if (timeout.Initialized()) {
    auto timeout_millis = timeout.ToMilliseconds();
    if (timeout_millis <= 0) {
      return STATUS(TimedOut, "Call timed out before sending");
    }
    return timeout_millis;
  } else {
    return 0;
  }
}

Status OutboundCall::InitHeader(RequestHeader* header) {
  header->set_call_id(call_id_);
  remote_method_->ToPB(header->mutable_remote_method());

  if (!IsFinished()) {
    header->set_timeout_millis(VERIFY_RESULT(TimeoutMs()));
  }
  return Status::OK();
}

///
/// ConnectionId
///

string ConnectionId::ToString() const {
  return Format("{ remote: $0 idx: $1 protocol: $2 }", remote_, idx_, protocol_);
}

size_t ConnectionId::HashCode() const {
  size_t seed = 0;
  boost::hash_combine(seed, hash_value(remote_));
  boost::hash_combine(seed, idx_);
  boost::hash_combine(seed, protocol_);
  return seed;
}

size_t ConnectionIdHash::operator() (const ConnectionId& conn_id) const {
  return conn_id.HashCode();
}

///
/// CallResponse
///

CallResponse::CallResponse()
    : parsed_(false) {
}

Result<Slice> CallResponse::GetSidecar(int idx) const {
  DCHECK(parsed_);
  if (idx < 0 || idx + 1 >= sidecar_bounds_.size()) {
    return STATUS_FORMAT(InvalidArgument,
        "Index $0 does not reference a valid sidecar", idx);
  }
  return Slice(sidecar_bounds_[idx], sidecar_bounds_[idx + 1]);
}

Status CallResponse::ParseFrom(CallData* call_data) {
  CHECK(!parsed_);
  Slice entire_message;

  response_data_ = std::move(*call_data);
  Slice source(response_data_.data(), response_data_.size());
  RETURN_NOT_OK(serialization::ParseYBMessage(source, &header_, &entire_message));

  // Use information from header to extract the payload slices.
  const size_t sidecars = header_.sidecar_offsets_size();

  if (sidecars > 0) {
    serialized_response_ = Slice(entire_message.data(),
                                 header_.sidecar_offsets(0));
    sidecar_bounds_.reserve(sidecars + 1);

    uint32_t prev_offset = 0;
    for (auto offset : header_.sidecar_offsets()) {
      if (offset > entire_message.size() || offset < prev_offset) {
        return STATUS_FORMAT(
            Corruption,
            "Invalid sidecar offsets; sidecar apparently starts at $0,"
            " ends at $1, but the entire message has length $2",
            prev_offset, offset, entire_message.size());
      }
      sidecar_bounds_.push_back(entire_message.data() + offset);
      prev_offset = offset;
    }
    sidecar_bounds_.emplace_back(entire_message.end());
  } else {
    serialized_response_ = entire_message;
  }

  parsed_ = true;
  return Status::OK();
}

}  // namespace rpc
}  // namespace yb


text:
/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2015 Scientific Computing and Imaging Institute,
   University of Utah.

   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.
   */
/// @todo Documentation Core/Datatypes/ColorMap.cc

#include <Core/Math/MiscMath.h>
#include <Core/Datatypes/ColorMap.h>
#include <Core/Logging/Log.h>
#include <iostream>
#include <boost/functional/factory.hpp>
#include <boost/function.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm/copy.hpp>

using namespace SCIRun;
using namespace SCIRun::Core::Datatypes;
using namespace SCIRun::Core::Geometry;
using namespace SCIRun::Core::Logging;

ColorMap::ColorMap(ColorMapStrategyHandle color, const std::string& name, const size_t resolution, const double shift,
  const bool invert, const double rescale_scale, const double rescale_shift)
  : color_(color), nameInfo_(name), resolution_(resolution), shift_(shift),
  invert_(invert), rescale_scale_(rescale_scale), rescale_shift_(rescale_shift)
{

}

ColorMap* ColorMap::clone() const
{
  return new ColorMap(*this);
}

namespace detail
{
  class Rainbow : public ColorMapStrategy
  {
  public:
    virtual ColorRGB getColorMapVal(double v) const override;
  };

  class OldRainbow : public ColorMapStrategy
  {
  public:
    virtual ColorRGB getColorMapVal(double v) const override;
  };

  class Blackbody : public ColorMapStrategy
  {
  public:
    virtual ColorRGB getColorMapVal(double v) const override;
  };

  class Grayscale : public ColorMapStrategy
  {
  public:
    virtual ColorRGB getColorMapVal(double v) const override;
  };

  class OrangeBlackLime : public ColorMapStrategy
  {
  public:
    virtual ColorRGB getColorMapVal(double v) const override;
  };

  class Darkhue : public ColorMapStrategy
  {
  public:
    virtual Core::Datatypes::ColorRGB getColorMapVal(double v) const override;
  };

  class BPSeismic : public ColorMapStrategy
  {
  public:
    virtual Core::Datatypes::ColorRGB getColorMapVal(double v) const override;
  };

  typedef boost::function<ColorMapStrategy*()> ColorMapMaker;
  static std::map<std::string, ColorMapMaker> colorMapFactoryMap =
  {
    { "Rainbow", boost::factory<Rainbow*>() },
    { "Old Rainbow", boost::factory<OldRainbow*>() },
    { "Blackbody", boost::factory<Blackbody*>() },
    { "Grayscale", boost::factory<Grayscale*>() },
    { "Orange,Black,Lime", boost::factory<OrangeBlackLime*>() },
    { "Darkhue", boost::factory<Darkhue*>() },
    { "BP Seismic", boost::factory<BPSeismic*>() }
  };
}

ColorMapHandle StandardColorMapFactory::create(const std::string& name, const size_t &res,
  const double &shift, const bool &invert,
  const double &rescale_scale, const double &rescale_shift)
{
  using namespace detail;
  ColorMapStrategyHandle color;
  auto maker = colorMapFactoryMap.find(name);
  if (maker != colorMapFactoryMap.end())
    color.reset(maker->second());
  else
  {
    logError("Color map name not implemented/recognized. Returning Rainbow.");
    color.reset(new Rainbow);
  }

  return boost::make_shared<ColorMap>(color, name, res, shift, invert, rescale_scale, rescale_shift);
}

StandardColorMapFactory::NameList StandardColorMapFactory::getList()
{
  std::vector<std::string> names;
  boost::copy(detail::colorMapFactoryMap | boost::adaptors::map_keys, std::back_inserter(names));
  return names;
}

/**
 * @name getTransformedColor
 * @brief This method transforms the raw data into ColorMap space.
 * This includes the resolution, the gamma shift, and data rescaling (using data min/max)
 * @param v The input value from raw data that will be transformed (usually into [0,1] space).
 * @return The scalar double value transformed into ColorMap space from raw data.
 */
double ColorMap::getTransformedValue(double f) const
{
  /////////////////////////////////////////////////
  //TODO: this seemingly useless code fixes a nasty crash bug on Windows. Don't delete it until a proper fix is implemented!
  static bool x = true;
  if (x)
  {
    std::cout << "";// this;// << " " << name_ << " " << resolution_ << " " << shift_ << " " << invert_ << std::endl;
    x = false;
  }
  /////////////////////////////////////////////////

  const double rescaled01 = static_cast<double>((f + rescale_shift_) * rescale_scale_);

  double v = std::min(std::max(0., rescaled01), 1.);
  double shift = shift_;
  if (invert_) {
    v = 1.f - v;
    shift *= -1.;
  }
  //apply the resolution
  v = static_cast<double>((static_cast<int>(v *
    static_cast<double>(resolution_)))) /
    static_cast<double>(resolution_ - 1);
  // the shift is a gamma.
  double denom = std::tan(M_PI_2 * (0.5 - std::min(std::max(shift, -0.99), 0.99) * 0.5));
  // make sure we don't hit divide by zero
  if (std::isnan(denom)) denom = 0.f;
  denom = std::max(denom, 0.001);
  v = std::pow(v, (1. / denom));
  return std::min(std::max(0.,v),1.);
}
/**
 * @name getColorMapVal
 * @brief This method returns the RGB value for the current colormap parameters.
 * The input comes from raw data values. To scale to data, ColorMap
 *           must be created with those parameters. The input is transformed, then
 *           used to select a color from a set of color maps (currently defined by
 *           strings.
 * @param v The input value from raw data that will be mapped to a color.
 * @return The RGB value mapped from the transformed input into the ColorMap's named map.
 */
ColorRGB ColorMap::getColorMapVal(double v) const
{
  double f = getTransformedValue(v);
  //now grab the RGB
  auto colorWithoutAlpha = color_->getColorMapVal(f);
  //TODO:
  //return applyAlpha(f, colorWithoutAlpha);
  return colorWithoutAlpha;
}
/*
ColorRGB applyAlpha(double transformed, colorWithoutAlpha)
...easy

double alpha(double transformedValue)
{
  // interpolate in alphaLookup_
}
*/

/**
 * @name valueToColor
 * @brief Takes a scalar value and directly passes into getColorMap.
 * @param The raw data value as a scalar double.
 * @return The RGB value mapped from the scalar.
 */
ColorRGB ColorMap::valueToColor(double scalar) const {
    return getColorMapVal(scalar);
}
/**
 * @name valueToColor
 * @brief Takes a tensor value and creates an RGB value.
 * @param The raw data value as a tensor.
 * @return The RGB value mapped from the tensor.
 */
ColorRGB ColorMap::valueToColor(const Tensor &tensor) const {
    //TODO this is probably not implemented correctly.
    //return ColorRGB(getTransformedColor(fabs(tensor.xx())), getTransformedColor(fabs(tensor.yy())), getTransformedColor(fabs(tensor.zz())));
  double eigen1, eigen2, eigen3;
  Tensor ten = tensor;
  ten.get_eigenvalues(eigen1, eigen2, eigen3);
  double primaryEigen = std::max(std::max(eigen1, eigen2), eigen3);
  return getColorMapVal(primaryEigen);
}
/**
 * @name valueToColor
 * @brief Takes a vector value and creates an RGB value.
 * @param The raw data value as a vector.
 * @return The RGB value mapped from the vector.
 */
ColorRGB ColorMap::valueToColor(const Vector &vector) const {
    //TODO this is probably not implemented correctly.
   // return ColorRGB(getTransformedColor(fabs(vector.x())),getTransformedColor(fabs(vector.y())), getTransformedColor(fabs(vector.z())));
  return getColorMapVal(vector.length());
}

// This Rainbow takes into account scientific visualization recommendations.
// It tones down the yellow/cyan values so they don't appear to
// be "brighter" than the other colors. All colors "appear" to be the
// same brightness.
// Blue -> Dark Cyan -> Green -> Orange -> Red
ColorRGB detail::Rainbow::getColorMapVal(double f) const
{
  ColorRGB col;
  if (f < 0.25)
    col = ColorRGB(0., f*3., 1. - f);
  else if (0.25 <= f && f < 0.5)
    col = ColorRGB(0., f + 0.5, 1.5 - f*3.);
  else if (0.5 <= f && f < 0.75)
    col = ColorRGB(4.*f - 2., 2. - 2.*f, 0.);
  else
    col = ColorRGB(1., 2. - 2.*f, 0.);
  return col;
}

//The Old Rainbow that simply transitions from blue to red 1 color at a time.
// Blue -> Cyan -> Green -> Yellow -> Red
ColorRGB detail::OldRainbow::getColorMapVal(double f) const
{
  ColorRGB col;
  if (f < 0.25)
    col = ColorRGB(0., 4.*f, 1.);
  else if (0.25 <= f && f < 0.5)
    col = ColorRGB(0., 1., (.5 - f)*4.);
  else if (0.5 <= f && f < 0.75)
    col = ColorRGB((f - 0.5)*4., 1., 0.);
  else
    col = ColorRGB(1., (1. - f)*4., 0.);
  return col;
}

// This map is designed to appear like a heat-map, where "cooler" (lower) values
// are darker and approach black, and "hotter" (higher) values are lighter
// and approach white. In between, you have the red, orange, and yellow transitions.
ColorRGB detail::Blackbody::getColorMapVal(double f) const
{
  ColorRGB col;
  if (f < 0.333333)
    col = ColorRGB(f * 3., 0., 0.);
  else if (f < 0.6666666)
    col = ColorRGB(1., (f - 0.333333) * 3., 0.);
  else
    col = ColorRGB(1., 1., (f - 0.6666666) * 3.);
  return col;
}

// A very simple black to white map with grays in between.
ColorRGB detail::Grayscale::getColorMapVal(double f) const
{
  ColorRGB col;
  col = ColorRGB(f, f, f);
  return col;
}

// This color scheme sets a transition of color that goes
// Orange -> Black -> Lime
ColorRGB detail::OrangeBlackLime::getColorMapVal(double f) const
{
  ColorRGB col;
  if (f < 0.5)
    col = ColorRGB((0.5 - f) * 2., 0.5 - f, 0.);
  else
    col = ColorRGB(0., (f - 0.5) * 2., 0.);
  return col;
}

// This color scheme sets a transition of color that goes
// Blue -> White -> Red
ColorRGB detail::BPSeismic::getColorMapVal(double f) const
{
  ColorRGB col;
  if (f < 0.5)
    col = ColorRGB(f*2, f*2, 1);
  else
    col = ColorRGB(1, (1-f)*2, (1-f)*2);
  return col;
}

ColorRGB detail::Darkhue::getColorMapVal(double f) const
{
  ColorRGB col;
  if (f < 0.25)
    col = ColorRGB(0., 0., (f * 4.) * 0.333333);
  else if (0.25 <= f && f < 0.5)
    col = ColorRGB((f - 0.25) * 2., 0., f + ((0.5 - f) * 0.333333));
  else if (0.5 <= f && f < 0.75)
    col = ColorRGB(f + (f - 0.5), 0., f - ((f - 0.5) * 3.));
  else
    col = ColorRGB(1., (f - 0.75) * 4., (f - 0.75) * 2.6666666);
  return col;
}

std::string ColorMap::getColorMapName() const { return nameInfo_; }
size_t ColorMap::getColorMapResolution() const { return resolution_; }
double ColorMap::getColorMapShift() const { return shift_; }
bool ColorMap::getColorMapInvert() const { return invert_; }
double ColorMap::getColorMapRescaleScale() const { return rescale_scale_; }
double ColorMap::getColorMapRescaleShift() const { return rescale_shift_; }

max_stars_repo_name: Nahusa/SCIRun

max_issues_repo_name: Nahusa/SCIRun

max_forks_repo_name: Nahusa/SCIRun