<commit_before>// Copyright Daniel Wallin 2006. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#include <boost/python.hpp>
#include <boost/python/tuple.hpp>
#include <libtorrent/torrent_handle.hpp>
#include <boost/lexical_cast.hpp>
#include "gil.hpp"

using namespace boost::python;
using namespace libtorrent;

namespace
{

  list url_seeds(torrent_handle& handle)
  {
      list ret;
      std::set<std::string> urls;
      {
          allow_threading_guard guard;
          urls = handle.url_seeds();
      }

      for (std::set<std::string>::iterator i(urls.begin())
          , end(urls.end()); i != end; ++i)
          ret.append(*i);
      return ret;
  }

  list piece_availability(torrent_handle& handle)
  {
      list ret;
      std::vector<int> avail;
      {
          allow_threading_guard guard;
          handle.piece_availability(avail);
      }

      for (std::vector<int>::iterator i(avail.begin())
          , end(avail.end()); i != end; ++i)
          ret.append(*i);
      return ret;
  }

  list piece_priorities(torrent_handle& handle)
  {
      list ret;
      std::vector<int> prio;
      {
          allow_threading_guard guard;
          prio = handle.piece_priorities();
      }

      for (std::vector<int>::iterator i(prio.begin())
          , end(prio.end()); i != end; ++i)
          ret.append(*i);
      return ret;
  }

  std::vector<announce_entry>::const_iterator begin_trackers(torrent_handle& i)
  {
      allow_threading_guard guard;
      return i.trackers().begin();
  }

  std::vector<announce_entry>::const_iterator end_trackers(torrent_handle& i)
  {
      allow_threading_guard guard;
      return i.trackers().end();
  }

} // namespace unnamed

list file_progress(torrent_handle& handle)
{
    std::vector<size_type> p;

    {
        allow_threading_guard guard;
        p.reserve(handle.get_torrent_info().num_files());
        handle.file_progress(p);
    }

    list result;

    for (std::vector<size_type>::iterator i(p.begin()), e(p.end()); i != e; ++i)
        result.append(*i);

    return result;
}

list get_peer_info(torrent_handle const& handle)
{
    std::vector<peer_info> pi;

    {
        allow_threading_guard guard;
        handle.get_peer_info(pi);
    }

    list result;

    for (std::vector<peer_info>::iterator i = pi.begin(); i != pi.end(); ++i)
        result.append(*i);

    return result;
}

void prioritize_pieces(torrent_handle& info, object o)
{
   std::vector<int> result;
   try
   {
      object iter_obj = object( handle<>( PyObject_GetIter( o.ptr() ) ));
      while( 1 )
      {
         object obj = extract<object>( iter_obj.attr( "next" )() );
         result.push_back(extract<int const>( obj ));
      }
   }
   catch( error_already_set )
   {
      PyErr_Clear();
      info.prioritize_pieces(result);
      return;
   }
}

void prioritize_files(torrent_handle& info, object o)
{
   std::vector<int> result;
   try
   {
      object iter_obj = object( handle<>( PyObject_GetIter( o.ptr() ) ));
      while( 1 )
      {
         object obj = extract<object>( iter_obj.attr( "next" )() );
         result.push_back(extract<int const>( obj ));
      }
   }
   catch( error_already_set )
   {
      PyErr_Clear();
      info.prioritize_files(result);
      return;
   }
}

list file_priorities(torrent_handle& handle)
{
    list ret;
    std::vector<int> priorities = handle.file_priorities();

    for (std::vector<int>::iterator i = priorities.begin(); i != priorities.end(); ++i)
        ret.append(*i);

    return ret;
}

void replace_trackers(torrent_handle& info, object trackers)
{
    object iter(trackers.attr("__iter__")());

    std::vector<announce_entry> result;

    for (;;)
    {
        handle<> entry(allow_null(PyIter_Next(iter.ptr())));

        if (entry == handle<>())
            break;

        result.push_back(extract<announce_entry const&>(object(entry)));
    }

    allow_threading_guard guard;
    info.replace_trackers(result);
}

list get_download_queue(torrent_handle& handle)
{
    using boost::python::make_tuple;

    list ret;

    std::vector<partial_piece_info> downloading;

    {
        allow_threading_guard guard;
        handle.get_download_queue(downloading);
    }

    for (std::vector<partial_piece_info>::iterator i = downloading.begin()
        , end(downloading.end()); i != end; ++i)
    {
        dict partial_piece;
        partial_piece["piece_index"] = i->piece_index;
        partial_piece["blocks_in_piece"] = i->blocks_in_piece;
        list block_list;
        for (int k = 0; k < i->blocks_in_piece; ++k)
        {
            dict block_info;
            block_info["state"] = i->blocks[k].state;
            block_info["num_peers"] = i->blocks[k].num_peers;
            block_info["bytes_progress"] = i->blocks[k].bytes_progress;
            block_info["block_size"] = i->blocks[k].block_size;
            block_info["peer"] = make_tuple(
                boost::lexical_cast<std::string>(i->blocks[k].peer.address()), i->blocks[k].peer.port());
            block_list.append(block_info);
        }
        partial_piece["blocks"] = block_list;

        ret.append(partial_piece);
    }

    return ret;
}

namespace
{
    tcp::endpoint tuple_to_endpoint(tuple const& t)
    {
        return tcp::endpoint(address::from_string(extract<std::string>(t[0])), extract<int>(t[1]));
    }
}

void force_reannounce(torrent_handle& th, int s)
{
    th.force_reannounce(boost::posix_time::seconds(s));
}

void connect_peer(torrent_handle& th, tuple ip, int source)
{
    th.connect_peer(tuple_to_endpoint(ip), source);
}

void set_peer_upload_limit(torrent_handle& th, tuple const& ip, int limit)
{
    th.set_peer_upload_limit(tuple_to_endpoint(ip), limit);
}

void set_peer_download_limit(torrent_handle& th, tuple const& ip, int limit)
{
    th.set_peer_download_limit(tuple_to_endpoint(ip), limit);
}

void add_piece(torrent_handle& th, int piece, char const *data, int flags)
{
   th.add_piece(piece, data, flags);
}

void bind_torrent_handle()
{
    void (torrent_handle::*force_reannounce0)() const = &torrent_handle::force_reannounce;

    int (torrent_handle::*piece_priority0)(int) const = &torrent_handle::piece_priority;
    void (torrent_handle::*piece_priority1)(int, int) const = &torrent_handle::piece_priority;

    void (torrent_handle::*move_storage0)(fs::path const&) const = &torrent_handle::move_storage;
    void (torrent_handle::*move_storage1)(fs::wpath const&) const = &torrent_handle::move_storage;

    void (torrent_handle::*rename_file0)(int, fs::path const&) const = &torrent_handle::rename_file;
    void (torrent_handle::*rename_file1)(int, fs::wpath const&) const = &torrent_handle::rename_file;

#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
    bool (torrent_handle::*resolve_countries0)() const = &torrent_handle::resolve_countries;
    void (torrent_handle::*resolve_countries1)(bool) = &torrent_handle::resolve_countries;
#endif

#define _ allow_threads

    class_<torrent_handle>("torrent_handle")
        .def("get_peer_info", get_peer_info)
        .def("status", _(&torrent_handle::status))
        .def("get_download_queue", get_download_queue)
        .def("file_progress", file_progress)
        .def("trackers", range(begin_trackers, end_trackers))
        .def("replace_trackers", replace_trackers)
        .def("add_url_seed", _(&torrent_handle::add_url_seed))
        .def("remove_url_seed", _(&torrent_handle::remove_url_seed))
        .def("url_seeds", url_seeds)
        .def("has_metadata", _(&torrent_handle::has_metadata))
        .def("get_torrent_info", _(&torrent_handle::get_torrent_info), return_internal_reference<>())
        .def("is_valid", _(&torrent_handle::is_valid))
        .def("is_seed", _(&torrent_handle::is_seed))
        .def("is_finished", _(&torrent_handle::is_finished))
        .def("is_paused", _(&torrent_handle::is_paused))
        .def("pause", _(&torrent_handle::pause))
        .def("resume", _(&torrent_handle::resume))
        .def("clear_error", _(&torrent_handle::clear_error))

        .def("is_auto_managed", _(&torrent_handle::is_auto_managed))
        .def("auto_managed", _(&torrent_handle::auto_managed))
        .def("queue_position", _(&torrent_handle::queue_position))
        .def("queue_position_up", _(&torrent_handle::queue_position_up))
        .def("queue_position_down", _(&torrent_handle::queue_position_down))
        .def("queue_position_top", _(&torrent_handle::queue_position_top))
        .def("queue_position_bottom", _(&torrent_handle::queue_position_bottom))

#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
        .def("resolve_countries", _(resolve_countries0))
        .def("resolve_countries", _(resolve_countries1))
#endif
        // deprecated
#ifndef TORRENT_NO_DEPRECATE
        .def("filter_piece", _(&torrent_handle::filter_piece))
        .def("is_piece_filtered", _(&torrent_handle::is_piece_filtered))
        .def("write_resume_data", _(&torrent_handle::write_resume_data))
#endif
        .def("add_piece", add_piece)
        .def("read_piece", _(&torrent_handle::read_piece))
        .def("piece_availability", piece_availability)
        .def("piece_priority", _(piece_priority0))
        .def("piece_priority", _(piece_priority1))
        .def("prioritize_pieces", prioritize_pieces)
        .def("piece_priorities", piece_priorities)
        .def("prioritize_files", prioritize_files)
        .def("file_priorities", file_priorities)
        .def("use_interface", &torrent_handle::use_interface)
        .def("save_resume_data", _(&torrent_handle::save_resume_data))
        .def("force_reannounce", _(force_reannounce0))
        .def("force_reannounce", force_reannounce)
        .def("scrape_tracker", _(&torrent_handle::scrape_tracker))
        .def("name", _(&torrent_handle::name))
        .def("set_upload_limit", _(&torrent_handle::set_upload_limit))
        .def("upload_limit", _(&torrent_handle::upload_limit))
        .def("set_download_limit", _(&torrent_handle::set_download_limit))
        .def("download_limit", _(&torrent_handle::download_limit))
        .def("set_sequential_download", _(&torrent_handle::set_sequential_download))
        .def("set_peer_upload_limit", set_peer_upload_limit)
        .def("set_peer_download_limit", set_peer_download_limit)
        .def("connect_peer", connect_peer)
        .def("set_ratio", _(&torrent_handle::set_ratio))
        .def("save_path", _(&torrent_handle::save_path))
        .def("set_max_uploads", _(&torrent_handle::set_max_uploads))
        .def("set_max_connections", _(&torrent_handle::set_max_connections))
        .def("set_tracker_login", _(&torrent_handle::set_tracker_login))
        .def("move_storage", _(move_storage0))
        .def("move_storage", _(move_storage1))
        .def("info_hash", _(&torrent_handle::info_hash))
        .def("force_recheck", _(&torrent_handle::force_recheck))
        .def("rename_file", _(rename_file0))
        .def("rename_file", _(rename_file1))
        ;
}
<commit_msg>updated python bindings with the recent API change<commit_after>// Copyright Daniel Wallin 2006. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#include <boost/python.hpp>
#include <boost/python/tuple.hpp>
#include <libtorrent/torrent_handle.hpp>
#include <boost/lexical_cast.hpp>
#include "gil.hpp"

using namespace boost::python;
using namespace libtorrent;

namespace
{

  list url_seeds(torrent_handle& handle)
  {
      list ret;
      std::set<std::string> urls;
      {
          allow_threading_guard guard;
          urls = handle.url_seeds();
      }

      for (std::set<std::string>::iterator i(urls.begin())
          , end(urls.end()); i != end; ++i)
          ret.append(*i);
      return ret;
  }

  list piece_availability(torrent_handle& handle)
  {
      list ret;
      std::vector<int> avail;
      {
          allow_threading_guard guard;
          handle.piece_availability(avail);
      }

      for (std::vector<int>::iterator i(avail.begin())
          , end(avail.end()); i != end; ++i)
          ret.append(*i);
      return ret;
  }

  list piece_priorities(torrent_handle& handle)
  {
      list ret;
      std::vector<int> prio;
      {
          allow_threading_guard guard;
          prio = handle.piece_priorities();
      }

      for (std::vector<int>::iterator i(prio.begin())
          , end(prio.end()); i != end; ++i)
          ret.append(*i);
      return ret;
  }

  std::vector<announce_entry>::const_iterator begin_trackers(torrent_handle& i)
  {
      allow_threading_guard guard;
      return i.trackers().begin();
  }

  std::vector<announce_entry>::const_iterator end_trackers(torrent_handle& i)
  {
      allow_threading_guard guard;
      return i.trackers().end();
  }

} // namespace unnamed

list file_progress(torrent_handle& handle)
{
    std::vector<size_type> p;

    {
        allow_threading_guard guard;
        p.reserve(handle.get_torrent_info().num_files());
        handle.file_progress(p);
    }

    list result;

    for (std::vector<size_type>::iterator i(p.begin()), e(p.end()); i != e; ++i)
        result.append(*i);

    return result;
}

list get_peer_info(torrent_handle const& handle)
{
    std::vector<peer_info> pi;

    {
        allow_threading_guard guard;
        handle.get_peer_info(pi);
    }

    list result;

    for (std::vector<peer_info>::iterator i = pi.begin(); i != pi.end(); ++i)
        result.append(*i);

    return result;
}

void prioritize_pieces(torrent_handle& info, object o)
{
   std::vector<int> result;
   try
   {
      object iter_obj = object( handle<>( PyObject_GetIter( o.ptr() ) ));
      while( 1 )
      {
         object obj = extract<object>( iter_obj.attr( "next" )() );
         result.push_back(extract<int const>( obj ));
      }
   }
   catch( error_already_set )
   {
      PyErr_Clear();
      info.prioritize_pieces(result);
      return;
   }
}

void prioritize_files(torrent_handle& info, object o)
{
   std::vector<int> result;
   try
   {
      object iter_obj = object( handle<>( PyObject_GetIter( o.ptr() ) ));
      while( 1 )
      {
         object obj = extract<object>( iter_obj.attr( "next" )() );
         result.push_back(extract<int const>( obj ));
      }
   }
   catch( error_already_set )
   {
      PyErr_Clear();
      info.prioritize_files(result);
      return;
   }
}

list file_priorities(torrent_handle& handle)
{
    list ret;
    std::vector<int> priorities = handle.file_priorities();

    for (std::vector<int>::iterator i = priorities.begin(); i != priorities.end(); ++i)
        ret.append(*i);

    return ret;
}

void replace_trackers(torrent_handle& info, object trackers)
{
    object iter(trackers.attr("__iter__")());

    std::vector<announce_entry> result;

    for (;;)
    {
        handle<> entry(allow_null(PyIter_Next(iter.ptr())));

        if (entry == handle<>())
            break;

        result.push_back(extract<announce_entry const&>(object(entry)));
    }

    allow_threading_guard guard;
    info.replace_trackers(result);
}

list get_download_queue(torrent_handle& handle)
{
    using boost::python::make_tuple;

    list ret;

    std::vector<partial_piece_info> downloading;

    {
        allow_threading_guard guard;
        handle.get_download_queue(downloading);
    }

    for (std::vector<partial_piece_info>::iterator i = downloading.begin()
        , end(downloading.end()); i != end; ++i)
    {
        dict partial_piece;
        partial_piece["piece_index"] = i->piece_index;
        partial_piece["blocks_in_piece"] = i->blocks_in_piece;
        list block_list;
        for (int k = 0; k < i->blocks_in_piece; ++k)
        {
            dict block_info;
            block_info["state"] = i->blocks[k].state;
            block_info["num_peers"] = i->blocks[k].num_peers;
            block_info["bytes_progress"] = i->blocks[k].bytes_progress;
            block_info["block_size"] = i->blocks[k].block_size;
            block_info["peer"] = make_tuple(
                boost::lexical_cast<std::string>(i->blocks[k].peer().address()), i->blocks[k].peer().port());
            block_list.append(block_info);
        }
        partial_piece["blocks"] = block_list;

        ret.append(partial_piece);
    }

    return ret;
}

namespace
{
    tcp::endpoint tuple_to_endpoint(tuple const& t)
    {
        return tcp::endpoint(address::from_string(extract<std::string>(t[0])), extract<int>(t[1]));
    }
}

void force_reannounce(torrent_handle& th, int s)
{
    th.force_reannounce(boost::posix_time::seconds(s));
}

void connect_peer(torrent_handle& th, tuple ip, int source)
{
    th.connect_peer(tuple_to_endpoint(ip), source);
}

void set_peer_upload_limit(torrent_handle& th, tuple const& ip, int limit)
{
    th.set_peer_upload_limit(tuple_to_endpoint(ip), limit);
}

void set_peer_download_limit(torrent_handle& th, tuple const& ip, int limit)
{
    th.set_peer_download_limit(tuple_to_endpoint(ip), limit);
}

void add_piece(torrent_handle& th, int piece, char const *data, int flags)
{
   th.add_piece(piece, data, flags);
}

void bind_torrent_handle()
{
    void (torrent_handle::*force_reannounce0)() const = &torrent_handle::force_reannounce;

    int (torrent_handle::*piece_priority0)(int) const = &torrent_handle::piece_priority;
    void (torrent_handle::*piece_priority1)(int, int) const = &torrent_handle::piece_priority;

    void (torrent_handle::*move_storage0)(fs::path const&) const = &torrent_handle::move_storage;
    void (torrent_handle::*move_storage1)(fs::wpath const&) const = &torrent_handle::move_storage;

    void (torrent_handle::*rename_file0)(int, fs::path const&) const = &torrent_handle::rename_file;
    void (torrent_handle::*rename_file1)(int, fs::wpath const&) const = &torrent_handle::rename_file;

#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
    bool (torrent_handle::*resolve_countries0)() const = &torrent_handle::resolve_countries;
    void (torrent_handle::*resolve_countries1)(bool) = &torrent_handle::resolve_countries;
#endif

#define _ allow_threads

    class_<torrent_handle>("torrent_handle")
        .def("get_peer_info", get_peer_info)
        .def("status", _(&torrent_handle::status))
        .def("get_download_queue", get_download_queue)
        .def("file_progress", file_progress)
        .def("trackers", range(begin_trackers, end_trackers))
        .def("replace_trackers", replace_trackers)
        .def("add_url_seed", _(&torrent_handle::add_url_seed))
        .def("remove_url_seed", _(&torrent_handle::remove_url_seed))
        .def("url_seeds", url_seeds)
        .def("has_metadata", _(&torrent_handle::has_metadata))
        .def("get_torrent_info", _(&torrent_handle::get_torrent_info), return_internal_reference<>())
        .def("is_valid", _(&torrent_handle::is_valid))
        .def("is_seed", _(&torrent_handle::is_seed))
        .def("is_finished", _(&torrent_handle::is_finished))
        .def("is_paused", _(&torrent_handle::is_paused))
        .def("pause", _(&torrent_handle::pause))
        .def("resume", _(&torrent_handle::resume))
        .def("clear_error", _(&torrent_handle::clear_error))

        .def("is_auto_managed", _(&torrent_handle::is_auto_managed))
        .def("auto_managed", _(&torrent_handle::auto_managed))
        .def("queue_position", _(&torrent_handle::queue_position))
        .def("queue_position_up", _(&torrent_handle::queue_position_up))
        .def("queue_position_down", _(&torrent_handle::queue_position_down))
        .def("queue_position_top", _(&torrent_handle::queue_position_top))
        .def("queue_position_bottom", _(&torrent_handle::queue_position_bottom))

#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
        .def("resolve_countries", _(resolve_countries0))
        .def("resolve_countries", _(resolve_countries1))
#endif
        // deprecated
#ifndef TORRENT_NO_DEPRECATE
        .def("filter_piece", _(&torrent_handle::filter_piece))
        .def("is_piece_filtered", _(&torrent_handle::is_piece_filtered))
        .def("write_resume_data", _(&torrent_handle::write_resume_data))
#endif
        .def("add_piece", add_piece)
        .def("read_piece", _(&torrent_handle::read_piece))
        .def("piece_availability", piece_availability)
        .def("piece_priority", _(piece_priority0))
        .def("piece_priority", _(piece_priority1))
        .def("prioritize_pieces", prioritize_pieces)
        .def("piece_priorities", piece_priorities)
        .def("prioritize_files", prioritize_files)
        .def("file_priorities", file_priorities)
        .def("use_interface", &torrent_handle::use_interface)
        .def("save_resume_data", _(&torrent_handle::save_resume_data))
        .def("force_reannounce", _(force_reannounce0))
        .def("force_reannounce", force_reannounce)
        .def("scrape_tracker", _(&torrent_handle::scrape_tracker))
        .def("name", _(&torrent_handle::name))
        .def("set_upload_limit", _(&torrent_handle::set_upload_limit))
        .def("upload_limit", _(&torrent_handle::upload_limit))
        .def("set_download_limit", _(&torrent_handle::set_download_limit))
        .def("download_limit", _(&torrent_handle::download_limit))
        .def("set_sequential_download", _(&torrent_handle::set_sequential_download))
        .def("set_peer_upload_limit", set_peer_upload_limit)
        .def("set_peer_download_limit", set_peer_download_limit)
        .def("connect_peer", connect_peer)
        .def("set_ratio", _(&torrent_handle::set_ratio))
        .def("save_path", _(&torrent_handle::save_path))
        .def("set_max_uploads", _(&torrent_handle::set_max_uploads))
        .def("set_max_connections", _(&torrent_handle::set_max_connections))
        .def("set_tracker_login", _(&torrent_handle::set_tracker_login))
        .def("move_storage", _(move_storage0))
        .def("move_storage", _(move_storage1))
        .def("info_hash", _(&torrent_handle::info_hash))
        .def("force_recheck", _(&torrent_handle::force_recheck))
        .def("rename_file", _(rename_file0))
        .def("rename_file", _(rename_file1))
        ;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#ifndef DATABASE_HH_
#define DATABASE_HH_

#include "core/sstring.hh"
#include "core/shared_ptr.hh"
#include "net/byteorder.hh"
#include "utils/UUID.hh"
#include "db_clock.hh"
#include <functional>
#include <boost/any.hpp>
#include <cstdint>
#include <boost/variant.hpp>
#include <unordered_map>
#include <map>
#include <set>
#include <vector>
#include <iostream>
#include <boost/functional/hash.hpp>
#include <experimental/optional>
#include "core/future.hh"

// FIXME: should be int8_t
using bytes = basic_sstring<char, uint32_t, 31>;

using bytes_opt = std::experimental::optional<bytes>;

sstring to_hex(const bytes& b);
sstring to_hex(const bytes_opt& b);

using object_opt = std::experimental::optional<boost::any>;

class marshal_exception : public std::exception {
    sstring _why;
public:
    marshal_exception() : _why("marshalling error") {}
    marshal_exception(sstring why) : _why(sstring("marshaling error: ") + why) {}
    virtual const char* why() const { return _why.c_str(); }
};

struct runtime_exception : public std::exception {
    sstring _why;
public:
    runtime_exception(sstring why) : _why(sstring("runtime error: ") + why) {}
    virtual const char* why() const { return _why.c_str(); }
};

class abstract_type {
    sstring _name;
public:
    abstract_type(sstring name) : _name(name) {}
    virtual ~abstract_type() {}
    virtual void serialize(const boost::any& value, std::ostream& out) = 0;
    virtual object_opt deserialize(std::istream& in) = 0;
    virtual bool less(const bytes& v1, const bytes& v2) = 0;
    virtual int32_t compare(const bytes& v1, const bytes& v2) {
        if (less(v1, v2)) {
            return -1;
        } else if (less(v2, v1)) {
            return 1;
        } else {
            return 0;
        }
    }
    object_opt deserialize(const bytes& v) {
        // FIXME: optimize
        std::istringstream iss(v);
        return deserialize(iss);
    }
    virtual void validate(const bytes& v) {
        // FIXME
    }
    virtual object_opt compose(const bytes& v) {
        return deserialize(v);
    }
    bytes decompose(const boost::any& value) {
        // FIXME: optimize
        std::ostringstream oss;
        serialize(value, oss);
        auto s = oss.str();
        return bytes(s.data(), s.size());
    }
    sstring name() const {
        return _name;
    }
protected:
    template <typename T, typename Compare = std::less<T>>
    bool default_less(const bytes& b1, const bytes& b2, Compare compare = Compare());
};

using data_type = shared_ptr<abstract_type>;

inline
size_t hash_value(const shared_ptr<abstract_type>& x) {
    return std::hash<abstract_type*>()(x.get());
}

template <typename Type>
shared_ptr<abstract_type> data_type_for();

class key_compare {
    shared_ptr<abstract_type> _type;
public:
    key_compare(shared_ptr<abstract_type> type) : _type(type) {}
    bool operator()(const bytes& v1, const bytes& v2) const {
        return _type->less(v1, v2);
    }
};

struct row;
struct paritition;
struct column_family;

struct row {
    std::vector<bytes> cells;
};

struct partition {
    explicit partition(column_family& cf);
    row static_columns;
    // row key within partition -> row
    std::map<bytes, row, key_compare> rows;
};

// FIXME: add missing types
extern thread_local shared_ptr<abstract_type> int32_type;
extern thread_local shared_ptr<abstract_type> long_type;
extern thread_local shared_ptr<abstract_type> ascii_type;
extern thread_local shared_ptr<abstract_type> bytes_type;
extern thread_local shared_ptr<abstract_type> utf8_type;
extern thread_local shared_ptr<abstract_type> boolean_type;
extern thread_local shared_ptr<abstract_type> timeuuid_type;
extern thread_local shared_ptr<abstract_type> timestamp_type;
extern thread_local shared_ptr<abstract_type> uuid_type;

template <>
inline
shared_ptr<abstract_type> data_type_for<int32_t>() {
    return int32_type;
}

template <>
inline
shared_ptr<abstract_type> data_type_for<int64_t>() {
    return long_type;
}

template <>
inline
shared_ptr<abstract_type> data_type_for<sstring>() {
    return utf8_type;
}

struct column_definition {
    sstring name;
    shared_ptr<abstract_type> type;
    struct name_compare {
        bool operator()(const column_definition& cd1, const column_definition& cd2) const {
            return std::lexicographical_compare(
                    cd1.name.begin(), cd1.name.end(),
                    cd2.name.begin(), cd2.name.end(),
                    [] (char c1, char c2) { return uint8_t(c1) < uint8_t(c1); });
        }
    };
};

struct column_family {
    column_family(shared_ptr<abstract_type> partition_key_type, shared_ptr<abstract_type> clustering_key_type);
    // primary key = paritition key + clustering_key
    shared_ptr<abstract_type> partition_key_type;
    shared_ptr<abstract_type> clustering_key_type;
    std::vector<column_definition> partition_key;
    std::vector<column_definition> clustering_key;
    std::vector<column_definition> column_defs; // sorted by name
    partition& find_or_create_partition(const bytes& key);
    row& find_or_create_row(const bytes& partition_key, const bytes& clustering_key);
    partition* find_partition(const bytes& key);
    row* find_row(const bytes& partition_key, const bytes& clustering_key);
    // partition key -> partition
    std::map<bytes, partition, key_compare> partitions;
};

class keyspace {
public:
    std::unordered_map<sstring, column_family> column_families;
    static future<keyspace> populate(sstring datadir);
};

class database {
public:
    std::unordered_map<sstring, keyspace> keyspaces;
    static future<database> populate(sstring datadir);
};

namespace std {

template <>
struct hash<shared_ptr<abstract_type>> : boost::hash<shared_ptr<abstract_type>> {
};

}

inline
bytes
to_bytes(const char* x) {
    return bytes(reinterpret_cast<const char*>(x), std::strlen(x));
}

inline
bytes
to_bytes(const std::string& x) {
    return bytes(reinterpret_cast<const char*>(x.data()), x.size());
}

inline
bytes
to_bytes(const sstring& x) {
    return bytes(reinterpret_cast<const char*>(x.c_str()), x.size());
}

inline
bytes
to_bytes(const utils::UUID& uuid) {
    struct {
        uint64_t msb;
        uint64_t lsb;
    } tmp = { net::hton(uint64_t(uuid.get_most_significant_bits())),
              net::hton(uint64_t(uuid.get_least_significant_bits())) };
    return bytes(reinterpret_cast<char*>(&tmp), 16);
}

// This follows java.util.Comparator
// FIXME: Choose a better place than database.hh
template <typename T>
struct comparator {
    virtual ~comparator() {}
    virtual bool operator()(const T& v1, const T& v2) const = 0;
};

inline bool
less_unsigned(const bytes& v1, const bytes& v2) {
    return std::lexicographical_compare(v1.begin(), v1.end(), v2.begin(), v2.end(),
            [](int8_t v1, int8_t v2) { return uint8_t(v1) < uint8_t(v2); });
}

inline int32_t compare_unsigned(const bytes& v1, const bytes& v2) {
    if (less_unsigned(v1, v2)) {
        return -1;
    } else if (less_unsigned(v2, v1)) {
        return 1;
    } else {
        return 0;
    }
}

#endif /* DATABASE_HH_ */
<commit_msg>Add abstract_type::validate_collection_member<commit_after>/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#ifndef DATABASE_HH_
#define DATABASE_HH_

#include "core/sstring.hh"
#include "core/shared_ptr.hh"
#include "net/byteorder.hh"
#include "utils/UUID.hh"
#include "db_clock.hh"
#include <functional>
#include <boost/any.hpp>
#include <cstdint>
#include <boost/variant.hpp>
#include <unordered_map>
#include <map>
#include <set>
#include <vector>
#include <iostream>
#include <boost/functional/hash.hpp>
#include <experimental/optional>
#include "core/future.hh"

// FIXME: should be int8_t
using bytes = basic_sstring<char, uint32_t, 31>;

using bytes_opt = std::experimental::optional<bytes>;

sstring to_hex(const bytes& b);
sstring to_hex(const bytes_opt& b);

using object_opt = std::experimental::optional<boost::any>;

class marshal_exception : public std::exception {
    sstring _why;
public:
    marshal_exception() : _why("marshalling error") {}
    marshal_exception(sstring why) : _why(sstring("marshaling error: ") + why) {}
    virtual const char* why() const { return _why.c_str(); }
};

struct runtime_exception : public std::exception {
    sstring _why;
public:
    runtime_exception(sstring why) : _why(sstring("runtime error: ") + why) {}
    virtual const char* why() const { return _why.c_str(); }
};

class abstract_type {
    sstring _name;
public:
    abstract_type(sstring name) : _name(name) {}
    virtual ~abstract_type() {}
    virtual void serialize(const boost::any& value, std::ostream& out) = 0;
    virtual object_opt deserialize(std::istream& in) = 0;
    virtual bool less(const bytes& v1, const bytes& v2) = 0;
    virtual int32_t compare(const bytes& v1, const bytes& v2) {
        if (less(v1, v2)) {
            return -1;
        } else if (less(v2, v1)) {
            return 1;
        } else {
            return 0;
        }
    }
    object_opt deserialize(const bytes& v) {
        // FIXME: optimize
        std::istringstream iss(v);
        return deserialize(iss);
    }
    virtual void validate(const bytes& v) {
        // FIXME
    }
    virtual void validate_collection_member(const bytes& v, const bytes& collection_name) {
        validate(v);
    }
    virtual object_opt compose(const bytes& v) {
        return deserialize(v);
    }
    bytes decompose(const boost::any& value) {
        // FIXME: optimize
        std::ostringstream oss;
        serialize(value, oss);
        auto s = oss.str();
        return bytes(s.data(), s.size());
    }
    sstring name() const {
        return _name;
    }
protected:
    template <typename T, typename Compare = std::less<T>>
    bool default_less(const bytes& b1, const bytes& b2, Compare compare = Compare());
};

using data_type = shared_ptr<abstract_type>;

inline
size_t hash_value(const shared_ptr<abstract_type>& x) {
    return std::hash<abstract_type*>()(x.get());
}

template <typename Type>
shared_ptr<abstract_type> data_type_for();

class key_compare {
    shared_ptr<abstract_type> _type;
public:
    key_compare(shared_ptr<abstract_type> type) : _type(type) {}
    bool operator()(const bytes& v1, const bytes& v2) const {
        return _type->less(v1, v2);
    }
};

struct row;
struct paritition;
struct column_family;

struct row {
    std::vector<bytes> cells;
};

struct partition {
    explicit partition(column_family& cf);
    row static_columns;
    // row key within partition -> row
    std::map<bytes, row, key_compare> rows;
};

// FIXME: add missing types
extern thread_local shared_ptr<abstract_type> int32_type;
extern thread_local shared_ptr<abstract_type> long_type;
extern thread_local shared_ptr<abstract_type> ascii_type;
extern thread_local shared_ptr<abstract_type> bytes_type;
extern thread_local shared_ptr<abstract_type> utf8_type;
extern thread_local shared_ptr<abstract_type> boolean_type;
extern thread_local shared_ptr<abstract_type> timeuuid_type;
extern thread_local shared_ptr<abstract_type> timestamp_type;
extern thread_local shared_ptr<abstract_type> uuid_type;

template <>
inline
shared_ptr<abstract_type> data_type_for<int32_t>() {
    return int32_type;
}

template <>
inline
shared_ptr<abstract_type> data_type_for<int64_t>() {
    return long_type;
}

template <>
inline
shared_ptr<abstract_type> data_type_for<sstring>() {
    return utf8_type;
}

struct column_definition {
    sstring name;
    shared_ptr<abstract_type> type;
    struct name_compare {
        bool operator()(const column_definition& cd1, const column_definition& cd2) const {
            return std::lexicographical_compare(
                    cd1.name.begin(), cd1.name.end(),
                    cd2.name.begin(), cd2.name.end(),
                    [] (char c1, char c2) { return uint8_t(c1) < uint8_t(c1); });
        }
    };
};

struct column_family {
    column_family(shared_ptr<abstract_type> partition_key_type, shared_ptr<abstract_type> clustering_key_type);
    // primary key = paritition key + clustering_key
    shared_ptr<abstract_type> partition_key_type;
    shared_ptr<abstract_type> clustering_key_type;
    std::vector<column_definition> partition_key;
    std::vector<column_definition> clustering_key;
    std::vector<column_definition> column_defs; // sorted by name
    partition& find_or_create_partition(const bytes& key);
    row& find_or_create_row(const bytes& partition_key, const bytes& clustering_key);
    partition* find_partition(const bytes& key);
    row* find_row(const bytes& partition_key, const bytes& clustering_key);
    // partition key -> partition
    std::map<bytes, partition, key_compare> partitions;
};

class keyspace {
public:
    std::unordered_map<sstring, column_family> column_families;
    static future<keyspace> populate(sstring datadir);
};

class database {
public:
    std::unordered_map<sstring, keyspace> keyspaces;
    static future<database> populate(sstring datadir);
};

namespace std {

template <>
struct hash<shared_ptr<abstract_type>> : boost::hash<shared_ptr<abstract_type>> {
};

}

inline
bytes
to_bytes(const char* x) {
    return bytes(reinterpret_cast<const char*>(x), std::strlen(x));
}

inline
bytes
to_bytes(const std::string& x) {
    return bytes(reinterpret_cast<const char*>(x.data()), x.size());
}

inline
bytes
to_bytes(const sstring& x) {
    return bytes(reinterpret_cast<const char*>(x.c_str()), x.size());
}

inline
bytes
to_bytes(const utils::UUID& uuid) {
    struct {
        uint64_t msb;
        uint64_t lsb;
    } tmp = { net::hton(uint64_t(uuid.get_most_significant_bits())),
              net::hton(uint64_t(uuid.get_least_significant_bits())) };
    return bytes(reinterpret_cast<char*>(&tmp), 16);
}

// This follows java.util.Comparator
// FIXME: Choose a better place than database.hh
template <typename T>
struct comparator {
    virtual ~comparator() {}
    virtual bool operator()(const T& v1, const T& v2) const = 0;
};

inline bool
less_unsigned(const bytes& v1, const bytes& v2) {
    return std::lexicographical_compare(v1.begin(), v1.end(), v2.begin(), v2.end(),
            [](int8_t v1, int8_t v2) { return uint8_t(v1) < uint8_t(v2); });
}

inline int32_t compare_unsigned(const bytes& v1, const bytes& v2) {
    if (less_unsigned(v1, v2)) {
        return -1;
    } else if (less_unsigned(v2, v1)) {
        return 1;
    } else {
        return 0;
    }
}

#endif /* DATABASE_HH_ */
<|endoftext|>


<commit_before>/*
 *  PointerAgent.cpp
 *  openc2e
 *
 *  Created by Alyssa Milburn on Tue Aug 30 2005.
 *  Copyright (c) 2005 Alyssa Milburn. All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 */

#include "PointerAgent.h"
#include "openc2e.h"
#include "World.h"
#include "Engine.h"
#include "caosVM.h"
#include "Room.h"

// TODO: change imagecount?
PointerAgent::PointerAgent(std::string spritefile) : SimpleAgent(2, 1, 1, INT_MAX, spritefile, 0, 0) {
	name = "hand";
	handle_events = true;
	holdingWire = 0;
	wireOriginID = 0;
	// TODO: verify attributes on the pointer in c2e
	attr.setInt(256); // camera shy
}

void PointerAgent::finishInit() {
	Agent::finishInit();

	// float relative to main camera
	attr.setInt(attr.getInt() & 32);
	floatSetup();
}

void PointerAgent::carry(AgentRef a) {
	Agent::carry(a);

	int eve; if (engine.version < 3) eve = 53; else eve = 104;
	firePointerScript(eve, a); // Pointer Pickup
}

void PointerAgent::drop(AgentRef a) {
	Agent::drop(a);

	int eve; if (engine.version < 3) eve = 54; else eve = 105;
	firePointerScript(eve, a); // Pointer Drop
}

// TODO: this should have a queueScript equiv too
void PointerAgent::firePointerScript(unsigned short event, Agent *src) {
	assert(src); // TODO: I /think/ this should only be called by the engine..
	shared_ptr<script> s = src->findScript(event);
	if (!s && engine.version < 3) { // TODO: are we sure this doesn't apply to c2e?
		s = findScript(event); // TODO: we should make sure this actually belongs to the pointer agent and isn't a fallback, maybe
	}
	if (!s) return;
	if (!vm) vm = world.getVM(this);
	if (vm->fireScript(s, false, src)) { // TODO: should FROM be src?
		vm->setTarg(this);
		zotstack();
	}
}

void PointerAgent::physicsTick() {
	// TODO: this is a hack, which does nothing, because we set a velocity in main() but also move the cursor manually
}

void PointerAgent::kill() {
	// pointer agent isn't killable
}

void PointerAgent::setHotspot(int x, int y) {
	hotspotx = x;
	hotspoty = y;
}

void PointerAgent::handleEvent(SomeEvent &event) {
	int x = pointerX(), y = pointerY();

	if (event.type == eventmousemove) {
		moveTo(event.x + world.camera.getX() - hotspotx, event.y + world.camera.getY() - hotspoty);
		velx.setInt(event.xrel * 4);
		vely.setInt(event.yrel * 4);

		// middle mouse button scrolling
		if (event.button & buttonmiddle)
			world.camera.moveTo(world.camera.getX() - event.xrel, world.camera.getY() - event.yrel, jump);
	} else if (!handle_events) {
		/* mouse move events are (apparently - see eg C3 agent help) still handled with handle_events disabled, but nothing else */
		return;
	} else if (event.type == eventmousebuttondown) {
		// do our custom handling
		if (event.button == buttonleft) {
			CompoundPart *a = world.partAt(x, y);
			if (a /* && a->canActivate() */) { // TODO
				Agent* parent = a->getParent();

				int eve = -1;

				bool foundport = false;
				if (engine.version > 2) {
					for (std::map<unsigned int, boost::shared_ptr<OutputPort> >::iterator i = parent->outports.begin();
							 i != parent->outports.end(); i++) {
						// TODO: 4 is a magic number i pulled out of nooooowhere
						if (abs(i->second->x + parent->x - x) < 4 && abs(i->second->y + parent->y - y) < 4) {
							foundport = true;
							if (holdingWire == 2) {
								parent->join(i->first, wireOriginAgent, wireOriginID);
								holdingWire = 0;
								eve = 111;
							} else if (holdingWire == 0) {
								eve = 110;
								holdingWire = 1;
								wireOriginAgent = parent;
								wireOriginID = i->first;
							}
							break;
						}
					}
					if (!foundport) {
						for (std::map<unsigned int, boost::shared_ptr<InputPort> >::iterator i = parent->inports.begin();
								 i != parent->inports.end(); i++) {
							// TODO: 4 is a magic number i pulled out of nooooowhere
							if (abs(i->second->x + parent->x - x) < 4 && abs(i->second->y + parent->y - y) < 4) {
								foundport = true;
								if (holdingWire == 1) {
									if (i->second->source) {
										eve = 114;
									} else {
										wireOriginAgent->join(wireOriginID, parent, i->first);
										holdingWire = 0;
										eve = 111;
									}
								} else if (holdingWire == 0) {
									if (i->second->source) {
										eve = 112;
										holdingWire = 1;
										wireOriginAgent = i->second->source;
										wireOriginID = i->second->sourceid;
										i->second->source->outports[i->second->sourceid]->dests.remove(std::pair<AgentRef, unsigned int>(parent, i->first));
										i->second->source.clear();
									} else {
										eve = 110;
										holdingWire = 2;
										wireOriginAgent = parent;
										wireOriginID = i->first;
									}
								}
								break;
							}
						}
					}
				}

				if (!foundport) {
					if (holdingWire) {
						holdingWire = 0;
						eve = 113;
					} else {
						// if the agent isn't paused, tell it to handle a click
						int scriptid = a->handleClick(x - a->x - parent->x, y - a->y - parent->y);
						if (scriptid != -1) {
							// fire the script
							// _p1_ is id of part for button clicks, according to Edynn code
							// TODO: should _p1_ always be set? :)
							if (!parent->paused) parent->queueScript(scriptid, world.hand(), (int)a->id);

							// annoyingly queueScript doesn't reliably tell us if it did anything useful.
							// TODO: work out the mess which is queueScript's return values etc
							if (!parent->findScript(scriptid)) return;

							// fire the associated pointer script too, if necessary
							// TODO: fuzzie has no idea if this code is remotely correct
							if (engine.version < 3) {
								eve = 50;
							} else {
								eve = 101; // Pointer Activate 1
							}
							switch (scriptid) {
								case 0: eve += 2; break; // deactivate
								case 1: break; // activate 1
								case 2: eve += 1; break; // activate 2
								default: return;
							}
						}
					}
				}

				if (eve != -1) firePointerScript(eve, a->getParent());
			} else if (engine.version > 2) {
				if (holdingWire) {
					holdingWire = 0;
					queueScript(113, 0);
				} else {
					queueScript(116, 0); // Pointer Clicked Background
				}
			}
		} else if (event.button == buttonright) {
			if (world.paused) return; // TODO: wrong?

			// picking up and dropping are implictly handled by the scripts (well,
			// messages) 4 and 5	TODO: check if this is correct behaviour, one issue
			// is that this isn't instant, another is the messages might only be
			// fired in c2e when you use MESG WRIT, in which case we'll need to
			// manually set carrying to NULL and a here, respectively - fuzzie
			if (carrying) {
				// TODO: c1 support - these attributes are invalid for c1
				if (!carrying->suffercollisions() || (carrying->validInRoomSystem() || engine.version == 1)) {
					carrying->queueScript(5, this); // drop

					// TODO: is this the correct check?
					if (carrying->sufferphysics() && carrying->suffercollisions()) {
						// TODO: do this in the pointer agent?
						carrying->velx.setFloat(velx.getFloat());
						carrying->vely.setFloat(vely.getFloat());
					}
				} else {
					// TODO: some kind of "fail to drop" animation/sound?
				}
			} else {
				Agent *a = world.agentAt(x, y, false, true);
				if (a) {
					a->queueScript(4, this); // pickup
				}
			}
		} else if (event.button == buttonmiddle) {
			std::vector<shared_ptr<Room> > rooms = world.map.roomsAt(x, y);
			if (rooms.size() > 0) std::cout << "Room at cursor is " << rooms[0]->id << std::endl;
			Agent *a = world.agentAt(x, y, true);
			if (a)
				std::cout << "Agent under mouse is " << a->identify();
			else
				std::cout << "No agent under cursor";
			std::cout << std::endl;
		}
	}
}

/* vim: set noet: */
<commit_msg>C1: deny drops into black holes<commit_after>/*
 *  PointerAgent.cpp
 *  openc2e
 *
 *  Created by Alyssa Milburn on Tue Aug 30 2005.
 *  Copyright (c) 2005 Alyssa Milburn. All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 */

#include "PointerAgent.h"
#include "openc2e.h"
#include "World.h"
#include "Engine.h"
#include "caosVM.h"
#include "Room.h"
#include "MetaRoom.h"

// TODO: change imagecount?
PointerAgent::PointerAgent(std::string spritefile) : SimpleAgent(2, 1, 1, INT_MAX, spritefile, 0, 0) {
	name = "hand";
	handle_events = true;
	holdingWire = 0;
	wireOriginID = 0;
	// TODO: verify attributes on the pointer in c2e
	attr.setInt(256); // camera shy
}

void PointerAgent::finishInit() {
	Agent::finishInit();

	// float relative to main camera
	attr.setInt(attr.getInt() & 32);
	floatSetup();
}

void PointerAgent::carry(AgentRef a) {
	Agent::carry(a);

	int eve; if (engine.version < 3) eve = 53; else eve = 104;
	firePointerScript(eve, a); // Pointer Pickup
}

void PointerAgent::drop(AgentRef a) {
	Agent::drop(a);

	int eve; if (engine.version < 3) eve = 54; else eve = 105;
	firePointerScript(eve, a); // Pointer Drop
}

// TODO: this should have a queueScript equiv too
void PointerAgent::firePointerScript(unsigned short event, Agent *src) {
	assert(src); // TODO: I /think/ this should only be called by the engine..
	shared_ptr<script> s = src->findScript(event);
	if (!s && engine.version < 3) { // TODO: are we sure this doesn't apply to c2e?
		s = findScript(event); // TODO: we should make sure this actually belongs to the pointer agent and isn't a fallback, maybe
	}
	if (!s) return;
	if (!vm) vm = world.getVM(this);
	if (vm->fireScript(s, false, src)) { // TODO: should FROM be src?
		vm->setTarg(this);
		zotstack();
	}
}

void PointerAgent::physicsTick() {
	// TODO: this is a hack, which does nothing, because we set a velocity in main() but also move the cursor manually
}

void PointerAgent::kill() {
	// pointer agent isn't killable
}

void PointerAgent::setHotspot(int x, int y) {
	hotspotx = x;
	hotspoty = y;
}

void PointerAgent::handleEvent(SomeEvent &event) {
	int x = pointerX(), y = pointerY();

	if (event.type == eventmousemove) {
		moveTo(event.x + world.camera.getX() - hotspotx, event.y + world.camera.getY() - hotspoty);
		velx.setInt(event.xrel * 4);
		vely.setInt(event.yrel * 4);

		// middle mouse button scrolling
		if (event.button & buttonmiddle)
			world.camera.moveTo(world.camera.getX() - event.xrel, world.camera.getY() - event.yrel, jump);
	} else if (!handle_events) {
		/* mouse move events are (apparently - see eg C3 agent help) still handled with handle_events disabled, but nothing else */
		return;
	} else if (event.type == eventmousebuttondown) {
		// do our custom handling
		if (event.button == buttonleft) {
			CompoundPart *a = world.partAt(x, y);
			if (a /* && a->canActivate() */) { // TODO
				Agent* parent = a->getParent();

				int eve = -1;

				bool foundport = false;
				if (engine.version > 2) {
					for (std::map<unsigned int, boost::shared_ptr<OutputPort> >::iterator i = parent->outports.begin();
							 i != parent->outports.end(); i++) {
						// TODO: 4 is a magic number i pulled out of nooooowhere
						if (abs(i->second->x + parent->x - x) < 4 && abs(i->second->y + parent->y - y) < 4) {
							foundport = true;
							if (holdingWire == 2) {
								parent->join(i->first, wireOriginAgent, wireOriginID);
								holdingWire = 0;
								eve = 111;
							} else if (holdingWire == 0) {
								eve = 110;
								holdingWire = 1;
								wireOriginAgent = parent;
								wireOriginID = i->first;
							}
							break;
						}
					}
					if (!foundport) {
						for (std::map<unsigned int, boost::shared_ptr<InputPort> >::iterator i = parent->inports.begin();
								 i != parent->inports.end(); i++) {
							// TODO: 4 is a magic number i pulled out of nooooowhere
							if (abs(i->second->x + parent->x - x) < 4 && abs(i->second->y + parent->y - y) < 4) {
								foundport = true;
								if (holdingWire == 1) {
									if (i->second->source) {
										eve = 114;
									} else {
										wireOriginAgent->join(wireOriginID, parent, i->first);
										holdingWire = 0;
										eve = 111;
									}
								} else if (holdingWire == 0) {
									if (i->second->source) {
										eve = 112;
										holdingWire = 1;
										wireOriginAgent = i->second->source;
										wireOriginID = i->second->sourceid;
										i->second->source->outports[i->second->sourceid]->dests.remove(std::pair<AgentRef, unsigned int>(parent, i->first));
										i->second->source.clear();
									} else {
										eve = 110;
										holdingWire = 2;
										wireOriginAgent = parent;
										wireOriginID = i->first;
									}
								}
								break;
							}
						}
					}
				}

				if (!foundport) {
					if (holdingWire) {
						holdingWire = 0;
						eve = 113;
					} else {
						// if the agent isn't paused, tell it to handle a click
						int scriptid = a->handleClick(x - a->x - parent->x, y - a->y - parent->y);
						if (scriptid != -1) {
							// fire the script
							// _p1_ is id of part for button clicks, according to Edynn code
							// TODO: should _p1_ always be set? :)
							if (!parent->paused) parent->queueScript(scriptid, world.hand(), (int)a->id);

							// annoyingly queueScript doesn't reliably tell us if it did anything useful.
							// TODO: work out the mess which is queueScript's return values etc
							if (!parent->findScript(scriptid)) return;

							// fire the associated pointer script too, if necessary
							// TODO: fuzzie has no idea if this code is remotely correct
							if (engine.version < 3) {
								eve = 50;
							} else {
								eve = 101; // Pointer Activate 1
							}
							switch (scriptid) {
								case 0: eve += 2; break; // deactivate
								case 1: break; // activate 1
								case 2: eve += 1; break; // activate 2
								default: return;
							}
						}
					}
				}

				if (eve != -1) firePointerScript(eve, a->getParent());
			} else if (engine.version > 2) {
				if (holdingWire) {
					holdingWire = 0;
					queueScript(113, 0);
				} else {
					queueScript(116, 0); // Pointer Clicked Background
				}
			}
		} else if (event.button == buttonright) {
			if (world.paused) return; // TODO: wrong?

			// picking up and dropping are implictly handled by the scripts (well,
			// messages) 4 and 5	TODO: check if this is correct behaviour, one issue
			// is that this isn't instant, another is the messages might only be
			// fired in c2e when you use MESG WRIT, in which case we'll need to
			// manually set carrying to NULL and a here, respectively - fuzzie
			if (carrying) {
				if (engine.version == 1) {
					// ensure there's a room to drop into, in C1
					MetaRoom* m = world.map.metaRoomAt(x, y);
					if (!m) return;
					shared_ptr<Room> r = m->nextFloorFromPoint(x, y);
					if (!r) return;

					carrying->queueScript(5, this); // drop

					return;
				} else if (!carrying->suffercollisions() || carrying->validInRoomSystem()) {
					carrying->queueScript(5, this); // drop

					// TODO: is this the correct check?
					if (carrying->sufferphysics() && carrying->suffercollisions()) {
						// TODO: do this in the pointer agent?
						carrying->velx.setFloat(velx.getFloat());
						carrying->vely.setFloat(vely.getFloat());
					}

					return;
				}

				// TODO: some kind of "fail to drop" animation/sound?
			} else {
				Agent *a = world.agentAt(x, y, false, true);
				if (a) {
					a->queueScript(4, this); // pickup
				}
			}
		} else if (event.button == buttonmiddle) {
			std::vector<shared_ptr<Room> > rooms = world.map.roomsAt(x, y);
			if (rooms.size() > 0) std::cout << "Room at cursor is " << rooms[0]->id << std::endl;
			Agent *a = world.agentAt(x, y, true);
			if (a)
				std::cout << "Agent under mouse is " << a->identify();
			else
				std::cout << "No agent under cursor";
			std::cout << std::endl;
		}
	}
}

/* vim: set noet: */
<|endoftext|>


<commit_before>/*****************************************************************************
   Copyright 2018 Karl Nelson

   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 <Python.h>
#include <jpype.h>
#include <jp_thunk.h>

namespace
{ // impl detail, gets initialized by JPProxy::init()
	jobject classLoader;
	jmethodID findClassID;
}

void JPClassLoader::init()
{
	JPJavaFrame frame;
	JP_TRACE_IN("JPClassLoader::init");

	// Define the class loader
	jobject cl = JPJni::getSystemClassLoader();
	jclass cls = frame.DefineClass("org/jpype/classloader/JPypeClassLoader", cl,
			JPThunk::_org_jpype_classloader_JPypeClassLoader,
			JPThunk::_org_jpype_classloader_JPypeClassLoader_size);

	jvalue v;

	// Set up class loader
	//jmethodID ctorID = frame.GetMethodID(cls, "<init>", "(Ljava/lang/ClassLoader;)V");
	//v.l = cl;

	jmethodID getInstanceID = frame.GetStaticMethodID(cls, "getInstance", "()Lorg.jpype.classloader.JPypeClassLoader;");
	classLoader = frame.NewGlobalRef(frame.CallStaticObjectMethod(cls, getInstanceID));

	// Load the jar
	jbyteArray jar = frame.NewByteArray(JPThunk::_org_jpype_size);
	frame.SetByteArrayRegion(jar, 0, JPThunk::_org_jpype_size, JPThunk::_org_jpype);
	v.l = jar;

	jmethodID importJarID = frame.GetMethodID(cls, "importJar", "([B)V");
	frame.CallVoidMethodA(classLoader, importJarID, &v);

	// Set up the loader
	findClassID = frame.GetMethodID(cls, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");

	JP_TRACE_OUT;
}

jclass JPClassLoader::findClass(string name)
{
	JPJavaFrame frame;
	jvalue v;
	v.l = frame.NewStringUTF(name.c_str());
	return (jclass) frame.keep(frame.CallObjectMethodA(classLoader, findClassID, &v));
}
<commit_msg>Work on classloader.<commit_after>/*****************************************************************************
   Copyright 2018 Karl Nelson

   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 <Python.h>
#include <jpype.h>
#include <jp_thunk.h>

namespace
{ // impl detail, gets initialized by JPProxy::init()
	jobject classLoader;
	jmethodID findClassID;
}

void JPClassLoader::init()
{
	JPJavaFrame frame;
	JP_TRACE_IN("JPClassLoader::init");

	// Define the class loader
	jobject cl = JPJni::getSystemClassLoader();
	jclass cls = frame.DefineClass("org/jpype/classloader/JPypeClassLoader", cl,
			JPThunk::_org_jpype_classloader_JPypeClassLoader,
			JPThunk::_org_jpype_classloader_JPypeClassLoader_size);

	jvalue v;

	// Set up class loader
	jmethodID ctorID = frame.GetMethodID(cls, "<init>", "(Ljava/lang/ClassLoader;)V");
	//v.l = cl;

	jmethodID getInstanceID = frame.GetStaticMethodID(cls, "getInstance", "()Lorg/jpype/classloader/JPypeClassLoader;");
	classLoader = frame.NewGlobalRef(frame.CallStaticObjectMethod(cls, getInstanceID));

	// Load the jar
	jbyteArray jar = frame.NewByteArray(JPThunk::_org_jpype_size);
	frame.SetByteArrayRegion(jar, 0, JPThunk::_org_jpype_size, JPThunk::_org_jpype);
	v.l = jar;

	jmethodID importJarID = frame.GetMethodID(cls, "importJar", "([B)V");
	frame.CallVoidMethodA(classLoader, importJarID, &v);

	// Set up the loader
	findClassID = frame.GetMethodID(cls, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");

	JP_TRACE_OUT;
}

jclass JPClassLoader::findClass(string name)
{
	JPJavaFrame frame;
	jvalue v;
	v.l = frame.NewStringUTF(name.c_str());
	return (jclass) frame.keep(frame.CallObjectMethodA(classLoader, findClassID, &v));
}
<|endoftext|>


<commit_before># include "conf.hpp"
# include "error.hpp"
# include "broker-util.hpp"
# include <cstdlib>

using std::getenv;

namespace
{
    const char* unix_family = "UNIX";
    const char* inet_family = "INET";

    const char* webapp_addr_env_var	  = "CHATTP_WEBAPP_ADDR";
    const char* webapp_family_env_var	  = "CHATTP_WEBAPP_FAMILY";
    const char* webapp_port_env_var	  = "CHATTP_WEBAPP_PORT";
    const char* mesg_relay_addr_env_var   = "CHATTP_MESG_RELAY_ADDR";
    const char* mesg_relay_family_env_var = "CHATTP_MESG_RELAY_FAMILY";
    const char* mesg_relay_port_env_var   = "CHATTP_MESG_RELAY_PORT";
    const char* persistence_addr_env_var  = "CHATTP_PERSISTENCE_LAYER_ADDR";
    const char* persistence_family_env_var= "CHATTP_PERSISTENCE_LAYER_FAMILY";
    const char* persistence_port_env_var  = "CHATTP_PERSISTENCE_LAYER_PORT";

    const char* broker_webapp_bind_addr_var	= "CHATTP_MSGBROKER_WEBAPP_BIND_ADDR";
    const char* broker_webapp_bind_port_var	= "CHATTP_MSGBROKER_WEBAPP_BIND_PORT";
    const char* broker_msgrelay_bind_addr_var	= "CHATTP_MSGBROKER_MSGRELAY_BIND_ADDR";
    const char* broker_msgrelay_bind_port_var	= "CHATTP_MSGBROKER_MSGRELAY_BIND_PORT";
    const char* broker_persistence_bind_addr_var= "CHATTP_MSGBROKER_PERSISTENCE_BIND_ADDR";
    const char* broker_persistence_bind_port_var= "CHATTP_MSGBROKER_PERSISTENCE_BIND_PORT";
}

time_point<steady_clock> start_time;
unsigned int packets_processed;

/**
 * @brief Fetch configuration from environment.
 *
 * This class configures the message broker from environment variables.
 *
 */
BrokerSettings::BrokerSettings(void)
{
    // Fetch services.
    message_relay_info = extractConnInfo(mesg_relay_addr_env_var,mesg_relay_family_env_var,mesg_relay_port_env_var);
    persistence_layer_info = extractConnInfo(persistence_addr_env_var,persistence_family_env_var,persistence_port_env_var);
    webapp_info = extractConnInfo(webapp_addr_env_var,webapp_family_env_var,webapp_port_env_var);

    // Fetch bind info.
    message_relay_bind_info = extractConnInfo(broker_msgrelay_bind_addr_var, mesg_relay_family_env_var, broker_msgrelay_bind_port_var);
    persistence_bind_info = extractConnInfo(broker_persistence_bind_addr_var, persistence_family_env_var, broker_persistence_bind_port_var);
    webapp_bind_info = extractConnInfo(broker_webapp_bind_addr_var, webapp_family_env_var, broker_webapp_bind_port_var);

    checkSanity(); // Throws on configuration error.
}

connectionInformation BrokerSettings::extractConnInfo (const char* addr_var, const char* family_var, const char* port_var)
{
    connectionInformation conninfo;

    if ( getenv(addr_var) )
	conninfo.address = getenv(addr_var);
    else
	throw BrokerError(ErrorType::configurationError,string("There is no ") + addr_var + " environment variable.");

    if ( getenv(family_var) )
    {
	string conn_type(getenv(family_var));

	if (conn_type == unix_family)
	{
	    conninfo.type = connectionType::UNIX;

	} else if (conn_type == inet_family)
	{
	    conninfo.type = connectionType::INET;

	    if ( getenv(port_var) )
	    {
		conninfo.port = getenv(port_var);
	    } else
		throw BrokerError(ErrorType::configurationError,string("The ") + port_var + " environment variable could not be found.");
	} else
	    throw BrokerError(ErrorType::configurationError,string("There's something wrong with the ") + family_var + " environment variable");
    } else
	throw BrokerError(ErrorType::configurationError,string("There is no ") + family_var + " environment variable");

    return conninfo;
}
<commit_msg>Removed a last checkSanity() call.<commit_after># include "conf.hpp"
# include "error.hpp"
# include "broker-util.hpp"
# include <cstdlib>

using std::getenv;

namespace
{
    const char* unix_family = "UNIX";
    const char* inet_family = "INET";

    const char* webapp_addr_env_var	  = "CHATTP_WEBAPP_ADDR";
    const char* webapp_family_env_var	  = "CHATTP_WEBAPP_FAMILY";
    const char* webapp_port_env_var	  = "CHATTP_WEBAPP_PORT";
    const char* mesg_relay_addr_env_var   = "CHATTP_MESG_RELAY_ADDR";
    const char* mesg_relay_family_env_var = "CHATTP_MESG_RELAY_FAMILY";
    const char* mesg_relay_port_env_var   = "CHATTP_MESG_RELAY_PORT";
    const char* persistence_addr_env_var  = "CHATTP_PERSISTENCE_LAYER_ADDR";
    const char* persistence_family_env_var= "CHATTP_PERSISTENCE_LAYER_FAMILY";
    const char* persistence_port_env_var  = "CHATTP_PERSISTENCE_LAYER_PORT";

    const char* broker_webapp_bind_addr_var	= "CHATTP_MSGBROKER_WEBAPP_BIND_ADDR";
    const char* broker_webapp_bind_port_var	= "CHATTP_MSGBROKER_WEBAPP_BIND_PORT";
    const char* broker_msgrelay_bind_addr_var	= "CHATTP_MSGBROKER_MSGRELAY_BIND_ADDR";
    const char* broker_msgrelay_bind_port_var	= "CHATTP_MSGBROKER_MSGRELAY_BIND_PORT";
    const char* broker_persistence_bind_addr_var= "CHATTP_MSGBROKER_PERSISTENCE_BIND_ADDR";
    const char* broker_persistence_bind_port_var= "CHATTP_MSGBROKER_PERSISTENCE_BIND_PORT";
}

time_point<steady_clock> start_time;
unsigned int packets_processed;

/**
 * @brief Fetch configuration from environment.
 *
 * This class configures the message broker from environment variables.
 *
 */
BrokerSettings::BrokerSettings(void)
{
    // Fetch services.
    message_relay_info = extractConnInfo(mesg_relay_addr_env_var,mesg_relay_family_env_var,mesg_relay_port_env_var);
    persistence_layer_info = extractConnInfo(persistence_addr_env_var,persistence_family_env_var,persistence_port_env_var);
    webapp_info = extractConnInfo(webapp_addr_env_var,webapp_family_env_var,webapp_port_env_var);

    // Fetch bind info.
    message_relay_bind_info = extractConnInfo(broker_msgrelay_bind_addr_var, mesg_relay_family_env_var, broker_msgrelay_bind_port_var);
    persistence_bind_info = extractConnInfo(broker_persistence_bind_addr_var, persistence_family_env_var, broker_persistence_bind_port_var);
    webapp_bind_info = extractConnInfo(broker_webapp_bind_addr_var, webapp_family_env_var, broker_webapp_bind_port_var);
}

connectionInformation BrokerSettings::extractConnInfo (const char* addr_var, const char* family_var, const char* port_var)
{
    connectionInformation conninfo;

    if ( getenv(addr_var) )
	conninfo.address = getenv(addr_var);
    else
	throw BrokerError(ErrorType::configurationError,string("There is no ") + addr_var + " environment variable.");

    if ( getenv(family_var) )
    {
	string conn_type(getenv(family_var));

	if (conn_type == unix_family)
	{
	    conninfo.type = connectionType::UNIX;

	} else if (conn_type == inet_family)
	{
	    conninfo.type = connectionType::INET;

	    if ( getenv(port_var) )
	    {
		conninfo.port = getenv(port_var);
	    } else
		throw BrokerError(ErrorType::configurationError,string("The ") + port_var + " environment variable could not be found.");
	} else
	    throw BrokerError(ErrorType::configurationError,string("There's something wrong with the ") + family_var + " environment variable");
    } else
	throw BrokerError(ErrorType::configurationError,string("There is no ") + family_var + " environment variable");

    return conninfo;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#ifndef DATABASE_HH_
#define DATABASE_HH_

#include "core/sstring.hh"
#include <functional>
#include <boost/any.hpp>
#include <cstdint>
#include <boost/variant.hpp>
#include <unordered_map>
#include <map>
#include <set>
#include <vector>
#include <iostream>
#include <boost/functional/hash.hpp>

// FIXME: should be int8_t
using bytes = basic_sstring<char, uint32_t, 31>;

class data_type {
public:
    // Hide the virtual stuff behind an impl class.  This allows us to treat
    // data_type as a normal value - we can copy, assign, and destroy it
    // without worrying about the destructor.
    struct impl {
        sstring name;
        impl(sstring name) : name(name) {}
        virtual ~impl() {}
        virtual void serialize(const boost::any& value, std::ostream& out) = 0;
        virtual boost::any deserialize(std::istream& in) = 0;
        virtual bool less(const bytes& v1, const bytes& v2) = 0;
        boost::any deserialize(const bytes& v) {
            // FIXME: optimize
            std::istringstream iss(v);
            return deserialize(iss);
        }
    };
private:
    impl* _impl;
public:
    explicit data_type(impl* impl) : _impl(impl) {}
    static data_type find(const sstring& name);
    const sstring& name() const { return _impl->name; }
    void serialize(const boost::any& value, std::ostream& out) {
        return _impl->serialize(value, out);
    }
    bytes decompose(const boost::any& value) {
        // FIXME: optimize
        std::ostringstream oss;
        _impl->serialize(value, oss);
        auto s = oss.str();
        return bytes(s.data(), s.size());
    }
    boost::any deserialize(std::istream& in) {
        return _impl->deserialize(in);
    }
    boost::any deserialize(const bytes& v) {
        return _impl->deserialize(v);
    }
    bool operator==(const data_type& x) const {
        return _impl == x._impl;
    }
    bool operator!=(const data_type& x) const {
        return _impl != x._impl;
    }
    bool less(const bytes& v1, const bytes& v2) const {
        return _impl->less(v1, v2);
    }
    friend size_t hash_value(const data_type& x) {
        return std::hash<impl*>()(x._impl);
    }
};

template <typename Type>
data_type data_type_for();

class key_compare {
    data_type _type;
public:
    key_compare(data_type type) : _type(type) {}
    bool operator()(const bytes& v1, const bytes& v2) const {
        return _type.less(v1, v2);
    }
};

struct row;
struct paritition;
struct column_family;

struct row {
    std::vector<bytes> cells;
};

struct partition {
    explicit partition(column_family& cf);
    row static_columns;
    // row key within partition -> row
    std::map<bytes, row, key_compare> rows;
};

// FIXME: add missing types
extern data_type int_type;
extern data_type bigint_type;
extern data_type ascii_type;
extern data_type blob_type;
extern data_type varchar_type;
extern data_type text_type;

template <>
inline
data_type data_type_for<int32_t>() {
    return int_type;
}

template <>
inline
data_type data_type_for<int64_t>() {
    return bigint_type;
}

template <>
inline
data_type data_type_for<sstring>() {
    return varchar_type;
}

struct column_definition {
    sstring name;
    data_type type;
    struct name_compare {
        bool operator()(const column_definition& cd1, const column_definition& cd2) const {
            return std::lexicographical_compare(
                    cd1.name.begin(), cd1.name.end(),
                    cd2.name.begin(), cd2.name.end(),
                    [] (char c1, char c2) { return uint8_t(c1) < uint8_t(c1); });
        }
    };
};

struct column_family {
    column_family(data_type partition_key_type, data_type clustering_key_type);
    // primary key = paritition key + clustering_key
    data_type partition_key_type;
    data_type clustering_key_type;
    std::vector<column_definition> partition_key;
    std::vector<column_definition> clustering_key;
    std::vector<column_definition> column_defs; // sorted by name
    partition& find_or_create_partition(const bytes& key);
    row& find_or_create_row(const bytes& partition_key, const bytes& clustering_key);
    partition* find_partition(const bytes& key);
    row* find_row(const bytes& partition_key, const bytes& clustering_key);
    // partition key -> partition
    std::map<bytes, partition, key_compare> partitions;
};

struct keyspace {
    std::unordered_map<sstring, column_family> column_families;
};

struct database {
    std::unordered_map<sstring, keyspace> keyspaces;
};

namespace std {

template <>
struct hash<data_type> : boost::hash<data_type> {
};

}

inline
bytes
to_bytes(const char* x) {
    return bytes(reinterpret_cast<const char*>(x), std::strlen(x));
}

inline
bytes
to_bytes(const std::string& x) {
    return bytes(reinterpret_cast<const char*>(x.data()), x.size());
}

inline
bytes
to_bytes(const sstring& x) {
    return bytes(reinterpret_cast<const char*>(x.c_str()), x.size());
}

#endif /* DATABASE_HH_ */
<commit_msg>Add comparator<commit_after>/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#ifndef DATABASE_HH_
#define DATABASE_HH_

#include "core/sstring.hh"
#include <functional>
#include <boost/any.hpp>
#include <cstdint>
#include <boost/variant.hpp>
#include <unordered_map>
#include <map>
#include <set>
#include <vector>
#include <iostream>
#include <boost/functional/hash.hpp>

// FIXME: should be int8_t
using bytes = basic_sstring<char, uint32_t, 31>;

class data_type {
public:
    // Hide the virtual stuff behind an impl class.  This allows us to treat
    // data_type as a normal value - we can copy, assign, and destroy it
    // without worrying about the destructor.
    struct impl {
        sstring name;
        impl(sstring name) : name(name) {}
        virtual ~impl() {}
        virtual void serialize(const boost::any& value, std::ostream& out) = 0;
        virtual boost::any deserialize(std::istream& in) = 0;
        virtual bool less(const bytes& v1, const bytes& v2) = 0;
        boost::any deserialize(const bytes& v) {
            // FIXME: optimize
            std::istringstream iss(v);
            return deserialize(iss);
        }
    };
private:
    impl* _impl;
public:
    explicit data_type(impl* impl) : _impl(impl) {}
    static data_type find(const sstring& name);
    const sstring& name() const { return _impl->name; }
    void serialize(const boost::any& value, std::ostream& out) {
        return _impl->serialize(value, out);
    }
    bytes decompose(const boost::any& value) {
        // FIXME: optimize
        std::ostringstream oss;
        _impl->serialize(value, oss);
        auto s = oss.str();
        return bytes(s.data(), s.size());
    }
    boost::any deserialize(std::istream& in) {
        return _impl->deserialize(in);
    }
    boost::any deserialize(const bytes& v) {
        return _impl->deserialize(v);
    }
    bool operator==(const data_type& x) const {
        return _impl == x._impl;
    }
    bool operator!=(const data_type& x) const {
        return _impl != x._impl;
    }
    bool less(const bytes& v1, const bytes& v2) const {
        return _impl->less(v1, v2);
    }
    friend size_t hash_value(const data_type& x) {
        return std::hash<impl*>()(x._impl);
    }
};

template <typename Type>
data_type data_type_for();

class key_compare {
    data_type _type;
public:
    key_compare(data_type type) : _type(type) {}
    bool operator()(const bytes& v1, const bytes& v2) const {
        return _type.less(v1, v2);
    }
};

struct row;
struct paritition;
struct column_family;

struct row {
    std::vector<bytes> cells;
};

struct partition {
    explicit partition(column_family& cf);
    row static_columns;
    // row key within partition -> row
    std::map<bytes, row, key_compare> rows;
};

// FIXME: add missing types
extern data_type int_type;
extern data_type bigint_type;
extern data_type ascii_type;
extern data_type blob_type;
extern data_type varchar_type;
extern data_type text_type;

template <>
inline
data_type data_type_for<int32_t>() {
    return int_type;
}

template <>
inline
data_type data_type_for<int64_t>() {
    return bigint_type;
}

template <>
inline
data_type data_type_for<sstring>() {
    return varchar_type;
}

struct column_definition {
    sstring name;
    data_type type;
    struct name_compare {
        bool operator()(const column_definition& cd1, const column_definition& cd2) const {
            return std::lexicographical_compare(
                    cd1.name.begin(), cd1.name.end(),
                    cd2.name.begin(), cd2.name.end(),
                    [] (char c1, char c2) { return uint8_t(c1) < uint8_t(c1); });
        }
    };
};

struct column_family {
    column_family(data_type partition_key_type, data_type clustering_key_type);
    // primary key = paritition key + clustering_key
    data_type partition_key_type;
    data_type clustering_key_type;
    std::vector<column_definition> partition_key;
    std::vector<column_definition> clustering_key;
    std::vector<column_definition> column_defs; // sorted by name
    partition& find_or_create_partition(const bytes& key);
    row& find_or_create_row(const bytes& partition_key, const bytes& clustering_key);
    partition* find_partition(const bytes& key);
    row* find_row(const bytes& partition_key, const bytes& clustering_key);
    // partition key -> partition
    std::map<bytes, partition, key_compare> partitions;
};

struct keyspace {
    std::unordered_map<sstring, column_family> column_families;
};

struct database {
    std::unordered_map<sstring, keyspace> keyspaces;
};

namespace std {

template <>
struct hash<data_type> : boost::hash<data_type> {
};

}

inline
bytes
to_bytes(const char* x) {
    return bytes(reinterpret_cast<const char*>(x), std::strlen(x));
}

inline
bytes
to_bytes(const std::string& x) {
    return bytes(reinterpret_cast<const char*>(x.data()), x.size());
}

inline
bytes
to_bytes(const sstring& x) {
    return bytes(reinterpret_cast<const char*>(x.c_str()), x.size());
}

// This follows java.util.Comparator
// FIXME: Choose a better place than database.hh
template <typename T>
struct comparator {
    virtual ~comparator() {}
    virtual bool operator()(const T& v1, const T& v2) const = 0;
};

#endif /* DATABASE_HH_ */
<|endoftext|>


<commit_before>// This file is part of the "x0" project
//   (c) 2009-2015 Christian Parpart <https://github.com/christianparpart>
//
// x0 is free software: you can redistribute it and/or modify it under
// the terms of the GNU Affero General Public License v3.0.
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

#include "XzeroModule.h"
#include "XzeroDaemon.h"
#include "sysconfig.h"

#include <xzero-flow/ASTPrinter.h>
#include <xzero/executor/NativeScheduler.h>
#include <xzero/logging/LogTarget.h>
#include <xzero/logging/ConsoleLogTarget.h>
#include <xzero/logging.h>
#include <xzero/cli/CLI.h>
#include <xzero/cli/Flags.h>
#include <xzero/Application.h>
#include <iostream>
#include <unistd.h>

#define PACKAGE_VERSION X0_VERSION
#define PACKAGE_HOMEPAGE_URL "https://xzero.io"

using namespace xzero;
using namespace xzero::http;

void printHelp(const CLI& cli) {
  std::cout
    << "x0d: Xzero HTTP Web Server " PACKAGE_VERSION
        << " [" PACKAGE_HOMEPAGE_URL "]" << std::endl
    << "Copyright (c) 2009-2015 by Christian Parpart <trapni@gmail.com>" << std::endl
    << std::endl
    << "Usage: x0d [options ...]" << std::endl
    << std::endl
    << "Options:" << std::endl
    << cli.helpText() << std::endl;
}

#define DEFAULT_CONFIG_PATH PROJECT_ROOT_SRC_DIR "/x0d.conf"

int main(int argc, const char* argv[]) {
  try {
    Application::init();

    CLI cli;
    cli.defineBool("help", 'h', "Prints this help and terminates.")
       .defineString("config", 'c', "PATH", "Specify a custom configuration file.", "/etc/x0d/x0d.conf", nullptr)
       .defineString("user", 'u', "NAME", "User privileges to drop down to.", Application::userName())
       .defineString("group", 'g', "NAME", "Group privileges to drop down to.", Application::groupName())
       .defineString("log-level", 'L', "ENUM", "Defines the minimum log level.", "info", nullptr)
       .defineString("log-target", 0, "ENUM", "Specifies logging target. One of syslog, file, systemd, console.", "console", nullptr)
       .defineString("log-file", 'l', "PATH", "Path to application log file.", "", nullptr)
       .defineString("instant", 'i', "PATH[:PORT]", "Enable instant-mode (does not need config file).", "", nullptr)
       .defineNumber("optimization-level", 'O', "LEVEL", "Sets the configuration optimization level.", 1)
       .defineBool("daemonize", 'd', "Forks the process into background.")
       .defineBool("dump-ast", 0, "Dumps configuration AST and exits.")
       .defineBool("dump-ir", 0, "Dumps configuration IR and exits.")
       .defineBool("dump-tc", 0, "Dumps configuration opcode stream and exits.")
       ;

    Flags flags = cli.evaluate(argc, argv);

    if (flags.getBool("help")) {
      printHelp(cli);
      return 0;
    }

    // {{{ setup logging
    Logger::get()->setMinimumLogLevel(to_loglevel(flags.getString("log-level")));

    std::string logTarget = flags.getString("log-target");
    if (logTarget == "null") {
      ; // ignore
    } else if (logTarget == "console") {
      Logger::get()->addTarget(ConsoleLogTarget::get());
    } else if (logTarget == "file") {
      ; // TODO
    } else if (logTarget == "syslog") {
      ; // TODO Logger::get()->addTarget(SyslogTarget::get());
    } else if (logTarget == "systemd") {
      ; // TODO Logger::get()->addTarget(SystemdLogTarget::get());
    } else {
      fprintf(stderr, "Invalid log target \"%s\".\n", logTarget.c_str());
      return 1;
    }
    // }}}

    x0d::XzeroDaemon x0d;

    x0d.setOptimizationLevel(flags.getNumber("optimization-level"));

    x0d.loadConfigFile(flags.getString("config"));

    bool exitBeforeRun = false;

    if (flags.getBool("dump-ast")) {
      xzero::flow::ASTPrinter::print(x0d.programAST());
      exitBeforeRun = true;
    }

    if (flags.getBool("dump-ir")) {
      x0d.programIR()->dump();
      exitBeforeRun = true;
    }

    if (flags.getBool("dump-tc")) {
      x0d.program()->dump();
      exitBeforeRun = true;
    }

    if (exitBeforeRun)
      return 0;

    if (!x0d.configure())
      return 1;

    Application::dropPrivileges(flags.getString("user"), flags.getString("group"));

    if (flags.getBool("daemonize"))
      Application::daemonize();

    x0d.run();
  } catch (const std::exception& e) {
    fprintf(stderr, "Unhandled exception caught. %s\n", e.what());
    return 1;
  }

  return 0;
}
<commit_msg>x0d: cleanup<commit_after>// This file is part of the "x0" project
//   (c) 2009-2015 Christian Parpart <https://github.com/christianparpart>
//
// x0 is free software: you can redistribute it and/or modify it under
// the terms of the GNU Affero General Public License v3.0.
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

#include "XzeroModule.h"
#include "XzeroDaemon.h"
#include "sysconfig.h"

#include <xzero-flow/ASTPrinter.h>
#include <xzero/logging/ConsoleLogTarget.h>
#include <xzero/logging.h>
#include <xzero/cli/CLI.h>
#include <xzero/cli/Flags.h>
#include <xzero/Application.h>
#include <iostream>
#include <unistd.h>

#define PACKAGE_VERSION X0_VERSION
#define PACKAGE_HOMEPAGE_URL "https://xzero.io"

using namespace xzero;
using namespace xzero::http;

void printHelp(const CLI& cli) {
  std::cout
    << "x0d: Xzero HTTP Web Server " PACKAGE_VERSION
        << " [" PACKAGE_HOMEPAGE_URL "]" << std::endl
    << "Copyright (c) 2009-2015 by Christian Parpart <trapni@gmail.com>" << std::endl
    << std::endl
    << "Usage: x0d [options ...]" << std::endl
    << std::endl
    << "Options:" << std::endl
    << cli.helpText() << std::endl;
}

#define DEFAULT_CONFIG_PATH PROJECT_ROOT_SRC_DIR "/x0d.conf"

int main(int argc, const char* argv[]) {
  try {
    Application::init();

    CLI cli;
    cli.defineBool("help", 'h', "Prints this help and terminates.")
       .defineString("config", 'c', "PATH", "Specify a custom configuration file.", "/etc/x0d/x0d.conf", nullptr)
       .defineString("user", 'u', "NAME", "User privileges to drop down to.", Application::userName())
       .defineString("group", 'g', "NAME", "Group privileges to drop down to.", Application::groupName())
       .defineString("log-level", 'L', "ENUM", "Defines the minimum log level.", "info", nullptr)
       .defineString("log-target", 0, "ENUM", "Specifies logging target. One of syslog, file, systemd, console.", "console", nullptr)
       .defineString("log-file", 'l', "PATH", "Path to application log file.", "", nullptr)
       .defineString("instant", 'i', "PATH[:PORT]", "Enable instant-mode (does not need config file).", "", nullptr)
       .defineNumber("optimization-level", 'O', "LEVEL", "Sets the configuration optimization level.", 1)
       .defineBool("daemonize", 'd', "Forks the process into background.")
       .defineBool("dump-ast", 0, "Dumps configuration AST and exits.")
       .defineBool("dump-ir", 0, "Dumps configuration IR and exits.")
       .defineBool("dump-tc", 0, "Dumps configuration opcode stream and exits.")
       ;

    Flags flags = cli.evaluate(argc, argv);

    if (flags.getBool("help")) {
      printHelp(cli);
      return 0;
    }

    // {{{ setup logging
    Logger::get()->setMinimumLogLevel(to_loglevel(flags.getString("log-level")));

    std::string logTarget = flags.getString("log-target");
    if (logTarget == "null") {
      ; // ignore
    } else if (logTarget == "console") {
      Logger::get()->addTarget(ConsoleLogTarget::get());
    } else if (logTarget == "file") {
      ; // TODO
    } else if (logTarget == "syslog") {
      ; // TODO Logger::get()->addTarget(SyslogTarget::get());
    } else if (logTarget == "systemd") {
      ; // TODO Logger::get()->addTarget(SystemdLogTarget::get());
    } else {
      fprintf(stderr, "Invalid log target \"%s\".\n", logTarget.c_str());
      return 1;
    }
    // }}}

    x0d::XzeroDaemon x0d;

    x0d.setOptimizationLevel(flags.getNumber("optimization-level"));

    x0d.loadConfigFile(flags.getString("config"));

    bool exitBeforeRun = false;

    if (flags.getBool("dump-ast")) {
      xzero::flow::ASTPrinter::print(x0d.programAST());
      exitBeforeRun = true;
    }

    if (flags.getBool("dump-ir")) {
      x0d.programIR()->dump();
      exitBeforeRun = true;
    }

    if (flags.getBool("dump-tc")) {
      x0d.program()->dump();
      exitBeforeRun = true;
    }

    if (exitBeforeRun)
      return 0;

    if (!x0d.configure())
      return 1;

    Application::dropPrivileges(flags.getString("user"), flags.getString("group"));

    if (flags.getBool("daemonize"))
      Application::daemonize();

    x0d.run();
  } catch (const std::exception& e) {
    fprintf(stderr, "Unhandled exception caught. %s\n", e.what());
    return 1;
  }

  return 0;
}
<|endoftext|>


<commit_before>//===-- ScheduleDAG.cpp - Implement a trivial DAG scheduler ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Chris Lattner and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This implements a simple code linearizer for DAGs.  This is not a very good
// way to emit code, but gets working code quickly.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "sched"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetInstrInfo.h"
using namespace llvm;

namespace {
  class SimpleSched {
    SelectionDAG &DAG;
    MachineBasicBlock *BB;
    const TargetMachine &TM;
    const TargetInstrInfo &TII;

    std::map<SDNode *, unsigned> EmittedOps;
  public:
    SimpleSched(SelectionDAG &D, MachineBasicBlock *bb)
      : DAG(D), BB(bb), TM(D.getTarget()), TII(*TM.getInstrInfo()) {
      assert(&TII && "Target doesn't provide instr info?");
    }

    void Run() {
      Emit(DAG.getRoot());
    }

  private:
    unsigned Emit(SDOperand Op);
  };
}

unsigned SimpleSched::Emit(SDOperand Op) {
  // Check to see if we have already emitted this.  If so, return the value
  // already emitted.  Note that if a node has a single use it cannot be
  // revisited, so don't bother putting it in the map.
  unsigned *OpSlot;
  if (Op.Val->hasOneUse()) {
    OpSlot = 0;  // No reuse possible.
  } else {
    std::map<SDNode *, unsigned>::iterator OpI = EmittedOps.lower_bound(Op.Val);
    if (OpI != EmittedOps.end() && OpI->first == Op.Val)
      return OpI->second + Op.ResNo;
    OpSlot = &EmittedOps.insert(OpI, std::make_pair(Op.Val, 0))->second;
  }

  unsigned ResultReg = 0;
  if (Op.isTargetOpcode()) {
    unsigned Opc = Op.getTargetOpcode();
    const TargetInstrDescriptor &II = TII.get(Opc);

    // Target nodes have any register or immediate operands before any chain
    // nodes.  Check that the DAG matches the TD files's expectation of #
    // operands.
    assert((unsigned(II.numOperands) == Op.getNumOperands() ||
            // It could be some number of operands followed by a token chain.
           (unsigned(II.numOperands)+1 == Op.getNumOperands() &&
            Op.getOperand(II.numOperands).getValueType() == MVT::Other)) &&
           "#operands for dag node doesn't match .td file!");

    // Create the new machine instruction.
    MachineInstr *MI = new MachineInstr(Opc, II.numOperands, true, true);

    // Add result register values for things that are defined by this
    // instruction.
    assert(Op.Val->getNumValues() == 1 &&
           Op.getValue(0).getValueType() == MVT::Other &&
           "Return values not implemented yet");

    // Emit all of the operands of this instruction, adding them to the
    // instruction as appropriate.
    for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i) {
      if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(i))) {
        MI->addZeroExtImm64Operand(C->getValue());
      } else if (RegisterSDNode*R =dyn_cast<RegisterSDNode>(Op.getOperand(i))) {
        MI->addRegOperand(R->getReg(), MachineOperand::Use);
      } else {
        unsigned R = Emit(Op.getOperand(i));
        // Add an operand, unless this corresponds to a chain node.
        if (Op.getOperand(i).getValueType() != MVT::Other)
          MI->addRegOperand(R, MachineOperand::Use);
      }
    }

    // Now that we have emitted all operands, emit this instruction itself.
    BB->insert(BB->end(), MI);
  } else {
    switch (Op.getOpcode()) {
    default: assert(0 &&
                    "This target-independent node should have been selected!");
    case ISD::EntryToken: break;
    }
  }

  if (OpSlot) *OpSlot = ResultReg;
  return ResultReg+Op.ResNo;
}

/// Pick a safe ordering and emit instructions for each target node in the
/// graph.
void SelectionDAGISel::ScheduleAndEmitDAG(SelectionDAG &SD) {
  SimpleSched(SD, BB).Run();
}
<commit_msg>add a new -view-sched-dags option to view dags as they are sent to the scheduler.<commit_after>//===-- ScheduleDAG.cpp - Implement a trivial DAG scheduler ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Chris Lattner and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This implements a simple code linearizer for DAGs.  This is not a very good
// way to emit code, but gets working code quickly.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "sched"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Support/CommandLine.h"
using namespace llvm;

#ifndef _NDEBUG
static cl::opt<bool>
ViewDAGs("view-sched-dags", cl::Hidden,
         cl::desc("Pop up a window to show sched dags as they are processed"));
#else
static const bool ViewDAGS = 0;
#endif

namespace {
  class SimpleSched {
    SelectionDAG &DAG;
    MachineBasicBlock *BB;
    const TargetMachine &TM;
    const TargetInstrInfo &TII;

    std::map<SDNode *, unsigned> EmittedOps;
  public:
    SimpleSched(SelectionDAG &D, MachineBasicBlock *bb)
      : DAG(D), BB(bb), TM(D.getTarget()), TII(*TM.getInstrInfo()) {
      assert(&TII && "Target doesn't provide instr info?");
    }

    void Run() {
      Emit(DAG.getRoot());
    }

  private:
    unsigned Emit(SDOperand Op);
  };
}

unsigned SimpleSched::Emit(SDOperand Op) {
  // Check to see if we have already emitted this.  If so, return the value
  // already emitted.  Note that if a node has a single use it cannot be
  // revisited, so don't bother putting it in the map.
  unsigned *OpSlot;
  if (Op.Val->hasOneUse()) {
    OpSlot = 0;  // No reuse possible.
  } else {
    std::map<SDNode *, unsigned>::iterator OpI = EmittedOps.lower_bound(Op.Val);
    if (OpI != EmittedOps.end() && OpI->first == Op.Val)
      return OpI->second + Op.ResNo;
    OpSlot = &EmittedOps.insert(OpI, std::make_pair(Op.Val, 0))->second;
  }

  unsigned ResultReg = 0;
  if (Op.isTargetOpcode()) {
    unsigned Opc = Op.getTargetOpcode();
    const TargetInstrDescriptor &II = TII.get(Opc);

    // Target nodes have any register or immediate operands before any chain
    // nodes.  Check that the DAG matches the TD files's expectation of #
    // operands.
    assert((unsigned(II.numOperands) == Op.getNumOperands() ||
            // It could be some number of operands followed by a token chain.
           (unsigned(II.numOperands)+1 == Op.getNumOperands() &&
            Op.getOperand(II.numOperands).getValueType() == MVT::Other)) &&
           "#operands for dag node doesn't match .td file!");

    // Create the new machine instruction.
    MachineInstr *MI = new MachineInstr(Opc, II.numOperands, true, true);

    // Add result register values for things that are defined by this
    // instruction.
    assert(Op.Val->getNumValues() == 1 &&
           Op.getValue(0).getValueType() == MVT::Other &&
           "Return values not implemented yet");

    // Emit all of the operands of this instruction, adding them to the
    // instruction as appropriate.
    for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i) {
      if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(i))) {
        MI->addZeroExtImm64Operand(C->getValue());
      } else if (RegisterSDNode*R =dyn_cast<RegisterSDNode>(Op.getOperand(i))) {
        MI->addRegOperand(R->getReg(), MachineOperand::Use);
      } else {
        unsigned R = Emit(Op.getOperand(i));
        // Add an operand, unless this corresponds to a chain node.
        if (Op.getOperand(i).getValueType() != MVT::Other)
          MI->addRegOperand(R, MachineOperand::Use);
      }
    }

    // Now that we have emitted all operands, emit this instruction itself.
    BB->insert(BB->end(), MI);
  } else {
    switch (Op.getOpcode()) {
    default: assert(0 &&
                    "This target-independent node should have been selected!");
    case ISD::EntryToken: break;
    }
  }

  if (OpSlot) *OpSlot = ResultReg;
  return ResultReg+Op.ResNo;
}

/// Pick a safe ordering and emit instructions for each target node in the
/// graph.
void SelectionDAGISel::ScheduleAndEmitDAG(SelectionDAG &SD) {
  if (ViewDAGs) SD.viewGraph();
  SimpleSched(SD, BB).Run();
}
<|endoftext|>