<commit_before>#include "clustering/reactor/reactor.hpp"

#include "clustering/immediate_consistency/branch/broadcaster.hpp"
#include "clustering/immediate_consistency/branch/replier.hpp"
#include "clustering/immediate_consistency/query/master.hpp"
#include "clustering/immediate_consistency/branch/multistore.hpp"

template<class key_t, class value_t>
std::map<key_t, value_t> collapse_optionals_in_map(const std::map<key_t, boost::optional<value_t> > &map) {
    std::map<key_t, value_t> res;
    for (typename std::map<key_t, boost::optional<value_t> >::const_iterator it = map.begin(); it != map.end(); it++) {
        if (it->second) {
            res.insert(std::make_pair(it->first, it->second.get()));
        }
    }
    return res;
}

template<class protocol_t>
reactor_t<protocol_t>::reactor_t(
        io_backender_t *_io_backender,
        mailbox_manager_t *mm,
        typename master_t<protocol_t>::ack_checker_t *ack_checker_,
        clone_ptr_t<watchable_t<std::map<peer_id_t, boost::optional<directory_echo_wrapper_t<reactor_business_card_t<protocol_t> > > > > > rd,
        branch_history_manager_t<protocol_t> *bhm,
        clone_ptr_t<watchable_t<blueprint_t<protocol_t> > > b,
        multistore_ptr_t<protocol_t> *_underlying_svs,
        perfmon_collection_t *_parent_perfmon_collection,
        typename protocol_t::context_t *_ctx) THROWS_NOTHING :
    io_backender(_io_backender),
    mailbox_manager(mm),
    ack_checker(ack_checker_),
    reactor_directory(rd),
    directory_echo_writer(mailbox_manager, reactor_business_card_t<protocol_t>()),
    directory_echo_mirror(mailbox_manager, rd->subview(&collapse_optionals_in_map<peer_id_t, directory_echo_wrapper_t<reactor_business_card_t<protocol_t> > >)),
    branch_history_manager(bhm),
    blueprint_watchable(b),
    underlying_svs(_underlying_svs),
    blueprint_subscription(boost::bind(&reactor_t<protocol_t>::on_blueprint_changed, this)),
    parent_perfmon_collection(_parent_perfmon_collection),
    regions_perfmon_collection(),
    regions_perfmon_membership(parent_perfmon_collection, &regions_perfmon_collection, "regions"),
    ctx(_ctx)
{
    {
        typename watchable_t<blueprint_t<protocol_t> >::freeze_t freeze(blueprint_watchable);
        blueprint_watchable->get().assert_valid();
        try_spawn_roles();
        blueprint_subscription.reset(blueprint_watchable, &freeze);
    }
}

template <class protocol_t>
reactor_t<protocol_t>::directory_entry_t::directory_entry_t(reactor_t<protocol_t> *_parent, typename protocol_t::region_t _region)
    : parent(_parent), region(_region), reactor_activity_id(nil_uuid())
{ }

template <class protocol_t>
directory_echo_version_t reactor_t<protocol_t>::directory_entry_t::set(typename reactor_business_card_t<protocol_t>::activity_t activity) {
    typename directory_echo_writer_t<reactor_business_card_t<protocol_t> >::our_value_change_t our_value_change(&parent->directory_echo_writer);
    if (!reactor_activity_id.is_nil()) {
        our_value_change.buffer.activities.erase(reactor_activity_id);
    }
    reactor_activity_id = generate_uuid();
    our_value_change.buffer.activities.insert(std::make_pair(reactor_activity_id, std::make_pair(region, activity)));
    return our_value_change.commit();
}

template <class protocol_t>
directory_echo_version_t reactor_t<protocol_t>::directory_entry_t::update_without_changing_id(typename reactor_business_card_t<protocol_t>::activity_t activity) {
    typename directory_echo_writer_t<reactor_business_card_t<protocol_t> >::our_value_change_t our_value_change(&parent->directory_echo_writer);
    rassert(!reactor_activity_id.is_nil(), "This method should only be called when an activity has already been set\n");

    our_value_change.buffer.activities[reactor_activity_id].second = activity;
    return our_value_change.commit();
}

template <class protocol_t>
reactor_t<protocol_t>::directory_entry_t::~directory_entry_t() {
    if (!reactor_activity_id.is_nil()) {
        typename directory_echo_writer_t<reactor_business_card_t<protocol_t> >::our_value_change_t our_value_change(&parent->directory_echo_writer);
        our_value_change.buffer.activities.erase(reactor_activity_id);
        our_value_change.commit();
    }
}

template<class protocol_t>
void reactor_t<protocol_t>::on_blueprint_changed() THROWS_NOTHING {
    blueprint_t<protocol_t> blueprint = blueprint_watchable->get();
    blueprint.assert_valid();
    rassert(std_contains(blueprint.peers_roles, get_me()), "reactor_t assumes that it is mentioned in the blueprint it's given.");

    std::map<typename protocol_t::region_t, blueprint_role_t> blueprint_roles =
        blueprint.peers_roles.find(get_me())->second;
    for (typename std::map<typename protocol_t::region_t, current_role_t *>::iterator it = current_roles.begin();
            it != current_roles.end(); it++) {
        typename std::map<typename protocol_t::region_t, blueprint_role_t>::iterator it2 =
            blueprint_roles.find((*it).first);
        if (it2 == blueprint_roles.end()) {
            /* The shard boundaries have changed, and the shard that the running
            coroutine was for no longer exists; interrupt it */
            it->second->abort.pulse_if_not_already_pulsed();
        } else {
            if (it->second->role != it2->second) {
                /* Our role for the shard has changed; interrupt the running
                coroutine */
                it->second->abort.pulse_if_not_already_pulsed();
            } else {
                /* Notify the running coroutine of the new blueprint */
                it->second->blueprint.set_value(blueprint);
            }
        }
    }
}

template<class protocol_t>
void reactor_t<protocol_t>::try_spawn_roles() THROWS_NOTHING {
    blueprint_t<protocol_t> blueprint = blueprint_watchable->get();
    rassert(std_contains(blueprint.peers_roles, get_me()), "reactor_t assumes that it is mentioned in the blueprint it's given.");

    std::map<typename protocol_t::region_t, blueprint_role_t> blueprint_roles =
        (*blueprint.peers_roles.find(get_me())).second;
    typename std::map<typename protocol_t::region_t, blueprint_role_t>::iterator it;
    for (it = blueprint_roles.begin(); it != blueprint_roles.end(); it++) {
        bool none_overlap = true;
        for (typename std::map<typename protocol_t::region_t, current_role_t *>::iterator it2 = current_roles.begin();
                it2 != current_roles.end(); it2++) {
            if (region_overlaps((*it).first, (*it2).first)) {
                none_overlap = false;
                break;
            }
        }

        if (none_overlap) {
            //This state will be cleaned up in run_role
            current_role_t *role = new current_role_t(it->second, blueprint);
            current_roles.insert(std::make_pair(it->first, role));
            coro_t::spawn_sometime(boost::bind(&reactor_t<protocol_t>::run_role, this, it->first,
                                               role, auto_drainer_t::lock_t(&drainer)));
        }
    }
}

template<class protocol_t>
void reactor_t<protocol_t>::run_role(
        typename protocol_t::region_t region,
        current_role_t *role,
        auto_drainer_t::lock_t keepalive) THROWS_NOTHING {

    //A store_view_t derived object that acts as a store for the specified region
    multistore_ptr_t<protocol_t> svs_subview(underlying_svs, ctx, region);

    {
        //All of the be_{role} functions respond identically to blueprint changes
        //and interruptions... so we just unify those signals
        wait_any_t wait_any(&role->abort, keepalive.get_drain_signal());

        switch (role->role) {
            case blueprint_role_primary:
                be_primary(region, &svs_subview, role->blueprint.get_watchable(), &wait_any);
                break;
            case blueprint_role_secondary:
                be_secondary(region, &svs_subview, role->blueprint.get_watchable(), &wait_any);
                break;
            case blueprint_role_nothing:
                be_nothing(region, &svs_subview, role->blueprint.get_watchable(), &wait_any);
                break;
            default:
                unreachable();
                break;
        }
    }

    //As promised, clean up the state from try_spawn_roles
    current_roles.erase(region);
    delete role;

    if (!keepalive.get_drain_signal()->is_pulsed()) {
        try_spawn_roles();
    }
}

template<class protocol_t>
boost::optional<boost::optional<broadcaster_business_card_t<protocol_t> > > reactor_t<protocol_t>::extract_broadcaster_from_reactor_business_card_primary(const boost::optional<boost::optional<typename reactor_business_card_t<protocol_t>::primary_t> > &bcard) {
    if (!bcard) {
        return boost::optional<boost::optional<broadcaster_business_card_t<protocol_t> > >();
    }
    if (!bcard.get()) {
        return boost::optional<boost::optional<broadcaster_business_card_t<protocol_t> > >(
            boost::optional<broadcaster_business_card_t<protocol_t> >());
    }
    return boost::optional<boost::optional<broadcaster_business_card_t<protocol_t> > >(
        boost::optional<broadcaster_business_card_t<protocol_t> >(bcard.get().get().broadcaster));
}

template <class protocol_t>
void reactor_t<protocol_t>::wait_for_directory_acks(directory_echo_version_t version_to_wait_on, signal_t *interruptor) THROWS_ONLY(interrupted_exc_t) {
    while (true) {
        /* This function waits for acks from all the peers mentioned in the
        blueprint. If the blueprint changes while we're waiting for acks, we
        restart from the top. This is important because otherwise we might
        deadlock. For example, if we were waiting for a machine to come back up
        and then it was declared dead, our interruptor might not be pulsed but
        the `ack_waiter_t` would never be pulsed so we would get stuck. */
        cond_t blueprint_changed;
        blueprint_t<protocol_t> bp;
        typename watchable_t<blueprint_t<protocol_t> >::subscription_t subscription(
            boost::bind(&cond_t::pulse_if_not_already_pulsed, &blueprint_changed));
        {
            typename watchable_t<blueprint_t<protocol_t> >::freeze_t freeze(blueprint_watchable);
            bp = blueprint_watchable->get();
            subscription.reset(blueprint_watchable, &freeze);
        }
        typename std::map<peer_id_t, std::map<typename protocol_t::region_t, blueprint_role_t> >::iterator it = bp.peers_roles.begin();
        for (it = bp.peers_roles.begin(); it != bp.peers_roles.end(); it++) {
            typename directory_echo_writer_t<reactor_business_card_t<protocol_t> >::ack_waiter_t ack_waiter(&directory_echo_writer, it->first, version_to_wait_on);
            wait_any_t waiter(&ack_waiter, &blueprint_changed);
            wait_interruptible(&waiter, interruptor);
            if (blueprint_changed.is_pulsed()) {
                break;
            }
        }
        if (!blueprint_changed.is_pulsed()) {
            break;
        }
    }
}

#include "mock/dummy_protocol.hpp"
#include "memcached/protocol.hpp"
#include "rdb_protocol/protocol.hpp"

template class reactor_t<mock::dummy_protocol_t>;
template class reactor_t<memcached_protocol_t>;
template class reactor_t<rdb_protocol_t>;
<commit_msg>Rightened up some iterator usage in try_spawn_roles.<commit_after>#include "clustering/reactor/reactor.hpp"

#include "clustering/immediate_consistency/branch/broadcaster.hpp"
#include "clustering/immediate_consistency/branch/replier.hpp"
#include "clustering/immediate_consistency/query/master.hpp"
#include "clustering/immediate_consistency/branch/multistore.hpp"

template<class key_t, class value_t>
std::map<key_t, value_t> collapse_optionals_in_map(const std::map<key_t, boost::optional<value_t> > &map) {
    std::map<key_t, value_t> res;
    for (typename std::map<key_t, boost::optional<value_t> >::const_iterator it = map.begin(); it != map.end(); it++) {
        if (it->second) {
            res.insert(std::make_pair(it->first, it->second.get()));
        }
    }
    return res;
}

template<class protocol_t>
reactor_t<protocol_t>::reactor_t(
        io_backender_t *_io_backender,
        mailbox_manager_t *mm,
        typename master_t<protocol_t>::ack_checker_t *ack_checker_,
        clone_ptr_t<watchable_t<std::map<peer_id_t, boost::optional<directory_echo_wrapper_t<reactor_business_card_t<protocol_t> > > > > > rd,
        branch_history_manager_t<protocol_t> *bhm,
        clone_ptr_t<watchable_t<blueprint_t<protocol_t> > > b,
        multistore_ptr_t<protocol_t> *_underlying_svs,
        perfmon_collection_t *_parent_perfmon_collection,
        typename protocol_t::context_t *_ctx) THROWS_NOTHING :
    io_backender(_io_backender),
    mailbox_manager(mm),
    ack_checker(ack_checker_),
    reactor_directory(rd),
    directory_echo_writer(mailbox_manager, reactor_business_card_t<protocol_t>()),
    directory_echo_mirror(mailbox_manager, rd->subview(&collapse_optionals_in_map<peer_id_t, directory_echo_wrapper_t<reactor_business_card_t<protocol_t> > >)),
    branch_history_manager(bhm),
    blueprint_watchable(b),
    underlying_svs(_underlying_svs),
    blueprint_subscription(boost::bind(&reactor_t<protocol_t>::on_blueprint_changed, this)),
    parent_perfmon_collection(_parent_perfmon_collection),
    regions_perfmon_collection(),
    regions_perfmon_membership(parent_perfmon_collection, &regions_perfmon_collection, "regions"),
    ctx(_ctx)
{
    {
        typename watchable_t<blueprint_t<protocol_t> >::freeze_t freeze(blueprint_watchable);
        blueprint_watchable->get().assert_valid();
        try_spawn_roles();
        blueprint_subscription.reset(blueprint_watchable, &freeze);
    }
}

template <class protocol_t>
reactor_t<protocol_t>::directory_entry_t::directory_entry_t(reactor_t<protocol_t> *_parent, typename protocol_t::region_t _region)
    : parent(_parent), region(_region), reactor_activity_id(nil_uuid())
{ }

template <class protocol_t>
directory_echo_version_t reactor_t<protocol_t>::directory_entry_t::set(typename reactor_business_card_t<protocol_t>::activity_t activity) {
    typename directory_echo_writer_t<reactor_business_card_t<protocol_t> >::our_value_change_t our_value_change(&parent->directory_echo_writer);
    if (!reactor_activity_id.is_nil()) {
        our_value_change.buffer.activities.erase(reactor_activity_id);
    }
    reactor_activity_id = generate_uuid();
    our_value_change.buffer.activities.insert(std::make_pair(reactor_activity_id, std::make_pair(region, activity)));
    return our_value_change.commit();
}

template <class protocol_t>
directory_echo_version_t reactor_t<protocol_t>::directory_entry_t::update_without_changing_id(typename reactor_business_card_t<protocol_t>::activity_t activity) {
    typename directory_echo_writer_t<reactor_business_card_t<protocol_t> >::our_value_change_t our_value_change(&parent->directory_echo_writer);
    rassert(!reactor_activity_id.is_nil(), "This method should only be called when an activity has already been set\n");

    our_value_change.buffer.activities[reactor_activity_id].second = activity;
    return our_value_change.commit();
}

template <class protocol_t>
reactor_t<protocol_t>::directory_entry_t::~directory_entry_t() {
    if (!reactor_activity_id.is_nil()) {
        typename directory_echo_writer_t<reactor_business_card_t<protocol_t> >::our_value_change_t our_value_change(&parent->directory_echo_writer);
        our_value_change.buffer.activities.erase(reactor_activity_id);
        our_value_change.commit();
    }
}

template<class protocol_t>
void reactor_t<protocol_t>::on_blueprint_changed() THROWS_NOTHING {
    blueprint_t<protocol_t> blueprint = blueprint_watchable->get();
    blueprint.assert_valid();
    rassert(std_contains(blueprint.peers_roles, get_me()), "reactor_t assumes that it is mentioned in the blueprint it's given.");

    std::map<typename protocol_t::region_t, blueprint_role_t> blueprint_roles =
        blueprint.peers_roles.find(get_me())->second;
    for (typename std::map<typename protocol_t::region_t, current_role_t *>::iterator it = current_roles.begin();
            it != current_roles.end(); it++) {
        typename std::map<typename protocol_t::region_t, blueprint_role_t>::iterator it2 =
            blueprint_roles.find((*it).first);
        if (it2 == blueprint_roles.end()) {
            /* The shard boundaries have changed, and the shard that the running
            coroutine was for no longer exists; interrupt it */
            it->second->abort.pulse_if_not_already_pulsed();
        } else {
            if (it->second->role != it2->second) {
                /* Our role for the shard has changed; interrupt the running
                coroutine */
                it->second->abort.pulse_if_not_already_pulsed();
            } else {
                /* Notify the running coroutine of the new blueprint */
                it->second->blueprint.set_value(blueprint);
            }
        }
    }
}

template<class protocol_t>
void reactor_t<protocol_t>::try_spawn_roles() THROWS_NOTHING {
    blueprint_t<protocol_t> blueprint = blueprint_watchable->get();
    rassert(std_contains(blueprint.peers_roles, get_me()), "reactor_t assumes that it is mentioned in the blueprint it's given.");

    std::map<typename protocol_t::region_t, blueprint_role_t> blueprint_roles =
        blueprint.peers_roles.find(get_me())->second;
    for (typename std::map<typename protocol_t::region_t, blueprint_role_t>::iterator it = blueprint_roles.begin();
         it != blueprint_roles.end(); ++it) {
        bool none_overlap = true;
        for (typename std::map<typename protocol_t::region_t, current_role_t *>::iterator it2 = current_roles.begin();
             it2 != current_roles.end(); ++it2) {
            if (region_overlaps(it->first, it2->first)) {
                none_overlap = false;
                break;
            }
        }

        if (none_overlap) {
            //This state will be cleaned up in run_role
            current_role_t *role = new current_role_t(it->second, blueprint);
            current_roles.insert(std::make_pair(it->first, role));
            coro_t::spawn_sometime(boost::bind(&reactor_t<protocol_t>::run_role, this, it->first,
                                               role, auto_drainer_t::lock_t(&drainer)));
        }
    }
}

template<class protocol_t>
void reactor_t<protocol_t>::run_role(
        typename protocol_t::region_t region,
        current_role_t *role,
        auto_drainer_t::lock_t keepalive) THROWS_NOTHING {

    //A store_view_t derived object that acts as a store for the specified region
    multistore_ptr_t<protocol_t> svs_subview(underlying_svs, ctx, region);

    {
        //All of the be_{role} functions respond identically to blueprint changes
        //and interruptions... so we just unify those signals
        wait_any_t wait_any(&role->abort, keepalive.get_drain_signal());

        switch (role->role) {
            case blueprint_role_primary:
                be_primary(region, &svs_subview, role->blueprint.get_watchable(), &wait_any);
                break;
            case blueprint_role_secondary:
                be_secondary(region, &svs_subview, role->blueprint.get_watchable(), &wait_any);
                break;
            case blueprint_role_nothing:
                be_nothing(region, &svs_subview, role->blueprint.get_watchable(), &wait_any);
                break;
            default:
                unreachable();
                break;
        }
    }

    //As promised, clean up the state from try_spawn_roles
    current_roles.erase(region);
    delete role;

    if (!keepalive.get_drain_signal()->is_pulsed()) {
        try_spawn_roles();
    }
}

template<class protocol_t>
boost::optional<boost::optional<broadcaster_business_card_t<protocol_t> > > reactor_t<protocol_t>::extract_broadcaster_from_reactor_business_card_primary(const boost::optional<boost::optional<typename reactor_business_card_t<protocol_t>::primary_t> > &bcard) {
    if (!bcard) {
        return boost::optional<boost::optional<broadcaster_business_card_t<protocol_t> > >();
    }
    if (!bcard.get()) {
        return boost::optional<boost::optional<broadcaster_business_card_t<protocol_t> > >(
            boost::optional<broadcaster_business_card_t<protocol_t> >());
    }
    return boost::optional<boost::optional<broadcaster_business_card_t<protocol_t> > >(
        boost::optional<broadcaster_business_card_t<protocol_t> >(bcard.get().get().broadcaster));
}

template <class protocol_t>
void reactor_t<protocol_t>::wait_for_directory_acks(directory_echo_version_t version_to_wait_on, signal_t *interruptor) THROWS_ONLY(interrupted_exc_t) {
    while (true) {
        /* This function waits for acks from all the peers mentioned in the
        blueprint. If the blueprint changes while we're waiting for acks, we
        restart from the top. This is important because otherwise we might
        deadlock. For example, if we were waiting for a machine to come back up
        and then it was declared dead, our interruptor might not be pulsed but
        the `ack_waiter_t` would never be pulsed so we would get stuck. */
        cond_t blueprint_changed;
        blueprint_t<protocol_t> bp;
        typename watchable_t<blueprint_t<protocol_t> >::subscription_t subscription(
            boost::bind(&cond_t::pulse_if_not_already_pulsed, &blueprint_changed));
        {
            typename watchable_t<blueprint_t<protocol_t> >::freeze_t freeze(blueprint_watchable);
            bp = blueprint_watchable->get();
            subscription.reset(blueprint_watchable, &freeze);
        }
        typename std::map<peer_id_t, std::map<typename protocol_t::region_t, blueprint_role_t> >::iterator it = bp.peers_roles.begin();
        for (it = bp.peers_roles.begin(); it != bp.peers_roles.end(); it++) {
            typename directory_echo_writer_t<reactor_business_card_t<protocol_t> >::ack_waiter_t ack_waiter(&directory_echo_writer, it->first, version_to_wait_on);
            wait_any_t waiter(&ack_waiter, &blueprint_changed);
            wait_interruptible(&waiter, interruptor);
            if (blueprint_changed.is_pulsed()) {
                break;
            }
        }
        if (!blueprint_changed.is_pulsed()) {
            break;
        }
    }
}

#include "mock/dummy_protocol.hpp"
#include "memcached/protocol.hpp"
#include "rdb_protocol/protocol.hpp"

template class reactor_t<mock::dummy_protocol_t>;
template class reactor_t<memcached_protocol_t>;
template class reactor_t<rdb_protocol_t>;
<|endoftext|>


<commit_before>// Copyright (c) 2013, Cloudera, inc.

#include "common/maintenance_manager.h"

#include <boost/foreach.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <errno.h>
#include <gflags/gflags.h>
#include <set>
#include <stdint.h>
#include <string>
#include <sys/sysinfo.h>
#include <tr1/memory>
#include <utility>

#include "tablet/mvcc.h"
#include "util/countdown_latch.h"
#include "util/monotime.h"
#include "util/thread.h"

using std::pair;
using std::tr1::shared_ptr;

DEFINE_int32(maintenance_manager_num_threads, 4,
       "Size of the maintenance manager thread pool.");
DEFINE_int32(maintenance_manager_polling_interval_ms, 250,
       "Polling interval for the maintenance manager scheduler, "
       "in milliseconds.");
DEFINE_int64(maintenance_manager_memory_limit, 0,
       "Maximum amount of memory this daemon should use.  -1 for "
       "autosizing based on the total system memory.");
DEFINE_int64(maintenance_manager_max_ts_anchored_secs, 0,
       "We will try not to let entries sit in the write-ahead log for "
       "longer than this interval in milliseconds.");

namespace kudu {

void MaintenanceOpStats::Clear() {
  runnable = false;
  ram_anchored = 0;
  ts_anchored_secs = 0;
  perf_improvement = 0;
}

MaintenanceOp::MaintenanceOp(const std::string &name)
  : name_(name),
    running_(0) {
}

MaintenanceOp::~MaintenanceOp() {
  MaintenanceManager* manager =  manager_.get();
  if (manager) {
    manager->UnregisterOp(this);
  }
}

std::string MaintenanceOp::name() const {
  return name_;
}

Atomic32 MaintenanceManager::disabled_ = 0;

const MaintenanceManager::Options MaintenanceManager::DEFAULT_OPTIONS = {
  0,
  0,
  0,
  0,
};

MaintenanceManager::MaintenanceManager(const Options& options)
  : num_threads_(options.num_threads <= 0 ?
      FLAGS_maintenance_manager_num_threads : options.num_threads),
    thread_pool_("MaintenanceManager",
        num_threads_, num_threads_, ThreadPool::DEFAULT_TIMEOUT),
    shutdown_(false),
    mem_target_(0),
    running_ops_(0),
    polling_interval_ms_(options.polling_interval_ms < 0 ?
          FLAGS_maintenance_manager_polling_interval_ms :
          options.polling_interval_ms),
    memory_limit_(options.memory_limit <= 0 ?
          FLAGS_maintenance_manager_memory_limit : options.memory_limit),
    max_ts_anchored_secs_(options.max_ts_anchored_secs < 0 ?
          FLAGS_maintenance_manager_max_ts_anchored_secs :
          options.max_ts_anchored_secs) { }

MaintenanceManager::~MaintenanceManager() {
  Shutdown();
}

Status MaintenanceManager::Init() {
  RETURN_NOT_OK(CalculateMemTarget(&mem_target_));
  LOG(INFO) << StringPrintf("MaintenanceManager: targetting memory size of %.6f GB",
                (static_cast<float>(mem_target_) / (1024.0 * 1024.0 * 1024.0)));
  RETURN_NOT_OK(thread_pool_.Init());
  RETURN_NOT_OK(Thread::Create("maintenance", "maintenance_scheduler",
      boost::bind(&MaintenanceManager::RunSchedulerThread, this),
      &monitor_thread_));
  return Status::OK();
}

void MaintenanceManager::Shutdown() {
  {
    boost::lock_guard<boost::mutex> guard(lock_);
    if (shutdown_) {
      return;
    }
    shutdown_ = true;
    cond_.notify_all();
  }
  if (monitor_thread_.get()) {
    CHECK_OK(ThreadJoiner(monitor_thread_.get()).Join());
    monitor_thread_.reset();
    thread_pool_.Shutdown();
  }
}

void MaintenanceManager::Disable() {
  LOG(INFO) << "Disabling maintenance manager";
  base::subtle::Acquire_Store(&disabled_, 1);
}

void MaintenanceManager::RegisterOp(MaintenanceOp* op) {
  boost::lock_guard<boost::mutex> guard(lock_);
  CHECK(!op->manager_.get()) << "Tried to register " << op->name()
          << ", but it was already registered.";
  pair<OpMapTy::iterator, bool> val
    (ops_.insert(OpMapTy::value_type(op, MaintenanceOpStats())));
  CHECK(val.second)
      << "Tried to register " << op->name()
      << ", but it already exists in ops_.";
  op->manager_ = shared_from_this();
  VLOG(1) << "Registered " << op->name();
}

void MaintenanceManager::UnregisterOp(MaintenanceOp* op) {
  CHECK(op->manager_.get() == this) << "Tried to unregister " << op->name()
        << ", but it was not registered with this maintenance manager.";
  boost::unique_lock<boost::mutex> guard(lock_);
  OpMapTy::iterator iter = ops_.find(op);
  CHECK(iter != ops_.end()) << "Tried to unregister " << op->name()
      << ", but it was never registered";
  // While the op is running, wait for it to be finished.
  if (iter->first->running_ > 0) {
    VLOG(1) << "Waiting for op " << op->name() << " to finish so "
           << "we can unregister it.";
  }
  while (iter->first->running_ > 0) {
    op->cond_.wait(guard);
    iter = ops_.find(op);
    CHECK(iter != ops_.end()) << "Tried to unregister " << op->name()
        << ", but another thread unregistered it while we were "
        << "waiting for it to complete";
  }
  ops_.erase(iter);
  LOG(INFO) << "Unregistered op " << op->name();
  guard.unlock();
  // Remove the op's shared_ptr reference to us.  This might 'delete this'
  op->manager_.reset();
}

void MaintenanceManager::RunSchedulerThread() {
  boost::posix_time::milliseconds
        polling_interval(polling_interval_ms_);

  boost::unique_lock<boost::mutex> guard(lock_);
  boost::system_time cur_time;
  next_schedule_time_ = boost::get_system_time() + polling_interval;
  while (true) {
    // Loop until we are shutting down or it is time to run another op.
    do {
      cond_.timed_wait(guard, next_schedule_time_);
      if (shutdown_) {
        VLOG(1) << "Shutting down maintenance manager.";
        return;
      }
      cur_time = boost::get_system_time();
    } while (cur_time < next_schedule_time_);

    // Find the best op.
    MaintenanceOp* op = FindBestOp();
    if (!op) {
      VLOG(2) << "No maintenance operations look worth doing.";
      next_schedule_time_ = cur_time + polling_interval;
      continue;
    }

    // Prepare the maintenance operation.
    op->running_++;
    running_ops_++;
    guard.unlock();
    bool ready = op->Prepare();
    guard.lock();
    if (!ready) {
      LOG(INFO) << "Prepare failed for " << op->name()
                << ".  Re-running scheduler.";
      op->running_--;
      op->cond_.notify_one();
      continue;
    }

    // Run the maintenance operation.
    Status s = thread_pool_.SubmitFunc(boost::bind(
          &MaintenanceManager::LaunchOp, this, op));
    CHECK(s.ok());
    next_schedule_time_ = cur_time + polling_interval;
  }
}

MaintenanceOp* MaintenanceManager::FindBestOp() {
  if (base::subtle::Acquire_Load(&disabled_)) return NULL;
  size_t free_threads = num_threads_ - running_ops_;
  if (free_threads == 0) {
    VLOG(1) << "there are no free threads, so we can't run anything.";
    return NULL;
  }

  uint64_t mem_total = 0;
  uint64_t most_mem_anchored = 0;
  MaintenanceOp* most_mem_anchored_op = NULL;
  int32_t ts_anchored_secs = 0;
  MaintenanceOp* ts_anchored_secs_op = NULL;
  uint64_t best_perf_improvement = 0;
  MaintenanceOp* best_perf_improvement_op = NULL;
  BOOST_FOREACH(OpMapTy::value_type &val, ops_) {
    MaintenanceOp* op(val.first);
    MaintenanceOpStats& stats(val.second);
    // Update op stats.
    stats.Clear();
    op->UpdateStats(&stats);
    // Add anchored memory to the total.
    mem_total += stats.ram_anchored;
    if (stats.runnable) {
      if (stats.ram_anchored > most_mem_anchored) {
        most_mem_anchored_op = op;
        most_mem_anchored = stats.ram_anchored;
      }
      if (stats.ts_anchored_secs > ts_anchored_secs) {
        ts_anchored_secs_op = op;
        ts_anchored_secs = stats.ts_anchored_secs;
      }
      if ((!best_perf_improvement_op) ||
          (stats.perf_improvement > best_perf_improvement)) {
        best_perf_improvement_op = op;
        best_perf_improvement = stats.perf_improvement;
      }
    }
  }
  // Look at free memory.  If it is dangerously low, we must select something
  // that frees memory-- the op with the most anchored memory.
  if (mem_total > mem_target_) {
    if (!most_mem_anchored_op) {
      LOG(INFO) << "mem_total is at " << mem_total << ", whereas we are "
              << "targetting " << mem_target_ << ".  However, there are "
              << "no ops currently runnable which would free memory. ";
      return NULL;
    }
    VLOG(1) << "mem_total is at " << mem_total << ", whereas we are "
            << "targetting " << mem_target_ << ".  Running the op "
            << "which anchors the most memory: "
            << most_mem_anchored_op->name();
    return most_mem_anchored_op;
  }
  // At this point, we know memory pressure is not too high.
  // If our threadpool has more than one thread, we should leave a spare thread for future
  // memory emergencies that might happen in the future.
  if ((num_threads_ > 1) && (free_threads == 1)) {
    VLOG(1) << "Leaving a free thread in case memory pressure becomes "
            << "high in the future.";
    return NULL;
  }
  if (ts_anchored_secs > max_ts_anchored_secs_) {
    CHECK_NOTNULL(ts_anchored_secs_op);
    VLOG(1) << "Performing " << ts_anchored_secs_op->name() << ", "
               << "because it anchors a transaction ID which is "
               << ts_anchored_secs << "ms old, and "
               << "max_ts_anchored_secs_ = " << max_ts_anchored_secs_;
    return ts_anchored_secs_op;
  }
  if (best_perf_improvement_op) {
    if (best_perf_improvement > 0) {
      VLOG(1) << "Performing " << best_perf_improvement_op->name() << ", "
                 << "because it had the best perf_improvement score, "
                 << "at " << best_perf_improvement;
      return best_perf_improvement_op;
    }
  }
  return NULL;
}

void MaintenanceManager::LaunchOp(MaintenanceOp* op) {
  MonoTime start_time(MonoTime::Now(MonoTime::FINE));
  op->Perform();
  MonoTime end_time(MonoTime::Now(MonoTime::FINE));
  MonoDelta delta(end_time.GetDeltaSince(start_time));
  LOG(INFO) << StringPrintf("MaintenanceManager ran %s in %0.5gs",
                            op->name().c_str(), delta.ToSeconds());
  boost::lock_guard<boost::mutex> guard(lock_);
  running_ops_--;
  op->running_--;
  op->cond_.notify_one();
}

Status MaintenanceManager::CalculateMemTarget(uint64_t* mem_target) {
  if (memory_limit_ > 0) {
    *mem_target = memory_limit_;
    return Status::OK();
  }
  uint64_t mem_total = 0;
  RETURN_NOT_OK(CalculateMemTotal(&mem_total));
  *mem_target = mem_total * 4;
  *mem_target /= 5;
  return Status::OK();
}

// TODO: put this into Env
Status MaintenanceManager::CalculateMemTotal(uint64_t* total) {
#ifdef __linux__
  struct sysinfo info;
  if (sysinfo(&info) < 0) {
    int ret = errno;
    return Status::IOError("sysinfo() failed",
                           ErrnoToString(ret), ret);
  }
  *total = info.totalram;
  return Status::OK();
#else
#error "please implement CalculateMemTotal for this platform"
#endif
}

} // namespace kudu
<commit_msg>Maintenance manager: fix defaults<commit_after>// Copyright (c) 2013, Cloudera, inc.

#include "common/maintenance_manager.h"

#include <boost/foreach.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <errno.h>
#include <gflags/gflags.h>
#include <set>
#include <stdint.h>
#include <string>
#include <sys/sysinfo.h>
#include <tr1/memory>
#include <utility>

#include "tablet/mvcc.h"
#include "util/countdown_latch.h"
#include "util/monotime.h"
#include "util/thread.h"

using std::pair;
using std::tr1::shared_ptr;

DEFINE_int32(maintenance_manager_num_threads, 4,
       "Size of the maintenance manager thread pool.");
DEFINE_int32(maintenance_manager_polling_interval_ms, 250,
       "Polling interval for the maintenance manager scheduler, "
       "in milliseconds.");
DEFINE_int64(maintenance_manager_memory_limit, 0,
       "Maximum amount of memory this daemon should use.  0 for "
       "autosizing based on the total system memory.");
DEFINE_int64(maintenance_manager_max_ts_anchored_secs, 0,
       "We will try not to let entries sit in the write-ahead log for "
       "longer than this interval in milliseconds.");

namespace kudu {

void MaintenanceOpStats::Clear() {
  runnable = false;
  ram_anchored = 0;
  ts_anchored_secs = 0;
  perf_improvement = 0;
}

MaintenanceOp::MaintenanceOp(const std::string &name)
  : name_(name),
    running_(0) {
}

MaintenanceOp::~MaintenanceOp() {
  MaintenanceManager* manager =  manager_.get();
  if (manager) {
    manager->UnregisterOp(this);
  }
}

std::string MaintenanceOp::name() const {
  return name_;
}

Atomic32 MaintenanceManager::disabled_ = 0;

const MaintenanceManager::Options MaintenanceManager::DEFAULT_OPTIONS = {
  0,
  0,
  0,
  0,
};

MaintenanceManager::MaintenanceManager(const Options& options)
  : num_threads_(options.num_threads <= 0 ?
      FLAGS_maintenance_manager_num_threads : options.num_threads),
    thread_pool_("MaintenanceManager",
        num_threads_, num_threads_, ThreadPool::DEFAULT_TIMEOUT),
    shutdown_(false),
    mem_target_(0),
    running_ops_(0),
    polling_interval_ms_(options.polling_interval_ms <= 0 ?
          FLAGS_maintenance_manager_polling_interval_ms :
          options.polling_interval_ms),
    memory_limit_(options.memory_limit <= 0 ?
          FLAGS_maintenance_manager_memory_limit : options.memory_limit),
    max_ts_anchored_secs_(options.max_ts_anchored_secs <= 0 ?
          FLAGS_maintenance_manager_max_ts_anchored_secs :
          options.max_ts_anchored_secs) { }

MaintenanceManager::~MaintenanceManager() {
  Shutdown();
}

Status MaintenanceManager::Init() {
  RETURN_NOT_OK(CalculateMemTarget(&mem_target_));
  LOG(INFO) << StringPrintf("MaintenanceManager: targetting memory size of %.6f GB",
                (static_cast<float>(mem_target_) / (1024.0 * 1024.0 * 1024.0)));
  RETURN_NOT_OK(thread_pool_.Init());
  RETURN_NOT_OK(Thread::Create("maintenance", "maintenance_scheduler",
      boost::bind(&MaintenanceManager::RunSchedulerThread, this),
      &monitor_thread_));
  return Status::OK();
}

void MaintenanceManager::Shutdown() {
  {
    boost::lock_guard<boost::mutex> guard(lock_);
    if (shutdown_) {
      return;
    }
    shutdown_ = true;
    cond_.notify_all();
  }
  if (monitor_thread_.get()) {
    CHECK_OK(ThreadJoiner(monitor_thread_.get()).Join());
    monitor_thread_.reset();
    thread_pool_.Shutdown();
  }
}

void MaintenanceManager::Disable() {
  LOG(INFO) << "Disabling maintenance manager";
  base::subtle::Acquire_Store(&disabled_, 1);
}

void MaintenanceManager::RegisterOp(MaintenanceOp* op) {
  boost::lock_guard<boost::mutex> guard(lock_);
  CHECK(!op->manager_.get()) << "Tried to register " << op->name()
          << ", but it was already registered.";
  pair<OpMapTy::iterator, bool> val
    (ops_.insert(OpMapTy::value_type(op, MaintenanceOpStats())));
  CHECK(val.second)
      << "Tried to register " << op->name()
      << ", but it already exists in ops_.";
  op->manager_ = shared_from_this();
  VLOG(1) << "Registered " << op->name();
}

void MaintenanceManager::UnregisterOp(MaintenanceOp* op) {
  CHECK(op->manager_.get() == this) << "Tried to unregister " << op->name()
        << ", but it was not registered with this maintenance manager.";
  boost::unique_lock<boost::mutex> guard(lock_);
  OpMapTy::iterator iter = ops_.find(op);
  CHECK(iter != ops_.end()) << "Tried to unregister " << op->name()
      << ", but it was never registered";
  // While the op is running, wait for it to be finished.
  if (iter->first->running_ > 0) {
    VLOG(1) << "Waiting for op " << op->name() << " to finish so "
           << "we can unregister it.";
  }
  while (iter->first->running_ > 0) {
    op->cond_.wait(guard);
    iter = ops_.find(op);
    CHECK(iter != ops_.end()) << "Tried to unregister " << op->name()
        << ", but another thread unregistered it while we were "
        << "waiting for it to complete";
  }
  ops_.erase(iter);
  LOG(INFO) << "Unregistered op " << op->name();
  guard.unlock();
  // Remove the op's shared_ptr reference to us.  This might 'delete this'
  op->manager_.reset();
}

void MaintenanceManager::RunSchedulerThread() {
  boost::posix_time::milliseconds
        polling_interval(polling_interval_ms_);

  boost::unique_lock<boost::mutex> guard(lock_);
  boost::system_time cur_time;
  next_schedule_time_ = boost::get_system_time() + polling_interval;
  while (true) {
    // Loop until we are shutting down or it is time to run another op.
    do {
      cond_.timed_wait(guard, next_schedule_time_);
      if (shutdown_) {
        VLOG(1) << "Shutting down maintenance manager.";
        return;
      }
      cur_time = boost::get_system_time();
    } while (cur_time < next_schedule_time_);

    // Find the best op.
    MaintenanceOp* op = FindBestOp();
    if (!op) {
      VLOG(2) << "No maintenance operations look worth doing.";
      next_schedule_time_ = cur_time + polling_interval;
      continue;
    }

    // Prepare the maintenance operation.
    op->running_++;
    running_ops_++;
    guard.unlock();
    bool ready = op->Prepare();
    guard.lock();
    if (!ready) {
      LOG(INFO) << "Prepare failed for " << op->name()
                << ".  Re-running scheduler.";
      op->running_--;
      op->cond_.notify_one();
      continue;
    }

    // Run the maintenance operation.
    Status s = thread_pool_.SubmitFunc(boost::bind(
          &MaintenanceManager::LaunchOp, this, op));
    CHECK(s.ok());
    next_schedule_time_ = cur_time + polling_interval;
  }
}

MaintenanceOp* MaintenanceManager::FindBestOp() {
  if (base::subtle::Acquire_Load(&disabled_)) return NULL;
  size_t free_threads = num_threads_ - running_ops_;
  if (free_threads == 0) {
    VLOG(1) << "there are no free threads, so we can't run anything.";
    return NULL;
  }

  uint64_t mem_total = 0;
  uint64_t most_mem_anchored = 0;
  MaintenanceOp* most_mem_anchored_op = NULL;
  int32_t ts_anchored_secs = 0;
  MaintenanceOp* ts_anchored_secs_op = NULL;
  uint64_t best_perf_improvement = 0;
  MaintenanceOp* best_perf_improvement_op = NULL;
  BOOST_FOREACH(OpMapTy::value_type &val, ops_) {
    MaintenanceOp* op(val.first);
    MaintenanceOpStats& stats(val.second);
    // Update op stats.
    stats.Clear();
    op->UpdateStats(&stats);
    // Add anchored memory to the total.
    mem_total += stats.ram_anchored;
    if (stats.runnable) {
      if (stats.ram_anchored > most_mem_anchored) {
        most_mem_anchored_op = op;
        most_mem_anchored = stats.ram_anchored;
      }
      if (stats.ts_anchored_secs > ts_anchored_secs) {
        ts_anchored_secs_op = op;
        ts_anchored_secs = stats.ts_anchored_secs;
      }
      if ((!best_perf_improvement_op) ||
          (stats.perf_improvement > best_perf_improvement)) {
        best_perf_improvement_op = op;
        best_perf_improvement = stats.perf_improvement;
      }
    }
  }
  // Look at free memory.  If it is dangerously low, we must select something
  // that frees memory-- the op with the most anchored memory.
  if (mem_total > mem_target_) {
    if (!most_mem_anchored_op) {
      LOG(INFO) << "mem_total is at " << mem_total << ", whereas we are "
              << "targetting " << mem_target_ << ".  However, there are "
              << "no ops currently runnable which would free memory. ";
      return NULL;
    }
    VLOG(1) << "mem_total is at " << mem_total << ", whereas we are "
            << "targetting " << mem_target_ << ".  Running the op "
            << "which anchors the most memory: "
            << most_mem_anchored_op->name();
    return most_mem_anchored_op;
  }
  // At this point, we know memory pressure is not too high.
  // If our threadpool has more than one thread, we should leave a spare thread for future
  // memory emergencies that might happen in the future.
  if ((num_threads_ > 1) && (free_threads == 1)) {
    VLOG(1) << "Leaving a free thread in case memory pressure becomes "
            << "high in the future.";
    return NULL;
  }
  if (ts_anchored_secs > max_ts_anchored_secs_) {
    CHECK_NOTNULL(ts_anchored_secs_op);
    VLOG(1) << "Performing " << ts_anchored_secs_op->name() << ", "
               << "because it anchors a transaction ID which is "
               << ts_anchored_secs << "ms old, and "
               << "max_ts_anchored_secs_ = " << max_ts_anchored_secs_;
    return ts_anchored_secs_op;
  }
  if (best_perf_improvement_op) {
    if (best_perf_improvement > 0) {
      VLOG(1) << "Performing " << best_perf_improvement_op->name() << ", "
                 << "because it had the best perf_improvement score, "
                 << "at " << best_perf_improvement;
      return best_perf_improvement_op;
    }
  }
  return NULL;
}

void MaintenanceManager::LaunchOp(MaintenanceOp* op) {
  MonoTime start_time(MonoTime::Now(MonoTime::FINE));
  op->Perform();
  MonoTime end_time(MonoTime::Now(MonoTime::FINE));
  MonoDelta delta(end_time.GetDeltaSince(start_time));
  LOG(INFO) << StringPrintf("MaintenanceManager ran %s in %0.5gs",
                            op->name().c_str(), delta.ToSeconds());
  boost::lock_guard<boost::mutex> guard(lock_);
  running_ops_--;
  op->running_--;
  op->cond_.notify_one();
}

Status MaintenanceManager::CalculateMemTarget(uint64_t* mem_target) {
  if (memory_limit_ > 0) {
    *mem_target = memory_limit_;
    return Status::OK();
  }
  uint64_t mem_total = 0;
  RETURN_NOT_OK(CalculateMemTotal(&mem_total));
  *mem_target = mem_total * 4;
  *mem_target /= 5;
  return Status::OK();
}

// TODO: put this into Env
Status MaintenanceManager::CalculateMemTotal(uint64_t* total) {
#ifdef __linux__
  struct sysinfo info;
  if (sysinfo(&info) < 0) {
    int ret = errno;
    return Status::IOError("sysinfo() failed",
                           ErrnoToString(ret), ret);
  }
  *total = info.totalram;
  return Status::OK();
#else
#error "please implement CalculateMemTotal for this platform"
#endif
}

} // namespace kudu
<|endoftext|>


<commit_before>#include <sstream>
#include <vector>
#include <string>
#include <stack>
#include <map>

#include "Constants.h"
#include "ExpressionMaker.h"
#include "UnaryOperator.h"
#include "BinaryOperator.h"
#include "Operand.h"

ExpressionMaker::ExpressionMaker(VariableTable& varTable)
	: m_isTreeGenerated(false), m_postfix(""), m_internalExpression(), m_varTable(varTable)
{ }

ExpressionMaker::~ExpressionMaker()
{ }

void ExpressionMaker::SetPostfix(const std::string& postfix)
{
	m_postfix = postfix;
	m_isTreeGenerated = false;
}

Expression ExpressionMaker::GetExpression()
{
	if (m_postfix == "")
	{
		throw ExpressionMakerError("Postfix is empty");
	}
	else if (!m_isTreeGenerated)
	{
		Expression e(MakeExpressionTree(m_postfix));
		m_internalExpression = e;
		m_isTreeGenerated = true;
	}

	return m_internalExpression;
}

ExpressionTree* ExpressionMaker::MakeExpressionTree(const std::string& postfix)
{
	std::stack<ExpressionTree*> treeStack;
	std::string token;
	std::istringstream iss(postfix);

	while (iss >> token)
	{
		if (token == "u-")
		{
			ExpressionTree* rhs = treeStack.top();
			treeStack.pop();

			treeStack.push(new UnaryMinus(rhs));
		}
		else if (token == "sin")
		{
			ExpressionTree* rhs = treeStack.top();
			treeStack.pop();

			treeStack.push(new Sine(rhs));
		}
		else if (token == "cos")
		{
			ExpressionTree* rhs = treeStack.top();
			treeStack.pop();

			treeStack.push(new Cosine(rhs));
		}
		else if (token == "tan")
		{
			ExpressionTree* rhs = treeStack.top();
			treeStack.pop();

			treeStack.push(new UnaryMinus(rhs));
		}
		else if (std::find(operators.begin(), operators.end(), token) != operators.end())
		{
			ExpressionTree* rhs = treeStack.top();
			treeStack.pop();
			ExpressionTree* lhs = treeStack.top();
			treeStack.pop();

			if (token == "^")
			{
				treeStack.push(new Power(lhs, rhs));
			}
			else if (token == "*")
			{
				treeStack.push(new Multiply(lhs, rhs));
			}
			else if (token == "/")
			{
				treeStack.push(new Divide(lhs, rhs));
			}
			else if (token == "+")
			{
				treeStack.push(new Plus(lhs, rhs));
			}
			else if (token == "-")
			{
				treeStack.push(new BinaryMinus(lhs, rhs));
			}
			else if (token == "=")
			{
				treeStack.push(new Assign(lhs, rhs, m_varTable));
			}
		}
		else if (token.find_first_not_of(integer_chars) == std::string::npos)
		{
			treeStack.push(new Integer(atoi(token.c_str())));
		}
		else if (token.find_first_not_of(real_chars) == std::string::npos)
		{
			treeStack.push(new Real(atof(token.c_str())));
		}
		else if (token.find_first_not_of(identifier_chars) == std::string::npos)
		{
			treeStack.push(new Variable(token, m_varTable));
		}
		else
		{
			while (!treeStack.empty())
			{
				delete treeStack.top();
				treeStack.pop();
			}

			throw ExpressionMakerError("Invalid Postfix");
		}
	}

	if (treeStack.empty())
	{
		throw ExpressionMakerError("Invalid Postfix");
	}

	if (treeStack.size() > 1)
	{
		while (!treeStack.empty())
		{
			delete treeStack.top();
			treeStack.pop();
		}

		throw ExpressionMakerError("Invalid Postfix");
	}

	return treeStack.top();
}
<commit_msg>fix wrong ExpressionMaker of Tangent()<commit_after>#include <sstream>
#include <vector>
#include <string>
#include <stack>
#include <map>

#include "Constants.h"
#include "ExpressionMaker.h"
#include "UnaryOperator.h"
#include "BinaryOperator.h"
#include "Operand.h"

ExpressionMaker::ExpressionMaker(VariableTable& varTable)
	: m_isTreeGenerated(false), m_postfix(""), m_internalExpression(), m_varTable(varTable)
{ }

ExpressionMaker::~ExpressionMaker()
{ }

void ExpressionMaker::SetPostfix(const std::string& postfix)
{
	m_postfix = postfix;
	m_isTreeGenerated = false;
}

Expression ExpressionMaker::GetExpression()
{
	if (m_postfix == "")
	{
		throw ExpressionMakerError("Postfix is empty");
	}
	else if (!m_isTreeGenerated)
	{
		Expression e(MakeExpressionTree(m_postfix));
		m_internalExpression = e;
		m_isTreeGenerated = true;
	}

	return m_internalExpression;
}

ExpressionTree* ExpressionMaker::MakeExpressionTree(const std::string& postfix)
{
	std::stack<ExpressionTree*> treeStack;
	std::string token;
	std::istringstream iss(postfix);

	while (iss >> token)
	{
		if (token == "u-")
		{
			ExpressionTree* rhs = treeStack.top();
			treeStack.pop();

			treeStack.push(new UnaryMinus(rhs));
		}
		else if (token == "sin")
		{
			ExpressionTree* rhs = treeStack.top();
			treeStack.pop();

			treeStack.push(new Sine(rhs));
		}
		else if (token == "cos")
		{
			ExpressionTree* rhs = treeStack.top();
			treeStack.pop();

			treeStack.push(new Cosine(rhs));
		}
		else if (token == "tan")
		{
			ExpressionTree* rhs = treeStack.top();
			treeStack.pop();

			treeStack.push(new Tangent(rhs));
		}
		else if (std::find(operators.begin(), operators.end(), token) != operators.end())
		{
			ExpressionTree* rhs = treeStack.top();
			treeStack.pop();
			ExpressionTree* lhs = treeStack.top();
			treeStack.pop();

			if (token == "^")
			{
				treeStack.push(new Power(lhs, rhs));
			}
			else if (token == "*")
			{
				treeStack.push(new Multiply(lhs, rhs));
			}
			else if (token == "/")
			{
				treeStack.push(new Divide(lhs, rhs));
			}
			else if (token == "+")
			{
				treeStack.push(new Plus(lhs, rhs));
			}
			else if (token == "-")
			{
				treeStack.push(new BinaryMinus(lhs, rhs));
			}
			else if (token == "=")
			{
				treeStack.push(new Assign(lhs, rhs, m_varTable));
			}
		}
		else if (token.find_first_not_of(integer_chars) == std::string::npos)
		{
			treeStack.push(new Integer(atoi(token.c_str())));
		}
		else if (token.find_first_not_of(real_chars) == std::string::npos)
		{
			treeStack.push(new Real(atof(token.c_str())));
		}
		else if (token.find_first_not_of(identifier_chars) == std::string::npos)
		{
			treeStack.push(new Variable(token, m_varTable));
		}
		else
		{
			while (!treeStack.empty())
			{
				delete treeStack.top();
				treeStack.pop();
			}

			throw ExpressionMakerError("Invalid Postfix");
		}
	}

	if (treeStack.empty())
	{
		throw ExpressionMakerError("Invalid Postfix");
	}

	if (treeStack.size() > 1)
	{
		while (!treeStack.empty())
		{
			delete treeStack.top();
			treeStack.pop();
		}

		throw ExpressionMakerError("Invalid Postfix");
	}

	return treeStack.top();
}
<|endoftext|>


<commit_before>#include "Stdafx.h"

using namespace System;
using namespace System::Reflection;
using namespace System::Runtime::CompilerServices;
using namespace System::Runtime::InteropServices;
using namespace System::Security::Permissions;
using namespace CefSharp;

[assembly:AssemblyTitle("CefSharp.Core")];
[assembly:AssemblyCompany(AssemblyInfo::AssemblyCompany)];
[assembly:AssemblyProduct(AssemblyInfo::AssemblyProduct)];
[assembly:AssemblyCopyright(AssemblyInfo::AssemblyCopyright)]

[assembly:AssemblyVersion(AssemblyInfo::AssemblyVersion)];
[assembly:ComVisible(AssemblyInfo::ComVisible)];
[assembly:CLSCompliant(AssemblyInfo::ClsCompliant)];
[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];

[assembly:AssemblyDescription("")]
[assembly:AssemblyConfiguration("")]
[assembly:AssemblyTrademark("")]
[assembly:AssemblyCulture("")]

[assembly:InternalsVisibleTo(AssemblyInfo::CefSharpBrowserSubprocessProject)];
[assembly:InternalsVisibleTo(AssemblyInfo::CefSharpWpfProject)];
[assembly:InternalsVisibleTo(AssemblyInfo::CefSharpWinFormsProject)];
[assembly:InternalsVisibleTo(AssemblyInfo::CefSharpTestProject)];
<commit_msg>Added missing trailing semicolons.<commit_after>#include "Stdafx.h"

using namespace System;
using namespace System::Reflection;
using namespace System::Runtime::CompilerServices;
using namespace System::Runtime::InteropServices;
using namespace System::Security::Permissions;
using namespace CefSharp;

[assembly:AssemblyTitle("CefSharp.Core")];
[assembly:AssemblyCompany(AssemblyInfo::AssemblyCompany)];
[assembly:AssemblyProduct(AssemblyInfo::AssemblyProduct)];
[assembly:AssemblyCopyright(AssemblyInfo::AssemblyCopyright)];

[assembly:AssemblyVersion(AssemblyInfo::AssemblyVersion)];
[assembly:ComVisible(AssemblyInfo::ComVisible)];
[assembly:CLSCompliant(AssemblyInfo::ClsCompliant)];
[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];

[assembly:AssemblyDescription("")];
[assembly:AssemblyConfiguration("")];
[assembly:AssemblyTrademark("")];
[assembly:AssemblyCulture("")];

[assembly:InternalsVisibleTo(AssemblyInfo::CefSharpBrowserSubprocessProject)];
[assembly:InternalsVisibleTo(AssemblyInfo::CefSharpWpfProject)];
[assembly:InternalsVisibleTo(AssemblyInfo::CefSharpWinFormsProject)];
[assembly:InternalsVisibleTo(AssemblyInfo::CefSharpTestProject)];
<|endoftext|>


<commit_before>//=====================================================================//
/*!	@file
	@brief	RL78 サーミスター・メイン
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2016 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RL78/blob/master/LICENSE
*/
//=====================================================================//
#include <cstdint>
#include "common/renesas.hpp"
#include "common/port_utils.hpp"
#include "common/fifo.hpp"
#include "common/uart_io.hpp"
#include "common/format.hpp"
#include "common/itimer.hpp"
#include "common/adc_io.hpp"
#include "common/task.hpp"
#include "chip/NTCTH.hpp"

namespace {

	typedef utils::fifo<uint8_t, 32> BUFFER;
	typedef device::uart_io<device::SAU02, device::SAU03, BUFFER, BUFFER> UART1;
	UART1	uart_;

	typedef device::itimer<uint8_t> ITM;
	ITM		itm_;

	// 最終チャネル番号＋１を設定
	typedef device::adc_io<4, utils::null_task> ADC;
	ADC 	adc_;

	// サーミスタ定義
	// A/D: 10 bits, NT103_41G, 分圧抵抗: 10K オーム、サーミスタ: ＶＣＣ側
	typedef chip::NTCTH<1023, chip::thermistor::HX103_3380, 10000, true> THMISTER;
	THMISTER thmister_;
}

extern "C" {

	void sci_putch(char ch)
	{
		uart_.putch(ch);
	}

	void sci_puts(const char* str)
	{
		uart_.puts(str);
	}

	char sci_getch(void)
	{
		return uart_.getch();
	}

	uint16_t sci_length()
	{
		return uart_.recv_length();
	}

	void UART1_TX_intr(void)
	{
		uart_.send_task();
	}

	void UART1_RX_intr(void)
	{
		uart_.recv_task();
	}

	void UART1_ER_intr(void)
	{
		uart_.error_task();
	}

	void ADC_intr(void)
	{
		adc_.task();
	}

	void ITM_intr(void)
	{
		itm_.task();
	}
};

int main(int argc, char* argv[])
{
	utils::port::pullup_all();  ///< 安全の為、全ての入力をプルアップ

	device::PM4.B3 = 0;  // output

	{
		uint8_t intr_level = 1;
		uart_.start(115200, intr_level);
	}

	{
		uint8_t intr_level = 1;
		itm_.start(60, intr_level);
	}

	{
		device::PM2.B2 = 1;
		device::PM2.B3 = 1;
		uint8_t intr_level = 1;  // 割り込み設定
		adc_.start(ADC::REFP::VDD, ADC::REFM::VSS, intr_level);
	}

	utils::format("Start RL78/G13 THERMISTOR sample\n");

	uint8_t n = 0;
	uint8_t t = 0;
	while(1) {
		itm_.sync();
		adc_.start_scan(2);  // スキャン開始チャネル

		adc_.sync();  // スキャン終了待ち

		++t;
		if(t >= 60) {
			auto v = adc_.get(2);
#if 0
			utils::format("(%5d) CH0: %1.2:8y[V], %d\n")
				% nnn
				% static_cast<uint32_t>(((v + 1) * 10) >> 3)
				% v;
#endif
			utils::format("温度： %5.2f [度]\n") % thmister_(v);
			t = 0;
		}

		++n;
		if(n >= 30) n = 0;
		device::P4.B3 = n < 10 ? false : true;
	}
}
<commit_msg>update comment<commit_after>//=====================================================================//
/*!	@file
	@brief	RL78 サーミスター・メイン
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2016 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RL78/blob/master/LICENSE
*/
//=====================================================================//
#include <cstdint>
#include "common/renesas.hpp"
#include "common/port_utils.hpp"
#include "common/fifo.hpp"
#include "common/uart_io.hpp"
#include "common/format.hpp"
#include "common/itimer.hpp"
#include "common/adc_io.hpp"
#include "common/task.hpp"
#include "chip/NTCTH.hpp"

namespace {

	typedef utils::fifo<uint8_t, 32> BUFFER;
	typedef device::uart_io<device::SAU02, device::SAU03, BUFFER, BUFFER> UART1;
	UART1	uart_;

	typedef device::itimer<uint8_t> ITM;
	ITM		itm_;

	// 最終チャネル番号＋１を設定
	typedef device::adc_io<4, utils::null_task> ADC;
	ADC 	adc_;

	// サーミスタ定義
	// A/D: 10 bits, NT103_41G, 分圧抵抗: 10K オーム、サーミスタ: ＶＣＣ側
	typedef chip::NTCTH<1023, chip::thermistor::HX103_3380, 10000, true> THMISTER;
	THMISTER thmister_;
}

extern "C" {

	void sci_putch(char ch)
	{
		uart_.putch(ch);
	}

	void sci_puts(const char* str)
	{
		uart_.puts(str);
	}

	char sci_getch(void)
	{
		return uart_.getch();
	}

	uint16_t sci_length()
	{
		return uart_.recv_length();
	}

	void UART1_TX_intr(void)
	{
		uart_.send_task();
	}

	void UART1_RX_intr(void)
	{
		uart_.recv_task();
	}

	void UART1_ER_intr(void)
	{
		uart_.error_task();
	}

	void ADC_intr(void)
	{
		adc_.task();
	}

	void ITM_intr(void)
	{
		itm_.task();
	}
};

int main(int argc, char* argv[])
{
	utils::port::pullup_all();  ///< 安全の為、全ての入力をプルアップ

	device::PM4.B3 = 0;  // output

	{
		uint8_t intr_level = 1;
		uart_.start(115200, intr_level);
	}

	{
		uint8_t intr_level = 1;
		itm_.start(60, intr_level);
	}

	{
		device::PM2.B2 = 1;
		device::PM2.B3 = 1;
		uint8_t intr_level = 1;  // 割り込み設定
		adc_.start(ADC::REFP::VDD, ADC::REFM::VSS, intr_level);
	}

	utils::format("Start RL78/G13 THERMISTOR sample\n");

	uint8_t n = 0;
	uint8_t t = 0;
	while(1) {
		itm_.sync();

		++t;
		if(t >= 60) {
			adc_.start_scan(2); // スキャン開始チャネル
			adc_.sync();  		// スキャン終了待ち

			auto v = adc_.get(2);
			v >>= 6;
			utils::format("温度： %5.2f [度]\n") % thmister_(v);
			t = 0;
		}

		++n;
		if(n >= 30) n = 0;
		device::P4.B3 = n < 10 ? false : true;
	}
}
<|endoftext|>


<commit_before>#include <cstdio>

int main(){
    int p;
    while((scanf("%d", &p)) && p != 2002)
        printf("Senha Invalida\n");
    printf("Acesso Permitido\n");
}
<commit_msg>Refatorando 1114 mais ainda.<commit_after>#include <cstdio>

int main(){
    int p;
    while(scanf("%d", &p) && p != 2002)
        printf("Senha Invalida\n");
    printf("Acesso Permitido\n");
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <string>
#include <stdlib.h>
#include "SaveParser.h"

// Global variables
extern std::string pokemon_species[];
extern std::string items[];
extern std::string natures[];
extern std::string attacks[];

SaveParser* SaveParser::spInstance = NULL;

int SaveParser::get_newest_save(block *blocks[NUM_BLOCKS_TOTAL])
{
	int i, newestSave = 0;

	for (i = 0; i < NUM_BLOCKS_TOTAL; i++)
	{
		if (blocks[i]->footer.savenumber > newestSave)
			newestSave = blocks[i]->footer.savenumber;
	}

	return newestSave;
}

unsigned short int SaveParser::get_block_checksum(block* b)
{
	int checksum = 0;
	int i;
	for (i = 0; i < BLOCK_DATA_LEN; i+=4)
	{
		checksum += *((int*)b+i/4);
	}
	checksum += checksum >> 16;
	checksum &= 0xFFFF;

	return (unsigned short int)checksum;
}

char* SaveParser::parse_save(const char *filename, char *savefile, block *blocks[NUM_BLOCKS_TOTAL])
{
	FILE *f;
	char *data;
	int i, newestSave;

	// Make sure we can open the file for reading
	if ((f = fopen(filename, "rb")) == NULL) {
		fprintf(stderr, "error: unable to open %s for reading.\n", filename);

		return NULL;
	}

	// Make sure we can read a full .sav file
	if (fread(savefile, SAVEFILE_LEN, 1, f) != 1) {
		fprintf(stderr, "error: unable to read SRAM file data.\n");
		fclose(f);

		return NULL;
	}

	fclose(f);

	for (i = 0; i < NUM_BLOCKS_TOTAL; i++)
	{
		blocks[i] = (block*)(savefile + i*(sizeof(block)));
	}

	newestSave = get_newest_save(blocks);

	data = (char*)malloc(SAVESLOT_LEN);
	for (i = 0; i < NUM_BLOCKS_TOTAL; i++)
	{
		if (blocks[i]->footer.savenumber == newestSave)
			memcpy(data + BLOCK_DATA_LEN * blocks[i]->footer.blocknum, blocks[i]->data, BLOCK_DATA_LEN);
	}

	return data;
}

int SaveParser::pack_save(const char *filename, char *unpackeddata, block *blocks[NUM_BLOCKS_TOTAL], char savefile[SAVEFILE_LEN])
{
	FILE *f;
	int i, newestSave;
	int tempCount = 0;

	newestSave = get_newest_save(blocks);

	// Re-split into blocks and place over buffer
	for(i = 0; i < NUM_BLOCKS_TOTAL; i++)
	{
		if (blocks[i]->footer.savenumber == newestSave) {
			memcpy(blocks[i]->data, unpackeddata + BLOCK_DATA_LEN * blocks[i]->footer.blocknum, BLOCK_DATA_LEN);
			// Re-calculate and set this block's checksum
			blocks[i]->footer.checksum = get_block_checksum(blocks[i]);
			tempCount++;
		}
	}
	free(unpackeddata);

	// Save back to file
	if ((f = fopen(filename, "wb")) == NULL) {
		printf("ERROR: Unable to open %s for writing.\n", filename);

		return -1;
	}

	if (fwrite(savefile, SAVEFILE_LEN, 1, f) != 1) {
		printf("ERROR: Unable to write to file.\n");
		fclose(f);

		return -1;
	}
	fclose(f);

	return 0;
}

void SaveParser::print_pokemon(box_pokemon_t* pokemon)
{
	pokemon_attacks_t *pa;
	pokemon_effort_t *pe;
	pokemon_growth_t *pg;
	pokemon_misc_t *pm;
	int o, totalIVs, totalEVs;

	// Figure out the order
	o = pokemon->personality % 24;
	pa = (pokemon_attacks_t *)(pokemon->data + DataOrderTable[o][0] * sizeof(pokemon_attacks_t));
	pe = (pokemon_effort_t *)(pokemon->data + DataOrderTable[o][1] * sizeof(pokemon_effort_t));
	pg = (pokemon_growth_t *)(pokemon->data + DataOrderTable[o][2] * sizeof(pokemon_growth_t));
	pm = (pokemon_misc_t *)(pokemon->data + DataOrderTable[o][3] * sizeof(pokemon_misc_t));

	totalIVs = pm->IVs.hp + pm->IVs.atk + pm->IVs.def + pm->IVs.spatk + pm->IVs.spdef + pm->IVs.spd;
	totalEVs = pe->hp + pe->attack + pe->defense + pe->spatk + pe->spdef + pe->speed;
	fprintf(stdout, "Species: %s, held: %s, Nature: %s\n", pokemon_species[pg->species], items[pg->held], natures[pokemon->personality % 25]);
	fprintf(stdout, "Attacks: 1:%s, 2:%s, 3:%s, 4:%s\n", attacks[pa->atk1], attacks[pa->atk2], attacks[pa->atk3], attacks[pa->atk4] );
	fprintf(stdout, "IVs:\tHP:%d\tAtk:%d\tDef:%d\tSpA:%d\tSpD:%d\tSpe:%d\tTotal:%d\n", pm->IVs.hp, pm->IVs.atk, pm->IVs.def, pm->IVs.spatk, pm->IVs.spdef, pm->IVs.spd, totalIVs );
	fprintf(stdout, "EVs:\tHP:%d\tAtk:%d\tDef:%d\tSpA:%d\tSpD:%d\tSpe:%d\tTotal:%d\n", pe->hp, pe->attack, pe->defense, pe->spatk, pe->spdef, pe->speed, totalEVs );
}

int SaveParser::parse_pokemon(char* buf, int offset, void** pokemon, pokemon_attacks_t** pa, pokemon_effort_t** pe, pokemon_growth_t** pg, pokemon_misc_t** pm, int num, int size)
{
	int i;
	if (size != sizeof(belt_pokemon_t) && size != sizeof(box_pokemon_t)) {
		fprintf(stderr, "Pokemon size must be either 80 or 100 bytes\n");
		return -1;
	}

	// Parse pokemon
	for(i = 0; i < num; i++)
	{
		int o;

		// Read data on pokemon
		pokemon[i] = (buf + offset + (i * size));

		// Unencrypt pokemon's data
		// box and belt pokemon have these struct members all at
		// the same offset so we can cast to either type
		SaveParser::Instance()->encrypt(((box_pokemon_t*)pokemon[i])->data, ((box_pokemon_t*)pokemon[i])->personality, ((box_pokemon_t*)pokemon[i])->otid);

		// Figure out the order
		o = ((box_pokemon_t*)pokemon[i])->personality % 24;
		pa[i] = (pokemon_attacks_t *)(((box_pokemon_t*)pokemon[i])->data + DataOrderTable[o][0] * sizeof(pokemon_attacks_t));
		pe[i] = (pokemon_effort_t *)(((box_pokemon_t*)pokemon[i])->data + DataOrderTable[o][1] * sizeof(pokemon_effort_t));
		pg[i] = (pokemon_growth_t *)(((box_pokemon_t*)pokemon[i])->data + DataOrderTable[o][2] * sizeof(pokemon_growth_t));
		pm[i] = (pokemon_misc_t *)(((box_pokemon_t*)pokemon[i])->data + DataOrderTable[o][3] * sizeof(pokemon_misc_t));
		if (pg[i]->species) {
			//fprintf(stdout, "\nPokemon %d\n", i);
			//print_pokemon((box_pokemon_t*)pokemon[i]);
		}
	}

	return 0;
}

SaveParser* SaveParser::Instance()
{
	if (!spInstance) // If an instance hasn't already been created, so do
		spInstance = new SaveParser();

	return spInstance;
}

int SaveParser::load(const char *fn, int game)
{
	// Parse save
	unpackeddata = parse_save(fn, savefile, blocks);
	if (unpackeddata == NULL)
	{
		fprintf(stderr, "Could not parse save file.\n");
		return -1;
	}

	// Decode belt part
	parse_pokemon(unpackeddata, belt_offsets[game], (void**)pokemon, pokemon_attacks, pokemon_effort, pokemon_growth, pokemon_misc, NUM_BELT_POKEMON, sizeof(belt_pokemon_t));

	return 0;
}

int SaveParser::save(const char *fn)
{
	// Re encrypt and set checksum
	for(int i = 0; i < NUM_BELT_POKEMON; i++)
	{
		pokemon[i]->checksum = encrypt(pokemon[i]->data, pokemon[i]->personality, pokemon[i]->otid);
	}

	if (pack_save(fn, unpackeddata, blocks, savefile)) {
		fprintf(stderr, "Could not save changes!\n");
		return -1;
	} else {
		fprintf(stdout, "Saved!\n");
	}

	return 0;
}

/*
 *	Encrypts/decrypts the 48 byte data buffer based on the xored pv and otid values
 *  TODO: Make it encrypt its own data/not need arguments
 */
unsigned short int SaveParser::encrypt(unsigned char *data, unsigned int pv, unsigned int otid) {
	unsigned int xorkey = pv ^ otid;
	unsigned short int checksum = 0;
	unsigned int i;

	for (i = 0; i < POKEMON_DATA_LENGTH; i+=4)
	{
		checksum += data[i+1]<<8 | data[i];
		checksum += data[i+3]<<8 | data[i+2];

		data[i] ^= (xorkey >> 0)&0xFF;
		data[i+1] ^= (xorkey >> 8)&0xFF;
		data[i+2] ^= (xorkey >> 16)&0xFF;
		data[i+3] ^= (xorkey >> 24)&0xFF;
	}

	return checksum;

}
<commit_msg>pokehack: fixed GCC incompatibility<commit_after>#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <stdlib.h>
#include "SaveParser.h"

// Global variables
extern std::string pokemon_species[];
extern std::string items[];
extern std::string natures[];
extern std::string attacks[];

SaveParser* SaveParser::spInstance = NULL;

int SaveParser::get_newest_save(block *blocks[NUM_BLOCKS_TOTAL])
{
	int i, newestSave = 0;

	for (i = 0; i < NUM_BLOCKS_TOTAL; i++)
	{
		if (blocks[i]->footer.savenumber > newestSave)
			newestSave = blocks[i]->footer.savenumber;
	}

	return newestSave;
}

unsigned short int SaveParser::get_block_checksum(block* b)
{
	int checksum = 0;
	int i;
	for (i = 0; i < BLOCK_DATA_LEN; i+=4)
	{
		checksum += *((int*)b+i/4);
	}
	checksum += checksum >> 16;
	checksum &= 0xFFFF;

	return (unsigned short int)checksum;
}

char* SaveParser::parse_save(const char *filename, char *savefile, block *blocks[NUM_BLOCKS_TOTAL])
{
	FILE *f;
	char *data;
	int i, newestSave;

	// Make sure we can open the file for reading
	if ((f = fopen(filename, "rb")) == NULL) {
		fprintf(stderr, "error: unable to open %s for reading.\n", filename);

		return NULL;
	}

	// Make sure we can read a full .sav file
	if (fread(savefile, SAVEFILE_LEN, 1, f) != 1) {
		fprintf(stderr, "error: unable to read SRAM file data.\n");
		fclose(f);

		return NULL;
	}

	fclose(f);

	for (i = 0; i < NUM_BLOCKS_TOTAL; i++)
	{
		blocks[i] = (block*)(savefile + i*(sizeof(block)));
	}

	newestSave = get_newest_save(blocks);

	data = (char*)malloc(SAVESLOT_LEN);
	for (i = 0; i < NUM_BLOCKS_TOTAL; i++)
	{
		if (blocks[i]->footer.savenumber == newestSave)
			memcpy(data + BLOCK_DATA_LEN * blocks[i]->footer.blocknum, blocks[i]->data, BLOCK_DATA_LEN);
	}

	return data;
}

int SaveParser::pack_save(const char *filename, char *unpackeddata, block *blocks[NUM_BLOCKS_TOTAL], char savefile[SAVEFILE_LEN])
{
	FILE *f;
	int i, newestSave;
	int tempCount = 0;

	newestSave = get_newest_save(blocks);

	// Re-split into blocks and place over buffer
	for(i = 0; i < NUM_BLOCKS_TOTAL; i++)
	{
		if (blocks[i]->footer.savenumber == newestSave) {
			memcpy(blocks[i]->data, unpackeddata + BLOCK_DATA_LEN * blocks[i]->footer.blocknum, BLOCK_DATA_LEN);
			// Re-calculate and set this block's checksum
			blocks[i]->footer.checksum = get_block_checksum(blocks[i]);
			tempCount++;
		}
	}
	free(unpackeddata);

	// Save back to file
	if ((f = fopen(filename, "wb")) == NULL) {
		printf("ERROR: Unable to open %s for writing.\n", filename);

		return -1;
	}

	if (fwrite(savefile, SAVEFILE_LEN, 1, f) != 1) {
		printf("ERROR: Unable to write to file.\n");
		fclose(f);

		return -1;
	}
	fclose(f);

	return 0;
}

void SaveParser::print_pokemon(box_pokemon_t* pokemon)
{
	pokemon_attacks_t *pa;
	pokemon_effort_t *pe;
	pokemon_growth_t *pg;
	pokemon_misc_t *pm;
	int o, totalIVs, totalEVs;

	// Figure out the order
	o = pokemon->personality % 24;
	pa = (pokemon_attacks_t *)(pokemon->data + DataOrderTable[o][0] * sizeof(pokemon_attacks_t));
	pe = (pokemon_effort_t *)(pokemon->data + DataOrderTable[o][1] * sizeof(pokemon_effort_t));
	pg = (pokemon_growth_t *)(pokemon->data + DataOrderTable[o][2] * sizeof(pokemon_growth_t));
	pm = (pokemon_misc_t *)(pokemon->data + DataOrderTable[o][3] * sizeof(pokemon_misc_t));

	totalIVs = pm->IVs.hp + pm->IVs.atk + pm->IVs.def + pm->IVs.spatk + pm->IVs.spdef + pm->IVs.spd;
	totalEVs = pe->hp + pe->attack + pe->defense + pe->spatk + pe->spdef + pe->speed;
    std::cout << "Species: " << pokemon_species[pg->species] << ", held: " << items[pg->held] << ", Nature: "
         << natures[pokemon->personality % 25] << std::endl;
    std::cout << "Attacks: 1:" << attacks[pa->atk1] << ", 2:" << attacks[pa->atk2] << ", 3:" << attacks[pa->atk3]
         << ", 4:" << attacks[pa->atk4] << std::endl;
    std::cout << "IVs: HP:" << pm->IVs.hp << ", Atk:" << pm->IVs.atk << ", Def:" << pm->IVs.def << ", SpA:"
         << pm->IVs.spatk << ", SpD:" << pm->IVs.spdef << ", Spe:" << pm->IVs.spd << ", Total:" << totalIVs
         << std::endl;
    std::cout << "EVs: HP:" << pe->hp << ", Atk:" << pe->attack << ", Def:" << pe->defense << ", SpA:"
         << pe->spatk << ", SpD:" << pe->spdef << ", Spe:" << pe->speed << ", Total:" << totalEVs
         << std::endl;
}

int SaveParser::parse_pokemon(char* buf, int offset, void** pokemon, pokemon_attacks_t** pa, pokemon_effort_t** pe, pokemon_growth_t** pg, pokemon_misc_t** pm, int num, int size)
{
	int i;
	if (size != sizeof(belt_pokemon_t) && size != sizeof(box_pokemon_t)) {
		fprintf(stderr, "Pokemon size must be either 80 or 100 bytes\n");
		return -1;
	}

	// Parse pokemon
	for(i = 0; i < num; i++)
	{
		int o;

		// Read data on pokemon
		pokemon[i] = (buf + offset + (i * size));

		// Unencrypt pokemon's data
		// box and belt pokemon have these struct members all at
		// the same offset so we can cast to either type
		SaveParser::Instance()->encrypt(((box_pokemon_t*)pokemon[i])->data, ((box_pokemon_t*)pokemon[i])->personality, ((box_pokemon_t*)pokemon[i])->otid);

		// Figure out the order
		o = ((box_pokemon_t*)pokemon[i])->personality % 24;
		pa[i] = (pokemon_attacks_t *)(((box_pokemon_t*)pokemon[i])->data + DataOrderTable[o][0] * sizeof(pokemon_attacks_t));
		pe[i] = (pokemon_effort_t *)(((box_pokemon_t*)pokemon[i])->data + DataOrderTable[o][1] * sizeof(pokemon_effort_t));
		pg[i] = (pokemon_growth_t *)(((box_pokemon_t*)pokemon[i])->data + DataOrderTable[o][2] * sizeof(pokemon_growth_t));
		pm[i] = (pokemon_misc_t *)(((box_pokemon_t*)pokemon[i])->data + DataOrderTable[o][3] * sizeof(pokemon_misc_t));
		if (pg[i]->species) {
			//fprintf(stdout, "\nPokemon %d\n", i);
			//print_pokemon((box_pokemon_t*)pokemon[i]);
		}
	}

	return 0;
}

SaveParser* SaveParser::Instance()
{
	if (!spInstance) // If an instance hasn't already been created, so do
		spInstance = new SaveParser();

	return spInstance;
}

int SaveParser::load(const char *fn, int game)
{
	// Parse save
	unpackeddata = parse_save(fn, savefile, blocks);
	if (unpackeddata == NULL)
	{
		fprintf(stderr, "Could not parse save file.\n");
		return -1;
	}

	// Decode belt part
	parse_pokemon(unpackeddata, belt_offsets[game], (void**)pokemon, pokemon_attacks, pokemon_effort, pokemon_growth, pokemon_misc, NUM_BELT_POKEMON, sizeof(belt_pokemon_t));

	return 0;
}

int SaveParser::save(const char *fn)
{
	// Re encrypt and set checksum
	for(int i = 0; i < NUM_BELT_POKEMON; i++)
	{
		pokemon[i]->checksum = encrypt(pokemon[i]->data, pokemon[i]->personality, pokemon[i]->otid);
	}

	if (pack_save(fn, unpackeddata, blocks, savefile)) {
		fprintf(stderr, "Could not save changes!\n");
		return -1;
	} else {
		fprintf(stdout, "Saved!\n");
	}

	return 0;
}

/*
 *	Encrypts/decrypts the 48 byte data buffer based on the xored pv and otid values
 *  TODO: Make it encrypt its own data/not need arguments
 */
unsigned short int SaveParser::encrypt(unsigned char *data, unsigned int pv, unsigned int otid) {
	unsigned int xorkey = pv ^ otid;
	unsigned short int checksum = 0;
	unsigned int i;

	for (i = 0; i < POKEMON_DATA_LENGTH; i+=4)
	{
		checksum += data[i+1]<<8 | data[i];
		checksum += data[i+3]<<8 | data[i+2];

		data[i] ^= (xorkey >> 0)&0xFF;
		data[i+1] ^= (xorkey >> 8)&0xFF;
		data[i+2] ^= (xorkey >> 16)&0xFF;
		data[i+3] ^= (xorkey >> 24)&0xFF;
	}

	return checksum;

}
<|endoftext|>


<commit_before>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "mitkPointSetWriter.h"
#include <iostream>
#include <fstream>

//
// Initialization of the xml tags.
//

const char* mitk::PointSetWriter::XML_POINT_SET_FILE = "point_set_file" ;

const char* mitk::PointSetWriter::XML_FILE_VERSION = "file_version" ;

const char* mitk::PointSetWriter::XML_POINT_SET = "point_set" ;

const char* mitk::PointSetWriter::XML_POINT = "point" ;

const char* mitk::PointSetWriter::XML_ID = "id" ;

const char* mitk::PointSetWriter::XML_X = "x" ;

const char* mitk::PointSetWriter::XML_Y = "y" ;

const char* mitk::PointSetWriter::XML_Z = "z" ;

const char* mitk::PointSetWriter::VERSION_STRING = "0.1" ;

mitk::PointSetWriter::PointSetWriter()
{
    this->SetNumberOfRequiredInputs( 1 );
    this->SetNumberOfOutputs( 1 );
    this->SetNthOutput( 0, mitk::PointSet::New().GetPointer() );
    m_Indent = 2;
    m_IndentDepth = 0;
}

mitk::PointSetWriter::~PointSetWriter()
{}

void mitk::PointSetWriter::GenerateData()
{
    m_IndentDepth = 0;

    //
    // Opening the file to write to
    //
    if ( m_FileName == "" )
    {
        itkWarningMacro( << "Sorry, filename has not been set!" );
        return ;
    }
    std::ofstream out( m_FileName.c_str() );
    if ( !out.good() )
    {
        itkWarningMacro( << "Sorry, file " << m_FileName << " could not be opened!" );
        out.close();
        return ;
    }

    //
    // Here the actual xml writing begins
    //
    WriteXMLHeader( out );
    WriteStartElement( XML_POINT_SET_FILE, out );
    WriteStartElement( XML_FILE_VERSION, out );
    WriteCharacterData( VERSION_STRING, out );
    WriteEndElement( XML_FILE_VERSION, out, false );

    //
    // for each input object write its xml representation to
    // the stream
    //
    for ( unsigned int i = 0 ; i < this->GetNumberOfInputs(); ++i )
    {
        InputType::Pointer pointSet = this->GetInput( i );
        assert( pointSet.IsNotNull() );
        WriteXML( pointSet.GetPointer(), out );
    }

    WriteEndElement( XML_POINT_SET_FILE, out );

    out.close();
}

void mitk::PointSetWriter::WriteXML( mitk::PointSet* pointSet, std::ofstream& out )
{
    WriteStartElement( XML_POINT_SET, out );
    mitk::PointSet::PointsContainer* pointsContainer = pointSet->GetPointSet()->GetPoints();
    mitk::PointSet::PointsContainer::Iterator it;
    for ( it = pointsContainer->Begin(); it != pointsContainer->End(); ++it )
    {
        WriteStartElement( XML_POINT, out );

        WriteStartElement( XML_ID, out );
        WriteCharacterData( ConvertToString<int>( it->Index() ).c_str() , out );
        WriteEndElement( XML_ID, out, false );

        mitk::PointSet::PointType point = it->Value();

        WriteStartElement( XML_X, out );
        WriteCharacterData( ConvertToString<mitk::ScalarType>( point[ 0 ] ).c_str(), out );
        WriteEndElement( XML_X, out, false );

        WriteStartElement( XML_Y, out );
        WriteCharacterData( ConvertToString<mitk::ScalarType>( point[ 1 ] ).c_str(), out );
        WriteEndElement( XML_Y, out, false );

        WriteStartElement( XML_Z, out );
        WriteCharacterData( ConvertToString<mitk::ScalarType>( point[ 2 ] ).c_str(), out );
        WriteEndElement( XML_Z, out, false );

        WriteEndElement( XML_POINT, out );
    }
    WriteEndElement( XML_POINT_SET, out );
}

void mitk::PointSetWriter::ResizeInputs( const unsigned int& num )
{
    unsigned int prevNum = this->GetNumberOfInputs();
    this->SetNumberOfInputs( num );
    for ( unsigned int i = prevNum; i < num; ++i )
    {
        this->SetNthInput( i, mitk::PointSet::New().GetPointer() );
    }
}

void mitk::PointSetWriter::SetInput( InputType* pointSet )
{
    this->ProcessObject::SetNthInput( 0, pointSet );
}

void mitk::PointSetWriter::SetInput( const unsigned int& id, InputType* pointSet )
{
    if ( id >= this->GetNumberOfInputs() )
        this->ResizeInputs( id + 1 );
    this->ProcessObject::SetNthInput( id, pointSet );
}

mitk::PointSet* mitk::PointSetWriter::GetInput()
{
    if ( this->GetNumberOfInputs() < 1 )
    {
        return 0;
    }
    else
    {
        return dynamic_cast<InputType*> ( this->GetInput( 0 ) );
    }
}

mitk::PointSet* mitk::PointSetWriter::GetInput( const unsigned int& num )
{
    return dynamic_cast<InputType*> ( this->ProcessObject::GetInput( num ) );
}

template < typename T>
std::string mitk::PointSetWriter::ConvertToString( T value )
{
    std::ostringstream o;
    if ( o << value )
        return o.str();
    else
        return "conversion error";
}

void mitk::PointSetWriter::WriteXMLHeader( std::ofstream &file )
{
    file << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>";
}

void mitk::PointSetWriter::WriteStartElement( const char *const tag, std::ofstream &file )
{
    file << std::endl;
    WriteIndent( file );
    file << '<' << tag << '>';
    m_IndentDepth++;
}

void mitk::PointSetWriter::WriteEndElement( const char *const tag, std::ofstream &file, const bool& indent )
{
    m_IndentDepth--;
    if ( indent )
    {
        file << std::endl;
        WriteIndent( file );
    }
    file << '<' << '/' << tag << '>';
}

void mitk::PointSetWriter::WriteCharacterData( const char *const data, std::ofstream &file )
{
    file << data;
}

void mitk::PointSetWriter::WriteStartElement( std::string &tag, std::ofstream &file )
{
    WriteStartElement( tag.c_str(), file );
}

void mitk::PointSetWriter::WriteEndElement( std::string &tag, std::ofstream &file, const bool& indent )
{
    WriteEndElement( tag.c_str(), file, indent );
}

void mitk::PointSetWriter::WriteCharacterData( std::string &data, std::ofstream &file )
{
    WriteCharacterData( data.c_str(), file );
}

void mitk::PointSetWriter::WriteIndent( std::ofstream& file )
{
    std::string spaces( m_IndentDepth * m_Indent, ' ' );
    file << spaces.c_str();
}

<commit_msg>added missing initialization of member variables<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "mitkPointSetWriter.h"
#include <iostream>
#include <fstream>

//
// Initialization of the xml tags.
//

const char* mitk::PointSetWriter::XML_POINT_SET_FILE = "point_set_file" ;

const char* mitk::PointSetWriter::XML_FILE_VERSION = "file_version" ;

const char* mitk::PointSetWriter::XML_POINT_SET = "point_set" ;

const char* mitk::PointSetWriter::XML_POINT = "point" ;

const char* mitk::PointSetWriter::XML_ID = "id" ;

const char* mitk::PointSetWriter::XML_X = "x" ;

const char* mitk::PointSetWriter::XML_Y = "y" ;

const char* mitk::PointSetWriter::XML_Z = "z" ;

const char* mitk::PointSetWriter::VERSION_STRING = "0.1" ;

mitk::PointSetWriter::PointSetWriter()
    : m_FileName(""), m_FilePrefix(""), m_FilePattern("")
{
    this->SetNumberOfRequiredInputs( 1 );
    this->SetNumberOfOutputs( 1 );
    this->SetNthOutput( 0, mitk::PointSet::New().GetPointer() );
    m_Indent = 2;
    m_IndentDepth = 0;
}

mitk::PointSetWriter::~PointSetWriter()
{}

void mitk::PointSetWriter::GenerateData()
{
    m_IndentDepth = 0;

    //
    // Opening the file to write to
    //
    if ( m_FileName == "" )
    {
        itkWarningMacro( << "Sorry, filename has not been set!" );
        return ;
    }
    std::ofstream out( m_FileName.c_str() );
    if ( !out.good() )
    {
        itkWarningMacro( << "Sorry, file " << m_FileName << " could not be opened!" );
        out.close();
        return ;
    }

    //
    // Here the actual xml writing begins
    //
    WriteXMLHeader( out );
    WriteStartElement( XML_POINT_SET_FILE, out );
    WriteStartElement( XML_FILE_VERSION, out );
    WriteCharacterData( VERSION_STRING, out );
    WriteEndElement( XML_FILE_VERSION, out, false );

    //
    // for each input object write its xml representation to
    // the stream
    //
    for ( unsigned int i = 0 ; i < this->GetNumberOfInputs(); ++i )
    {
        InputType::Pointer pointSet = this->GetInput( i );
        assert( pointSet.IsNotNull() );
        WriteXML( pointSet.GetPointer(), out );
    }

    WriteEndElement( XML_POINT_SET_FILE, out );

    out.close();
}

void mitk::PointSetWriter::WriteXML( mitk::PointSet* pointSet, std::ofstream& out )
{
    WriteStartElement( XML_POINT_SET, out );
    mitk::PointSet::PointsContainer* pointsContainer = pointSet->GetPointSet()->GetPoints();
    mitk::PointSet::PointsContainer::Iterator it;
    for ( it = pointsContainer->Begin(); it != pointsContainer->End(); ++it )
    {
        WriteStartElement( XML_POINT, out );

        WriteStartElement( XML_ID, out );
        WriteCharacterData( ConvertToString<int>( it->Index() ).c_str() , out );
        WriteEndElement( XML_ID, out, false );

        mitk::PointSet::PointType point = it->Value();

        WriteStartElement( XML_X, out );
        WriteCharacterData( ConvertToString<mitk::ScalarType>( point[ 0 ] ).c_str(), out );
        WriteEndElement( XML_X, out, false );

        WriteStartElement( XML_Y, out );
        WriteCharacterData( ConvertToString<mitk::ScalarType>( point[ 1 ] ).c_str(), out );
        WriteEndElement( XML_Y, out, false );

        WriteStartElement( XML_Z, out );
        WriteCharacterData( ConvertToString<mitk::ScalarType>( point[ 2 ] ).c_str(), out );
        WriteEndElement( XML_Z, out, false );

        WriteEndElement( XML_POINT, out );
    }
    WriteEndElement( XML_POINT_SET, out );
}

void mitk::PointSetWriter::ResizeInputs( const unsigned int& num )
{
    unsigned int prevNum = this->GetNumberOfInputs();
    this->SetNumberOfInputs( num );
    for ( unsigned int i = prevNum; i < num; ++i )
    {
        this->SetNthInput( i, mitk::PointSet::New().GetPointer() );
    }
}

void mitk::PointSetWriter::SetInput( InputType* pointSet )
{
    this->ProcessObject::SetNthInput( 0, pointSet );
}

void mitk::PointSetWriter::SetInput( const unsigned int& id, InputType* pointSet )
{
    if ( id >= this->GetNumberOfInputs() )
        this->ResizeInputs( id + 1 );
    this->ProcessObject::SetNthInput( id, pointSet );
}

mitk::PointSet* mitk::PointSetWriter::GetInput()
{
    if ( this->GetNumberOfInputs() < 1 )
    {
        return 0;
    }
    else
    {
        return dynamic_cast<InputType*> ( this->GetInput( 0 ) );
    }
}

mitk::PointSet* mitk::PointSetWriter::GetInput( const unsigned int& num )
{
    return dynamic_cast<InputType*> ( this->ProcessObject::GetInput( num ) );
}

template < typename T>
std::string mitk::PointSetWriter::ConvertToString( T value )
{
    std::ostringstream o;
    if ( o << value )
        return o.str();
    else
        return "conversion error";
}

void mitk::PointSetWriter::WriteXMLHeader( std::ofstream &file )
{
    file << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>";
}

void mitk::PointSetWriter::WriteStartElement( const char *const tag, std::ofstream &file )
{
    file << std::endl;
    WriteIndent( file );
    file << '<' << tag << '>';
    m_IndentDepth++;
}

void mitk::PointSetWriter::WriteEndElement( const char *const tag, std::ofstream &file, const bool& indent )
{
    m_IndentDepth--;
    if ( indent )
    {
        file << std::endl;
        WriteIndent( file );
    }
    file << '<' << '/' << tag << '>';
}

void mitk::PointSetWriter::WriteCharacterData( const char *const data, std::ofstream &file )
{
    file << data;
}

void mitk::PointSetWriter::WriteStartElement( std::string &tag, std::ofstream &file )
{
    WriteStartElement( tag.c_str(), file );
}

void mitk::PointSetWriter::WriteEndElement( std::string &tag, std::ofstream &file, const bool& indent )
{
    WriteEndElement( tag.c_str(), file, indent );
}

void mitk::PointSetWriter::WriteCharacterData( std::string &data, std::ofstream &file )
{
    WriteCharacterData( data.c_str(), file );
}

void mitk::PointSetWriter::WriteIndent( std::ofstream& file )
{
    std::string spaces( m_IndentDepth * m_Indent, ' ' );
    file << spaces.c_str();
}

<|endoftext|>