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

/*
 * Description:
 *     helper functions in replica object
 *
 * Revision history:
 *     Mar., 2015, @imzhenyu (Zhenyu Guo), first version
 *     xxxx-xx-xx, author, fix bug about xxx
 */

#include "replica.h"
#include "mutation.h"
#include "mutation_log.h"
#include "replica_stub.h"
#include <dsn/cpp/json_helper.h>

# ifdef __TITLE__
# undef __TITLE__
# endif
# define __TITLE__ "replica"

namespace dsn { namespace replication {

replica::replica(replica_stub* stub, global_partition_id gpid, const char* app_type, const char* dir)
    : serverlet<replica>("replica"),
    _primary_states(gpid, stub->options().staleness_for_commit, stub->options().batch_write_disabled)
{
    dassert(stub != nullptr, "");
    _stub = stub;
    _app_type = app_type;
    _dir = dir;
    sprintf(_name, "%u.%u@%s", gpid.app_id, gpid.pidx, stub->_primary_address.to_string());
    _options = &stub->options();
    init_state();
    _config.gpid = gpid;

    std::stringstream ss;
    ss << _name << ".2pc.latency(ns)";
    _counter_commit_latency.init("eon.replication", ss.str().c_str(), COUNTER_TYPE_NUMBER_PERCENTILES, "commit latency (from mutation create to commit)");
}

void replica::json_state(std::stringstream& out) const
{
    JSON_DICT_ENTRIES(out, *this, name(), _config, _app->last_committed_decree(), _app->last_durable_decree());
}

void replica::update_commit_statistics(int count)
{
    _stub->_counter_replicas_total_commit_throught.add((uint64_t)count);
}

void replica::init_state()
{
    _inactive_is_transient = false;
    _prepare_list = new prepare_list(
        0,
        _options->max_mutation_count_in_prepare_list,
        std::bind(
            &replica::execute_mutation,
            this,
            std::placeholders::_1
            )
    );

    _config.ballot = 0;
    _config.gpid.pidx = 0;
    _config.gpid.app_id = 0;
    _config.status = PS_INACTIVE;
    _primary_states.membership.ballot = 0;
    _last_config_change_time_ms = now_ms();
    _private_log = nullptr;
}

replica::~replica(void)
{
    close();

    if (nullptr != _prepare_list)
    {
        delete _prepare_list;
        _prepare_list = nullptr;
    }

    dinfo("%s: replica destroyed", name());
}

void replica::on_client_read(const read_request_header& meta, dsn_message_t request)
{
    if (status() == PS_INACTIVE || status() == PS_POTENTIAL_SECONDARY)
    {
        response_client_message(request, ERR_INVALID_STATE);
        return;
    }

    if (meta.semantic == read_semantic::ReadLastUpdate)
    {
        if (status() != PS_PRIMARY ||
            last_committed_decree() < _primary_states.last_prepare_decree_on_new_primary)
        {
            response_client_message(request, ERR_INVALID_STATE);
            return;
        }
    }

    dassert (_app != nullptr, "");

    rpc_read_stream reader(request);
    _app->dispatch_rpc_call(meta.code, reader, dsn_msg_create_response(request));
}

void replica::response_client_message(dsn_message_t request, error_code error, decree d/* = invalid_decree*/)
{
    if (nullptr == request)
    {
        error.end_tracking();
        return;
    }

    ddebug("%s: reply client read/write, err = %s", name(), error.to_string());

    // well, replication layer error is 1
    // application layer result is 2
    reply_field(request, error, 1);
}

//error_code replica::check_and_fix_private_log_completeness()
//{
//    error_code err = ERR_OK;
//
//    auto mind = _private_log->max_gced_decree(get_gpid());
//    if (_prepare_list->max_decree())
//
//    if (!(mind <= last_durable_decree()))
//    {
//        err = ERR_INCOMPLETE_DATA;
//        derror("%s: private log is incomplete (gced/durable): %" PRId64 " vs %" PRId64,
//            name(),
//            mind,
//            last_durable_decree()
//            );
//    }
//    else
//    {
//        mind = _private_log->max_decree(get_gpid());
//        if (!(mind >= _app->last_committed_decree()))
//        {
//            err = ERR_INCOMPLETE_DATA;
//            derror("%s: private log is incomplete (max/commit): %" PRId64 " vs %" PRId64,
//                name(),
//                mind,
//                _app->last_committed_decree()
//                );
//        }
//    }
//
//    if (ERR_INCOMPLETE_DATA == err)
//    {
//        _private_log->close(true);
//        _private_log->open(nullptr);
//        _private_log->set_private(get_gpid(), _app->last_durable_decree());
//    }
//
//    return err;
//}

void replica::check_state_completeness()
{
    /* prepare commit durable */
    dassert(max_prepared_decree() >= last_committed_decree(), "");
    dassert(last_committed_decree() >= last_durable_decree(), "");

    auto mind = _stub->_log->max_gced_decree(get_gpid(), _app->init_info().init_offset_in_shared_log);
    dassert(mind <= last_durable_decree(), "");
    _stub->_log->check_valid_start_offset(get_gpid(), _app->init_info().init_offset_in_shared_log);

    if (_private_log != nullptr)
    {
        auto mind = _private_log->max_gced_decree(get_gpid(), _app->init_info().init_offset_in_private_log);
        dassert(mind <= last_durable_decree(), "");
        _private_log->check_valid_start_offset(get_gpid(), _app->init_info().init_offset_in_private_log);
    }
}

void replica::execute_mutation(mutation_ptr& mu)
{
    dinfo("%s: execute mutation %s: request_count = %u",
        name(),
        mu->name(),
        static_cast<int>(mu->client_requests.size())
        );

    error_code err = ERR_OK;
    decree d = mu->data.header.decree;

    switch (status())
    {
    case PS_INACTIVE:
        if (_app->last_committed_decree() + 1 == d)
        {
            err = _app->write_internal(mu);
        }
        else
        {
            ddebug(
                "%s: mutation %s commit to %s skipped, app.last_committed_decree = %" PRId64,
                name(), mu->name(),
                enum_to_string(status()),
                _app->last_committed_decree()
                );
        }
        break;
    case PS_PRIMARY:
        {
            check_state_completeness();
            dassert(_app->last_committed_decree() + 1 == d, "");
            err = _app->write_internal(mu);
        }
        break;

    case PS_SECONDARY:
        if (!_secondary_states.checkpoint_is_running)
        {
            check_state_completeness();
            dassert (_app->last_committed_decree() + 1 == d, "");
            err = _app->write_internal(mu);
        }
        else
        {
            ddebug(
                "%s: mutation %s commit to %s skipped, app.last_committed_decree = %" PRId64,
                name(), mu->name(),
                enum_to_string(status()),
                _app->last_committed_decree()
                );

            // make sure private log saves the state
            // catch-up will be done later after checkpoint task is fininished
            dassert(_private_log != nullptr, "");
        }
        break;
    case PS_POTENTIAL_SECONDARY:
        if (_potential_secondary_states.learning_status == LearningSucceeded ||
            _potential_secondary_states.learning_status == LearningWithPrepareTransient)
        {
            dassert(_app->last_committed_decree() + 1 == d, "");
            err = _app->write_internal(mu);
        }
        else
        {
            // prepare also happens with LearningWithPrepare, in this case
            // make sure private log saves the state,
            // catch-up will be done later after the checkpoint task is finished

            ddebug(
                "%s: mutation %s commit to %s skipped, app.last_committed_decree = %" PRId64,
                name(), mu->name(),
                enum_to_string(status()),
                _app->last_committed_decree()
                );
        }
        break;
    case PS_ERROR:
        break;
    }

    ddebug("TwoPhaseCommit, %s: mutation %s committed, err = %s", name(), mu->name(), err.to_string());

    _counter_commit_latency.set(dsn_now_ns() - mu->create_ts_ns());

    if (err != ERR_OK)
    {
        handle_local_failure(err);
    }

    if (status() == PS_PRIMARY)
    {
        mutation_ptr next = _primary_states.write_queue.check_possible_work(
            static_cast<int>(_prepare_list->max_decree() - d)
            );

        if (next)
        {
            init_prepare(next);
        }
    }
}

mutation_ptr replica::new_mutation(decree decree)
{
    mutation_ptr mu(new mutation());
    mu->data.header.gpid = get_gpid();
    mu->data.header.ballot = get_ballot();
    mu->data.header.decree = decree;
    mu->data.header.log_offset = invalid_offset;
    return mu;
}

bool replica::group_configuration(/*out*/ partition_configuration& config) const
{
    if (PS_PRIMARY != status())
        return false;

    config = _primary_states.membership;
    return true;
}

decree replica::last_durable_decree() const { return _app->last_durable_decree(); }

decree replica::last_prepared_decree() const
{
    ballot lastBallot = 0;
    decree start = last_committed_decree();
    while (true)
    {
        auto mu = _prepare_list->get_mutation_by_decree(start + 1);
        if (mu == nullptr
            || mu->data.header.ballot < lastBallot
            || !mu->is_logged()
            )
            break;

        start++;
        lastBallot = mu->data.header.ballot;
    }
    return start;
}

void replica::close()
{
    dassert(
        status() == PS_ERROR || status() == PS_INACTIVE,
        "%s: invalid state %s when calling replica::close",
        name(),
        enum_to_string(status())
        );

    if (nullptr != _checkpoint_timer)
    {
        _checkpoint_timer->cancel(true);
        _checkpoint_timer = nullptr;
    }

    cleanup_preparing_mutations(true);
    dassert(_primary_states.is_cleaned(), "primary context is not cleared");

    if (PS_INACTIVE == status())
    {
        dassert(_secondary_states.is_cleaned(), "secondary context is not cleared");
        dassert(_potential_secondary_states.is_cleaned(), "potential secondary context is not cleared");
    }

    // for PS_ERROR, context cleanup is done here as they may block
    else
    {
        bool r = _secondary_states.cleanup(true);
        dassert(r, "secondary context is not cleared");

        r = _potential_secondary_states.cleanup(true);
        dassert(r, "potential secondary context is not cleared");
    }

    if (_private_log != nullptr)
    {
        _private_log->close();
        _private_log = nullptr;
    }

    if (_app != nullptr)
    {
        _app->close(false);
    }
}

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

/*
 * Description:
 *     helper functions in replica object
 *
 * Revision history:
 *     Mar., 2015, @imzhenyu (Zhenyu Guo), first version
 *     xxxx-xx-xx, author, fix bug about xxx
 */

#include "replica.h"
#include "mutation.h"
#include "mutation_log.h"
#include "replica_stub.h"
#include <dsn/cpp/json_helper.h>

# ifdef __TITLE__
# undef __TITLE__
# endif
# define __TITLE__ "replica"

namespace dsn { namespace replication {

replica::replica(replica_stub* stub, global_partition_id gpid, const char* app_type, const char* dir)
    : serverlet<replica>("replica"),
    _primary_states(gpid, stub->options().staleness_for_commit, stub->options().batch_write_disabled)
{
    dassert(stub != nullptr, "");
    _stub = stub;
    _app_type = app_type;
    _dir = dir;
    sprintf(_name, "%u.%u@%s", gpid.app_id, gpid.pidx, stub->_primary_address.to_string());
    _options = &stub->options();
    init_state();
    _config.gpid = gpid;

    std::stringstream ss;
    ss << _name << ".2pc.latency(ns)";
    _counter_commit_latency.init("eon.replication", ss.str().c_str(), COUNTER_TYPE_NUMBER_PERCENTILES, "commit latency (from mutation create to commit)");
}

void replica::json_state(std::stringstream& out) const
{
    JSON_DICT_ENTRIES(out, *this, name(), _config, _app->last_committed_decree(), _app->last_durable_decree());
}

void replica::update_commit_statistics(int count)
{
    _stub->_counter_replicas_total_commit_throught.add((uint64_t)count);
}

void replica::init_state()
{
    _inactive_is_transient = false;
    _prepare_list = new prepare_list(
        0,
        _options->max_mutation_count_in_prepare_list,
        std::bind(
            &replica::execute_mutation,
            this,
            std::placeholders::_1
            )
    );

    _config.ballot = 0;
    _config.gpid.pidx = 0;
    _config.gpid.app_id = 0;
    _config.status = PS_INACTIVE;
    _primary_states.membership.ballot = 0;
    _last_config_change_time_ms = now_ms();
    _private_log = nullptr;
}

replica::~replica(void)
{
    close();

    if (nullptr != _prepare_list)
    {
        delete _prepare_list;
        _prepare_list = nullptr;
    }

    dinfo("%s: replica destroyed", name());
}

void replica::on_client_read(const read_request_header& meta, dsn_message_t request)
{
    if (status() == PS_INACTIVE || status() == PS_POTENTIAL_SECONDARY)
    {
        derror("%s: invalid status: read_semantic=%s, partition_status=%s",
               name(), enum_to_string(meta.semantic), enum_to_string(status()));
        response_client_message(request, ERR_INVALID_STATE);
        return;
    }

    if (meta.semantic == read_semantic::ReadLastUpdate)
    {
        if (status() != PS_PRIMARY)
        {
            derror("%s: invalid status: read_semantic=%s, partition_status=%s",
                   name(), enum_to_string(meta.semantic), enum_to_string(status()));
            response_client_message(request, ERR_INVALID_STATE);
            return;
        }

        if (last_committed_decree() < _primary_states.last_prepare_decree_on_new_primary)
        {
            derror("%s: last_committed_decree(%" PRId64 ") < last_prepare_decree_on_new_primary(" PRId64 ")",
                   name(), last_committed_decree(), _primary_states.last_prepare_decree_on_new_primary);
            response_client_message(request, ERR_INVALID_STATE);
            return;
        }
    }

    dassert (_app != nullptr, "");

    rpc_read_stream reader(request);
    _app->dispatch_rpc_call(meta.code, reader, dsn_msg_create_response(request));
}

void replica::response_client_message(dsn_message_t request, error_code error, decree d/* = invalid_decree*/)
{
    if (nullptr == request)
    {
        error.end_tracking();
        return;
    }

    if (error == ERR_OK)
    {
        ddebug("%s: reply client read/write, err = %s", name(), error.to_string());
    }
    else
    {
        derror("%s: reply client read/write, err = %s", name(), error.to_string());
    }

    // well, replication layer error is 1
    // application layer result is 2
    reply_field(request, error, 1);
}

//error_code replica::check_and_fix_private_log_completeness()
//{
//    error_code err = ERR_OK;
//
//    auto mind = _private_log->max_gced_decree(get_gpid());
//    if (_prepare_list->max_decree())
//
//    if (!(mind <= last_durable_decree()))
//    {
//        err = ERR_INCOMPLETE_DATA;
//        derror("%s: private log is incomplete (gced/durable): %" PRId64 " vs %" PRId64,
//            name(),
//            mind,
//            last_durable_decree()
//            );
//    }
//    else
//    {
//        mind = _private_log->max_decree(get_gpid());
//        if (!(mind >= _app->last_committed_decree()))
//        {
//            err = ERR_INCOMPLETE_DATA;
//            derror("%s: private log is incomplete (max/commit): %" PRId64 " vs %" PRId64,
//                name(),
//                mind,
//                _app->last_committed_decree()
//                );
//        }
//    }
//
//    if (ERR_INCOMPLETE_DATA == err)
//    {
//        _private_log->close(true);
//        _private_log->open(nullptr);
//        _private_log->set_private(get_gpid(), _app->last_durable_decree());
//    }
//
//    return err;
//}

void replica::check_state_completeness()
{
    /* prepare commit durable */
    dassert(max_prepared_decree() >= last_committed_decree(), "");
    dassert(last_committed_decree() >= last_durable_decree(), "");

    auto mind = _stub->_log->max_gced_decree(get_gpid(), _app->init_info().init_offset_in_shared_log);
    dassert(mind <= last_durable_decree(), "");
    _stub->_log->check_valid_start_offset(get_gpid(), _app->init_info().init_offset_in_shared_log);

    if (_private_log != nullptr)
    {
        auto mind = _private_log->max_gced_decree(get_gpid(), _app->init_info().init_offset_in_private_log);
        dassert(mind <= last_durable_decree(), "");
        _private_log->check_valid_start_offset(get_gpid(), _app->init_info().init_offset_in_private_log);
    }
}

void replica::execute_mutation(mutation_ptr& mu)
{
    dinfo("%s: execute mutation %s: request_count = %u",
        name(),
        mu->name(),
        static_cast<int>(mu->client_requests.size())
        );

    error_code err = ERR_OK;
    decree d = mu->data.header.decree;

    switch (status())
    {
    case PS_INACTIVE:
        if (_app->last_committed_decree() + 1 == d)
        {
            err = _app->write_internal(mu);
        }
        else
        {
            ddebug(
                "%s: mutation %s commit to %s skipped, app.last_committed_decree = %" PRId64,
                name(), mu->name(),
                enum_to_string(status()),
                _app->last_committed_decree()
                );
        }
        break;
    case PS_PRIMARY:
        {
            check_state_completeness();
            dassert(_app->last_committed_decree() + 1 == d, "");
            err = _app->write_internal(mu);
        }
        break;

    case PS_SECONDARY:
        if (!_secondary_states.checkpoint_is_running)
        {
            check_state_completeness();
            dassert (_app->last_committed_decree() + 1 == d, "");
            err = _app->write_internal(mu);
        }
        else
        {
            ddebug(
                "%s: mutation %s commit to %s skipped, app.last_committed_decree = %" PRId64,
                name(), mu->name(),
                enum_to_string(status()),
                _app->last_committed_decree()
                );

            // make sure private log saves the state
            // catch-up will be done later after checkpoint task is fininished
            dassert(_private_log != nullptr, "");
        }
        break;
    case PS_POTENTIAL_SECONDARY:
        if (_potential_secondary_states.learning_status == LearningSucceeded ||
            _potential_secondary_states.learning_status == LearningWithPrepareTransient)
        {
            dassert(_app->last_committed_decree() + 1 == d, "");
            err = _app->write_internal(mu);
        }
        else
        {
            // prepare also happens with LearningWithPrepare, in this case
            // make sure private log saves the state,
            // catch-up will be done later after the checkpoint task is finished

            ddebug(
                "%s: mutation %s commit to %s skipped, app.last_committed_decree = %" PRId64,
                name(), mu->name(),
                enum_to_string(status()),
                _app->last_committed_decree()
                );
        }
        break;
    case PS_ERROR:
        break;
    }

    ddebug("TwoPhaseCommit, %s: mutation %s committed, err = %s", name(), mu->name(), err.to_string());

    _counter_commit_latency.set(dsn_now_ns() - mu->create_ts_ns());

    if (err != ERR_OK)
    {
        handle_local_failure(err);
    }

    if (status() == PS_PRIMARY)
    {
        mutation_ptr next = _primary_states.write_queue.check_possible_work(
            static_cast<int>(_prepare_list->max_decree() - d)
            );

        if (next)
        {
            init_prepare(next);
        }
    }
}

mutation_ptr replica::new_mutation(decree decree)
{
    mutation_ptr mu(new mutation());
    mu->data.header.gpid = get_gpid();
    mu->data.header.ballot = get_ballot();
    mu->data.header.decree = decree;
    mu->data.header.log_offset = invalid_offset;
    return mu;
}

bool replica::group_configuration(/*out*/ partition_configuration& config) const
{
    if (PS_PRIMARY != status())
        return false;

    config = _primary_states.membership;
    return true;
}

decree replica::last_durable_decree() const { return _app->last_durable_decree(); }

decree replica::last_prepared_decree() const
{
    ballot lastBallot = 0;
    decree start = last_committed_decree();
    while (true)
    {
        auto mu = _prepare_list->get_mutation_by_decree(start + 1);
        if (mu == nullptr
            || mu->data.header.ballot < lastBallot
            || !mu->is_logged()
            )
            break;

        start++;
        lastBallot = mu->data.header.ballot;
    }
    return start;
}

void replica::close()
{
    dassert(
        status() == PS_ERROR || status() == PS_INACTIVE,
        "%s: invalid state %s when calling replica::close",
        name(),
        enum_to_string(status())
        );

    if (nullptr != _checkpoint_timer)
    {
        _checkpoint_timer->cancel(true);
        _checkpoint_timer = nullptr;
    }

    cleanup_preparing_mutations(true);
    dassert(_primary_states.is_cleaned(), "primary context is not cleared");

    if (PS_INACTIVE == status())
    {
        dassert(_secondary_states.is_cleaned(), "secondary context is not cleared");
        dassert(_potential_secondary_states.is_cleaned(), "potential secondary context is not cleared");
    }

    // for PS_ERROR, context cleanup is done here as they may block
    else
    {
        bool r = _secondary_states.cleanup(true);
        dassert(r, "secondary context is not cleared");

        r = _potential_secondary_states.cleanup(true);
        dassert(r, "potential secondary context is not cleared");
    }

    if (_private_log != nullptr)
    {
        _private_log->close();
        _private_log = nullptr;
    }

    if (_app != nullptr)
    {
        _app->close(false);
    }
}

}} // namespace
<|endoftext|>


<commit_before>/* ****************************************************************************
*
* FILE                     iomMsgSend.cpp
*
* AUTHOR                   Ken Zangelin
*
* CREATION DATE            Oct 13 2010
*
*/
#include <unistd.h>             // write
#include <memory.h>             // memset
#include <sys/uio.h>            // writev, struct iovec, ...
#include <sys/time.h>           // gettimeofday

#include "logMsg.h"             // LM_*
#include "traceLevels.h"        // LmtWrite, ...

#include "Buffer.h"				// ss::Buffer
#include "MemoryManager.h"      // MemoryManager
#include "Endpoint.h"           // Endpoint
#include "Message.h"            // Message::Header, MessageCode, MessageType, ...
#include "Packet.h"             // Packet
#include "iomMsgSend.h"         // Own interface

/* ****************************************************************************
*
* iomWriteOk -
*/
bool iomWriteOk(int fd, const char* name, const char* ip)
{
	int             fds;
	fd_set          wFds;
	struct timeval  timeVal;
	int             tryh;
	int             tries = 30;

	for (tryh = 0; tryh < tries; tryh++)
	{
		timeVal.tv_sec  = 0;
		timeVal.tv_usec = 1000000;

		FD_ZERO(&wFds);
		FD_SET(fd, &wFds);

		do
		{
			fds = select(fd + 1, NULL, &wFds, NULL, &timeVal);
		} while ((fds == -1) && (errno == EINTR));

		if ((fds == 1) && (FD_ISSET(fd, &wFds)))
			return true;

        if( fds == -1 )
            LM_X(1, ("Error while writing to fd %d", fd));

		LM_W(("Problems to send to %s@%s (%d/%d secs)", name, ip, tryh, tries));
        sleep(1);
	}

	LM_X(1, ("cannot write to fd %d", fd));
	return false;
}

/* ****************************************************************************
*
* partWrite -
*/
static int partWrite(ss::Endpoint* to, void* dataP, int dataLen, const char* what)
{
	int    nb;
	int    tot  = 0;
	char*  data = (char*) dataP;

	while (tot < dataLen)
	{
		if (iomWriteOk(to->wFd, to->name.c_str(), to->ip) == false)
		{
			LM_E(("Cannot write to '%s' (fd %d) (returning -2 as if it was a 'connection closed' ...)", to->name.c_str(), to->wFd));
			return -2;
		}

		nb = write(to->wFd, &data[tot], dataLen - tot);
		if (nb == -1)
		{
			to->msgsOutErrors += 1;
			LM_RE(-1, ("error writing to '%s': %s", to->name.c_str(), strerror(errno)));
		}
		else if (nb == 0)
		{
			to->msgsOutErrors += 1;
			LM_RE(-1, ("part-write written ZERO bytes to '%s' (total: %d)", to->name.c_str(), tot));
		}

		tot += nb;
	}

	LM_WRITES(to->name.c_str(), what, data, dataLen, LmfByte);

	return tot;
}

/* ****************************************************************************
*
* iomMsgSend - send a message to an endpoint
*/
int iomMsgSend
(
	ss::Endpoint*               to,
	ss::Endpoint*               from,
	ss::Message::MessageCode    code,
	ss::Message::MessageType    type,
	void*                       data,
	int                         dataLen,
	ss::Packet*                 packetP
)
{

   //LM_M(("START iomMsgSend to fd %d", to->wFd));

	ss::Message::Header  header;
	int                  s;
	struct timeval       start;
	struct timeval       end;
	bool                 outHook;

	outHook = lmOutHookInhibit();

	if (code == ss::Message::Die)
		LM_W(("%s sending a Die to %s", from->name.c_str(), to->name.c_str()));

	gettimeofday(&start, NULL);

	memset(&header, 0, sizeof(header));

	header.code        = code;
	header.type        = type;
	header.magic       = 0xFEEDC0DE;

	if ((dataLen != 0) && (data != NULL))
		header.dataLen = dataLen;

	if ((packetP != NULL) && (packetP->message->ByteSize() != 0))
		header.gbufLen = packetP->message->ByteSize();

	if (packetP && (packetP->buffer != 0))
		header.kvDataLen = packetP->buffer->getSize();

	LM_T(LmtWrite, ("Sending '%s' %s to '%s', data bytes: { data: %d, gbuf: %d, kv: %d }",
				   messageCode(code), messageType(type), to->name.c_str(), header.dataLen, header.gbufLen, header.kvDataLen));

	s = partWrite(to, &header, sizeof(header), "header");
	if (s != sizeof(header))
	{
		LM_E(("partWrite returned %d and not the expected %d", s, sizeof(header)));
		lmOutHookRestore(outHook);
		return -1;
	}

	if ((dataLen != 0) && (data != NULL))
	{
		s = partWrite(to, data, dataLen, "msg data");
		if (s != dataLen)
		{
			LM_E(("partWrite returned %d and not the expected %d", s, dataLen));
			lmOutHookRestore(outHook);
			return -1;
		}
	}

	if ((packetP != NULL) && (packetP->message->ByteSize() != 0))
	{
		char* outputVec;

		outputVec = (char*) malloc(header.gbufLen + 2);
		if (outputVec == NULL)
			LM_XP(1, ("malloc(%d)", header.gbufLen));

		if (packetP->message->SerializeToArray(outputVec, header.gbufLen) == false)
			LM_X(1, ("SerializeToArray failed"));

		s = partWrite(to, outputVec, packetP->message->ByteSize(), "Google Protocol Buffer");
		free(outputVec);
		if (s != packetP->message->ByteSize())
		{
			LM_E(("partWrite returned %d and not the expected %d", s, packetP->message->ByteSize()));
			lmOutHookRestore(outHook);
			return -1;
		}
	}

	if (packetP && (packetP->buffer != 0))
	{
		s = partWrite(to, packetP->buffer->getData(), packetP->buffer->getSize(), "KV data");
		if (s != (int) packetP->buffer->getSize())
		{
			LM_E(("partWrite returned %d and not the expected %d", s, packetP->buffer->getSize()));
			lmOutHookRestore(outHook);
			return -1;
		}
	}

	if (packetP != NULL)
	{
        engine::MemoryManager::shared()->destroyBuffer(packetP->buffer);
		delete packetP;
	}

	int bytesSent = sizeof(header) + header.dataLen + header.gbufLen + header.kvDataLen;
	to->msgsOut  += 1;
	to->bytesOut += bytesSent;

	//LM_M(("FINISH iomMsgSend to fd %d", to->wFd));

	if (bytesSent > 100)
	{
		struct timeval diff;
		int            usecs;

		gettimeofday(&end, NULL);
		diff.tv_sec  = end.tv_sec  - start.tv_sec;
		diff.tv_usec = end.tv_usec - start.tv_usec;

		if (diff.tv_usec < 0)
		{
			diff.tv_sec  -= 1;
			diff.tv_usec += 1000000;
		}

		usecs = diff.tv_sec * 1000000 + diff.tv_usec;

		if (usecs < 0)
			LM_X(1, ("usecs cannot be < 0 ..."));

		if (usecs == 0)
		{
			lmOutHookRestore(outHook);
			return 0;
		}

		to->wMbps = bytesSent / usecs;

		to->wAccMbps = (to->wAccMbps * to->writes + to->wMbps) / (to->writes + 1);
		to->writes += 1;
	}

	lmOutHookRestore(outHook);
	return 0;
}
<commit_msg>Fix an error with the timeval structure. Ken.... sorry for that ;)<commit_after>/* ****************************************************************************
*
* FILE                     iomMsgSend.cpp
*
* AUTHOR                   Ken Zangelin
*
* CREATION DATE            Oct 13 2010
*
*/
#include <unistd.h>             // write
#include <memory.h>             // memset
#include <sys/uio.h>            // writev, struct iovec, ...
#include <sys/time.h>           // gettimeofday

#include "logMsg.h"             // LM_*
#include "traceLevels.h"        // LmtWrite, ...

#include "Buffer.h"				// ss::Buffer
#include "MemoryManager.h"      // MemoryManager
#include "Endpoint.h"           // Endpoint
#include "Message.h"            // Message::Header, MessageCode, MessageType, ...
#include "Packet.h"             // Packet
#include "iomMsgSend.h"         // Own interface

/* ****************************************************************************
*
* iomWriteOk -
*/
bool iomWriteOk(int fd, const char* name, const char* ip)
{
	int             fds;
	fd_set          wFds;
	struct timeval  timeVal;
	int             tryh;
	int             tries = 30;

	for (tryh = 0; tryh < tries; tryh++)
	{
		timeVal.tv_sec  = 1;
		timeVal.tv_usec = 0;

		FD_ZERO(&wFds);
		FD_SET(fd, &wFds);

		do
		{
			fds = select(fd + 1, NULL, &wFds, NULL, &timeVal);
		} while ((fds == -1) && (errno == EINTR));

		if ((fds == 1) && (FD_ISSET(fd, &wFds)))
			return true;

		if (fds == -1 )
		  LM_W(("write select error on fd %d: %s", fd, strerror(errno)));

		LM_W(("Problems to send to %s@%s (%d/%d secs)", name, ip, tryh, tries));
		sleep(1);
	}

	LM_X(1, ("cannot write to fd %d", fd));
	return false;
}

/* ****************************************************************************
*
* partWrite -
*/
static int partWrite(ss::Endpoint* to, void* dataP, int dataLen, const char* what)
{
	int    nb;
	int    tot  = 0;
	char*  data = (char*) dataP;

	while (tot < dataLen)
	{
		if (iomWriteOk(to->wFd, to->name.c_str(), to->ip) == false)
		{
			LM_E(("Cannot write to '%s' (fd %d) (returning -2 as if it was a 'connection closed' ...)", to->name.c_str(), to->wFd));
			return -2;
		}

		nb = write(to->wFd, &data[tot], dataLen - tot);
		if (nb == -1)
		{
			to->msgsOutErrors += 1;
			LM_RE(-1, ("error writing to '%s': %s", to->name.c_str(), strerror(errno)));
		}
		else if (nb == 0)
		{
			to->msgsOutErrors += 1;
			LM_RE(-1, ("part-write written ZERO bytes to '%s' (total: %d)", to->name.c_str(), tot));
		}

		tot += nb;
	}

	LM_WRITES(to->name.c_str(), what, data, dataLen, LmfByte);

	return tot;
}

/* ****************************************************************************
*
* iomMsgSend - send a message to an endpoint
*/
int iomMsgSend
(
	ss::Endpoint*               to,
	ss::Endpoint*               from,
	ss::Message::MessageCode    code,
	ss::Message::MessageType    type,
	void*                       data,
	int                         dataLen,
	ss::Packet*                 packetP
)
{

   //LM_M(("START iomMsgSend to fd %d", to->wFd));

	ss::Message::Header  header;
	int                  s;
	struct timeval       start;
	struct timeval       end;
	bool                 outHook;

	outHook = lmOutHookInhibit();

	if (code == ss::Message::Die)
		LM_W(("%s sending a Die to %s", from->name.c_str(), to->name.c_str()));

	gettimeofday(&start, NULL);

	memset(&header, 0, sizeof(header));

	header.code        = code;
	header.type        = type;
	header.magic       = 0xFEEDC0DE;

	if ((dataLen != 0) && (data != NULL))
		header.dataLen = dataLen;

	if ((packetP != NULL) && (packetP->message->ByteSize() != 0))
		header.gbufLen = packetP->message->ByteSize();

	if (packetP && (packetP->buffer != 0))
		header.kvDataLen = packetP->buffer->getSize();

	LM_T(LmtWrite, ("Sending '%s' %s to '%s', data bytes: { data: %d, gbuf: %d, kv: %d }",
				   messageCode(code), messageType(type), to->name.c_str(), header.dataLen, header.gbufLen, header.kvDataLen));

	s = partWrite(to, &header, sizeof(header), "header");
	if (s != sizeof(header))
	{
		LM_E(("partWrite returned %d and not the expected %d", s, sizeof(header)));
		lmOutHookRestore(outHook);
		return -1;
	}

	if ((dataLen != 0) && (data != NULL))
	{
		s = partWrite(to, data, dataLen, "msg data");
		if (s != dataLen)
		{
			LM_E(("partWrite returned %d and not the expected %d", s, dataLen));
			lmOutHookRestore(outHook);
			return -1;
		}
	}

	if ((packetP != NULL) && (packetP->message->ByteSize() != 0))
	{
		char* outputVec;

		outputVec = (char*) malloc(header.gbufLen + 2);
		if (outputVec == NULL)
			LM_XP(1, ("malloc(%d)", header.gbufLen));

		if (packetP->message->SerializeToArray(outputVec, header.gbufLen) == false)
			LM_X(1, ("SerializeToArray failed"));

		s = partWrite(to, outputVec, packetP->message->ByteSize(), "Google Protocol Buffer");
		free(outputVec);
		if (s != packetP->message->ByteSize())
		{
			LM_E(("partWrite returned %d and not the expected %d", s, packetP->message->ByteSize()));
			lmOutHookRestore(outHook);
			return -1;
		}
	}

	if (packetP && (packetP->buffer != 0))
	{
		s = partWrite(to, packetP->buffer->getData(), packetP->buffer->getSize(), "KV data");
		if (s != (int) packetP->buffer->getSize())
		{
			LM_E(("partWrite returned %d and not the expected %d", s, packetP->buffer->getSize()));
			lmOutHookRestore(outHook);
			return -1;
		}
	}

	if (packetP != NULL)
	{
        engine::MemoryManager::shared()->destroyBuffer(packetP->buffer);
		delete packetP;
	}

	int bytesSent = sizeof(header) + header.dataLen + header.gbufLen + header.kvDataLen;
	to->msgsOut  += 1;
	to->bytesOut += bytesSent;

	//LM_M(("FINISH iomMsgSend to fd %d", to->wFd));

	if (bytesSent > 100)
	{
		struct timeval diff;
		int            usecs;

		gettimeofday(&end, NULL);
		diff.tv_sec  = end.tv_sec  - start.tv_sec;
		diff.tv_usec = end.tv_usec - start.tv_usec;

		if (diff.tv_usec < 0)
		{
			diff.tv_sec  -= 1;
			diff.tv_usec += 1000000;
		}

		usecs = diff.tv_sec * 1000000 + diff.tv_usec;

		if (usecs < 0)
			LM_X(1, ("usecs cannot be < 0 ..."));

		if (usecs == 0)
		{
			lmOutHookRestore(outHook);
			return 0;
		}

		to->wMbps = bytesSent / usecs;

		to->wAccMbps = (to->wAccMbps * to->writes + to->wMbps) / (to->writes + 1);
		to->writes += 1;
	}

	lmOutHookRestore(outHook);
	return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: EnhancedCustomShapeGeometry.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 16:44:12 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _ENHANCEDCUSTOMSHAPEGEOMETRY_HXX
#define _ENHANCEDCUSTOMSHAPEGEOMETRY_HXX

#ifndef _SAL_TYPES_H_
#include <sal/types.h>
#endif
#ifndef _MSDFFDEF_HXX
#include <svx/msdffdef.hxx>
#endif

struct SvxMSDffVertPair
{
    sal_Int32   nValA;
    sal_Int32   nValB;
};
struct SvxMSDffCalculationData
{
    sal_uInt16  nFlags;
    sal_Int16   nVal[ 3 ];
};
struct SvxMSDffTextRectangles
{
    SvxMSDffVertPair    nPairA;
    SvxMSDffVertPair    nPairB;
};

#define MSDFF_HANDLE_FLAGS_MIRRORED_X                   0x0001
#define MSDFF_HANDLE_FLAGS_MIRRORED_Y                   0x0002
#define MSDFF_HANDLE_FLAGS_SWITCHED                     0x0004
#define MSDFF_HANDLE_FLAGS_POLAR                        0x0008
#define MSDFF_HANDLE_FLAGS_MAP                          0x0010
#define MSDFF_HANDLE_FLAGS_RANGE                        0x0020
#define MSDFF_HANDLE_FLAGS_RANGE_X_MIN_IS_SPECIAL       0x0080
#define MSDFF_HANDLE_FLAGS_RANGE_X_MAX_IS_SPECIAL       0x0100
#define MSDFF_HANDLE_FLAGS_RANGE_Y_MIN_IS_SPECIAL       0x0200
#define MSDFF_HANDLE_FLAGS_RANGE_Y_MAX_IS_SPECIAL       0x0400
#define MSDFF_HANDLE_FLAGS_CENTER_X_IS_SPECIAL          0x0800
#define MSDFF_HANDLE_FLAGS_CENTER_Y_IS_SPECIAL          0x1000
#define MSDFF_HANDLE_FLAGS_RADIUS_RANGE                 0x2000

struct SvxMSDffHandle
{
    sal_uInt32  nFlags;
    sal_Int32   nPositionX, nPositionY, nCenterX, nCenterY, nRangeXMin, nRangeXMax, nRangeYMin, nRangeYMax;
};
struct mso_CustomShape
{
    SvxMSDffVertPair*                       pVertices;
    sal_uInt32                              nVertices;
    sal_uInt16*                             pElements;
    sal_uInt32                              nElements;
    SvxMSDffCalculationData*                pCalculation;
    sal_uInt32                              nCalculation;
    sal_Int32*                              pDefData;
    SvxMSDffTextRectangles*                 pTextRect;
    sal_uInt32                              nTextRect;
    sal_Int32                               nCoordWidth;
    sal_Int32                               nCoordHeight;
    sal_Int32                               nXRef;
    sal_Int32                               nYRef;
    SvxMSDffVertPair*                       pGluePoints;
    sal_uInt32                              nGluePoints;
    SvxMSDffHandle*                         pHandles;
    sal_uInt32                              nHandles;
};

#define MSO_I | (sal_Int32)0x80000000

const sal_Bool          SortFilledObjectsToBackByDefault( MSO_SPT eSpType );
const sal_Bool          IsCustomShapeFilledByDefault( MSO_SPT eSpType );
const sal_Int16         GetCustomShapeConnectionTypeDefault( MSO_SPT eSpType );

// #i28269#
const sal_Bool          IsCustomShapeStrokedByDefault( MSO_SPT eSpType );

const mso_CustomShape*  GetCustomShapeContent( MSO_SPT eSpType );

#endif
<commit_msg>INTEGRATION: CWS changefileheader (1.7.368); FILE MERGED 2008/04/01 15:50:11 thb 1.7.368.3: #i85898# Stripping all external header guards 2008/04/01 12:48:02 thb 1.7.368.2: #i85898# Stripping all external header guards 2008/03/31 14:19:17 rt 1.7.368.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: EnhancedCustomShapeGeometry.hxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _ENHANCEDCUSTOMSHAPEGEOMETRY_HXX
#define _ENHANCEDCUSTOMSHAPEGEOMETRY_HXX

#include <sal/types.h>
#include <svx/msdffdef.hxx>

struct SvxMSDffVertPair
{
    sal_Int32   nValA;
    sal_Int32   nValB;
};
struct SvxMSDffCalculationData
{
    sal_uInt16  nFlags;
    sal_Int16   nVal[ 3 ];
};
struct SvxMSDffTextRectangles
{
    SvxMSDffVertPair    nPairA;
    SvxMSDffVertPair    nPairB;
};

#define MSDFF_HANDLE_FLAGS_MIRRORED_X                   0x0001
#define MSDFF_HANDLE_FLAGS_MIRRORED_Y                   0x0002
#define MSDFF_HANDLE_FLAGS_SWITCHED                     0x0004
#define MSDFF_HANDLE_FLAGS_POLAR                        0x0008
#define MSDFF_HANDLE_FLAGS_MAP                          0x0010
#define MSDFF_HANDLE_FLAGS_RANGE                        0x0020
#define MSDFF_HANDLE_FLAGS_RANGE_X_MIN_IS_SPECIAL       0x0080
#define MSDFF_HANDLE_FLAGS_RANGE_X_MAX_IS_SPECIAL       0x0100
#define MSDFF_HANDLE_FLAGS_RANGE_Y_MIN_IS_SPECIAL       0x0200
#define MSDFF_HANDLE_FLAGS_RANGE_Y_MAX_IS_SPECIAL       0x0400
#define MSDFF_HANDLE_FLAGS_CENTER_X_IS_SPECIAL          0x0800
#define MSDFF_HANDLE_FLAGS_CENTER_Y_IS_SPECIAL          0x1000
#define MSDFF_HANDLE_FLAGS_RADIUS_RANGE                 0x2000

struct SvxMSDffHandle
{
    sal_uInt32  nFlags;
    sal_Int32   nPositionX, nPositionY, nCenterX, nCenterY, nRangeXMin, nRangeXMax, nRangeYMin, nRangeYMax;
};
struct mso_CustomShape
{
    SvxMSDffVertPair*                       pVertices;
    sal_uInt32                              nVertices;
    sal_uInt16*                             pElements;
    sal_uInt32                              nElements;
    SvxMSDffCalculationData*                pCalculation;
    sal_uInt32                              nCalculation;
    sal_Int32*                              pDefData;
    SvxMSDffTextRectangles*                 pTextRect;
    sal_uInt32                              nTextRect;
    sal_Int32                               nCoordWidth;
    sal_Int32                               nCoordHeight;
    sal_Int32                               nXRef;
    sal_Int32                               nYRef;
    SvxMSDffVertPair*                       pGluePoints;
    sal_uInt32                              nGluePoints;
    SvxMSDffHandle*                         pHandles;
    sal_uInt32                              nHandles;
};

#define MSO_I | (sal_Int32)0x80000000

const sal_Bool          SortFilledObjectsToBackByDefault( MSO_SPT eSpType );
const sal_Bool          IsCustomShapeFilledByDefault( MSO_SPT eSpType );
const sal_Int16         GetCustomShapeConnectionTypeDefault( MSO_SPT eSpType );

// #i28269#
const sal_Bool          IsCustomShapeStrokedByDefault( MSO_SPT eSpType );

const mso_CustomShape*  GetCustomShapeContent( MSO_SPT eSpType );

#endif
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2016 Artem Pavlenko
 *
 * 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.1 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <mapnik/json/parse_feature.hpp>
#include <mapnik/json/json_grammar_config.hpp>
#include <mapnik/json/feature_grammar_x3.hpp>
#include <mapnik/json/create_geometry.hpp>
#include <mapnik/util/conversions.hpp>
#include <mapnik/value.hpp>
#include <mapnik/geometry/geometry_types.hpp>

namespace mapnik { namespace json {

template <typename Iterator>
void parse_feature(Iterator start, Iterator end, feature_impl& feature, mapnik::transcoder const& tr)
{
    namespace x3 = boost::spirit::x3;
    using space_type = mapnik::json::grammar::space_type;
    auto grammar = x3::with<mapnik::json::grammar::transcoder_tag>(std::ref(tr))
        [x3::with<mapnik::json::grammar::feature_tag>(std::ref(feature))
          [ mapnik::json::feature_grammar() ]];
    if (!x3::phrase_parse(start, end, grammar, space_type()))
    {
        throw std::runtime_error("Can't parser GeoJSON Feature");
    }
}

template <typename Iterator>
void parse_geometry(Iterator start, Iterator end, feature_impl& feature)
{
    namespace x3 = boost::spirit::x3;
    using space_type = mapnik::json::grammar::space_type;
    auto grammar = mapnik::json::geometry_grammar();
    if (!x3::phrase_parse(start, end, grammar, space_type(), feature.get_geometry()))
    {
        throw std::runtime_error("Can't parser GeoJSON Geometry");
    }
}

using iterator_type = mapnik::json::grammar::iterator_type;
template void parse_feature<iterator_type>(iterator_type,iterator_type, feature_impl& feature, mapnik::transcoder const& tr);
template void parse_geometry<iterator_type>(iterator_type,iterator_type, feature_impl& feature);

}}
<commit_msg>remove unused headers<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2016 Artem Pavlenko
 *
 * 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.1 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <mapnik/json/parse_feature.hpp>
#include <mapnik/json/json_grammar_config.hpp>
#include <mapnik/json/feature_grammar_x3.hpp>

namespace mapnik { namespace json {

template <typename Iterator>
void parse_feature(Iterator start, Iterator end, feature_impl& feature, mapnik::transcoder const& tr)
{
    namespace x3 = boost::spirit::x3;
    using space_type = mapnik::json::grammar::space_type;
    auto grammar = x3::with<mapnik::json::grammar::transcoder_tag>(std::ref(tr))
        [x3::with<mapnik::json::grammar::feature_tag>(std::ref(feature))
          [ mapnik::json::feature_grammar() ]];
    if (!x3::phrase_parse(start, end, grammar, space_type()))
    {
        throw std::runtime_error("Can't parser GeoJSON Feature");
    }
}

template <typename Iterator>
void parse_geometry(Iterator start, Iterator end, feature_impl& feature)
{
    namespace x3 = boost::spirit::x3;
    using space_type = mapnik::json::grammar::space_type;
    auto grammar = mapnik::json::geometry_grammar();
    if (!x3::phrase_parse(start, end, grammar, space_type(), feature.get_geometry()))
    {
        throw std::runtime_error("Can't parser GeoJSON Geometry");
    }
}

using iterator_type = mapnik::json::grammar::iterator_type;
template void parse_feature<iterator_type>(iterator_type,iterator_type, feature_impl& feature, mapnik::transcoder const& tr);
template void parse_geometry<iterator_type>(iterator_type,iterator_type, feature_impl& feature);

}}
<|endoftext|>


<commit_before>{
   gSystem.Load("/usr/X11/lib/libXmu.so");
   gSystem.Load("$ROOTSYS/opengl/lib/libMesaGL.so");
   gSystem.Load("$ROOTSYS/opengl/lib/libMesaGLU.so");
   gSystem.Load("$ROOTSYS/lib/libRGL.so");
}
<commit_msg>correct path of libXmu on Linux<commit_after>{
   gSystem.Load("/usr/X11R6/lib/libXmu.so");
   gSystem.Load("$ROOTSYS/opengl/lib/libMesaGL.so");
   gSystem.Load("$ROOTSYS/opengl/lib/libMesaGLU.so");
   gSystem.Load("$ROOTSYS/lib/libRGL.so");
}
<|endoftext|>


<commit_before>#include "maestro.h"

area* current_area;

struct holdable_keys {
	bool key_up;
	bool key_down;
	bool key_left;
	bool key_right;
	bool key_accept;
	bool key_cancel;
	bool key_menu;
	bool key_other;
	bool key_esc;
};

holdable_keys key_status = {
	false, false, false, false,
	false, false, false, false, false
};

int main(int argc, char** argv)
{
	ALLEGRO_DISPLAY* display = NULL;
	ALLEGRO_EVENT_QUEUE* event_queue = NULL;
	ALLEGRO_TIMER* timer = NULL;
	ALLEGRO_BITMAP* quitbitmap;
	bool redraw = true;
	unsigned int holdesc = 0;

	if(!al_init()) {
		fprintf(stderr, "failed to initialize allegro!\n");
		return -1;
	}

	if(!al_install_keyboard()) {
		fprintf(stderr, "failed to initialize the keyboard!\n");
		return -1;
	}

	timer = al_create_timer(1.0 / FPS);
	if(!timer) {
		fprintf(stderr, "failed to create timer!\n");
		return -1;
	}

	display = al_create_display(SCREEN_W, SCREEN_H);
	if(!display) {
		fprintf(stderr, "failed to create display!\n");
		al_destroy_timer(timer);
		return -1;
	}

	//TODO reinterpret cast seems ugly
	current_area = reinterpret_cast<area*>(new(nothrow) FIRST_AREA());
	if(!current_area) {
		fprintf(stderr, "failed to create current area!\n");
		al_destroy_display(display);
		al_destroy_timer(timer);
		return -1;
	}

	if(!al_init_image_addon()) {
		fprintf(stderr, "failed to load image addon!\n");
		delete current_area;
		al_destroy_display(display);
		al_destroy_timer(timer);
		return -1;
	}

	quitbitmap = al_load_bitmap(QUITIMAGE);
	if(!quitbitmap) {
		fprintf(stderr, "failed to load quit image!\n");
		delete current_area;
		al_shutdown_image_addon();
		al_destroy_display(display);
		al_destroy_timer(timer);
		return -1;
	}

	event_queue = al_create_event_queue();
	if(!event_queue) {
		fprintf(stderr, "failed to create event_queue!\n");
		delete current_area;
		al_shutdown_image_addon();
		al_destroy_bitmap(quitbitmap);
		al_destroy_display(display);
		al_destroy_timer(timer);
		return -1;
	}

	al_register_event_source(event_queue, al_get_display_event_source(display));
	al_register_event_source(event_queue, al_get_timer_event_source(timer));
	al_register_event_source(event_queue, al_get_keyboard_event_source());

	al_set_target_bitmap(al_get_backbuffer(display));
	al_clear_to_color(al_map_rgb(0,0,0));
	al_flip_display();

	al_start_timer(timer);

	while(holdesc < FPS) {
		ALLEGRO_EVENT ev;
		al_wait_for_event(event_queue, &ev);

		if(ev.type == ALLEGRO_EVENT_TIMER) {
			if(key_status.key_up)
				current_area->key_hold_up();
			if(key_status.key_down)
				current_area->key_hold_down();
			if(key_status.key_left)
				current_area->key_hold_left();
			if(key_status.key_right)
				current_area->key_hold_right();
			if(key_status.key_accept)
				current_area->key_hold_accept();
			if(key_status.key_cancel)
				current_area->key_hold_cancel();
			if(key_status.key_menu)
				current_area->key_hold_menu();
			if(key_status.key_other)
				current_area->key_hold_other();
			if(key_status.key_esc)
				holdesc++;

			current_area->loop();

			redraw = true;
		}
		else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
			break;
		}
		else if(ev.type == ALLEGRO_EVENT_KEY_DOWN) {
			switch(ev.keyboard.keycode) {
				case ALLEGRO_KEY_UP:
				case ALLEGRO_KEY_W:
					key_status.key_up = true;
					current_area->key_press_up();
				break;

				case ALLEGRO_KEY_DOWN:
				case ALLEGRO_KEY_S:
					key_status.key_down = true;
					current_area->key_press_down();
				break;

				case ALLEGRO_KEY_LEFT:
				case ALLEGRO_KEY_A:
					key_status.key_left = true;
					current_area->key_press_left();
				break;

				case ALLEGRO_KEY_RIGHT:
				case ALLEGRO_KEY_D:
					key_status.key_right = true;
					current_area->key_press_right();
				break;

				case ALLEGRO_KEY_ENTER:
				case ALLEGRO_KEY_SPACE:
					key_status.key_accept = true;
					current_area->key_press_accept();
				break;

				case ALLEGRO_KEY_LSHIFT:
				case ALLEGRO_KEY_RSHIFT:
					key_status.key_cancel = true;
					current_area->key_press_cancel();
				break;

				case ALLEGRO_KEY_LCTRL:
				case ALLEGRO_KEY_RCTRL:
					key_status.key_menu = true;
					current_area->key_press_menu();
				break;

				case ALLEGRO_KEY_ALT:
					key_status.key_other = true;
					current_area->key_press_other();
				break;

				case ALLEGRO_KEY_ESCAPE:
					key_status.key_esc = true;
				break;
			}
		}
		else if(ev.type == ALLEGRO_EVENT_KEY_UP) {
			switch(ev.keyboard.keycode) {
				case ALLEGRO_KEY_UP:
				case ALLEGRO_KEY_W:
					key_status.key_up = false;
					current_area->key_release_up();
				break;

				case ALLEGRO_KEY_DOWN:
				case ALLEGRO_KEY_S:
					key_status.key_down = false;
					current_area->key_release_down();
				break;

				case ALLEGRO_KEY_LEFT:
				case ALLEGRO_KEY_A:
					key_status.key_left = false;
					current_area->key_release_left();
				break;

				case ALLEGRO_KEY_RIGHT:
				case ALLEGRO_KEY_D:
					key_status.key_right = false;
					current_area->key_release_right();
				break;

				case ALLEGRO_KEY_ENTER:
				case ALLEGRO_KEY_SPACE:
					key_status.key_accept = false;
					current_area->key_release_accept();
				break;

				case ALLEGRO_KEY_LSHIFT:
				case ALLEGRO_KEY_RSHIFT:
					key_status.key_cancel = false;
					current_area->key_release_cancel();
				break;

				case ALLEGRO_KEY_LCTRL:
				case ALLEGRO_KEY_RCTRL:
					key_status.key_menu = false;
					current_area->key_release_menu();
				break;

				case ALLEGRO_KEY_ALT:
					key_status.key_other = false;
					current_area->key_release_other();
				break;
				//TODO customize mapping

				case ALLEGRO_KEY_ESCAPE:
					key_status.key_esc = false;
					holdesc = 0;
				break;

				case ALLEGRO_KEY_F4:
				case ALLEGRO_KEY_F11:
					toggle_fullscreen();
				break;
			}
		}

		if(redraw && al_is_event_queue_empty(event_queue)) {
			redraw = false;
			current_area->draw();

			if(holdesc>0) {
				unsigned char tint = (256*holdesc)/FPS;
				al_draw_tinted_bitmap(quitbitmap, al_map_rgb(tint, tint, tint), 0, 0, 0);
			}
			al_flip_display();
		}
	}

	delete current_area;
	al_shutdown_image_addon();
	al_destroy_bitmap(quitbitmap);
	al_destroy_timer(timer);
	al_destroy_display(display);
	al_destroy_event_queue(event_queue);

return 0;
}

//Misc functions
bool key_get_hold_up()
{
	return key_status.key_up;
}

bool key_get_hold_down()
{
	return key_status.key_down;
}

bool key_get_hold_left()
{
	return key_status.key_left;
}

bool key_get_hold_right()
{
	return key_status.key_right;
}

bool key_get_hold_accept()
{
	return key_status.key_accept;
}

bool key_get_hold_cancel()
{
	return key_status.key_cancel;
}

bool key_get_hold_menu()
{
	return key_status.key_menu;
}

bool key_get_hold_other()
{
	return key_status.key_other;
}

//screen size functions:
int get_screen_w()
{
	return SCREEN_W;
}

int get_screen_h()
{
	return SCREEN_H;
}

//screen scale functions:
//TODO save these changes
void set_screen_scale(float scalefactor)
{
	//TODO not implemented
}

float get_screen_scale()
{
	//TODO, static for now
	return SCREEN_S;
}

//fullscreen functions:
//TODO save these changes
void set_fullscreen(bool value)
{
	//TODO not implemented
}

void toggle_fullscreen()
{
	//TODO not implemented
}

bool get_fullscreen()
{
	//TODO, static for now
	return SCREEN_F;
}

//Object common functionality
object::object() :
	spriteflags(0), depth(0),
	subsprites(NULL), sprite_counter(0),
	sprite(NULL), x(0), y(0),
	visible(true), solid(true),
	bx(0), by(0), bw(0), bh(0),
	current_subsprite(0), animation_rate(0)
{}

object::object(int x, int y, ALLEGRO_BITMAP* sprite) :
	spriteflags(0), depth(0),
	subsprites(NULL), sprite_counter(0),
	sprite(sprite), x(x), y(y),
	visible(true), solid(true),
	bx(0), by(0), bw(0), bh(0),
	current_subsprite(0), animation_rate(0)
{
	if(sprite) {
		bw = al_get_bitmap_width(sprite);
		bh = al_get_bitmap_height(sprite);
	}
}

object::~object()
{
	remove_subsprites();
}

void object::sprite_horz_flip()
{
	if(sprite)
		spriteflags ^= (int) ALLEGRO_FLIP_HORIZONTAL;
}

void object::sprite_vert_flip()
{
	if(sprite)
		spriteflags ^= (int) ALLEGRO_FLIP_VERTICAL;
}

void add_subsprite(unsigned int x, unsigned int y, unsigned int w, unsigned int h)
{
	size_t i = 0;
	if(subsprites) {
		i = sizeof(subsprites);
		subspriteframes* old = subsprites;
		subsprites = new(nothrow) subspriteframes[i+1];
		if(subsprites) {
			memcpy(subsprites, old, sizeof(subspriteframes)*i);
			delete[] old;
		} else {
			subsprites = old;
			return;//Alloc failure
		}
	} else {
		subsprites = new(nothrow) subsprites[1];
	}
	if(subsprites) {
		subsprites[i].x = x;
		subsprites[i].y = y;
		subsprites[i].w = w;
		subsprites[i].h = h;
	}
}

void object::set_subsprites(subspriteframes subspritesarray[], unsigned int subsprite_count)
{
	remove_subsprites();
	subsprites = new(nothrow) subspriteframes[subsprite_count];
	if(subsprites)
		memcpy(subsprites, subspritesarray, sizeof(subspriteframes)*subsprite_count);
}

void remove_subsprites()
{
	delete[] subsprites;
	subsprites = NULL;
}

void object::set_depth(int newdepth)
{
	depth = newdepth;
	current_area->refresh_object_in_draw_order(this);
}

int object::get_depth()
{
	return depth;
}

//Object default functionality
void object::draw()
{
	if(sprite &&
	   x < current_area->viewx + get_screen_w() &&
	   y < current_area->viewy + get_screen_h() &&
	   x + al_get_bitmap_width(sprite) > current_area->viewx &&
	   y + al_get_bitmap_height(sprite) > current_area->viewy) {
		//TODO implement subsprite handling
		al_draw_bitmap(sprite, x - current_area->viewx,
		               y - current_area->viewy, spriteflags);
	}
}

//Area common functionality
void area::init(ALLEGRO_COLOR background)
{
	objectlist=NULL;
	backgroundcol = background;
	viewx = 0;
	viewy = 0;
};

area::~area()
{
	objectll* list = objectlist;
	while ( list != NULL ) {
		delete list->obj;
		objectlist = list->next;
		delete list;
		list = objectlist;
	}
}

object* area::new_object(int x, int y, ALLEGRO_BITMAP* sprite)
{
	//TODO allow specifying depth, and automically sort the object list by depth
	object* newobject = NULL;
	objectll* newobjectlist = new(nothrow) objectll();
	if(newobjectlist) {
		newobject = new(nothrow) object(x, y, sprite);
		if(newobject) {
			newobjectlist->obj = newobject;
			newobjectlist->next = objectlist;
			objectlist = newobjectlist;
		} else {
			delete newobjectlist;
		}
	}
	return newobject;
}

void area::del_object(object* obj)
{
	//TODO not implemented
}

bool area::check_collision_at_point(object* obj, int x, int y)
{
	//TODO not implemented
	return false;
}

void area::refresh_object_in_draw_order(object* obj)
{
	//TODO not implemented
}

//Area default functionality
void area::draw()
{
	al_clear_to_color(backgroundcol);

	objectll* list = objectlist;
	while ( list != NULL ) {
		if(list->obj->visible)
			list->obj->draw();
		list = list->next;
	}
}
<commit_msg>Implement subsprites and animation<commit_after>#include "maestro.h"

area* current_area;

struct holdable_keys {
	bool key_up;
	bool key_down;
	bool key_left;
	bool key_right;
	bool key_accept;
	bool key_cancel;
	bool key_menu;
	bool key_other;
	bool key_esc;
};

holdable_keys key_status = {
	false, false, false, false,
	false, false, false, false, false
};

int main(int argc, char** argv)
{
	ALLEGRO_DISPLAY* display = NULL;
	ALLEGRO_EVENT_QUEUE* event_queue = NULL;
	ALLEGRO_TIMER* timer = NULL;
	ALLEGRO_BITMAP* quitbitmap;
	bool redraw = true;
	unsigned int holdesc = 0;

	if(!al_init()) {
		fprintf(stderr, "failed to initialize allegro!\n");
		return -1;
	}

	if(!al_install_keyboard()) {
		fprintf(stderr, "failed to initialize the keyboard!\n");
		return -1;
	}

	timer = al_create_timer(1.0 / FPS);
	if(!timer) {
		fprintf(stderr, "failed to create timer!\n");
		return -1;
	}

	display = al_create_display(SCREEN_W, SCREEN_H);
	if(!display) {
		fprintf(stderr, "failed to create display!\n");
		al_destroy_timer(timer);
		return -1;
	}

	//TODO reinterpret cast seems ugly
	current_area = reinterpret_cast<area*>(new(nothrow) FIRST_AREA());
	if(!current_area) {
		fprintf(stderr, "failed to create current area!\n");
		al_destroy_display(display);
		al_destroy_timer(timer);
		return -1;
	}

	if(!al_init_image_addon()) {
		fprintf(stderr, "failed to load image addon!\n");
		delete current_area;
		al_destroy_display(display);
		al_destroy_timer(timer);
		return -1;
	}

	quitbitmap = al_load_bitmap(QUITIMAGE);
	if(!quitbitmap) {
		fprintf(stderr, "failed to load quit image!\n");
		delete current_area;
		al_shutdown_image_addon();
		al_destroy_display(display);
		al_destroy_timer(timer);
		return -1;
	}

	event_queue = al_create_event_queue();
	if(!event_queue) {
		fprintf(stderr, "failed to create event_queue!\n");
		delete current_area;
		al_shutdown_image_addon();
		al_destroy_bitmap(quitbitmap);
		al_destroy_display(display);
		al_destroy_timer(timer);
		return -1;
	}

	al_register_event_source(event_queue, al_get_display_event_source(display));
	al_register_event_source(event_queue, al_get_timer_event_source(timer));
	al_register_event_source(event_queue, al_get_keyboard_event_source());

	al_set_target_bitmap(al_get_backbuffer(display));
	al_clear_to_color(al_map_rgb(0,0,0));
	al_flip_display();

	al_start_timer(timer);

	while(holdesc < FPS) {
		ALLEGRO_EVENT ev;
		al_wait_for_event(event_queue, &ev);

		if(ev.type == ALLEGRO_EVENT_TIMER) {
			if(key_status.key_up)
				current_area->key_hold_up();
			if(key_status.key_down)
				current_area->key_hold_down();
			if(key_status.key_left)
				current_area->key_hold_left();
			if(key_status.key_right)
				current_area->key_hold_right();
			if(key_status.key_accept)
				current_area->key_hold_accept();
			if(key_status.key_cancel)
				current_area->key_hold_cancel();
			if(key_status.key_menu)
				current_area->key_hold_menu();
			if(key_status.key_other)
				current_area->key_hold_other();
			if(key_status.key_esc)
				holdesc++;

			current_area->loop();

			redraw = true;
		}
		else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
			break;
		}
		else if(ev.type == ALLEGRO_EVENT_KEY_DOWN) {
			switch(ev.keyboard.keycode) {
				case ALLEGRO_KEY_UP:
				case ALLEGRO_KEY_W:
					key_status.key_up = true;
					current_area->key_press_up();
				break;

				case ALLEGRO_KEY_DOWN:
				case ALLEGRO_KEY_S:
					key_status.key_down = true;
					current_area->key_press_down();
				break;

				case ALLEGRO_KEY_LEFT:
				case ALLEGRO_KEY_A:
					key_status.key_left = true;
					current_area->key_press_left();
				break;

				case ALLEGRO_KEY_RIGHT:
				case ALLEGRO_KEY_D:
					key_status.key_right = true;
					current_area->key_press_right();
				break;

				case ALLEGRO_KEY_ENTER:
				case ALLEGRO_KEY_SPACE:
					key_status.key_accept = true;
					current_area->key_press_accept();
				break;

				case ALLEGRO_KEY_LSHIFT:
				case ALLEGRO_KEY_RSHIFT:
					key_status.key_cancel = true;
					current_area->key_press_cancel();
				break;

				case ALLEGRO_KEY_LCTRL:
				case ALLEGRO_KEY_RCTRL:
					key_status.key_menu = true;
					current_area->key_press_menu();
				break;

				case ALLEGRO_KEY_ALT:
					key_status.key_other = true;
					current_area->key_press_other();
				break;

				case ALLEGRO_KEY_ESCAPE:
					key_status.key_esc = true;
				break;
			}
		}
		else if(ev.type == ALLEGRO_EVENT_KEY_UP) {
			switch(ev.keyboard.keycode) {
				case ALLEGRO_KEY_UP:
				case ALLEGRO_KEY_W:
					key_status.key_up = false;
					current_area->key_release_up();
				break;

				case ALLEGRO_KEY_DOWN:
				case ALLEGRO_KEY_S:
					key_status.key_down = false;
					current_area->key_release_down();
				break;

				case ALLEGRO_KEY_LEFT:
				case ALLEGRO_KEY_A:
					key_status.key_left = false;
					current_area->key_release_left();
				break;

				case ALLEGRO_KEY_RIGHT:
				case ALLEGRO_KEY_D:
					key_status.key_right = false;
					current_area->key_release_right();
				break;

				case ALLEGRO_KEY_ENTER:
				case ALLEGRO_KEY_SPACE:
					key_status.key_accept = false;
					current_area->key_release_accept();
				break;

				case ALLEGRO_KEY_LSHIFT:
				case ALLEGRO_KEY_RSHIFT:
					key_status.key_cancel = false;
					current_area->key_release_cancel();
				break;

				case ALLEGRO_KEY_LCTRL:
				case ALLEGRO_KEY_RCTRL:
					key_status.key_menu = false;
					current_area->key_release_menu();
				break;

				case ALLEGRO_KEY_ALT:
					key_status.key_other = false;
					current_area->key_release_other();
				break;
				//TODO customize mapping

				case ALLEGRO_KEY_ESCAPE:
					key_status.key_esc = false;
					holdesc = 0;
				break;

				case ALLEGRO_KEY_F4:
				case ALLEGRO_KEY_F11:
					toggle_fullscreen();
				break;
			}
		}

		if(redraw && al_is_event_queue_empty(event_queue)) {
			redraw = false;
			current_area->draw();

			if(holdesc>0) {
				unsigned char tint = (256*holdesc)/FPS;
				al_draw_tinted_bitmap(quitbitmap, al_map_rgb(tint, tint, tint), 0, 0, 0);
			}
			al_flip_display();
		}
	}

	delete current_area;
	al_shutdown_image_addon();
	al_destroy_bitmap(quitbitmap);
	al_destroy_timer(timer);
	al_destroy_display(display);
	al_destroy_event_queue(event_queue);

return 0;
}

//Misc functions
bool key_get_hold_up()
{
	return key_status.key_up;
}

bool key_get_hold_down()
{
	return key_status.key_down;
}

bool key_get_hold_left()
{
	return key_status.key_left;
}

bool key_get_hold_right()
{
	return key_status.key_right;
}

bool key_get_hold_accept()
{
	return key_status.key_accept;
}

bool key_get_hold_cancel()
{
	return key_status.key_cancel;
}

bool key_get_hold_menu()
{
	return key_status.key_menu;
}

bool key_get_hold_other()
{
	return key_status.key_other;
}

//screen size functions:
int get_screen_w()
{
	return SCREEN_W;
}

int get_screen_h()
{
	return SCREEN_H;
}

//screen scale functions:
//TODO save these changes
void set_screen_scale(float scalefactor)
{
	//TODO not implemented
}

float get_screen_scale()
{
	//TODO, static for now
	return SCREEN_S;
}

//fullscreen functions:
//TODO save these changes
void set_fullscreen(bool value)
{
	//TODO not implemented
}

void toggle_fullscreen()
{
	//TODO not implemented
}

bool get_fullscreen()
{
	//TODO, static for now
	return SCREEN_F;
}

//Object common functionality
object::object() :
	spriteflags(0), depth(0),
	subsprites(NULL), sprite_counter(0),
	sprite(NULL), x(0), y(0),
	visible(true), solid(true),
	bx(0), by(0), bw(0), bh(0),
	current_subsprite(0), animation_rate(0)
{}

object::object(int x, int y, ALLEGRO_BITMAP* sprite) :
	spriteflags(0), depth(0),
	subsprites(NULL), sprite_counter(0),
	sprite(sprite), x(x), y(y),
	visible(true), solid(true),
	bx(0), by(0), bw(0), bh(0),
	current_subsprite(0), animation_rate(0)
{
	if(sprite) {
		bw = al_get_bitmap_width(sprite);
		bh = al_get_bitmap_height(sprite);
	}
}

object::~object()
{
	remove_subsprites();
}

void object::sprite_horz_flip()
{
	if(sprite)
		spriteflags ^= (int) ALLEGRO_FLIP_HORIZONTAL;
}

void object::sprite_vert_flip()
{
	if(sprite)
		spriteflags ^= (int) ALLEGRO_FLIP_VERTICAL;
}

void add_subsprite(unsigned int x, unsigned int y, unsigned int w, unsigned int h)
{
	size_t i = 0;
	if(subsprites) {
		i = sizeof(subsprites);
		subspriteframes* old = subsprites;
		subsprites = new(nothrow) subspriteframes[i+1];
		if(subsprites) {
			memcpy(subsprites, old, sizeof(subspriteframes)*i);
			delete[] old;
		} else {
			subsprites = old;
			return;//Alloc failure
		}
	} else {
		subsprites = new(nothrow) subsprites[1];
	}
	if(subsprites) {
		subsprites[i].x = x;
		subsprites[i].y = y;
		subsprites[i].w = w;
		subsprites[i].h = h;
	}
}

void object::set_subsprites(subspriteframes subspritesarray[], unsigned int subsprite_count)
{
	remove_subsprites();
	subsprites = new(nothrow) subspriteframes[subsprite_count];
	if(subsprites)
		memcpy(subsprites, subspritesarray, sizeof(subspriteframes)*subsprite_count);
}

void remove_subsprites()
{
	delete[] subsprites;
	subsprites = NULL;
}

void object::set_depth(int newdepth)
{
	depth = newdepth;
	current_area->refresh_object_in_draw_order(this);
}

int object::get_depth()
{
	return depth;
}

//Object default functionality
void object::draw()
{
	if(sprite &&
	   x < current_area->viewx + get_screen_w() &&
	   y < current_area->viewy + get_screen_h() &&
	   x + al_get_bitmap_width(sprite) > current_area->viewx &&
	   y + al_get_bitmap_height(sprite) > current_area->viewy) {
		if(subsprites) {
			sprite_counter++;
			if(sprite_counter >= animation_rate) {
				sprite_counter=0;
				current_subsprite++;
			}
			if(current_subsprite >= sizeof(subsprites))
				current_subsprite=0;
			al_draw_bitmap(sprite, subsprites[current_subsprite].x,
			               subsprites[current_subsprite].y,
			               subsprites[current_subsprite].w,
			               subsprites[current_subsprite].h,
			               x - current_area->viewx,
			               y - current_area->viewy, spriteflags);
		} else {
			al_draw_bitmap(sprite, x - current_area->viewx,
				       y - current_area->viewy, spriteflags);
		}
	}
}

//Area common functionality
void area::init(ALLEGRO_COLOR background)
{
	objectlist=NULL;
	backgroundcol = background;
	viewx = 0;
	viewy = 0;
};

area::~area()
{
	objectll* list = objectlist;
	while ( list != NULL ) {
		delete list->obj;
		objectlist = list->next;
		delete list;
		list = objectlist;
	}
}

object* area::new_object(int x, int y, ALLEGRO_BITMAP* sprite)
{
	//TODO allow specifying depth, and automically sort the object list by depth
	object* newobject = NULL;
	objectll* newobjectlist = new(nothrow) objectll();
	if(newobjectlist) {
		newobject = new(nothrow) object(x, y, sprite);
		if(newobject) {
			newobjectlist->obj = newobject;
			newobjectlist->next = objectlist;
			objectlist = newobjectlist;
		} else {
			delete newobjectlist;
		}
	}
	return newobject;
}

void area::del_object(object* obj)
{
	//TODO not implemented
}

bool area::check_collision_at_point(object* obj, int x, int y)
{
	//TODO not implemented
	return false;
}

void area::refresh_object_in_draw_order(object* obj)
{
	//TODO not implemented
}

//Area default functionality
void area::draw()
{
	al_clear_to_color(backgroundcol);

	objectll* list = objectlist;
	while ( list != NULL ) {
		if(list->obj->visible)
			list->obj->draw();
		list = list->next;
	}
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// <unordered_set>

// template <class Value, class Hash = hash<Value>, class Pred = equal_to<Value>,
//           class Alloc = allocator<Value>>
// class unordered_set

// iterator insert(const_iterator p, value_type&& x);

#if _LIBCPP_DEBUG >= 1
#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
#endif

//#include <unordered_set>
//#include <cassert>

//#include "MoveOnly.h"
//#include "min_allocator.h"

void main()
{
    {
        typedef unordered_set<double> C;
        typedef C::iterator R;
        typedef double P;
        C c;
        //C::const_iterator e = c.end();
        R r = c.insert(/*e*/c.find(3.5), P(3.5));
        assert(c.size() == 1);
        assert(*r == 3.5);

#ifndef MOMO_USE_UNORDERED_HINT_ITERATORS
        r = c.insert(/*r*/c.find(3.5), P(3.5));
        assert(c.size() == 1);
        assert(*r == 3.5);
#endif

        r = c.insert(/*e*/c.find(4.5), P(4.5));
        assert(c.size() == 2);
        assert(*r == 4.5);

        r = c.insert(/*e*/c.find(5.5), P(5.5));
        assert(c.size() == 3);
        assert(*r == 5.5);
    }
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
    {
        typedef unordered_set<MoveOnly> C;
        typedef C::iterator R;
        typedef MoveOnly P;
        C c;
        C::const_iterator e = c.end();
        R r = c.insert(/*e*/c.find(3), P(3));
        assert(c.size() == 1);
        assert(*r == 3);

#ifndef MOMO_USE_UNORDERED_HINT_ITERATORS
        r = c.insert(/*r*/c.find(3), P(3));
        assert(c.size() == 1);
        assert(*r == 3);
#endif

        r = c.insert(/*e*/c.find(4), P(4));
        assert(c.size() == 2);
        assert(*r == 4);

        r = c.insert(/*e*/c.find(5), P(5));
        assert(c.size() == 3);
        assert(*r == 5);
    }
#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
//#if __cplusplus >= 201103L
#ifdef LIBCPP_TEST_MIN_ALLOCATOR
    {
        typedef unordered_set<double, std::hash<double>,
                                std::equal_to<double>, min_allocator<double>> C;
        typedef C::iterator R;
        typedef double P;
        C c;
        C::const_iterator e = c.end();
        R r = c.insert(e, P(3.5));
        assert(c.size() == 1);
        assert(*r == 3.5);

        r = c.insert(r, P(3.5));
        assert(c.size() == 1);
        assert(*r == 3.5);

        r = c.insert(e, P(4.5));
        assert(c.size() == 2);
        assert(*r == 4.5);

        r = c.insert(e, P(5.5));
        assert(c.size() == 3);
        assert(*r == 5.5);
    }
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
    {
        typedef unordered_set<MoveOnly, std::hash<MoveOnly>,
                            std::equal_to<MoveOnly>, min_allocator<MoveOnly>> C;
        typedef C::iterator R;
        typedef MoveOnly P;
        C c;
        C::const_iterator e = c.end();
        R r = c.insert(e, P(3));
        assert(c.size() == 1);
        assert(*r == 3);

        r = c.insert(r, P(3));
        assert(c.size() == 1);
        assert(*r == 3);

        r = c.insert(e, P(4));
        assert(c.size() == 2);
        assert(*r == 4);

        r = c.insert(e, P(5));
        assert(c.size() == 3);
        assert(*r == 5);
    }
#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
#endif
#if _LIBCPP_DEBUG >= 1
#ifdef LIBCPP_HAS_BAD_NEWS_FOR_MOMO
    {
        typedef unordered_set<double> C;
        typedef C::iterator R;
        typedef C::value_type P;
        C c;
        C c2;
        C::const_iterator e = c2.end();
        LIBCPP_CATCH(c.insert(e, P(3.5)));
        //assert(false);
    }
#endif
#endif
//#endif
}
<commit_msg>Testing hint iterators<commit_after>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// <unordered_set>

// template <class Value, class Hash = hash<Value>, class Pred = equal_to<Value>,
//           class Alloc = allocator<Value>>
// class unordered_set

// iterator insert(const_iterator p, value_type&& x);

#if _LIBCPP_DEBUG >= 1
#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
#endif

//#include <unordered_set>
//#include <cassert>

//#include "MoveOnly.h"
//#include "min_allocator.h"

void main()
{
    {
        typedef unordered_set<double> C;
        typedef C::iterator R;
        typedef double P;
        C c;
        //C::const_iterator e = c.end();
        R r = c.insert(/*e*/c.find(3.5), P(3.5));
        assert(c.size() == 1);
        assert(*r == 3.5);

#ifndef MOMO_USE_UNORDERED_HINT_ITERATORS
        r = c.insert(/*r*/c.find(3.5), P(3.5));
        assert(c.size() == 1);
        assert(*r == 3.5);
#endif

        r = c.insert(/*e*/c.find(4.5), P(4.5));
        assert(c.size() == 2);
        assert(*r == 4.5);

        r = c.insert(/*e*/c.find(5.5), P(5.5));
        assert(c.size() == 3);
        assert(*r == 5.5);
    }
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
    {
        typedef unordered_set<MoveOnly> C;
        typedef C::iterator R;
        typedef MoveOnly P;
        C c;
        //C::const_iterator e = c.end();
        R r = c.insert(/*e*/c.find(3), P(3));
        assert(c.size() == 1);
        assert(*r == 3);

#ifndef MOMO_USE_UNORDERED_HINT_ITERATORS
        r = c.insert(/*r*/c.find(3), P(3));
        assert(c.size() == 1);
        assert(*r == 3);
#endif

        r = c.insert(/*e*/c.find(4), P(4));
        assert(c.size() == 2);
        assert(*r == 4);

        r = c.insert(/*e*/c.find(5), P(5));
        assert(c.size() == 3);
        assert(*r == 5);
    }
#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
//#if __cplusplus >= 201103L
#ifdef LIBCPP_TEST_MIN_ALLOCATOR
    {
        typedef unordered_set<double, std::hash<double>,
                                std::equal_to<double>, min_allocator<double>> C;
        typedef C::iterator R;
        typedef double P;
        C c;
        C::const_iterator e = c.end();
        R r = c.insert(e, P(3.5));
        assert(c.size() == 1);
        assert(*r == 3.5);

        r = c.insert(r, P(3.5));
        assert(c.size() == 1);
        assert(*r == 3.5);

        r = c.insert(e, P(4.5));
        assert(c.size() == 2);
        assert(*r == 4.5);

        r = c.insert(e, P(5.5));
        assert(c.size() == 3);
        assert(*r == 5.5);
    }
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
    {
        typedef unordered_set<MoveOnly, std::hash<MoveOnly>,
                            std::equal_to<MoveOnly>, min_allocator<MoveOnly>> C;
        typedef C::iterator R;
        typedef MoveOnly P;
        C c;
        C::const_iterator e = c.end();
        R r = c.insert(e, P(3));
        assert(c.size() == 1);
        assert(*r == 3);

        r = c.insert(r, P(3));
        assert(c.size() == 1);
        assert(*r == 3);

        r = c.insert(e, P(4));
        assert(c.size() == 2);
        assert(*r == 4);

        r = c.insert(e, P(5));
        assert(c.size() == 3);
        assert(*r == 5);
    }
#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
#endif
#if _LIBCPP_DEBUG >= 1
#ifdef LIBCPP_HAS_BAD_NEWS_FOR_MOMO
    {
        typedef unordered_set<double> C;
        typedef C::iterator R;
        typedef C::value_type P;
        C c;
        C c2;
        C::const_iterator e = c2.end();
        LIBCPP_CATCH(c.insert(e, P(3.5)));
        //assert(false);
    }
#endif
#endif
//#endif
}
<|endoftext|>


<commit_before>/********************************************************************
 * Author:  Carlos Moreno
 * Created: 2015-06-04
 *
 * Description:
 *
 *      This is a sample code to connect to a server through TCP.
 *      You are allowed to use this as a sample / starting point
 *      for the assignment (both problems require a program that
 *      connects to something)
 *
 * Copytight and permissions:
 *      This file is for the exclusive purpose of our ECE-458
 *      assignment 2, and you are not allowed to use it for any
 *      other purpose.
 *
 ********************************************************************/

#include <iostream>
#include <sstream>
#include <map>
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <cerrno>

#include <inttypes.h>
#include <math.h>
using namespace std;

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <wait.h>
#include <unistd.h>

static __inline__ uint64_t rdtsc();
bool password_ok (const string &pwd);

int main(int argc, char *argv[])
{
	string possiblePwd = "";
	if(argc == 2){
		possiblePwd = argv[1];
	}
	srand(time(NULL));
	bool finished = false;
	int letters = 0;
	if((finished = password_ok (possiblePwd)) == true) cout<<"password correct: " <<possiblePwd <<endl;
	//static const char alphabet[] = "ghijnoptuvwabcxyzdefqrsklm";
	static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz";
	while(!finished){
		uint64_t timevalues [26] = {};
		uint64_t squarevalues [26] = {};
		int times_picked [26] = {};
		//destroy possible caching
		for(int i = 0; i < 100000; i++){
			int chosen_char = rand()%(sizeof(alphabet)-1);
			const char &current = alphabet[chosen_char];
			const string &pwd_attempt = possiblePwd + current;
            password_ok (pwd_attempt);

		}
		srand(time(NULL));
		for(int i = 0; i < 10000000; i++){
            int chosen_char = rand()%(sizeof(alphabet)-1);
			char current = alphabet[chosen_char];

			const string &pwd_attempt = possiblePwd + current;
			uint64_t start = rdtsc();
			finished = password_ok (pwd_attempt);
			uint64_t end = rdtsc();
			if(finished){
				cout<<"password guessed correct: " <<pwd_attempt <<endl;
				return 0;
			}
			uint64_t difference = end - start;
			//cout<< alphabet[chosen_char]<< ": time of " <<difference <<endl;
			timevalues[chosen_char] += difference;
			squarevalues[chosen_char] += (difference*difference);
			times_picked[chosen_char] = times_picked[chosen_char] + 1;

		}
		//initialize to "a"
		double highest_mean = 0.0;
		double highest_var = 0.0;
		char highest_char = 'a';
		double nexthighest_mean = 0.0;
		int highest_picktime = 0;
		for(int i = 0; i < 26; i++){
			double current_mean = (double)timevalues[i] / times_picked[i];
			double current_var = ((double)1/ (double)(times_picked[i] - 1)) * (double)(squarevalues[i] - times_picked[i] * (current_mean * current_mean));
			if(current_mean > nexthighest_mean && current_mean < highest_mean){
				nexthighest_mean = current_mean;
			}
			if(current_mean > highest_mean){
				nexthighest_mean = highest_mean;
				highest_mean = current_mean;
				highest_var = current_var;
				highest_picktime = times_picked[i];
				highest_char = alphabet[i];
			}
			cout<< alphabet[i] <<" mean: " <<current_mean << " ms, \tvariance: " <<current_var << " \tpicked " << times_picked[i] <<" times" <<endl;
		}
		double confidence95 = 1.96*sqrt(highest_var) / sqrt(highest_picktime);
		double confidence99 = 2.58*sqrt(highest_var) / sqrt(highest_picktime);
		cout<< "\nBEST GUESS: " << possiblePwd+highest_char << ", with time: " << highest_mean << " variance: " << highest_var <<endl;
		cout<<"\n95\% confidence interval: " <<highest_mean << " +- " <<confidence95 <<"\n99\% confidence interval: " <<highest_mean << " +- " <<confidence99<< endl;
		cout<<"next longest time: " << nexthighest_mean <<endl;

		if(highest_mean/nexthighest_mean < 1.01 ||confidence99/highest_mean > 0.02 || (highest_mean - confidence99) < nexthighest_mean){
			cout<< "Not confident about attempted password, try a shorter guess?" <<endl;
		}
		return 0;

	}

    return 0;
}

static __inline__ uint64_t rdtsc()
{
	uint32_t hi, lo;
	__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
	return ((uint64_t)lo) | (((uint64_t)hi) << 32);
}

bool password_ok (const string &pwd)
{
	return pwd == "mypassword";
    //return strcmp(pwd.c_str(), "mypassword") == 0;
}

<commit_msg>now shuffling alphabet every time for part 2<commit_after>/********************************************************************
 * Author:  Carlos Moreno
 * Created: 2015-06-04
 *
 * Description:
 *
 *      This is a sample code to connect to a server through TCP.
 *      You are allowed to use this as a sample / starting point
 *      for the assignment (both problems require a program that
 *      connects to something)
 *
 * Copytight and permissions:
 *      This file is for the exclusive purpose of our ECE-458
 *      assignment 2, and you are not allowed to use it for any
 *      other purpose.
 *
 ********************************************************************/

#include <iostream>
#include <sstream>
#include <map>
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <cerrno>

#include <inttypes.h>
#include <math.h>
using namespace std;

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <wait.h>
#include <unistd.h>

static __inline__ uint64_t rdtsc();
bool password_ok (const string &pwd);

int main(int argc, char *argv[])
{
	string possiblePwd = "";
	if(argc == 2){
		possiblePwd = argv[1];
	}
	srand(time(NULL));
	bool finished = false;
	int letters = 0;
	if((finished = password_ok (possiblePwd)) == true) cout<<"password correct: " <<possiblePwd <<endl;
	//static const char alphabet[] = "ghijnoptuvwabcxyzdefqrsklm";
	//static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz";
	string alphabet = "abcdefghijklmnopqrstuvwxyz";
	while(!finished){
		uint64_t timevalues [26] = {};
		uint64_t squarevalues [26] = {};
		int times_picked [26] = {};
		//destroy possible caching
		for(int i = 0; i < 100000; i++){
			int chosen_char = rand()%26;
			const char &current = alphabet.at(chosen_char);
			const string &pwd_attempt = possiblePwd + current;
            password_ok (pwd_attempt);

		}
		srand(time(NULL));
		for(int i = 0; i < 1000000; i++){
            int chosen_char = rand()%26;
            random_shuffle(alphabet.begin(),alphabet.end());
			char current = alphabet.at(chosen_char);

			const string &pwd_attempt = possiblePwd + current;
			uint64_t start = rdtsc();
			finished = password_ok (pwd_attempt);
			uint64_t end = rdtsc();
			if(finished){
				cout<<"password guessed correct: " <<pwd_attempt <<endl;
				return 0;
			}
			uint64_t difference = end - start;
			//cout<< alphabet[chosen_char]<< ": time of " <<difference <<endl;
			timevalues[((char)alphabet.at(chosen_char))-97] += difference;
			squarevalues[((char)alphabet.at(chosen_char))-97] += (difference*difference);
			times_picked[((char)alphabet.at(chosen_char))-97] = times_picked[((char)alphabet.at(chosen_char))-97] + 1;

		}
		//initialize to "a"
		double highest_mean = 0.0;
		double highest_var = 0.0;
		char highest_char = 'a';
		double nexthighest_mean = 0.0;
		int highest_picktime = 0;
		alphabet = "abcdefghijklmnopqrstuvwxyz";
		for(int i = 0; i < 26; i++){
			double current_mean = (double)timevalues[i] / times_picked[i];
			double current_var = ((double)1/ (double)(times_picked[i] - 1)) * (double)(squarevalues[i] - times_picked[i] * (current_mean * current_mean));
			if(current_mean > nexthighest_mean && current_mean < highest_mean){
				nexthighest_mean = current_mean;
			}
			if(current_mean > highest_mean){
				nexthighest_mean = highest_mean;
				highest_mean = current_mean;
				highest_var = current_var;
				highest_picktime = times_picked[i];
				highest_char = alphabet[i];
			}
			cout<< alphabet[i] <<" mean: " <<current_mean << " ms, \tvariance: " <<current_var << " \tpicked " << times_picked[i] <<" times" <<endl;
		}
		double confidence95 = 1.96*sqrt(highest_var) / sqrt(highest_picktime);
		double confidence99 = 2.58*sqrt(highest_var) / sqrt(highest_picktime);
		cout<< "\nBEST GUESS: " << possiblePwd+highest_char << ", with time: " << highest_mean << " variance: " << highest_var <<endl;
		cout<<"\n95\% confidence interval: " <<highest_mean << " +- " <<confidence95 <<"\n99\% confidence interval: " <<highest_mean << " +- " <<confidence99<< endl;
		cout<<"next longest time: " << nexthighest_mean <<endl;

		if(highest_mean/nexthighest_mean < 1.01 ||confidence99/highest_mean > 0.02 || (highest_mean - confidence99) < nexthighest_mean){
			cout<< "Not confident about attempted password, try a shorter guess?" <<endl;
		}
		return 0;

	}

    return 0;
}

static __inline__ uint64_t rdtsc()
{
	uint32_t hi, lo;
	__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
	return ((uint64_t)lo) | (((uint64_t)hi) << 32);
}

bool password_ok (const string &pwd)
{
	return pwd == "mypassword";
    //return strcmp(pwd.c_str(), "mypassword") == 0;
}

<|endoftext|>