<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_training.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file p9_mss_draminit_training.C
/// @brief Train dram
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <mss.H>

#include <p9_mss_draminit_training.H>
#include <lib/utils/count_dimm.H>
#include <lib/shared/mss_const.H>
#include <lib/workarounds/dp16_workarounds.H>
#include <lib/fir/unmask.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_MCA;

extern "C"
{
    ///
    /// @brief Train dram
    /// @param[in] i_target, the McBIST of the ports of the dram you're training
    /// @param[in] i_special_training, optional CAL_STEP_ENABLE override. Used in sim, debug
    /// @param[in] i_abort_on_error, optional CAL_ABORT_ON_ERROR override. Used in sim, debug
    /// @return FAPI2_RC_SUCCESS iff ok
    ///
    fapi2::ReturnCode p9_mss_draminit_training( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target,
            const uint16_t i_special_training,
            const uint8_t i_abort_on_error)
    {
        // Keep track of the last error seen by a port
        fapi2::ReturnCode l_port_error = fapi2::FAPI2_RC_SUCCESS;
        fapi2::buffer<uint16_t> l_cal_steps_enabled = i_special_training;

        FAPI_INF("Start draminit training");

        // If there are no DIMM we don't need to bother. In fact, we can't as we didn't setup
        // attributes for the PHY, etc.
        if (mss::count_dimm(i_target) == 0)
        {
            FAPI_INF("... skipping draminit_training %s - no DIMM ...", mss::c_str(i_target));
            return fapi2::FAPI2_RC_SUCCESS;
        }

        uint8_t l_reset_disable = 0;
        FAPI_TRY( mss::mrw_reset_delay_before_cal(l_reset_disable) );

        // Configure the CCS engine.
        {
            fapi2::buffer<uint64_t> l_ccs_config;

            FAPI_TRY( mss::ccs::read_mode(i_target, l_ccs_config) );

            // It's unclear if we want to run with this true or false. Right now (10/15) this
            // has to be false. Shelton was unclear if this should be on or off in general BRS
            mss::ccs::stop_on_err(i_target, l_ccs_config, mss::LOW);
            mss::ccs::ue_disable(i_target, l_ccs_config, mss::LOW);
            mss::ccs::copy_cke_to_spare_cke(i_target, l_ccs_config, mss::HIGH);
            mss::ccs::parity_after_cmd(i_target, l_ccs_config, mss::HIGH);

            // Hm. Centaur sets this up for the longest duration possible. Can we do better?
            mss::ccs::cal_count(i_target, l_ccs_config, ~0, ~0);
            FAPI_TRY( mss::ccs::write_mode(i_target, l_ccs_config) );
        }

        // Clean out any previous calibration results, set bad-bits and configure the ranks.
        FAPI_DBG("MCA's on this McBIST: %d", mss::find_targets<TARGET_TYPE_MCA>(i_target).size());

        for( const auto& p : mss::find_targets<TARGET_TYPE_MCA>(i_target))
        {
            // Keep track of the last error seen by a rank pair
            fapi2::ReturnCode l_rank_pair_error = fapi2::FAPI2_RC_SUCCESS;

            // Returned from set_rank_pairs, it tells us how many rank pairs
            // we configured on this port.
            std::vector<uint64_t> l_pairs;

            FAPI_TRY( mss::putScom(p, MCA_DDRPHY_PC_INIT_CAL_ERROR_P0, 0) );
            FAPI_TRY( mss::putScom(p, MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0, 0) );

            // Disable port fails as it doesn't appear the MC handles initial cal timeouts
            // correctly (cal_length.) BRS, see conversation with Brad Michael
            FAPI_TRY( mss::change_port_fail_disable(p, mss::ON ) );

            // The following registers must be configured to the correct operating environment:

            // These are reset in phy_scominit
            // Section 5.2.5.10 SEQ ODT Write Configuration {0-3} on page 422
            // Section 5.2.6.1 WC Configuration 0 Register on page 434
            // Section 5.2.6.2 WC Configuration 1 Register on page 436
            // Section 5.2.6.3 WC Configuration 2 Register on page 438

            // Get our rank pairs.
            FAPI_TRY( mss::rank::get_rank_pairs(p, l_pairs) );

            // Setup the config register
            //
            // Grab the attribute which contains the information on what cal steps we should run
            // if the i_specal_training bits have not been specified.
            // TODO RTC:166422 update training code to set cal step enable and consume it everywhere locally
            if (i_special_training == 0)
            {
                FAPI_TRY( mss::cal_step_enable(p, l_cal_steps_enabled) );
            }

            FAPI_DBG("cal steps enabled: 0x%x special training: 0x%x", l_cal_steps_enabled, i_special_training);

            // Check to see if we're supposed to reset the delay values before starting training
            // don't reset if we're running special training - assumes there's a checkpoint which has valid state.
            if ((l_reset_disable == fapi2::ENUM_ATTR_MSS_MRW_RESET_DELAY_BEFORE_CAL_YES) && (i_special_training == 0))
            {
                FAPI_INF("resetting delay values before cal %s", mss::c_str(p));
                FAPI_TRY( mss::dp16::reset_delay_values(p, l_pairs) );
            }

            FAPI_DBG("generating calibration CCS instructions: %d rank-pairs", l_pairs.size());

            // For each rank pair we need to calibrate, pop a ccs instruction in an array and execute it.
            // NOTE: IF YOU CALIBRATE MORE THAN ONE RANK PAIR PER CCS PROGRAM, MAKE SURE TO CHANGE
            // THE PROCESSING OF THE ERRORS. (it's hard to figure out which DIMM failed, too) BRS.
            for (const auto& rp : l_pairs)
            {
                uint8_t cal_abort_on_error = i_abort_on_error;

                if (i_abort_on_error == CAL_ABORT_SENTINAL)
                {
                    FAPI_TRY( mss::cal_abort_on_error(cal_abort_on_error) );
                }

                // Execute selected cal steps
                FAPI_TRY( mss::setup_and_execute_cal(p, rp, l_cal_steps_enabled, i_abort_on_error) );

                // Conducts workarounds after training if needed
                FAPI_TRY( mss::workarounds::dp16::post_training_workarounds( p, l_cal_steps_enabled ) );

                // If we're aborting on error we can just FAPI_TRY. If we're not, we don't want to exit if there's
                // an error but we want to log the error and keep on keeping on.
                if ((fapi2::current_err = mss::process_initial_cal_errors(p)) != fapi2::FAPI2_RC_SUCCESS)
                {
                    fapi2::logError(fapi2::current_err);

                    if (cal_abort_on_error)
                    {
                        goto fapi_try_exit;
                    }

                    // Keep tack of the last cal error we saw.
                    l_rank_pair_error = fapi2::current_err;
                }
            }

            // Once we've trained all the rank pairs we can record the bad bits in the attributes if we have an error
            // This error is the most recent error seen on a port, too, so we keep track of that.
            if (l_rank_pair_error != fapi2::FAPI2_RC_SUCCESS)
            {
                FAPI_TRY( mss::dp16::record_bad_bits(p) );
                l_port_error = l_rank_pair_error;
            }
        }

        // So we're calibrated the entire port. If we're here either we didn't have any errors or the last error
        // seen on a port is the error for this entire controller.
        FAPI_TRY(l_port_error, "Seeing port error, exiting training");

        // Unmask FIR
        FAPI_TRY( mss::unmask::after_draminit_training(i_target) );

    fapi_try_exit:
        FAPI_INF("End draminit training");
        return fapi2::current_err;
    }
}
<commit_msg>L3 procedure work for p9_mss_draminit_training<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_training.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file p9_mss_draminit_training.C
/// @brief Train dram
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <mss.H>

#include <p9_mss_draminit_training.H>
#include <lib/utils/count_dimm.H>
#include <lib/shared/mss_const.H>
#include <lib/workarounds/dp16_workarounds.H>
#include <lib/fir/unmask.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_MCA;

extern "C"
{
    ///
    /// @brief Train dram
    /// @param[in] i_target, the McBIST of the ports of the dram you're training
    /// @param[in] i_special_training, optional CAL_STEP_ENABLE override. Used in sim, debug
    /// @param[in] i_abort_on_error, optional CAL_ABORT_ON_ERROR override. Used in sim, debug
    /// @return FAPI2_RC_SUCCESS iff ok
    ///
    fapi2::ReturnCode p9_mss_draminit_training( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target,
            const uint16_t i_special_training,
            const uint8_t i_abort_on_error)
    {
        // Keep track of the last error seen by a port
        fapi2::ReturnCode l_port_error = fapi2::FAPI2_RC_SUCCESS;
        fapi2::buffer<uint16_t> l_cal_steps_enabled = i_special_training;

        FAPI_INF("Start draminit training");

        // If there are no DIMM we don't need to bother. In fact, we can't as we didn't setup
        // attributes for the PHY, etc.
        if (mss::count_dimm(i_target) == 0)
        {
            FAPI_INF("... skipping draminit_training %s - no DIMM ...", mss::c_str(i_target));
            return fapi2::FAPI2_RC_SUCCESS;
        }

        uint8_t l_reset_disable = 0;
        FAPI_TRY( mss::mrw_reset_delay_before_cal(l_reset_disable) );

        // Configure the CCS engine.
        {
            fapi2::buffer<uint64_t> l_ccs_config;

            FAPI_TRY( mss::ccs::read_mode(i_target, l_ccs_config) );

            // It's unclear if we want to run with this true or false. Right now (10/15) this
            // has to be false. Shelton was unclear if this should be on or off in general BRS
            mss::ccs::stop_on_err(i_target, l_ccs_config, mss::LOW);
            mss::ccs::ue_disable(i_target, l_ccs_config, mss::LOW);
            mss::ccs::copy_cke_to_spare_cke(i_target, l_ccs_config, mss::HIGH);
            mss::ccs::parity_after_cmd(i_target, l_ccs_config, mss::HIGH);

            // Hm. Centaur sets this up for the longest duration possible. Can we do better?
            mss::ccs::cal_count(i_target, l_ccs_config, ~0, ~0);
            FAPI_TRY( mss::ccs::write_mode(i_target, l_ccs_config) );
        }

        // Clean out any previous calibration results, set bad-bits and configure the ranks.
        FAPI_DBG("%s MCA's on this McBIST: %d", mss::c_str(i_target), mss::find_targets<TARGET_TYPE_MCA>(i_target).size());

        for( const auto& p : mss::find_targets<TARGET_TYPE_MCA>(i_target))
        {
            // Keep track of the last error seen by a rank pair
            fapi2::ReturnCode l_rank_pair_error = fapi2::FAPI2_RC_SUCCESS;

            // Returned from set_rank_pairs, it tells us how many rank pairs
            // we configured on this port.
            std::vector<uint64_t> l_pairs;

            FAPI_TRY( mss::putScom(p, MCA_DDRPHY_PC_INIT_CAL_ERROR_P0, 0) );
            FAPI_TRY( mss::putScom(p, MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0, 0) );

            // Disable port fails as it doesn't appear the MC handles initial cal timeouts
            // correctly (cal_length.) BRS, see conversation with Brad Michael
            FAPI_TRY( mss::change_port_fail_disable(p, mss::ON ) );

            // The following registers must be configured to the correct operating environment:

            // These are reset in phy_scominit
            // Section 5.2.5.10 SEQ ODT Write Configuration {0-3} on page 422
            // Section 5.2.6.1 WC Configuration 0 Register on page 434
            // Section 5.2.6.2 WC Configuration 1 Register on page 436
            // Section 5.2.6.3 WC Configuration 2 Register on page 438

            // Get our rank pairs.
            FAPI_TRY( mss::rank::get_rank_pairs(p, l_pairs) );

            // Setup the config register
            //
            // Grab the attribute which contains the information on what cal steps we should run
            // if the i_specal_training bits have not been specified.
            // TODO RTC:166422 update training code to set cal step enable and consume it everywhere locally
            if (i_special_training == 0)
            {
                FAPI_TRY( mss::cal_step_enable(p, l_cal_steps_enabled) );
            }

            FAPI_DBG("cal steps enabled: 0x%x special training: 0x%x", l_cal_steps_enabled, i_special_training);

            // Check to see if we're supposed to reset the delay values before starting training
            // don't reset if we're running special training - assumes there's a checkpoint which has valid state.
            if ((l_reset_disable == fapi2::ENUM_ATTR_MSS_MRW_RESET_DELAY_BEFORE_CAL_YES) && (i_special_training == 0))
            {
                FAPI_INF("resetting delay values before cal %s", mss::c_str(p));
                FAPI_TRY( mss::dp16::reset_delay_values(p, l_pairs) );
            }

            FAPI_DBG("generating calibration CCS instructions: %d rank-pairs", l_pairs.size());

            // For each rank pair we need to calibrate, pop a ccs instruction in an array and execute it.
            // NOTE: IF YOU CALIBRATE MORE THAN ONE RANK PAIR PER CCS PROGRAM, MAKE SURE TO CHANGE
            // THE PROCESSING OF THE ERRORS. (it's hard to figure out which DIMM failed, too) BRS.
            for (const auto& rp : l_pairs)
            {
                uint8_t cal_abort_on_error = i_abort_on_error;

                if (i_abort_on_error == CAL_ABORT_SENTINAL)
                {
                    FAPI_TRY( mss::cal_abort_on_error(cal_abort_on_error) );
                }

                // Execute selected cal steps
                FAPI_TRY( mss::setup_and_execute_cal(p, rp, l_cal_steps_enabled, i_abort_on_error) );

                // Conducts workarounds after training if needed
                FAPI_TRY( mss::workarounds::dp16::post_training_workarounds( p, l_cal_steps_enabled ) );

                // If we're aborting on error we can just FAPI_TRY. If we're not, we don't want to exit if there's
                // an error but we want to log the error and keep on keeping on.
                if ((fapi2::current_err = mss::process_initial_cal_errors(p)) != fapi2::FAPI2_RC_SUCCESS)
                {
                    fapi2::logError(fapi2::current_err);

                    if (cal_abort_on_error)
                    {
                        goto fapi_try_exit;
                    }

                    // Keep tack of the last cal error we saw.
                    l_rank_pair_error = fapi2::current_err;
                }
            }

            // Once we've trained all the rank pairs we can record the bad bits in the attributes if we have an error
            // This error is the most recent error seen on a port, too, so we keep track of that.
            if (l_rank_pair_error != fapi2::FAPI2_RC_SUCCESS)
            {
                FAPI_TRY( mss::dp16::record_bad_bits(p) );
                l_port_error = l_rank_pair_error;
            }
        }

        // So we're calibrated the entire port. If we're here either we didn't have any errors or the last error
        // seen on a port is the error for this entire controller.
        FAPI_TRY(l_port_error, "Seeing port error, exiting training");

        // Unmask FIR
        FAPI_TRY( mss::unmask::after_draminit_training(i_target) );

    fapi_try_exit:
        FAPI_INF("End draminit training");
        return fapi2::current_err;
    }
}
<|endoftext|>


<commit_before>#include <stutter/http/parser.h>
#include <stutter/http/message.h>
#include <stutter/http/request.h>
#include <stutter/http/reply.h>
#include <stutter/http/joyent/http_parser.h>

#include <string.h>
#include <cstdlib>
#include <iostream>

using namespace std;
using http::Parser;

#define MAX_UPLOAD_SIZE (1024*1024)
#define MAX_URI_LENGTH  (4096)

/* http-parser callbacks */

namespace http {
int
_http_on_url_cb(http_parser *p, const char *at, size_t sz)
{
	Parser *parser = reinterpret_cast<Parser*>(p->data);
	parser->add_url_fragment(at, sz);
	return 0;
}

int
_http_on_message_complete_cb(http_parser *p)
{
	Parser *parser = reinterpret_cast<Parser*>(p->data);
	parser->callback();
	return 0;
}

int
_http_on_header_field_cb(http_parser *p, const char *at, size_t sz)
{
	Parser *parser = reinterpret_cast<Parser*>(p->data);
	parser->save_last_header();
	parser->m_header_key.append(at, sz);
	return 0;
}

int
_http_on_header_value_cb(http_parser *p, const char *at, size_t sz)
{
	Parser *parser = reinterpret_cast<Parser*>(p->data);
	parser->m_header_val.append(at, sz);
	parser->m_header_gotval = true;
	return 0;
}

int
_http_on_body_cb(http_parser *p, const char *at, size_t sz)
{
	Parser *parser = reinterpret_cast<Parser*>(p->data);
	parser->add_body_fragment(at, sz);
	return 0;
}

int
_http_on_headers_complete_cb(http_parser *p)
{
	Parser *parser = reinterpret_cast<Parser*>(p->data);
	return parser->save_last_header();
}
}

int
Parser::save_last_header()
{
	if (m_header_gotval) {
		m_msg->add_header(m_header_key, m_header_val);

		m_header_key.clear();
		m_header_val.clear();
		m_header_gotval = false;
	}

	// check for large uploads
	if (m_mode == REQUEST) {
		string cl = m_request->get_header(Message::ContentLength);
		long sz = ::atol(cl.c_str());
		if (sz < 0 || sz > MAX_UPLOAD_SIZE) {
			m_error = PARSE_BODY_TOO_LARGE;
			return 0;
		}
	}

	// 100-continue
	if (m_mode == REQUEST && m_request->get_header(Message::Expect)
			== Message::OneHundredContinue) {
		m_error = PARSE_NEED_100_CONTINUE;
		return 0;
	}

	return 0;
}

void
Parser::add_url_fragment(const char *p, size_t sz)
{
	if (m_mode == REQUEST && m_error != PARSE_URI_TOO_LONG) {
		if (m_request->url().size() + sz > MAX_URI_LENGTH) {
			m_error = PARSE_URI_TOO_LONG;
		} else {
			m_request->add_url_fragment(p, sz);
		}
	}
}

void
Parser::add_body_fragment(const char *at, size_t sz)
{
	if (m_error != PARSE_BODY_TOO_LARGE)
		m_msg->add_body(at, sz);
}

void
Parser::callback()
{
	switch (m_mode) {
		case REQUEST: // handle Verb
			switch(m_parser->method) {
				case HTTP_GET:    m_request->set_verb(Request::GET);    break;
				case HTTP_POST:   m_request->set_verb(Request::POST);   break;
				case HTTP_PUT:    m_request->set_verb(Request::PUT);    break;
				case HTTP_HEAD:   m_request->set_verb(Request::HEAD);   break;
				case HTTP_DELETE: m_request->set_verb(Request::DELETE); break;
				default: break;
			}
			break;

		case RESPONSE: // handle status code
			// TODO: handle status line
			m_reply->set_status(m_parser->status_code, "");
			break;
	}

	m_fun(m_fun_data);
}

Parser::Parser(Mode m, http::Request *request, void (*fun)(void*), void *ptr)
	: m_mode(m)
	, m_request(request)
	, m_reply(0)
	, m_msg(m_request)
	, m_fun(fun)
	, m_fun_data(ptr)
{
	m_parser = new http_parser;
	m_parserconf = new http_parser_settings;
	reset();
}

Parser::Parser(Mode m, http::Reply *reply, void (*fun)(void*), void *ptr)
	: m_mode(m)
	, m_request(0)
	, m_reply(reply)
	, m_msg(m_reply)
	, m_fun(fun)
	, m_fun_data(ptr)
{
	m_parser = new http_parser;
	m_parserconf = new http_parser_settings;
	reset();
}

Parser::~Parser()
{
	delete m_parserconf;
	delete m_parser;
}

Parser::Error
Parser::add(const char *p, size_t sz)
{
	size_t nparsed = http_parser_execute(m_parser, m_parserconf, p, sz);
	if (nparsed == sz)
		return m_error;
	return PARSE_FAILURE; // invalid HTTP
}

Parser::Error
Parser::error() const
{
	return m_error;
}

void
Parser::reset()
{
	// parser
	http_parser_init(m_parser, (m_mode == REQUEST ? HTTP_REQUEST : HTTP_RESPONSE));
	m_parser->data = reinterpret_cast<void*>(this);

	// callback config
	memset(m_parserconf, 0, sizeof(m_parserconf));
	m_parserconf->on_url = _http_on_url_cb;
	m_parserconf->on_message_complete = _http_on_message_complete_cb;
	m_parserconf->on_header_field = _http_on_header_field_cb;
	m_parserconf->on_header_value = _http_on_header_value_cb;
	m_parserconf->on_headers_complete = _http_on_headers_complete_cb;
	m_parserconf->on_body = _http_on_body_cb;

	// http data
	m_header_key.clear();
	m_header_val.clear();
	m_header_gotval = false;
	m_error = PARSE_OK;
}

<commit_msg>Backed out changeset 0b771f478af5<commit_after>#include <stutter/http/parser.h>
#include <stutter/http/message.h>
#include <stutter/http/request.h>
#include <stutter/http/reply.h>
#include <stutter/http/joyent/http_parser.h>

#include <string.h>
#include <cstdlib>
#include <iostream>

using namespace std;
using http::Parser;

#define MAX_UPLOAD_SIZE (1024*1024)
#define MAX_URI_LENGTH  (4096)

/* http-parser callbacks */

namespace http {
int
_http_on_url_cb(http_parser *p, const char *at, size_t sz)
{
	Parser *parser = reinterpret_cast<Parser*>(p->data);
	parser->add_url_fragment(at, sz);
	return 0;
}

int
_http_on_message_complete_cb(http_parser *p)
{
	Parser *parser = reinterpret_cast<Parser*>(p->data);
	parser->callback();
	return 0;
}

int
_http_on_header_field_cb(http_parser *p, const char *at, size_t sz)
{
	Parser *parser = reinterpret_cast<Parser*>(p->data);
	parser->save_last_header();
	parser->m_header_key.append(at, sz);
	return 0;
}

int
_http_on_header_value_cb(http_parser *p, const char *at, size_t sz)
{
	Parser *parser = reinterpret_cast<Parser*>(p->data);
	parser->m_header_val.append(at, sz);
	parser->m_header_gotval = true;
	return 0;
}

int
_http_on_body_cb(http_parser *p, const char *at, size_t sz)
{
	Parser *parser = reinterpret_cast<Parser*>(p->data);
	parser->add_body_fragment(at, sz);
	return 0;
}

int
_http_on_headers_complete_cb(http_parser *p)
{
	Parser *parser = reinterpret_cast<Parser*>(p->data);
	return parser->save_last_header();
}
}

int
Parser::save_last_header()
{
	if (m_header_gotval) {
		m_msg->add_header(m_header_key, m_header_val);

		m_header_key.clear();
		m_header_val.clear();
		m_header_gotval = false;
	}

	// check for large uploads
	if (m_mode == REQUEST) {
		string cl = m_request->get_header(Message::ContentLength);
		long sz = ::atol(cl.c_str());
		if (sz < 0 || sz > MAX_UPLOAD_SIZE) {
			m_error = PARSE_BODY_TOO_LARGE;
			return 0;
		}
	}

	// 100-continue
	if (m_mode == REQUEST && m_request->get_header(Message::Expect)
			== Message::OneHundredContinue) {
		m_error = PARSE_NEED_100_CONTINUE;
		return 0;
	}

	return 0;
}

void
Parser::add_url_fragment(const char *p, size_t sz)
{
	if (m_mode == REQUEST && m_error != PARSE_URI_TOO_LONG) {
		if (m_request->url().size() + sz > MAX_URI_LENGTH) {
			m_error = PARSE_URI_TOO_LONG;
		} else {
			m_request->add_url_fragment(p, sz);
		}
	}
}

void
Parser::add_body_fragment(const char *at, size_t sz)
{
	if (m_error != PARSE_BODY_TOO_LARGE)
		m_msg->add_body(at, sz);
}

void
Parser::callback()
{
	switch (m_mode) {
		case REQUEST: // handle Verb
			switch(m_parser->method) {
				case HTTP_GET:    m_request->set_verb(Request::GET);    break;
				case HTTP_POST:   m_request->set_verb(Request::POST);   break;
				case HTTP_PUT:    m_request->set_verb(Request::PUT);    break;
				case HTTP_HEAD:   m_request->set_verb(Request::HEAD);   break;
				case HTTP_DELETE: m_request->set_verb(Request::DELETE); break;
				default: break;
			}
			break;

		case RESPONSE: // handle status code
			// TODO: handle status line
			m_reply->set_status(m_parser->status_code, "");
			break;
	}

	m_fun(m_fun_data);
}

Parser::Parser(Mode m, http::Request *request, void (*fun)(void*), void *ptr)
	: m_mode(m)
	, m_request(request)
	, m_reply(0)
	, m_msg(m_request)
	, m_fun(fun)
	, m_fun_data(ptr)
{
	m_parser = new http_parser;
	m_parserconf = new http_parser_settings;
	reset();
}

Parser::Parser(Mode m, http::Reply *reply, void (*fun)(void*), void *ptr)
	: m_mode(m)
	, m_request(0)
	, m_reply(reply)
	, m_msg(m_reply)
	, m_fun(fun)
	, m_fun_data(ptr)
{
	m_parser = new http_parser;
	m_parserconf = new http_parser_settings;
	reset();
}

Parser::~Parser()
{
	delete m_parserconf;
	delete m_parser;
}

Parser::Error
Parser::add(const char *p, size_t sz)
{
	m_error = PARSE_OK; // reset error state

	size_t nparsed = http_parser_execute(m_parser, m_parserconf, p, sz);
	if (nparsed == sz)
		return m_error;
	return PARSE_FAILURE; // invalid HTTP
}

Parser::Error
Parser::error() const
{
	return m_error;
}

void
Parser::reset()
{
	// parser
	http_parser_init(m_parser, (m_mode == REQUEST ? HTTP_REQUEST : HTTP_RESPONSE));
	m_parser->data = reinterpret_cast<void*>(this);

	// callback config
	memset(m_parserconf, 0, sizeof(m_parserconf));
	m_parserconf->on_url = _http_on_url_cb;
	m_parserconf->on_message_complete = _http_on_message_complete_cb;
	m_parserconf->on_header_field = _http_on_header_field_cb;
	m_parserconf->on_header_value = _http_on_header_value_cb;
	m_parserconf->on_headers_complete = _http_on_headers_complete_cb;
	m_parserconf->on_body = _http_on_body_cb;

	// http data
	m_header_key.clear();
	m_header_val.clear();
	m_header_gotval = false;
	m_error = PARSE_OK;
}

<|endoftext|>


<commit_before>#include "kernel.h"
#include "raster.h"
#include "connectorinterface.h"
#include "symboltable.h"
#include "ilwisoperation.h"

#include <QThread>
using namespace Ilwis;

OperationHelperRaster::OperationHelperRaster()
{
}

Box3D<qint32> OperationHelperRaster::initialize(const IRasterCoverage &inputRaster, IRasterCoverage &outputRaster, const Parameter& parm, quint64 what)
{
    Resource resource(itRASTER);
    Size sz = inputRaster->size();
    Box3D<qint32> box(sz);

    if ( what & itRASTERSIZE) {
        resource.addProperty("size", IVARIANT(sz));
    }
    if ( what & itENVELOPE) {
        if ( box.isNull() || !box.isValid()) {
            sz = inputRaster->size();
            box  = Box3D<qint32>(sz);
        }
        Box2D<double> bounds = inputRaster->georeference()->pixel2Coord(box);
        resource.addProperty("envelope", IVARIANT(bounds));
    }
    if ( what & itCOORDSYSTEM) {
        resource.addProperty("coordinatesystem", IVARIANT(inputRaster->coordinateSystem()));
    }

    if ( what & itGEOREF) {
        if ( box.isNull() || !box.isValid()) {
            sz = inputRaster->size();
            box  = Box3D<qint32>(sz);
        }
        if ( sz.xsize() == box.xlength() && sz.ysize() == box.ylength())
            resource.addProperty("georeference", IVARIANT(inputRaster->georeference()));
    }
    if ( what & itDOMAIN) {
        resource.addProperty("domain", IVARIANT(inputRaster->datadef().domain()));
    }
    resource.prepare();

    outputRaster.prepare(resource);
    if ( what & itTABLE) {
        if ( inputRaster->attributeTable().isValid())    {
            if ( inputRaster->datadef().domain() == outputRaster->datadef().domain()) {
                if ( outputRaster.isValid())
                    outputRaster->attributeTable(inputRaster->attributeTable());
            }
        }
    }

    return box;
}

IIlwisObject OperationHelperRaster::initialize(const IIlwisObject &inputObject, IlwisTypes tp, quint64 what)
{
    Resource resource(tp);
    if (inputObject->ilwisType() & itCOVERAGE) {
        if (inputObject->ilwisType() == itRASTER) {
            IRasterCoverage gcInput = inputObject.get<RasterCoverage>();
            if ( what & itRASTERSIZE) {
                Size sz = gcInput->size();
                Box3D<qint32> box(sz);
                resource.addProperty("size", IVARIANT(box.size()));
            }
            if ( what & itGEOREF) {
                resource.addProperty("georeference", IVARIANT(gcInput->georeference()));
            }
        }
     }

    resource.prepare();
    IIlwisObject obj;
    obj.prepare(resource);
    if (inputObject->ilwisType() & itCOVERAGE) {
        OperationHelper::initialize(inputObject, obj, tp, what);
    }

    return obj;
}

int OperationHelperRaster::subdivideTasks(ExecutionContext *ctx,const IRasterCoverage& raster, const Box3D<qint32> &bnds, std::vector<Box3D<qint32> > &boxes)
{
    if ( !raster.isValid() || raster->size().isNull() || raster->size().ysize() == 0) {
        return ERROR1(ERR_NO_INITIALIZED_1, "Grid size");
        return iUNDEF;
    }

    int cores = std::min(QThread::idealThreadCount(),raster->size().ysize());
    if (raster->size().totalSize() < 10000 || ctx->_threaded == false)
        cores = 1;

    boxes.clear();
    boxes.resize(cores);
    Box3D<qint32> bounds = bnds;
    if ( bounds.isNull())
        bounds = Box3D<qint32>(raster->size());
    int left = 0; //bounds.min_corner().x();
    int right = bounds.size().xsize();
    int top = bounds.size().ysize();
    int step = bounds.size().ysize() / cores;
    int currentY = 0;

    for(int i=0 ; i < cores; ++i){
        Box3D<qint32> smallBox(Voxel(left, currentY,0), Voxel(right - 1, std::min(top - 1,currentY + step),bounds.zlength()) );
        boxes[i] = smallBox;
        currentY = currentY + step  ;
    }
    return cores;
}

bool OperationHelperRaster::resample(IRasterCoverage& raster1, IRasterCoverage& raster2, ExecutionContext *ctx) {
    if ( !raster1.isValid())
        return false;

    IGeoReference commonGeoref = raster1->georeference();
    if ( ctx->_masterGeoref != sUNDEF) {
        if(!commonGeoref.prepare(ctx->_masterGeoref))
            return false;
    }
    if (raster1->georeference()!= commonGeoref ){
        Resource res;
        res.prepare();
        QString expr = QString("%3=resample(%1,%2,bicubic)").arg(raster1->source().url().toString()).arg(commonGeoref->source().url().toString()).arg(res.name());
        ExecutionContext ctxLocal;
        SymbolTable symtabLocal;
        if(!commandhandler()->execute(expr,&ctxLocal,symtabLocal))
            return false;
        QVariant var = symtabLocal.getValue(res.name());
        raster1 = var.value<IRasterCoverage>();
    }
    if ( raster2.isValid() && raster2->georeference()!= commonGeoref ){
        Resource res;
        res.prepare();
        QString expr = QString("%3=resample(%1,%2,bicubic)").arg(raster2->source().url().toString()).arg(commonGeoref->source().url().toString()).arg(res.name());
        ExecutionContext ctxLocal;
        SymbolTable symtabLocal;
        if(!commandhandler()->execute(expr,&ctxLocal,symtabLocal))
            return false;
        QVariant var = symtabLocal.getValue(res.name());
        raster2 = var.value<IRasterCoverage>();
    }
    return true;
}

<commit_msg>using assign method as the operator= might not be called and a copy constructor is called which is not wanted at this moment<commit_after>#include "kernel.h"
#include "raster.h"
#include "connectorinterface.h"
#include "symboltable.h"
#include "ilwisoperation.h"

#include <QThread>
using namespace Ilwis;

OperationHelperRaster::OperationHelperRaster()
{
}

Box3D<qint32> OperationHelperRaster::initialize(const IRasterCoverage &inputRaster, IRasterCoverage &outputRaster, const Parameter& parm, quint64 what)
{
    Resource resource(itRASTER);
    Size sz = inputRaster->size();
    Box3D<qint32> box(sz);

    if ( what & itRASTERSIZE) {
        resource.addProperty("size", IVARIANT(sz));
    }
    if ( what & itENVELOPE) {
        if ( box.isNull() || !box.isValid()) {
            sz = inputRaster->size();
            box  = Box3D<qint32>(sz);
        }
        Box2D<double> bounds = inputRaster->georeference()->pixel2Coord(box);
        resource.addProperty("envelope", IVARIANT(bounds));
    }
    if ( what & itCOORDSYSTEM) {
        resource.addProperty("coordinatesystem", IVARIANT(inputRaster->coordinateSystem()));
    }

    if ( what & itGEOREF) {
        if ( box.isNull() || !box.isValid()) {
            sz = inputRaster->size();
            box  = Box3D<qint32>(sz);
        }
        if ( sz.xsize() == box.xlength() && sz.ysize() == box.ylength())
            resource.addProperty("georeference", IVARIANT(inputRaster->georeference()));
    }
    if ( what & itDOMAIN) {
        resource.addProperty("domain", IVARIANT(inputRaster->datadef().domain()));
    }
    resource.prepare();

    outputRaster.prepare(resource);
    if ( what & itTABLE) {
        if ( inputRaster->attributeTable().isValid())    {
            if ( inputRaster->datadef().domain() == outputRaster->datadef().domain()) {
                if ( outputRaster.isValid())
                    outputRaster->attributeTable(inputRaster->attributeTable());
            }
        }
    }

    return box;
}

IIlwisObject OperationHelperRaster::initialize(const IIlwisObject &inputObject, IlwisTypes tp, quint64 what)
{
    Resource resource(tp);
    if (inputObject->ilwisType() & itCOVERAGE) {
        if (inputObject->ilwisType() == itRASTER) {
            IRasterCoverage gcInput = inputObject.get<RasterCoverage>();
            if ( what & itRASTERSIZE) {
                Size sz = gcInput->size();
                Box3D<qint32> box(sz);
                resource.addProperty("size", IVARIANT(box.size()));
            }
            if ( what & itGEOREF) {
                resource.addProperty("georeference", IVARIANT(gcInput->georeference()));
            }
        }
     }

    resource.prepare();
    IIlwisObject obj;
    obj.prepare(resource);
    if (inputObject->ilwisType() & itCOVERAGE) {
        OperationHelper::initialize(inputObject, obj, tp, what);
    }

    return obj;
}

int OperationHelperRaster::subdivideTasks(ExecutionContext *ctx,const IRasterCoverage& raster, const Box3D<qint32> &bnds, std::vector<Box3D<qint32> > &boxes)
{
    if ( !raster.isValid() || raster->size().isNull() || raster->size().ysize() == 0) {
        return ERROR1(ERR_NO_INITIALIZED_1, "Grid size");
        return iUNDEF;
    }

    int cores = std::min(QThread::idealThreadCount(),raster->size().ysize());
    if (raster->size().totalSize() < 10000 || ctx->_threaded == false)
        cores = 1;

    boxes.clear();
    boxes.resize(cores);
    Box3D<qint32> bounds = bnds;
    if ( bounds.isNull())
        bounds = Box3D<qint32>(raster->size());
    int left = 0; //bounds.min_corner().x();
    int right = bounds.size().xsize();
    int top = bounds.size().ysize();
    int step = bounds.size().ysize() / cores;
    int currentY = 0;

    for(int i=0 ; i < cores; ++i){
        Box3D<qint32> smallBox(Voxel(left, currentY,0), Voxel(right - 1, std::min(top - 1,currentY + step),bounds.zlength()) );
        boxes[i] = smallBox;
        currentY = currentY + step  ;
    }
    return cores;
}

bool OperationHelperRaster::resample(IRasterCoverage& raster1, IRasterCoverage& raster2, ExecutionContext *ctx) {
    if ( !raster1.isValid())
        return false;

    IGeoReference commonGeoref = raster1->georeference();
    if ( ctx->_masterGeoref != sUNDEF) {
        if(!commonGeoref.prepare(ctx->_masterGeoref))
            return false;
    }
    if (raster1->georeference()!= commonGeoref ){
        Resource res;
        res.prepare();
        QString expr = QString("%3=resample(%1,%2,bicubic)").arg(raster1->source().url().toString()).arg(commonGeoref->source().url().toString()).arg(res.name());
        ExecutionContext ctxLocal;
        SymbolTable symtabLocal;
        if(!commandhandler()->execute(expr,&ctxLocal,symtabLocal))
            return false;
        QVariant var = symtabLocal.getValue(res.name());
        raster1 = var.value<IRasterCoverage>();
    }
    if ( raster2.isValid() && raster2->georeference()!= commonGeoref ){
        Resource res;
        res.prepare();
        QString expr = QString("%3=resample(%1,%2,bicubic)").arg(raster2->source().url().toString()).arg(commonGeoref->source().url().toString()).arg(res.name());
        ExecutionContext ctxLocal;
        SymbolTable symtabLocal;
        if(!commandhandler()->execute(expr,&ctxLocal,symtabLocal))
            return false;
        QVariant var = symtabLocal.getValue(res.name());
        IRasterCoverage outRaster = var.value<IRasterCoverage>();
        raster2.assign(outRaster);
    }
    return true;
}

<|endoftext|>


<commit_before>#include "kernel.h"
#include "raster.h"
#include "connectorinterface.h"
#include "symboltable.h"
#include "ilwisoperation.h"

#include <QThread>
using namespace Ilwis;

OperationHelperRaster::OperationHelperRaster()
{
}

BoundingBox OperationHelperRaster::initialize(const IRasterCoverage &inputRaster, IRasterCoverage &outputRaster, quint64 what)
{
    Resource resource(itRASTER);
    Size<> sz = inputRaster->size();
    BoundingBox box(sz);

    if ( what & itRASTERSIZE) {
        resource.addProperty("size", IVARIANT(sz));
    }
    if ( what & itENVELOPE) {
        if ( box.isNull() || !box.isValid()) {
            sz = inputRaster->size();
            box  = BoundingBox(sz);
        }
        Envelope bounds = inputRaster->georeference()->pixel2Coord(box);
        resource.addProperty("envelope", IVARIANT(bounds));
    }
    if ( what & itCOORDSYSTEM) {
        resource.addProperty("coordinatesystem", IVARIANT(inputRaster->coordinateSystem()));
    }

    if ( what & itGEOREF) {
        if ( box.isNull() || !box.isValid()) {
            sz = inputRaster->size();
            box  = BoundingBox(sz);
        }
        if ( sz.xsize() == box.xlength() && sz.ysize() == box.ylength())
            resource.addProperty("georeference", IVARIANT(inputRaster->georeference()));
    }
    if ( what & itDOMAIN) {
        resource.addProperty("domain", IVARIANT(inputRaster->datadef().domain<>()));
    }
    resource.prepare();

    outputRaster.prepare(resource);
    if ( what & itTABLE) {
        if ( inputRaster->attributeTable().isValid())    {
            if ( inputRaster->datadef().domain<>() == outputRaster->datadef().domain<>()) {
                if ( outputRaster.isValid())
                    outputRaster->attributeTable(inputRaster->attributeTable());
            }
        }
    }

    return box;
}

IIlwisObject OperationHelperRaster::initialize(const IIlwisObject &inputObject, IlwisTypes tp, quint64 what)
{
    Resource resource(tp);
    if (inputObject->ilwisType() & itCOVERAGE) {
        if (inputObject->ilwisType() == itRASTER) {
            IRasterCoverage gcInput = inputObject.as<RasterCoverage>();
            if ( what & itRASTERSIZE) {
                Size<> sz = gcInput->size();
                BoundingBox box(sz);
                resource.addProperty("size", IVARIANT(box.size()));
            }
            if ( what & itGEOREF) {
                resource.addProperty("georeference", IVARIANT(gcInput->georeference()));
            }
        }
     }

    resource.prepare();
    IIlwisObject obj;
    obj.prepare(resource);
    if (inputObject->ilwisType() & itCOVERAGE) {
        OperationHelper::initialize(inputObject, obj, tp, what);
    }

    return obj;
}

int OperationHelperRaster::subdivideTasks(ExecutionContext *ctx,const IRasterCoverage& raster, const BoundingBox &bnds, std::vector<BoundingBox > &boxes)
{
    if ( !raster.isValid() || raster->size().isNull() || raster->size().ysize() == 0) {
        return ERROR1(ERR_NO_INITIALIZED_1, "Grid size");
        return iUNDEF;
    }

    int cores = std::min(QThread::idealThreadCount(),(int)raster->size().ysize());
    if (raster->size().linearSize() < 10000 || ctx->_threaded == false)
        cores = 1;

    boxes.clear();
    boxes.resize(cores);
    BoundingBox bounds = bnds;
    if ( bounds.isNull())
        bounds = BoundingBox(raster->size());
    int left = 0; //bounds.min_corner().x;
    int right = bounds.size().xsize();
    int top = bounds.size().ysize();
    int step = bounds.size().ysize() / cores;
    int currentY = 0;

    for(int i=0 ; i < cores; ++i){
        BoundingBox smallBox(Pixel(left, currentY,0), Pixel(right - 1, std::min(top - 1,currentY + step),bounds.zlength()) );
        boxes[i] = smallBox;
        currentY = currentY + step  ;
    }
    return cores;
}

bool OperationHelperRaster::resample(IRasterCoverage& raster1, IRasterCoverage& raster2, ExecutionContext *ctx) {
    if ( !raster1.isValid())
        return false;

    IGeoReference commonGeoref = raster1->georeference();
    if ( ctx->_masterGeoref != sUNDEF) {
        if(!commonGeoref.prepare(ctx->_masterGeoref))
            return false;
    }
    if (raster1->georeference()!= commonGeoref ){
        Resource res;
        res.prepare();
        QString expr = QString("%3=resample(%1,%2,bicubic)").arg(raster1->source().url().toString()).arg(commonGeoref->source().url().toString()).arg(res.name());
        ExecutionContext ctxLocal;
        SymbolTable symtabLocal;
        if(!commandhandler()->execute(expr,&ctxLocal,symtabLocal))
            return false;
        QVariant var = symtabLocal.getValue(res.name());
        raster1 = var.value<IRasterCoverage>();
    }
    if ( raster2.isValid() && raster2->georeference()!= commonGeoref ){
        Resource res;
        res.prepare();
        QString expr = QString("%3=resample(%1,%2,bicubic)").arg(raster2->source().url().toString()).arg(commonGeoref->source().url().toString()).arg(res.name());
        ExecutionContext ctxLocal;
        SymbolTable symtabLocal;
        if(!commandhandler()->execute(expr,&ctxLocal,symtabLocal))
            return false;
        QVariant var = symtabLocal.getValue(res.name());
        IRasterCoverage outRaster = var.value<IRasterCoverage>();
        raster2.assign(outRaster);
    }
    return true;
}

<commit_msg>reordering includes<commit_after>#include "kernel.h"
#include "ilwisdata.h"
#include "datadefinition.h"
#include "columndefinition.h"
#include "attributedefinition.h"
#include "raster.h"
#include "connectorinterface.h"
#include "symboltable.h"
#include "ilwisoperation.h"

#include <QThread>
using namespace Ilwis;

OperationHelperRaster::OperationHelperRaster()
{
}

BoundingBox OperationHelperRaster::initialize(const IRasterCoverage &inputRaster, IRasterCoverage &outputRaster, quint64 what)
{
    Resource resource(itRASTER);
    Size<> sz = inputRaster->size();
    BoundingBox box(sz);

    if ( what & itRASTERSIZE) {
        resource.addProperty("size", IVARIANT(sz));
    }
    if ( what & itENVELOPE) {
        if ( box.isNull() || !box.isValid()) {
            sz = inputRaster->size();
            box  = BoundingBox(sz);
        }
        Envelope bounds = inputRaster->georeference()->pixel2Coord(box);
        resource.addProperty("envelope", IVARIANT(bounds));
    }
    if ( what & itCOORDSYSTEM) {
        resource.addProperty("coordinatesystem", IVARIANT(inputRaster->coordinateSystem()));
    }

    if ( what & itGEOREF) {
        if ( box.isNull() || !box.isValid()) {
            sz = inputRaster->size();
            box  = BoundingBox(sz);
        }
        if ( sz.xsize() == box.xlength() && sz.ysize() == box.ylength())
            resource.addProperty("georeference", IVARIANT(inputRaster->georeference()));
    }
    if ( what & itDOMAIN) {
        resource.addProperty("domain", IVARIANT(inputRaster->datadef().domain<>()));
    }
    resource.prepare();

    outputRaster.prepare(resource);
    if ( what & itTABLE) {
        if ( inputRaster->attributeTable().isValid())    {
            if ( inputRaster->datadef().domain<>() == outputRaster->datadef().domain<>()) {
                if ( outputRaster.isValid())
                    outputRaster->attributeTable(inputRaster->attributeTable());
            }
        }
    }

    return box;
}

IIlwisObject OperationHelperRaster::initialize(const IIlwisObject &inputObject, IlwisTypes tp, quint64 what)
{
    Resource resource(tp);
    if (inputObject->ilwisType() & itCOVERAGE) {
        if (inputObject->ilwisType() == itRASTER) {
            IRasterCoverage gcInput = inputObject.as<RasterCoverage>();
            if ( what & itRASTERSIZE) {
                Size<> sz = gcInput->size();
                BoundingBox box(sz);
                resource.addProperty("size", IVARIANT(box.size()));
            }
            if ( what & itGEOREF) {
                resource.addProperty("georeference", IVARIANT(gcInput->georeference()));
            }
        }
     }

    resource.prepare();
    IIlwisObject obj;
    obj.prepare(resource);
    if (inputObject->ilwisType() & itCOVERAGE) {
        OperationHelper::initialize(inputObject, obj, tp, what);
    }

    return obj;
}

int OperationHelperRaster::subdivideTasks(ExecutionContext *ctx,const IRasterCoverage& raster, const BoundingBox &bnds, std::vector<BoundingBox > &boxes)
{
    if ( !raster.isValid() || raster->size().isNull() || raster->size().ysize() == 0) {
        return ERROR1(ERR_NO_INITIALIZED_1, "Grid size");
        return iUNDEF;
    }

    int cores = std::min(QThread::idealThreadCount(),(int)raster->size().ysize());
    if (raster->size().linearSize() < 10000 || ctx->_threaded == false)
        cores = 1;

    boxes.clear();
    boxes.resize(cores);
    BoundingBox bounds = bnds;
    if ( bounds.isNull())
        bounds = BoundingBox(raster->size());
    int left = 0; //bounds.min_corner().x;
    int right = bounds.size().xsize();
    int top = bounds.size().ysize();
    int step = bounds.size().ysize() / cores;
    int currentY = 0;

    for(int i=0 ; i < cores; ++i){
        BoundingBox smallBox(Pixel(left, currentY,0), Pixel(right - 1, std::min(top - 1,currentY + step),bounds.zlength()) );
        boxes[i] = smallBox;
        currentY = currentY + step  ;
    }
    return cores;
}

bool OperationHelperRaster::resample(IRasterCoverage& raster1, IRasterCoverage& raster2, ExecutionContext *ctx) {
    if ( !raster1.isValid())
        return false;

    IGeoReference commonGeoref = raster1->georeference();
    if ( ctx->_masterGeoref != sUNDEF) {
        if(!commonGeoref.prepare(ctx->_masterGeoref))
            return false;
    }
    if (raster1->georeference()!= commonGeoref ){
        Resource res;
        res.prepare();
        QString expr = QString("%3=resample(%1,%2,bicubic)").arg(raster1->source().url().toString()).arg(commonGeoref->source().url().toString()).arg(res.name());
        ExecutionContext ctxLocal;
        SymbolTable symtabLocal;
        if(!commandhandler()->execute(expr,&ctxLocal,symtabLocal))
            return false;
        QVariant var = symtabLocal.getValue(res.name());
        raster1 = var.value<IRasterCoverage>();
    }
    if ( raster2.isValid() && raster2->georeference()!= commonGeoref ){
        Resource res;
        res.prepare();
        QString expr = QString("%3=resample(%1,%2,bicubic)").arg(raster2->source().url().toString()).arg(commonGeoref->source().url().toString()).arg(res.name());
        ExecutionContext ctxLocal;
        SymbolTable symtabLocal;
        if(!commandhandler()->execute(expr,&ctxLocal,symtabLocal))
            return false;
        QVariant var = symtabLocal.getValue(res.name());
        IRasterCoverage outRaster = var.value<IRasterCoverage>();
        raster2.assign(outRaster);
    }
    return true;
}

<|endoftext|>


<commit_before>/* This file is part of Mapnik (c++ mapping toolkit)
 * Copyright (C) 2005 Artem Pavlenko
 *
 * Mapnik is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

//  Credits:
//  I gratefully acknowledge the inspiring work of Maxim Shemanarev (McSeem),
//  author of Anti-Grain Geometry (http://www.antigrain.com), and also the developers
//  of the FreeType library (http://www.freetype.org). I have slightly modified the polygon
//  rasterizing algorithm to work with my library, but render_line and
//  render_hline remain intact.

//$Id: scanline_aa.hpp 39 2005-04-10 20:39:53Z pavlenko $

#ifndef SCANLINE_AA_HPP
#define SCANLINE_AA_HPP

#include "envelope.hpp"
#include "geometry.hpp"
#include "graphics.hpp"
#include "style.hpp"

namespace mapnik
{
    enum path_commands_e
	{
	    path_cmd_stop     = 0,                    //----path_cmd_stop
	    path_cmd_move_to  = 1,                    //----path_cmd_move_to
	    path_cmd_line_to  = 2,                    //----path_cmd_line_to
	    path_cmd_curve3   = 3,                    //----path_cmd_curve3
	    path_cmd_curve4   = 4,                    //----path_cmd_curve4
	    path_cmd_end_poly = 6,                    //----path_cmd_end_poly
	    path_cmd_mask     = 0x0F                  //----path_cmd_mask
	};

    //------------------------------------------------------------path_flags_e
    enum path_flags_e
	{
	    path_flags_none  = 0,                     //----path_flags_none
	    path_flags_ccw   = 0x10,                  //----path_flags_ccw
	    path_flags_cw    = 0x20,                  //----path_flags_cw
	    path_flags_close = 0x40,                  //----path_flags_close
	    path_flags_mask  = 0xF0                   //----path_flags_mask
	};

    inline bool is_vertex(unsigned c)
    {
        return c >= path_cmd_move_to && c < path_cmd_end_poly;
    }

    inline bool is_move_to(unsigned c)
    {
        return c == path_cmd_move_to;
    }

    inline bool is_close(unsigned c)
    {
        return (c & ~(path_flags_cw | path_flags_ccw)) ==
            (path_cmd_end_poly | path_flags_close);
    }

    inline unsigned clipping_flags(int x, int y, const Envelope<int>& clip_box)
    {
        return  (x > clip_box.maxx()) |
            ((y > clip_box.maxy()) << 1) |
            ((x < clip_box.minx()) << 2) |
            ((y < clip_box.miny()) << 3);
    }

    template<class T>
    inline unsigned clip_liang_barsky(T x1, T y1, T x2, T y2,
				      const Envelope<T>& clip_box,
				      T* x, T* y)
    {
        const double nearzero = 1e-30;

        double deltax = x2 - x1;
        double deltay = y2 - y1;
        double xin;
        double xout;
        double yin;
        double yout;
        double tinx;
        double tiny;
        double toutx;
        double touty;
        double tin1;
        double tin2;
        double tout1;
        unsigned np = 0;

        if(deltax == 0.0)
        {
            // bump off of the vertical
            deltax = (x1 > clip_box.minx()) ? -nearzero : nearzero;
        }

        if(deltay == 0.0)
        {
            // bump off of the horizontal
            deltay = (y1 > clip_box.miny()) ? -nearzero : nearzero;
        }

        if(deltax > 0.0)
        {
            // points to right
            xin  = clip_box.minx();
            xout = clip_box.maxx();
        }
        else
        {
            xin  = clip_box.maxx();
            xout = clip_box.minx();
        }

        if(deltay > 0.0)
        {
            // points up
            yin  = clip_box.miny();
            yout = clip_box.maxy();
        }
        else
        {
            yin  = clip_box.maxy();
            yout = clip_box.miny();
        }

        tinx = (xin - x1) / deltax;
        tiny = (yin - y1) / deltay;

        if (tinx < tiny)
        {
            // hits x first
            tin1 = tinx;
            tin2 = tiny;
        }
        else
        {
            // hits y first
            tin1 = tiny;
            tin2 = tinx;
        }

        if(tin1 <= 1.0)
        {
            if(0.0 < tin1)
            {
                *x++ = (T)xin;
                *y++ = (T)yin;
                ++np;
            }

            if(tin2 <= 1.0)
            {
                toutx = (xout - x1) / deltax;
                touty = (yout - y1) / deltay;

                tout1 = (toutx < touty) ? toutx : touty;

                if(tin2 > 0.0 || tout1 > 0.0)
                {
                    if(tin2 <= tout1)
                    {
                        if(tin2 > 0.0)
                        {
                            if(tinx > tiny)
                            {
                                *x++ = (T)xin;
                                *y++ = (T)(y1 + tinx * deltay);
                            }
                            else
                            {
                                *x++ = (T)(x1 + tiny * deltax);
                                *y++ = (T)yin;
                            }
                            ++np;
                        }

                        if(tout1 < 1.0)
                        {
                            if(toutx < touty)
                            {
                                *x++ = (T)xout;
                                *y++ = (T)(y1 + toutx * deltay);
                            }
                            else
                            {
                                *x++ = (T)(x1 + touty * deltax);
                                *y++ = (T)yout;
                            }
                        }
                        else
                        {
                            *x++ = x2;
                            *y++ = y2;
                        }
                        ++np;
                    }
                    else
                    {
                        if(tinx > tiny)
                        {
                            *x++ = (T)xin;
                            *y++ = (T)yout;
                        }
                        else
                        {
                            *x++ = (T)xout;
                            *y++ = (T)yin;
                        }
                        ++np;
                    }
                }
            }
        }
        return np;
    }

    enum
	{
	    poly_base_shift = 8,
	    poly_base_size  = 1 << poly_base_shift,
	    poly_base_mask  = poly_base_size - 1
	};

    inline int poly_coord(double c)
    {
        return int(c * poly_base_size);
    }

    struct cell_aa
    {
        short x;
        short y;
        int   packed_coord;
        int   cover;
        int   area;

        void set(int x, int y, int c, int a);
        void set_coord(int x, int y);
        void set_cover(int c, int a);
        void add_cover(int c, int a);
    };

    class outline_aa
    {
        enum {
	    cell_block_shift = 12,
	    cell_block_size  = 1 << cell_block_shift,
	    cell_block_mask  = cell_block_size - 1,
	    cell_block_pool  = 256,
	    cell_block_limit = 1024
	};

    public:

	~outline_aa();
	outline_aa();

	void reset();

	void move_to(int x, int y);
	void line_to(int x, int y);

	int min_x() const { return m_min_x; }
	int min_y() const { return m_min_y; }
	int max_x() const { return m_max_x; }
	int max_y() const { return m_max_y; }

	const cell_aa* const* cells();
	unsigned num_cells() { cells(); return m_num_cells; }
	bool sorted() const { return m_sorted; }

    private:
	outline_aa(const outline_aa&);
	const outline_aa& operator = (const outline_aa&);

	void set_cur_cell(int x, int y);
	void add_cur_cell();
	void sort_cells();
	void render_hline(int ey, int x1, int y1, int x2, int y2);
	void render_line(int x1, int y1, int x2, int y2);
	void allocate_block();

	static void qsort_cells(cell_aa** start, unsigned num);

    private:
	unsigned  m_num_blocks;
	unsigned  m_max_blocks;
	unsigned  m_cur_block;
	unsigned  m_num_cells;
	cell_aa** m_cells;
	cell_aa*  m_cur_cell_ptr;
	cell_aa** m_sorted_cells;
	unsigned  m_sorted_size;
	cell_aa   m_cur_cell;
	int       m_cur_x;
	int       m_cur_y;
	int       m_min_x;
	int       m_min_y;
	int       m_max_x;
	int       m_max_y;
	bool      m_sorted;
    };

    enum filling_rule_e
	{
	    fill_non_zero,
	    fill_even_odd
	};

    template <typename PixBuffer> class ScanlineRasterizerAA
    {
        enum status
	    {
		status_initial,
		status_line_to,
		status_closed
	    };

        struct iterator
        {
            const cell_aa* const* cells;
            int                   cover;
            int                   last_y;
        };
        enum
	    {
		aa_shift = 8,
		aa_num   = 1 << aa_shift,
		aa_mask  = aa_num - 1,
		aa_2num  = aa_num * 2,
		aa_2mask = aa_2num - 1
	    };
    private:
	PixBuffer*     pixbuf_;
	outline_aa     m_outline;
	int            m_gamma[aa_num];
	filling_rule_e m_filling_rule;
	int            m_clipped_start_x;
	int            m_clipped_start_y;
	int            m_start_x;
	int            m_start_y;
	int            m_prev_x;
	int            m_prev_y;
	unsigned       m_prev_flags;
	unsigned       m_status;
	Envelope<int>  m_clip_box;
	bool           m_clipping;
	iterator       m_iterator;
    public:
	ScanlineRasterizerAA(PixBuffer& pixbuf)
	    :pixbuf_(&pixbuf),
	     m_filling_rule(fill_non_zero),
	     m_clipped_start_x(0),
	     m_clipped_start_y(0),
	     m_start_x(0),
	     m_start_y(0),
	     m_prev_x(0),
	     m_prev_y(0),
	     m_prev_flags(0),
	     m_status(status_initial),
	     m_clipping(false)
	{
	    for(int i = 0; i < aa_num; i++) m_gamma[i] = i;
	}

	template <typename Transform>
	void render(const geometry_type& geom,const Color& c);

    private:
	ScanlineRasterizerAA(const ScanlineRasterizerAA&);
	ScanlineRasterizerAA& operator=(const ScanlineRasterizerAA&);
	void render_hline(int x0,int x1,int y,unsigned rgba);
	void blend_hline(int x0,int x1,int y,const unsigned char* cover,
			 unsigned rgba);
	int min_x() const { return m_outline.min_x(); }
	int min_y() const { return m_outline.min_y(); }
	int max_x() const { return m_outline.max_x(); }
	int max_y() const { return m_outline.max_y(); }
	void reset();
	void filling_rule(filling_rule_e filling_rule);
	void clip_box(double x1, double y1, double x2, double y2);
	void reset_clipping();
	template<class GammaF> void gamma(const GammaF& gamma_function)
	{
	    int i;
	    for(i = 0; i < aa_num; i++)
	    {
		m_gamma[i] = int(floor(gamma_function(double(i) / aa_mask) * aa_mask + 0.5));
	    }
	}
	unsigned apply_gamma(unsigned cover) const
	{
	    return m_gamma[cover];
	}
	void add_vertex(double x, double y, unsigned cmd);
	void move_to(int x, int y);
	void line_to(int x, int y);
	void close_polygon();

	void move_to_no_clip(int x, int y);
	void line_to_no_clip(int x, int y);
	void close_polygon_no_clip();
	void clip_segment(int x, int y);
	unsigned calculate_alpha(int area) const
	{
	    int cover = area >> (poly_base_shift*2 + 1 - aa_shift);

	    if(cover < 0) cover = -cover;
	    if(m_filling_rule == fill_even_odd)
	    {
		cover &= aa_2mask;
		if(cover > aa_num)
		{
		    cover = aa_2num - cover;
		}
	    }
	    if(cover > aa_mask) cover = aa_mask;
	    return m_gamma[cover];
	}

	void sort()
	{
	    m_outline.cells();
	}

	bool rewind_scanlines()
	{
	    close_polygon();
	    m_iterator.cells = m_outline.cells();
	    if(m_outline.num_cells() == 0)
	    {
		return false;
	    }
	    m_iterator.cover  = 0;
	    m_iterator.last_y = (*m_iterator.cells)->y;
	    return true;
	}

	template<class Scanline> bool sweep_scanline(Scanline& sl)
	{
	    sl.reset_spans();
	    for(;;)
	    {
		const cell_aa* cur_cell = *m_iterator.cells;
		if(cur_cell == 0) return false;
		++m_iterator.cells;
		m_iterator.last_y = cur_cell->y;

		for(;;)
		{
		    int coord  = cur_cell->packed_coord;
		    int area   = cur_cell->area;
		    int last_x = cur_cell->x;

		    m_iterator.cover += cur_cell->cover;

		    //accumulate all cells with the same coordinates
		    for(; (cur_cell = *m_iterator.cells) != 0; ++m_iterator.cells)
		    {
			if(cur_cell->packed_coord != coord) break;
			area             += cur_cell->area;
			m_iterator.cover += cur_cell->cover;
		    }

		    int alpha;
		    if(cur_cell == 0 || cur_cell->y != m_iterator.last_y)
		    {

			if(area)
			{
			    alpha = calculate_alpha((m_iterator.cover << (poly_base_shift + 1)) - area);
			    if(alpha)
			    {
				sl.add_cell(last_x, alpha);
			    }
			    ++last_x;
			}
			break;
		    }

		    ++m_iterator.cells;

		    if(area)
		    {
			alpha = calculate_alpha((m_iterator.cover << (poly_base_shift + 1)) - area);
			if(alpha)
			{
			    sl.add_cell(last_x, alpha);
			}
			++last_x;
		    }

		    if(cur_cell->x > last_x)
		    {
			alpha = calculate_alpha(m_iterator.cover << (poly_base_shift + 1));
			if(alpha)
			{
			    sl.add_span(last_x, cur_cell->x - last_x, alpha);
			}
		    }
		}
		if(sl.num_spans())
		{
		    sl.finalize(m_iterator.last_y);
		    break;
		}
	    }
	    return true;
	}
    };

    template<typename PixBuffer>
    void  ScanlineRasterizerAA<PixBuffer>::reset()
    {
        m_outline.reset();
        m_status = status_initial;
    }

    template<typename PixBuffer>
    void ScanlineRasterizerAA<PixBuffer>::clip_box(double x1, double y1, double x2, double y2)
    {
        //reset();
        m_clip_box = Envelope<int>(poly_coord(x1), poly_coord(y1),
				   poly_coord(x2), poly_coord(y2));
        //m_clip_box.normalize();
        m_clipping = true;
    }

    template<typename PixBuffer>
    void ScanlineRasterizerAA<PixBuffer>::move_to_no_clip(int x, int y)
    {
        if(m_status == status_line_to)
        {
            close_polygon_no_clip();
        }
        m_outline.move_to(x,y);
        m_clipped_start_x = x;
        m_clipped_start_y = y;
        m_status = status_line_to;
    }

    template<typename PixBuffer>
    void ScanlineRasterizerAA<PixBuffer>::line_to_no_clip(int x, int y)
    {
        if(m_status != status_initial)
        {
            m_outline.line_to(x , y);
            m_status = status_line_to;
        }
    }

    template<typename PixBuffer>
    void ScanlineRasterizerAA<PixBuffer>::close_polygon_no_clip()
    {
        if(m_status == status_line_to)
        {
            m_outline.line_to(m_clipped_start_x, m_clipped_start_y);
            m_status = status_closed;
        }
    }

    template<typename PixBuffer>
    void ScanlineRasterizerAA<PixBuffer>::clip_segment(int x, int y)
    {
        unsigned flags = clipping_flags(x, y, m_clip_box);
        if(m_prev_flags == flags)
        {
            if(flags == 0)
            {
                if(m_status == status_initial)
                {
                    move_to_no_clip(x, y);
                }
                else
                {
                    line_to_no_clip(x, y);
                }
            }
        }
        else
        {

            int cx[4];
            int cy[4];
            unsigned n = clip_liang_barsky<int>(m_prev_x, m_prev_y,
						x, y,
						m_clip_box,
						cx, cy);
            const int* px = cx;
            const int* py = cy;
            while(n--)
            {
                if(m_status == status_initial)
                {
                    move_to_no_clip(*px++, *py++);
                }
                else
                {
                    line_to_no_clip(*px++, *py++);
                }
            }
        }

        m_prev_flags = flags;
        m_prev_x = x;
        m_prev_y = y;
    }

    template<typename PixBuffer>
    void ScanlineRasterizerAA<PixBuffer>::add_vertex(double x, double y, unsigned cmd)
    {
        if(is_close(cmd))
        {
            close_polygon();
        }
        else
        {
            if(is_move_to(cmd))
            {
                move_to(poly_coord(x), poly_coord(y));
            }
            else
            {
                if(is_vertex(cmd))
                {
                    line_to(poly_coord(x), poly_coord(y));
                }
            }
        }
    }

    template<typename PixBuffer>
    void ScanlineRasterizerAA<PixBuffer>::move_to(int x, int y)
    {
        if(m_clipping)
        {
            if(m_outline.sorted())
            {
                reset();
            }
            if(m_status == status_line_to)
            {
                close_polygon();
            }
            m_prev_x = m_start_x = x;
            m_prev_y = m_start_y = y;
            m_status = status_initial;
            m_prev_flags = clipping_flags(x, y, m_clip_box);
            if(m_prev_flags == 0)
            {
                move_to_no_clip(x, y);
            }
        }
        else
        {
            move_to_no_clip(x, y);
        }
    }

    template<typename PixBuffer>
    void ScanlineRasterizerAA<PixBuffer>::line_to(int x, int y)
    {
        if(m_clipping)
        {
            clip_segment(x, y);
        }
        else
        {
            line_to_no_clip(x, y);
        }
    }

    template<typename PixBuffer>
    void ScanlineRasterizerAA<PixBuffer>::close_polygon()
    {
        if(m_clipping)
        {
            clip_segment(m_start_x, m_start_y);
        }
        close_polygon_no_clip();
    }

    template<class T> class scanline_u
    {
    public:
	typedef T cover_type;
	struct span
	{
	    short x;
	    short len;
	    cover_type* covers;
	};

	typedef span* iterator;
	typedef const span* const_iterator;

	~scanline_u();
	scanline_u();

	void     reset(int min_x, int max_x);
	void     add_cell(int x, unsigned cover);
	void     add_cells(int x, unsigned len, const T* covers);
	void     add_span(int x, unsigned len, unsigned cover);
	void     finalize(int y) { m_y = y; }
	void     reset_spans();

	int      y()           const { return m_y; }
	unsigned num_spans()   const { return unsigned(m_cur_span - m_spans); }
	const_iterator begin() const { return m_spans + 1; }
	iterator       begin()       { return m_spans + 1; }

    private:
	scanline_u<T>(const scanline_u<T>&);
	const scanline_u<T>& operator = (const scanline_u<T>&);

    private:
	int           m_min_x;
	unsigned      m_max_len;
	int           m_last_x;
	int           m_y;
	cover_type*   m_covers;
	span*         m_spans;
	span*         m_cur_span;
    };

    template<class T> scanline_u<T>::~scanline_u()
    {
        delete [] m_spans;
        delete [] m_covers;
    }

    template<class T> scanline_u<T>::scanline_u() :
	m_min_x(0),
        m_max_len(0),
        m_last_x(0x7FFFFFF0),
        m_covers(0),
        m_spans(0),
        m_cur_span(0)
    {
    }

    template<class T> void scanline_u<T>::reset(int min_x, int max_x)
    {
        unsigned max_len = max_x - min_x + 2;
        if(max_len > m_max_len)
        {
            delete [] m_spans;
            delete [] m_covers;
            m_covers  = new cover_type [max_len];
            m_spans   = new span       [max_len];
            m_max_len = max_len;
        }
        m_last_x        = 0x7FFFFFF0;
        m_min_x         = min_x;
        m_cur_span      = m_spans;
    }

    template<class T> inline void scanline_u<T>::reset_spans()
    {
        m_last_x    = 0x7FFFFFF0;
        m_cur_span  = m_spans;
    }

    template<class T> inline void scanline_u<T>::add_cell(int x, unsigned cover)
    {
        x -= m_min_x;
        m_covers[x] = (unsigned char)cover;
        if(x == m_last_x+1)
        {
            m_cur_span->len++;
        }
        else
        {
            m_cur_span++;
            m_cur_span->x      = (short)(x + m_min_x);
            m_cur_span->len    = 1;
            m_cur_span->covers = m_covers + x;
        }
        m_last_x = x;
    }

    template<class T> void scanline_u<T>::add_cells(int x, unsigned len, const T* covers)
    {
        x -= m_min_x;
        memcpy(m_covers + x, covers, len * sizeof(T));
        if(x == m_last_x+1)
        {
            m_cur_span->len += (short)len;
        }
        else
        {
            m_cur_span++;
            m_cur_span->x      = (short)(x + m_min_x);
            m_cur_span->len    = (short)len;
            m_cur_span->covers = m_covers + x;
        }
        m_last_x = x + len - 1;
    }

    template<class T> void scanline_u<T>::add_span(int x, unsigned len, unsigned cover)
    {
        x -= m_min_x;
        memset(m_covers + x, cover, len);
        if(x == m_last_x+1)
        {
            m_cur_span->len += (short)len;
        }
        else
        {
            m_cur_span++;
            m_cur_span->x      = (short)(x + m_min_x);
            m_cur_span->len    = (short)len;
            m_cur_span->covers = m_covers + x;
        }
        m_last_x = x + len - 1;
    }

    typedef scanline_u<unsigned char> scanline_u8;
    typedef scanline_u<unsigned short> scanline_u16;
    typedef scanline_u<unsigned int> scanline_u32;
}

#endif //SCANLINE_AA_HPP
<commit_msg>removed unused files<commit_after><|endoftext|>


<commit_before><commit_msg>remove unused header xftsfit.hxx<commit_after><|endoftext|>


<commit_before>#include "bwpathfinder.hpp"
#include "network_simulation.hpp"

#include <queue>
#include <cstdio>

namespace bwpathfinder {

    size_t Node::id_counter = 0;

    void Network::simulateDeliveredBandwidth() {
        NetworkSimulation sim(shared_from_this());
        sim.simulate();
        sim.setDeliveredBandwidths();
        sim.flushMessages();

        // Zero all state variables
        for (LinkPtr link : this->links) {
            link->paths.clear();
            link->bwRequested = 0.0;
        }

        for (PathPtr path : this->paths) {
        	path->assign(path->path, path->delivered_bw);
        }
    }

    float Link::costToUse(float hopCost, float bw) const {
    	float totBW = bwRequested + bw;
        float overage = totBW > bandwidth ? totBW - bandwidth : 0;
        return hopCost + pow(overage, overageExponent);
    }

    float Pathfinder::solveConverge(float improvementThreshold, uint64_t maxIter) {
    	std::deque<float> costs;
    	printf("Pathfinder solveConverge:\n");
    	printf("\tNodes: %lu\n\tLinks: %lu\n\tPaths: %lu\n\tHopCost:%e\n\tThresh: %e\n",
    			network->nodes.size(), network->links.size(), network->paths.size(),
    			hopCost, improvementThreshold);
    	while (iteration < maxIter) {
    		float icost = iterate();
    		cost = solutionCost();
    		costs.push_back(cost);
    		while (costs.size() > 3) {
    			costs.pop_front();
    		}
    		iteration += 1;

    		float min = costs.front();
    		float max = min;
    		for (float c : costs) {
    			min = std::min(min, c);
    			max = std::max(max, c);
    		}

    		float diff = max - min;
    		if (costs.size() >= 3 && diff < improvementThreshold) {
    			break;
    		}

    		printf("\tIteration %lu cost: %e  linkcost: %e\n", iteration, icost, cost);
    	}

    	return cost;
    }

    float Pathfinder::solve(float desiredCost, uint64_t maxIter) {
    	while (cost > desiredCost && iteration < maxIter) {
    		iterate();
    		cost = solutionCost();
    		iteration += 1;
    	}

    	return cost;
    }

    struct PartialPath {
        PathPtr defn;
        float cost;
        float bw;
        NodePtr node;
        std::vector<LinkPtr> path;

        PartialPath(PathPtr defn) :
            defn(defn),
            cost(0),
            bw(defn->requested_bw),
            node(defn->src) {
        }

        PartialPath(float hopCost, const PartialPath& orig, LinkPtr next) :
            defn(orig.defn),
            cost(orig.cost),
            bw(next->bwShareW(orig.bw)),
            node(orig.node),
            path(orig.path) {
            path.push_back(next);
            float nextCost = next->costToUse(hopCost, bw);
            cost = cost + nextCost;

            if (node == next->a)
                node = next->b;
            else if (node == next->b)
                node = next->a;
            else
                assert(false && "Link being added doesn't connect");
        }

        void print() {
        	const char* fullPart = sinkFound() ? "Full" : "Part";
            printf("%s path  cost: %e node: %p\n", fullPart, cost, node.get());
            for (LinkPtr link : path) {
            	printf("\t%s -- %s : bw %e, req_bw: %e, paths: %lu\n",
            		link->a->label.c_str(), link->b->label.c_str(), link->bandwidth,
            		link->bwRequested, link->paths.size());
            }
        }

        LinkPtr last() {
            if (path.size() == 0)
                return LinkPtr();
            return path.back();
        }

        bool sinkFound() {
            if (path.size() == 0)
                return defn->src == defn->dst;
            LinkPtr lst = path.back();
            return lst->a == defn->dst || lst->b == defn->dst;
        }

        bool operator<(const PartialPath& other) const {
            return this->cost > other.cost;
        }

        bool hasCycle() const {
        	std::set<LinkPtr, smart_ptr_less_than> pathSet(path.begin(), path.end());
        	assert(pathSet.size() <= path.size());
        	return pathSet.size() < path.size();
        }
    };

    float Pathfinder::iterate() {
    	std::vector<PathPtr> allPaths = this->network->getPaths();
    	std::random_shuffle(allPaths.begin(), allPaths.end());

    	float cost = 0.0;
    	for (PathPtr path : allPaths) {
    		path->ripup();

    		// Find a new path
    		std::priority_queue<PartialPath> q;
    		q.push(PartialPath(path));

    		bool sinkFound = false;
    		while (!sinkFound) {
    			assert(!q.empty() && "Could not find path!");

    			PartialPath bestPath = q.top();
    			q.pop();
    			// bestPath.print();

    			if (bestPath.sinkFound()) {
    				// The current best path has found its destination
    				sinkFound = true;
    				path->assign(bestPath.path, bestPath.bw);
    				cost += bestPath.cost;
    				// printf("\t=== Assigned! === \n");
    			} else {
    				NodePtr node = bestPath.node;
    				// printf("\tAt node: %s\n", node->label.c_str());
    				auto& links = this->network->linkIndex[node];
    				for (LinkPtr link : links) {
    					// printf("\tConsidering: %s -- %s\n",
    						// link->a->label.c_str(), link->b->label.c_str());
						// Don't include the link we just used
    					if (link != bestPath.last()) {
    						PartialPath pp(this->hopCost, bestPath, link);
    						if (!pp.hasCycle()) {
	    						q.push(pp);
	    						// printf("\t\tpushed with cost %e\n", pp.cost);
	    					}
    					}
    				}
    			}
    		}
    	}

    	// Increment history penalties
    	for (LinkPtr link : this->network->links) {
    		link->incrementPenalties(0.01, 0.1);
    	}

    	return cost;
    }

    float Pathfinder::solutionCost() {
    	float cost = 0.0;
    	for (LinkPtr link : this->network->links) {
    		cost += link->solutionPartialCost();
    	}
    	return cost;
    }
}
<commit_msg>A speed optimization mentioned in the paper: only rip up and re-route signals on congested lines<commit_after>#include "bwpathfinder.hpp"
#include "network_simulation.hpp"

#include <queue>
#include <cstdio>

namespace bwpathfinder {

    size_t Node::id_counter = 0;

    void Network::simulateDeliveredBandwidth() {
        NetworkSimulation sim(shared_from_this());
        sim.simulate();
        sim.setDeliveredBandwidths();
        sim.flushMessages();

        // Zero all state variables
        for (LinkPtr link : this->links) {
            link->paths.clear();
            link->bwRequested = 0.0;
        }

        for (PathPtr path : this->paths) {
        	path->assign(path->path, path->delivered_bw);
        }
    }

    float Link::costToUse(float hopCost, float bw) const {
    	float totBW = bwRequested + bw;
        float overage = totBW > bandwidth ? totBW - bandwidth : 0;
        return hopCost + pow(overage, overageExponent);
    }

    float Pathfinder::solveConverge(float improvementThreshold, uint64_t maxIter) {
    	std::deque<float> costs;
    	printf("Pathfinder solveConverge:\n");
    	printf("\tNodes: %lu\n\tLinks: %lu\n\tPaths: %lu\n\tHopCost:%e\n\tThresh: %e\n",
    			network->nodes.size(), network->links.size(), network->paths.size(),
    			hopCost, improvementThreshold);
    	while (iteration < maxIter) {
    		float icost = iterate();
    		cost = solutionCost();
    		costs.push_back(cost);
    		while (costs.size() > 3) {
    			costs.pop_front();
    		}
    		iteration += 1;

    		float min = costs.front();
    		float max = min;
    		for (float c : costs) {
    			min = std::min(min, c);
    			max = std::max(max, c);
    		}

    		printf("\tIteration %lu cost: %e  linkcost: %e\n", iteration, icost, cost);

    		float diff = max - min;
    		if (costs.size() >= 3 && diff < improvementThreshold) {
    			break;
    		}
    		if (cost < 0.1) {
    			// < 1 is a very small cost
    			break;
    		}
    	}

    	return cost;
    }

    float Pathfinder::solve(float desiredCost, uint64_t maxIter) {
    	while (cost > desiredCost && iteration < maxIter) {
    		iterate();
    		cost = solutionCost();
    		iteration += 1;
    	}

    	return cost;
    }

    struct PartialPath {
        PathPtr defn;
        float cost;
        float bw;
        NodePtr node;
        std::vector<LinkPtr> path;

        PartialPath(PathPtr defn) :
            defn(defn),
            cost(0),
            bw(defn->requested_bw),
            node(defn->src) {
        }

        PartialPath(float hopCost, const PartialPath& orig, LinkPtr next) :
            defn(orig.defn),
            cost(orig.cost),
            bw(next->bwShareW(orig.bw)),
            node(orig.node),
            path(orig.path) {
            path.push_back(next);
            float nextCost = next->costToUse(hopCost, bw);
            cost = cost + nextCost;

            if (node == next->a)
                node = next->b;
            else if (node == next->b)
                node = next->a;
            else
                assert(false && "Link being added doesn't connect");
        }

        void print() {
        	const char* fullPart = sinkFound() ? "Full" : "Part";
            printf("%s path  cost: %e node: %p\n", fullPart, cost, node.get());
            for (LinkPtr link : path) {
            	printf("\t%s -- %s : bw %e, req_bw: %e, paths: %lu\n",
            		link->a->label.c_str(), link->b->label.c_str(), link->bandwidth,
            		link->bwRequested, link->paths.size());
            }
        }

        LinkPtr last() {
            if (path.size() == 0)
                return LinkPtr();
            return path.back();
        }

        bool sinkFound() {
            if (path.size() == 0)
                return defn->src == defn->dst;
            LinkPtr lst = path.back();
            return lst->a == defn->dst || lst->b == defn->dst;
        }

        bool operator<(const PartialPath& other) const {
            return this->cost > other.cost;
        }

        bool hasCycle() const {
        	std::set<LinkPtr, smart_ptr_less_than> pathSet(path.begin(), path.end());
        	assert(pathSet.size() <= path.size());
        	return pathSet.size() < path.size();
        }
    };

    float Pathfinder::iterate() {
    	std::vector<PathPtr> allPaths;

    	if (iteration == 0) {
	    	allPaths = this->network->getPaths();
	    } else {
	    	std::set<PathPtr, smart_ptr_less_than> congestedPaths;
	    	for (LinkPtr link : this->network->links) {
	    		if (link->bwRequested > link->bandwidth) {
	    			congestedPaths.insert(link->paths.begin(), link->paths.end());
	    		}
	    	}
	    	allPaths = std::vector<PathPtr>(congestedPaths.begin(), congestedPaths.end());
	    }
    	std::random_shuffle(allPaths.begin(), allPaths.end());

    	float cost = 0.0;
    	for (PathPtr path : allPaths) {
    		path->ripup();

    		// Find a new path
    		std::priority_queue<PartialPath> q;
    		q.push(PartialPath(path));

    		bool sinkFound = false;
    		while (!sinkFound) {
    			assert(!q.empty() && "Could not find path!");

    			PartialPath bestPath = q.top();
    			q.pop();
    			// bestPath.print();

    			if (bestPath.sinkFound()) {
    				// The current best path has found its destination
    				sinkFound = true;
    				path->assign(bestPath.path, bestPath.bw);
    				cost += bestPath.cost;
    				// printf("\t=== Assigned! === \n");
    			} else {
    				NodePtr node = bestPath.node;
    				// printf("\tAt node: %s\n", node->label.c_str());
    				auto& links = this->network->linkIndex[node];
    				for (LinkPtr link : links) {
    					// printf("\tConsidering: %s -- %s\n",
    						// link->a->label.c_str(), link->b->label.c_str());
						// Don't include the link we just used
    					if (link != bestPath.last()) {
    						PartialPath pp(this->hopCost, bestPath, link);
    						if (!pp.hasCycle()) {
	    						q.push(pp);
	    						// printf("\t\tpushed with cost %e\n", pp.cost);
	    					}
    					}
    				}
    			}
    		}
    	}

    	// Increment history penalties
    	for (LinkPtr link : this->network->links) {
    		link->incrementPenalties(0.01, 0.1);
    	}

    	return cost;
    }

    float Pathfinder::solutionCost() {
    	float cost = 0.0;
    	for (LinkPtr link : this->network->links) {
    		cost += link->solutionPartialCost();
    	}
    	return cost;
    }
}
<|endoftext|>


<commit_before>#pragma once

#include "common.hpp"
#include "utils/cache.hpp"

POLYBAR_NS

static cache<string, unsigned int> g_cache_hex;
static cache<unsigned int, string> g_cache_colors;

struct rgba;

namespace color_util {
  template <typename T = unsigned char>
  T alpha_channel(const unsigned int value) {
    unsigned char a = value >> 24;
    if (std::is_same<T, unsigned char>::value)
      return a << 8 / 0xff;
    else if (std::is_same<T, unsigned short int>::value)
      return a << 8 | a << 8 / 0xff;
  }

  template <typename T = unsigned char>
  T red_channel(const unsigned int value) {
    unsigned char r = value >> 16;
    if (std::is_same<T, unsigned char>::value)
      return r << 8 / 0xff;
    else if (std::is_same<T, unsigned short int>::value)
      return r << 8 | r << 8 / 0xff;
  }

  template <typename T = unsigned char>
  T green_channel(const unsigned int value) {
    unsigned char g = value >> 8;
    if (std::is_same<T, unsigned char>::value)
      return g << 8 / 0xff;
    else if (std::is_same<T, unsigned short int>::value)
      return g << 8 | g << 8 / 0xff;
  }

  template <typename T = unsigned char>
  T blue_channel(const unsigned int value) {
    unsigned char b = value;
    if (std::is_same<T, unsigned char>::value)
      return b << 8 / 0xff;
    else if (std::is_same<T, unsigned short int>::value)
      return b << 8 | b << 8 / 0xff;
  }

  template <typename T = unsigned int>
  unsigned int premultiply_alpha(const T value) {
    auto a = color_util::alpha_channel(value);
    auto r = color_util::red_channel(value) * a / 255;
    auto g = color_util::green_channel(value) * a / 255;
    auto b = color_util::blue_channel(value) * a / 255;
    return (a << 24) | (r << 16) | (g << 8) | b;
  }

  template <typename T>
  string hex(unsigned int color) {
    string hex;

    if (!g_cache_hex.check(color)) {
      char s[12];
      size_t len = 0;

      unsigned char a = alpha_channel<T>(color);
      unsigned char r = red_channel<T>(color);
      unsigned char g = green_channel<T>(color);
      unsigned char b = blue_channel<T>(color);

      if (std::is_same<T, unsigned short int>::value) {
        len = snprintf(s, sizeof(s), "#%02x%02x%02x%02x", a, r, g, b);
      } else if (std::is_same<T, unsigned char>::value) {
        len = snprintf(s, sizeof(s), "#%02x%02x%02x", r, g, b);
      }

      hex = string(s, len);
    }

    return *g_cache_hex.object(color, hex);
  }

  inline string parse_hex(string hex) {
    if (hex[0] != '#')
      hex.insert(0, 1, '#');
    if (hex.length() == 4)
      hex = {'#', hex[1], hex[1], hex[2], hex[2], hex[3], hex[3]};
    if (hex.length() == 7)
      hex = "#ff" + hex.substr(1);
    if (hex.length() != 9)
      return "";
    return hex;
  }

  inline unsigned int parse(string hex, unsigned int fallback = 0) {
    if ((hex = parse_hex(hex)).empty())
      return fallback;
    return strtoul(&hex[1], nullptr, 16);
  }

  inline string simplify_hex(string hex) {
    // convert #ffrrggbb to #rrggbb
    if (hex.length() == 9 && hex[1] == 'f' && hex[2] == 'f') {
      hex.erase(1, 2);
    }

    // convert #rrggbb to #rgb
    if (hex.length() == 7) {
      if (hex[1] == hex[2] && hex[3] == hex[4] && hex[5] == hex[6]) {
        hex = {'#', hex[1], hex[3], hex[5]};
      }
    }

    return hex;
  }
}

struct rgb {
  double r;
  double g;
  double b;

  // clang-format off
  explicit rgb(double r, double g, double b) : r(r), g(g), b(b) {}
  explicit rgb(unsigned int color) : rgb(
      color_util::red_channel<unsigned char>(color_util::premultiply_alpha(color)   / 255.0),
      color_util::green_channel<unsigned char>(color_util::premultiply_alpha(color) / 255.0),
      color_util::blue_channel<unsigned char>(color_util::premultiply_alpha(color)  / 255.0)) {}
  // clang-format on
};

struct rgba {
  double r;
  double g;
  double b;
  double a;

  // clang-format off
  explicit rgba(double r, double g, double b, double a) : r(r), g(g), b(b), a(a) {}
  explicit rgba(unsigned int color) : rgba(
      color_util::red_channel<unsigned char>(color)   / 255.0,
      color_util::green_channel<unsigned char>(color) / 255.0,
      color_util::blue_channel<unsigned char>(color)  / 255.0,
      color_util::alpha_channel<unsigned char>(color) / 255.0) {}
  // clang-format on

  operator unsigned int() {
    // clang-format off
    return static_cast<int>(a * 255) << 24
         | static_cast<int>(r * 255) << 16
         | static_cast<int>(g * 255) << 8
         | static_cast<int>(b * 255);
    // clang-format on
  }
};

POLYBAR_NS_END
<commit_msg>fix(color_util): Use lambda<commit_after>#pragma once

#include "common.hpp"
#include "utils/cache.hpp"

POLYBAR_NS

static cache<string, unsigned int> g_cache_hex;
static cache<unsigned int, string> g_cache_colors;

struct rgba;

namespace color_util {
  template <typename T = unsigned char>
  T alpha_channel(const unsigned int value) {
    unsigned char a = value >> 24;
    if (std::is_same<T, unsigned char>::value)
      return a << 8 / 0xff;
    else if (std::is_same<T, unsigned short int>::value)
      return a << 8 | a << 8 / 0xff;
  }

  template <typename T = unsigned char>
  T red_channel(const unsigned int value) {
    unsigned char r = value >> 16;
    if (std::is_same<T, unsigned char>::value)
      return r << 8 / 0xff;
    else if (std::is_same<T, unsigned short int>::value)
      return r << 8 | r << 8 / 0xff;
  }

  template <typename T = unsigned char>
  T green_channel(const unsigned int value) {
    unsigned char g = value >> 8;
    if (std::is_same<T, unsigned char>::value)
      return g << 8 / 0xff;
    else if (std::is_same<T, unsigned short int>::value)
      return g << 8 | g << 8 / 0xff;
  }

  template <typename T = unsigned char>
  T blue_channel(const unsigned int value) {
    unsigned char b = value;
    if (std::is_same<T, unsigned char>::value)
      return b << 8 / 0xff;
    else if (std::is_same<T, unsigned short int>::value)
      return b << 8 | b << 8 / 0xff;
  }

  template <typename T = unsigned int>
  unsigned int premultiply_alpha(const T value) {
    auto a = color_util::alpha_channel(value);
    auto r = color_util::red_channel(value) * a / 255;
    auto g = color_util::green_channel(value) * a / 255;
    auto b = color_util::blue_channel(value) * a / 255;
    return (a << 24) | (r << 16) | (g << 8) | b;
  }

  template <typename T>
  string hex(unsigned int color) {
    return *g_cache_hex.object(color, [&] {
      char s[12];
      size_t len = 0;

      unsigned char a = alpha_channel<T>(color);
      unsigned char r = red_channel<T>(color);
      unsigned char g = green_channel<T>(color);
      unsigned char b = blue_channel<T>(color);

      if (std::is_same<T, unsigned short int>::value) {
        len = snprintf(s, sizeof(s), "#%02x%02x%02x%02x", a, r, g, b);
      } else if (std::is_same<T, unsigned char>::value) {
        len = snprintf(s, sizeof(s), "#%02x%02x%02x", r, g, b);
      }

      return string(s, len);
    }());
  }

  inline string parse_hex(string hex) {
    if (hex[0] != '#')
      hex.insert(0, 1, '#');
    if (hex.length() == 4)
      hex = {'#', hex[1], hex[1], hex[2], hex[2], hex[3], hex[3]};
    if (hex.length() == 7)
      hex = "#ff" + hex.substr(1);
    if (hex.length() != 9)
      return "";
    return hex;
  }

  inline unsigned int parse(string hex, unsigned int fallback = 0) {
    if ((hex = parse_hex(hex)).empty())
      return fallback;
    return strtoul(&hex[1], nullptr, 16);
  }

  inline string simplify_hex(string hex) {
    // convert #ffrrggbb to #rrggbb
    if (hex.length() == 9 && hex[1] == 'f' && hex[2] == 'f') {
      hex.erase(1, 2);
    }

    // convert #rrggbb to #rgb
    if (hex.length() == 7) {
      if (hex[1] == hex[2] && hex[3] == hex[4] && hex[5] == hex[6]) {
        hex = {'#', hex[1], hex[3], hex[5]};
      }
    }

    return hex;
  }
}

struct rgb {
  double r;
  double g;
  double b;

  // clang-format off
  explicit rgb(double r, double g, double b) : r(r), g(g), b(b) {}
  explicit rgb(unsigned int color) : rgb(
      color_util::red_channel<unsigned char>(color_util::premultiply_alpha(color)   / 255.0),
      color_util::green_channel<unsigned char>(color_util::premultiply_alpha(color) / 255.0),
      color_util::blue_channel<unsigned char>(color_util::premultiply_alpha(color)  / 255.0)) {}
  // clang-format on
};

struct rgba {
  double r;
  double g;
  double b;
  double a;

  // clang-format off
  explicit rgba(double r, double g, double b, double a) : r(r), g(g), b(b), a(a) {}
  explicit rgba(unsigned int color) : rgba(
      color_util::red_channel<unsigned char>(color)   / 255.0,
      color_util::green_channel<unsigned char>(color) / 255.0,
      color_util::blue_channel<unsigned char>(color)  / 255.0,
      color_util::alpha_channel<unsigned char>(color) / 255.0) {}
  // clang-format on

  operator unsigned int() {
    // clang-format off
    return static_cast<int>(a * 255) << 24
         | static_cast<int>(r * 255) << 16
         | static_cast<int>(g * 255) << 8
         | static_cast<int>(b * 255);
    // clang-format on
  }
};

POLYBAR_NS_END
<|endoftext|>