<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2012-2015 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file motor_ramp.cpp
 * Application to test motor ramp up.
 *
 * @author Andreas Antener <andreas@uaventure.com>
 */

#include <px4_config.h>
#include <px4_defines.h>
#include <px4_tasks.h>
#include <px4_posix.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include <poll.h>

#include <arch/board/board.h>
#include <drivers/drv_hrt.h>
#include <drivers/drv_pwm_output.h>
#include <platforms/px4_defines.h>

#include "systemlib/systemlib.h"
#include "systemlib/err.h"

static bool _thread_should_exit = false;		/**< motor_ramp exit flag */
static bool _thread_running = false;		/**< motor_ramp status flag */
static int _motor_ramp_task;				/**< Handle of motor_ramp task / thread */
static float _ramp_time;
static int _min_pwm;

enum RampState {
	RAMP_INIT,
	RAMP_MIN,
	RAMP_RAMP,
	RAMP_WAIT
};

/**
 * motor_ramp management function.
 */
extern "C" __EXPORT int motor_ramp_main(int argc, char *argv[]);

/**
 * Mainloop of motor_ramp.
 */
int motor_ramp_thread_main(int argc, char *argv[]);

bool min_pwm_valid(unsigned pwm_value);

int set_min_pwm(int fd, unsigned long max_channels, unsigned pwm_value);

int set_out(int fd, unsigned long max_channels, float output);

int prepare(int fd, unsigned long *max_channels);

/**
 * Print the correct usage.
 */
static void usage(const char *reason);

static void
usage(const char *reason)
{
	if (reason) {
		PX4_ERR("[motor_ramp] %s", reason);
	}

	PX4_WARN("[motor_ramp]\n\nWARNING: motors will ramp up to full speed!\n");
	PX4_WARN("[motor_ramp] usage: motor_ramp <min_pwm> <ramp_time>");
	PX4_WARN("[motor_ramp] example:");
	PX4_WARN("[motor_ramp] nsh> sdlog2 on");
	PX4_WARN("[motor_ramp] nsh> mc_att_control stop");
	PX4_WARN("[motor_ramp] nsh> motor_ramp 1100 0.5\n");
}

/**
 * The motor_ramp app only briefly exists to start
 * the background job. The stack size assigned in the
 * Makefile does only apply to this management task.
 *
 * The actual stack size should be set in the call
 * to task_create().
 */
int motor_ramp_main(int argc, char *argv[])
{
	if (argc < 3) {
		usage("missing parameters");
		return 1;
	}

	if (_thread_running) {
		PX4_WARN("motor_ramp already running\n");
		/* this is not an error */
		return 0;
	}

	_min_pwm = atoi(argv[1]);

	if (!min_pwm_valid(_min_pwm)) {
		usage("min pwm not in range");
		return 1;
	}

	_ramp_time = atof(argv[2]);

	if (!(_ramp_time > 0)) {
		usage("ramp time must be greater than 0");
		return 1;
	}

	_thread_should_exit = false;
	_motor_ramp_task = px4_task_spawn_cmd("motor_ramp",
					      SCHED_DEFAULT,
					      SCHED_PRIORITY_DEFAULT + 40,
					      2000,
					      motor_ramp_thread_main,
					      (argv) ? (char *const *)&argv[2] : (char *const *)NULL);
	return 0;

	usage("unrecognized command");
	return 1;
}

bool min_pwm_valid(unsigned pwm_value)
{
	return pwm_value > 900 && pwm_value < 1300;
}

int set_min_pwm(int fd, unsigned long max_channels, unsigned pwm_value)
{
	int ret;

	struct pwm_output_values pwm_values;
	memset(&pwm_values, 0, sizeof(pwm_values));

	pwm_values.channel_count = max_channels;

	for (int i = 0; i < max_channels; i++) {
		pwm_values.values[i] = pwm_value;
	}

	ret = px4_ioctl(fd, PWM_SERVO_SET_MIN_PWM, (long unsigned int)&pwm_values);

	if (ret != OK) {
		PX4_ERR("[motor_ramp] failed setting min values");
		return 1;
	}

	return 0;
}

int set_out(int fd, unsigned long max_channels, float output)
{
	int ret;
	int pwm = (2000 - _min_pwm) * output + _min_pwm;

	for (unsigned i = 0; i < max_channels; i++) {

		ret = ioctl(fd, PWM_SERVO_SET(i), pwm);

		if (ret != OK) {
			PX4_ERR("PWM_SERVO_SET(%d), value: %d", i, pwm);
			return 1;
		}
	}

	return 0;
}

int prepare(int fd, unsigned long *max_channels)
{
	/* get number of channels available on the device */
	if (px4_ioctl(fd, PWM_SERVO_GET_COUNT, (unsigned long)max_channels) != OK) {
		PX4_ERR("[motor_ramp] PWM_SERVO_GET_COUNT");
		return 1;
	}

	/* tell IO/FMU that its ok to disable its safety with the switch */
	if (px4_ioctl(fd, PWM_SERVO_SET_ARM_OK, 0) != OK) {
		PX4_ERR("[motor_ramp] PWM_SERVO_SET_ARM_OK");
		return 1;
	}

	/* tell IO/FMU that the system is armed (it will output values if safety is off) */
	if (px4_ioctl(fd, PWM_SERVO_ARM, 0) != OK) {
		PX4_ERR("[motor_ramp] PWM_SERVO_ARM");
		return 1;
	}

	/* tell IO to switch off safety without using the safety switch */
	if (px4_ioctl(fd, PWM_SERVO_SET_FORCE_SAFETY_OFF, 0) != OK) {
		PX4_ERR("[motor_ramp] PWM_SERVO_SET_FORCE_SAFETY_OFF");
		return 1;
	}

	return 0;
}

int motor_ramp_thread_main(int argc, char *argv[])
{
	PX4_WARN("[motor_ramp] starting");

	_thread_running = true;

	char *dev = PWM_OUTPUT0_DEVICE_PATH;
	unsigned long max_channels = 0;

	int fd = px4_open(dev, 0);

	if (fd < 0) {
		PX4_ERR("[motor_ramp] can't open %s", dev);
	}

	if (prepare(fd, &max_channels) != OK) {
		_thread_should_exit = true;
	}

	PX4_WARN("[motor_ramp] max chan: %lu", max_channels);

	set_out(fd, max_channels, 0.0f);

	float dt = 0.01f; // prevent division with 0
	float timer = 0.0f;
	hrt_abstime start = 0;
	hrt_abstime last_run = 0;

	enum RampState ramp_state = RAMP_INIT;
	float output = 0.0f;

	while (!_thread_should_exit) {
		if (last_run > 0) {
			dt = hrt_elapsed_time(&last_run) * 1e-6;

		} else {
			start = hrt_absolute_time();
		}

		last_run = hrt_absolute_time();
		timer = hrt_elapsed_time(&start) * 1e-6;

		switch (ramp_state) {
		case RAMP_INIT: {
				PX4_WARN("[motor_ramp] setting pwm min: %d", _min_pwm);
				set_min_pwm(fd, max_channels, _min_pwm);
				ramp_state = RAMP_MIN;
				break;
			}

		case RAMP_MIN: {
				if (timer > 3.0f) {
					PX4_WARN("[motor_ramp] starting ramp: %.2f sec", (double)_ramp_time);
					start = hrt_absolute_time();
					ramp_state = RAMP_RAMP;
				}

				set_out(fd, max_channels, output);
				break;
			}

		case RAMP_RAMP: {
				output += dt / _ramp_time;

				if (output > 1.0f) {
					output = 1.0f;
					start = hrt_absolute_time();
					ramp_state = RAMP_WAIT;
					PX4_WARN("[motor_ramp] ramp finished, waiting");
				}

				set_out(fd, max_channels, output);
				break;
			}

		case RAMP_WAIT: {
				if (timer > 1.0f) {
					_thread_should_exit = true;
					break;
				}

				set_out(fd, max_channels, output);
				break;
			}
		}

		// rate limit
		usleep(2000);
	}

	if (fd >= 0) {
		/* disarm */
		ioctl(fd, PWM_SERVO_DISARM, 0);

		px4_close(fd);
	}

	PX4_WARN("[motor_ramp] exiting");

	_thread_running = false;

	return 0;
}
<commit_msg>added option to output sine wave<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2012-2015 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file motor_ramp.cpp
 * Application to test motor ramp up.
 *
 * @author Andreas Antener <andreas@uaventure.com>
 * @author Roman Bapst <bapstroman@gmail.com>
 */

#include <px4_config.h>
#include <px4_defines.h>
#include <px4_tasks.h>
#include <px4_posix.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include <poll.h>

#include <arch/board/board.h>
#include <drivers/drv_hrt.h>
#include <drivers/drv_pwm_output.h>
#include <platforms/px4_defines.h>

#include "systemlib/systemlib.h"
#include "systemlib/err.h"

static bool _thread_should_exit = false;		/**< motor_ramp exit flag */
static bool _thread_running = false;		/**< motor_ramp status flag */
static int _motor_ramp_task;				/**< Handle of motor_ramp task / thread */
static float _ramp_time;
static int _min_pwm;
static bool _sine_output = false;

enum RampState {
	RAMP_INIT,
	RAMP_MIN,
	RAMP_RAMP,
	RAMP_WAIT
};

/**
 * motor_ramp management function.
 */
extern "C" __EXPORT int motor_ramp_main(int argc, char *argv[]);

/**
 * Mainloop of motor_ramp.
 */
int motor_ramp_thread_main(int argc, char *argv[]);

bool min_pwm_valid(unsigned pwm_value);

int set_min_pwm(int fd, unsigned long max_channels, unsigned pwm_value);

int set_out(int fd, unsigned long max_channels, float output);

int prepare(int fd, unsigned long *max_channels);

/**
 * Print the correct usage.
 */
static void usage(const char *reason);

static void
usage(const char *reason)
{
	if (reason) {
		PX4_ERR("[motor_ramp] %s", reason);
	}

	PX4_WARN("[motor_ramp]\n\nWARNING: motors will ramp up to full speed!\n");
	PX4_WARN("[motor_ramp] usage: motor_ramp <min_pwm> <ramp_time> <-s>");
	PX4_WARN("[motor_ramp] setting option <-s> will enable sinus output with period <ramp_time>");
	PX4_WARN("[motor_ramp] example:");
	PX4_WARN("[motor_ramp] nsh> sdlog2 on");
	PX4_WARN("[motor_ramp] nsh> mc_att_control stop");
	PX4_WARN("[motor_ramp] nsh> motor_ramp 1100 0.5\n");
}

/**
 * The motor_ramp app only briefly exists to start
 * the background job. The stack size assigned in the
 * Makefile does only apply to this management task.
 *
 * The actual stack size should be set in the call
 * to task_create().
 */
int motor_ramp_main(int argc, char *argv[])
{
	if (argc < 3) {
		usage("missing parameters");
		return 1;
	}

	if (_thread_running) {
		PX4_WARN("motor_ramp already running\n");
		/* this is not an error */
		return 0;
	}

	_min_pwm = atoi(argv[1]);

	if (!min_pwm_valid(_min_pwm)) {
		usage("min pwm not in range");
		return 1;
	}

	_ramp_time = atof(argv[2]);

	// check if we should apply sine ouput instead of ramp
	if (argc > 3) {
		if (strcmp(argv[3], "-s") == 0) {
			_sine_output = true;
		}
	}

	if (!(_ramp_time > 0)) {
		usage("ramp time must be greater than 0");
		return 1;
	}

	_thread_should_exit = false;
	_motor_ramp_task = px4_task_spawn_cmd("motor_ramp",
					      SCHED_DEFAULT,
					      SCHED_PRIORITY_DEFAULT + 40,
					      2000,
					      motor_ramp_thread_main,
					      (argv) ? (char *const *)&argv[2] : (char *const *)NULL);
	return 0;

	usage("unrecognized command");
	return 1;
}

bool min_pwm_valid(unsigned pwm_value)
{
	return pwm_value > 900 && pwm_value < 1300;
}

int set_min_pwm(int fd, unsigned long max_channels, unsigned pwm_value)
{
	int ret;

	struct pwm_output_values pwm_values;
	memset(&pwm_values, 0, sizeof(pwm_values));

	pwm_values.channel_count = max_channels;

	for (int i = 0; i < max_channels; i++) {
		pwm_values.values[i] = pwm_value;
	}

	ret = px4_ioctl(fd, PWM_SERVO_SET_MIN_PWM, (long unsigned int)&pwm_values);

	if (ret != OK) {
		PX4_ERR("[motor_ramp] failed setting min values");
		return 1;
	}

	return 0;
}

int set_out(int fd, unsigned long max_channels, float output)
{
	int ret;
	int pwm = (2000 - _min_pwm) * output + _min_pwm;

	for (unsigned i = 0; i < max_channels; i++) {

		ret = ioctl(fd, PWM_SERVO_SET(i), pwm);

		if (ret != OK) {
			PX4_ERR("PWM_SERVO_SET(%d), value: %d", i, pwm);
			return 1;
		}
	}

	return 0;
}

int prepare(int fd, unsigned long *max_channels)
{
	/* get number of channels available on the device */
	if (px4_ioctl(fd, PWM_SERVO_GET_COUNT, (unsigned long)max_channels) != OK) {
		PX4_ERR("[motor_ramp] PWM_SERVO_GET_COUNT");
		return 1;
	}

	/* tell IO/FMU that its ok to disable its safety with the switch */
	if (px4_ioctl(fd, PWM_SERVO_SET_ARM_OK, 0) != OK) {
		PX4_ERR("[motor_ramp] PWM_SERVO_SET_ARM_OK");
		return 1;
	}

	/* tell IO/FMU that the system is armed (it will output values if safety is off) */
	if (px4_ioctl(fd, PWM_SERVO_ARM, 0) != OK) {
		PX4_ERR("[motor_ramp] PWM_SERVO_ARM");
		return 1;
	}

	/* tell IO to switch off safety without using the safety switch */
	if (px4_ioctl(fd, PWM_SERVO_SET_FORCE_SAFETY_OFF, 0) != OK) {
		PX4_ERR("[motor_ramp] PWM_SERVO_SET_FORCE_SAFETY_OFF");
		return 1;
	}

	return 0;
}

int motor_ramp_thread_main(int argc, char *argv[])
{
	PX4_WARN("[motor_ramp] starting");

	_thread_running = true;

	char *dev = PWM_OUTPUT0_DEVICE_PATH;
	unsigned long max_channels = 0;

	int fd = px4_open(dev, 0);

	if (fd < 0) {
		PX4_ERR("[motor_ramp] can't open %s", dev);
	}

	if (prepare(fd, &max_channels) != OK) {
		_thread_should_exit = true;
	}

	PX4_WARN("[motor_ramp] max chan: %lu", max_channels);

	set_out(fd, max_channels, 0.0f);

	float dt = 0.01f; // prevent division with 0
	float timer = 0.0f;
	hrt_abstime start = 0;
	hrt_abstime last_run = 0;

	enum RampState ramp_state = RAMP_INIT;
	float output = 0.0f;

	while (!_thread_should_exit) {
		if (last_run > 0) {
			dt = hrt_elapsed_time(&last_run) * 1e-6;

		} else {
			start = hrt_absolute_time();
		}

		last_run = hrt_absolute_time();
		timer = hrt_elapsed_time(&start) * 1e-6;

		switch (ramp_state) {
		case RAMP_INIT: {
				PX4_WARN("[motor_ramp] setting pwm min: %d", _min_pwm);
				set_min_pwm(fd, max_channels, _min_pwm);
				ramp_state = RAMP_MIN;
				break;
			}

		case RAMP_MIN: {
				if (timer > 3.0f) {
					PX4_WARN("[motor_ramp] starting %s: %.2f sec", _sine_output ? "sine" : "ramp", (double)_ramp_time);
					start = hrt_absolute_time();
					ramp_state = RAMP_RAMP;
				}

				set_out(fd, max_channels, output);
				break;
			}

		case RAMP_RAMP: {
				if (!_sine_output) {
					output += dt / _ramp_time;

				} else {
					// sine outpout with period T = _ramp_time and magnitude between [0,1]
					// phase shift makes sure that it starts at zero when timer is zero
					output = 0.5f * (1.0f + sinf(M_TWOPI_F * timer / (_ramp_time * 1e6f) - M_PI_2_F));
				}

				if ((output > 1.0f && !_sine_output) || (timer > 3.0f * _ramp_time * 1e6f && _sine_output)) {
					// for ramp mode we set output to 1, for sine mode we just leave it as is
					output = _sine_output ? output : 1.0f;
					start = hrt_absolute_time();
					ramp_state = RAMP_WAIT;
					PX4_WARN("[motor_ramp] %s finished, waiting", _sine_output ? "sine" : "ramp");
				}

				set_out(fd, max_channels, output);
				break;
			}

		case RAMP_WAIT: {
				if (timer > 1.0f) {
					_thread_should_exit = true;
					break;
				}

				set_out(fd, max_channels, output);
				break;
			}
		}

		// rate limit
		usleep(2000);
	}

	if (fd >= 0) {
		/* disarm */
		ioctl(fd, PWM_SERVO_DISARM, 0);

		px4_close(fd);
	}

	PX4_WARN("[motor_ramp] exiting");

	_thread_running = false;

	return 0;
}
<|endoftext|>


<commit_before>#ifndef MJOLNIR_GLOBAL_INTERACTION_VALUE
#define MJOLNIR_GLOBAL_INTERACTION_VALUE
#include <vector>

namespace mjolnir
{

template<typename valueT>
class GlobalInteractionValue
{
  public:
    typedef typename std::vector<std::size_t>::iterator iterator;
    typedef typename std::vector<std::size_t>::const_iterator const_iterator;

  public:
    GlobalInteractionValue() = default;
    GlobalInteractionValue(const std::size_t size): values_(size){}
    ~GlobalInteractionValue() = default;

    void emplace(const std::pair<std::size_t, valueT>& val);

    iterator begin(){return indices_.begin();}
    iterator end(){return indices_.end();}
    const_iterator cbegin() const {return indices_.cbegin();}
    const_iterator cend() const {return indices_.cend();}

    valueT&       at(const std::size_t i)       {return values_.at(i);}
    valueT const& at(const std::size_t i) const {return values_.at(i);}
    valueT&       operator[](const std::size_t i)       {return values_[i];}
    valueT const& operator[](const std::size_t i) const {return values_[i];}

  private:
    std::vector<std::size_t> indices_;
    std::vector<valueT>      values_;
};

template<typename valueT>
void GlobalInteractionValue<valueT>::emplace(
        const std::pair<std::size_t, valueT>& val)
{
    indices_.push_back(val.first);
    values_.at(val.first) = val.second;
    return ;
}

} // mjolnir
#endif /* MJOLNIR_GLOBAL_INTERACTION_VALUE */
<commit_msg>remove GlobalInteractionValue<commit_after><|endoftext|>


<commit_before>/*
 * Copyright 2007-2017 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "cgi_client.hxx"
#include "Error.hxx"
#include "cgi_parser.hxx"
#include "pool/pool.hxx"
#include "istream/UnusedPtr.hxx"
#include "istream/Pointer.hxx"
#include "istream/istream_null.hxx"
#include "header_parser.hxx"
#include "stopwatch.hxx"
#include "strmap.hxx"
#include "HttpResponseHandler.hxx"
#include "fb_pool.hxx"
#include "SliceFifoBuffer.hxx"
#include "util/Cast.hxx"
#include "util/Cancellable.hxx"
#include "util/Exception.hxx"

#include <string.h>
#include <stdlib.h>

class CGIClient final : Istream, IstreamHandler, Cancellable {
    Stopwatch *const stopwatch;

    IstreamPointer input;
    SliceFifoBuffer buffer;

    CGIParser parser;

    /**
     * This flag is true while cgi_parse_headers() is calling
     * HttpResponseHandler::InvokeResponse().  In this case,
     * istream_read(cgi->input) is already up in the stack, and must
     * not be called again.
     */
    bool in_response_callback;

    bool had_input, had_output;

    HttpResponseHandler &handler;

public:
    CGIClient(struct pool &_pool, Stopwatch *_stopwatch,
              UnusedIstreamPtr _input,
              HttpResponseHandler &_handler,
              CancellablePointer &cancel_ptr);

    /**
     * @return false if the connection has been closed
     */
    bool ReturnResponse();

    /**
     * Feed data into the input buffer and continue parsing response
     * headers from it.  After this function returns, the response may
     * have been delivered to the response handler, and the caller should
     * post the rest of the specified buffer to the response body stream.
     *
     * Caller must hold pool reference.
     *
     * @return the number of bytes consumed from the specified buffer
     * (moved to the input buffer), 0 if the object has been closed
     */
    size_t FeedHeaders(const void *data, size_t length);

    /**
     * Call FeedHeaders() in a loop, to parse as much as possible.
     *
     * Caller must hold pool reference.
     */
    size_t FeedHeadersLoop(const char *data, size_t length);

    /**
     * Caller must hold pool reference.
     */
    size_t FeedHeadersCheck(const char *data, size_t length);

    size_t FeedBody(const char *data, size_t length);

    /* virtual methods from class Cancellable */
    void Cancel() noexcept override;

    /* virtual methods from class Istream */
    off_t _GetAvailable(bool partial) noexcept override;
    void _Read() noexcept override;
    void _Close() noexcept override;

    /* virtual methods from class IstreamHandler */
    size_t OnData(const void *data, size_t length) override;
    ssize_t OnDirect(FdType type, int fd, size_t max_length) override;
    void OnEof() noexcept override;
    void OnError(std::exception_ptr ep) noexcept override;
};

inline bool
CGIClient::ReturnResponse()
{
    http_status_t status = parser.GetStatus();
    StringMap &headers = parser.GetHeaders();

    if (http_status_is_empty(status)) {
        /* this response does not have a response body, as indicated
           by the HTTP status code */

        stopwatch_event(stopwatch, "empty");
        stopwatch_dump(stopwatch);

        buffer.Free(fb_pool_get());
        input.ClearAndClose();
        handler.InvokeResponse(status, std::move(headers), UnusedIstreamPtr());
        Destroy();
        return false;
    } else if (parser.IsEOF()) {
        /* the response body is empty */

        stopwatch_event(stopwatch, "empty");
        stopwatch_dump(stopwatch);

        buffer.Free(fb_pool_get());
        input.ClearAndClose();
        handler.InvokeResponse(status, std::move(headers),
                               istream_null_new(GetPool()));
        Destroy();
        return false;
    } else {
        stopwatch_event(stopwatch, "headers");

        in_response_callback = true;
        handler.InvokeResponse(status, std::move(headers),
                               UnusedIstreamPtr(this));
        in_response_callback = false;
        return input.IsDefined();
    }
}

inline size_t
CGIClient::FeedHeaders(const void *data, size_t length)
try {
    assert(!parser.AreHeadersFinished());

    auto w = buffer.Write();
    assert(!w.empty());

    if (length > w.size)
        length = w.size;

    memcpy(w.data, data, length);
    buffer.Append(length);

    switch (parser.FeedHeaders(GetPool(), buffer)) {
    case Completion::DONE:
        /* the DONE status can only be triggered by new data that
           was just received; therefore, the amount of data still in
           the buffer (= response body) must be smaller */
        assert(buffer.GetAvailable() < length);

        if (!ReturnResponse())
            return 0;

        /* don't consider data still in the buffer (= response body)
           as "consumed"; the caller will attempt to submit it to the
           response body handler */
        return length - buffer.GetAvailable();

    case Completion::MORE:
        return length;

    case Completion::CLOSED:
        /* unreachable */
        assert(false);
        return 0;
    }

    /* unreachable */
    assert(false);
    return 0;
} catch (...) {
    buffer.Free(fb_pool_get());
    input.ClearAndClose();
    handler.InvokeError(std::current_exception());
    Destroy();
    return 0;
}

inline size_t
CGIClient::FeedHeadersLoop(const char *data, size_t length)
{
    assert(length > 0);
    assert(!parser.AreHeadersFinished());

    size_t consumed = 0;

    do {
        size_t nbytes = FeedHeaders(data + consumed, length - consumed);
        if (nbytes == 0)
            break;

        consumed += nbytes;
    } while (consumed < length && !parser.AreHeadersFinished());

    if (!input.IsDefined())
        return 0;

    return consumed;
}

inline size_t
CGIClient::FeedHeadersCheck(const char *data, size_t length)
{
    size_t nbytes = FeedHeadersLoop(data, length);

    assert(nbytes == 0 || input.IsDefined());
    assert(nbytes == 0 ||
           !parser.AreHeadersFinished() ||
           !parser.IsEOF());

    return nbytes;
}

inline size_t
CGIClient::FeedBody(const char *data, size_t length)
{
    if (parser.IsTooMuch(length)) {
        stopwatch_event(stopwatch, "malformed");
        stopwatch_dump(stopwatch);

        buffer.Free(fb_pool_get());
        input.ClearAndClose();

        DestroyError(std::make_exception_ptr(CgiError("too much data from CGI script")));
        return 0;
    }

    had_output = true;

    size_t nbytes = InvokeData(data, length);
    if (nbytes > 0 && parser.BodyConsumed(nbytes)) {
        stopwatch_event(stopwatch, "end");
        stopwatch_dump(stopwatch);

        buffer.Free(fb_pool_get());
        input.ClearAndClose();
        DestroyEof();
        return 0;
    }

    return nbytes;
}

/*
 * input handler
 *
 */

inline size_t
CGIClient::OnData(const void *data, size_t length)
{
    assert(input.IsDefined());

    had_input = true;

    if (!parser.AreHeadersFinished()) {
        const ScopePoolRef ref(GetPool() TRACE_ARGS);

        size_t nbytes = FeedHeadersCheck((const char *)data, length);

        if (nbytes > 0 && nbytes < length &&
            parser.AreHeadersFinished()) {
            /* the headers are finished; now begin sending the
               response body */
            size_t nbytes2 = FeedBody((const char *)data + nbytes,
                                      length - nbytes);
            if (nbytes2 > 0)
                /* more data was consumed */
                nbytes += nbytes2;
            else if (!input.IsDefined())
                /* the connection was closed, must return 0 */
                nbytes = 0;
        }

        return nbytes;
    } else {
        return FeedBody((const char *)data, length);
    }
}

inline ssize_t
CGIClient::OnDirect(FdType type, int fd, size_t max_length)
{
    assert(parser.AreHeadersFinished());

    had_input = true;
    had_output = true;

    if (parser.KnownLength() &&
        (off_t)max_length > parser.GetAvailable())
        max_length = (size_t)parser.GetAvailable();

    ssize_t nbytes = InvokeDirect(type, fd, max_length);
    if (nbytes > 0 && parser.BodyConsumed(nbytes)) {
        stopwatch_event(stopwatch, "end");
        stopwatch_dump(stopwatch);

        buffer.Free(fb_pool_get());
        input.Close();
        DestroyEof();
        return ISTREAM_RESULT_CLOSED;
    }

    return nbytes;
}

void
CGIClient::OnEof() noexcept
{
    input.Clear();

    if (!parser.AreHeadersFinished()) {
        stopwatch_event(stopwatch, "malformed");
        stopwatch_dump(stopwatch);

        assert(!HasHandler());

        buffer.Free(fb_pool_get());

        handler.InvokeError(std::make_exception_ptr(CgiError("premature end of headers from CGI script")));
        Destroy();
    } else if (parser.DoesRequireMore()) {
        stopwatch_event(stopwatch, "malformed");
        stopwatch_dump(stopwatch);

        buffer.Free(fb_pool_get());

        DestroyError(std::make_exception_ptr(CgiError("premature end of response body from CGI script")));
    } else {
        stopwatch_event(stopwatch, "end");
        stopwatch_dump(stopwatch);

        buffer.Free(fb_pool_get());
        DestroyEof();
    }
}

void
CGIClient::OnError(std::exception_ptr ep) noexcept
{
    stopwatch_event(stopwatch, "abort");
    stopwatch_dump(stopwatch);

    input.Clear();

    if (!parser.AreHeadersFinished()) {
        /* the response hasn't been sent yet: notify the response
           handler */
        assert(!HasHandler());

        buffer.Free(fb_pool_get());

        handler.InvokeError(NestException(ep,
                                          std::runtime_error("CGI request body failed")));
        Destroy();
    } else {
        /* response has been sent: abort only the output stream */
        buffer.Free(fb_pool_get());
        DestroyError(ep);
    }
}

/*
 * istream implementation
 *
 */

off_t
CGIClient::_GetAvailable(bool partial) noexcept
{
    if (parser.KnownLength())
        return parser.GetAvailable();

    if (!input.IsDefined())
        return 0;

    if (in_response_callback)
        /* this condition catches the case in cgi_parse_headers():
           HttpResponseHandler::InvokeResponse() might
           recursively call istream_read(input) */
        return (off_t)-1;

    return input.GetAvailable(partial);
}

void
CGIClient::_Read() noexcept
{
    if (input.IsDefined()) {
        input.SetDirect(GetHandlerDirect());

        /* this condition catches the case in cgi_parse_headers():
           HttpResponseHandler::InvokeResponse() might
           recursively call input.Read() */
        if (in_response_callback) {
            return;
        }

        const ScopePoolRef ref(GetPool() TRACE_ARGS);

        had_output = false;
        do {
            had_input = false;
            input.Read();
        } while (input.IsDefined() && had_input && !had_output);
    }
}

void
CGIClient::_Close() noexcept
{
    buffer.Free(fb_pool_get());

    if (input.IsDefined())
        input.ClearAndClose();

    Destroy();
}

/*
 * async operation
 *
 */

void
CGIClient::Cancel() noexcept
{
    assert(input.IsDefined());

    buffer.Free(fb_pool_get());
    input.Close();
    Destroy();
}

/*
 * constructor
 *
 */

inline
CGIClient::CGIClient(struct pool &_pool, Stopwatch *_stopwatch,
                     UnusedIstreamPtr _input,
                     HttpResponseHandler &_handler,
                     CancellablePointer &cancel_ptr)
    :Istream(_pool),
     stopwatch(_stopwatch),
     input(std::move(_input), *this),
     buffer(fb_pool_get()),
     parser(_pool),
     handler(_handler)
{
    cancel_ptr = *this;

    input.Read();
}

void
cgi_client_new(struct pool &pool, Stopwatch *stopwatch,
               UnusedIstreamPtr input,
               HttpResponseHandler &handler,
               CancellablePointer &cancel_ptr)
{
    NewFromPool<CGIClient>(pool, pool, stopwatch, std::move(input),
                           handler, cancel_ptr);
}
<commit_msg>cgi/Client: use class DestructObserver instead of accessing destructed instances<commit_after>/*
 * Copyright 2007-2017 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "cgi_client.hxx"
#include "Error.hxx"
#include "cgi_parser.hxx"
#include "pool/pool.hxx"
#include "istream/UnusedPtr.hxx"
#include "istream/Pointer.hxx"
#include "istream/istream_null.hxx"
#include "header_parser.hxx"
#include "stopwatch.hxx"
#include "strmap.hxx"
#include "HttpResponseHandler.hxx"
#include "fb_pool.hxx"
#include "SliceFifoBuffer.hxx"
#include "util/Cast.hxx"
#include "util/Cancellable.hxx"
#include "util/DestructObserver.hxx"
#include "util/Exception.hxx"

#include <string.h>
#include <stdlib.h>

class CGIClient final : Istream, IstreamHandler, Cancellable, DestructAnchor {
    Stopwatch *const stopwatch;

    IstreamPointer input;
    SliceFifoBuffer buffer;

    CGIParser parser;

    /**
     * This flag is true while cgi_parse_headers() is calling
     * HttpResponseHandler::InvokeResponse().  In this case,
     * istream_read(cgi->input) is already up in the stack, and must
     * not be called again.
     */
    bool in_response_callback;

    bool had_input, had_output;

    HttpResponseHandler &handler;

public:
    CGIClient(struct pool &_pool, Stopwatch *_stopwatch,
              UnusedIstreamPtr _input,
              HttpResponseHandler &_handler,
              CancellablePointer &cancel_ptr);

    /**
     * @return false if the connection has been closed
     */
    bool ReturnResponse();

    /**
     * Feed data into the input buffer and continue parsing response
     * headers from it.  After this function returns, the response may
     * have been delivered to the response handler, and the caller should
     * post the rest of the specified buffer to the response body stream.
     *
     * Caller must hold pool reference.
     *
     * @return the number of bytes consumed from the specified buffer
     * (moved to the input buffer), 0 if the object has been closed
     */
    size_t FeedHeaders(const void *data, size_t length);

    /**
     * Call FeedHeaders() in a loop, to parse as much as possible.
     *
     * Caller must hold pool reference.
     */
    size_t FeedHeadersLoop(const char *data, size_t length);

    /**
     * Caller must hold pool reference.
     */
    size_t FeedHeadersCheck(const char *data, size_t length);

    size_t FeedBody(const char *data, size_t length);

    /* virtual methods from class Cancellable */
    void Cancel() noexcept override;

    /* virtual methods from class Istream */
    off_t _GetAvailable(bool partial) noexcept override;
    void _Read() noexcept override;
    void _Close() noexcept override;

    /* virtual methods from class IstreamHandler */
    size_t OnData(const void *data, size_t length) override;
    ssize_t OnDirect(FdType type, int fd, size_t max_length) override;
    void OnEof() noexcept override;
    void OnError(std::exception_ptr ep) noexcept override;
};

inline bool
CGIClient::ReturnResponse()
{
    const ScopePoolRef ref(GetPool() TRACE_ARGS);
    http_status_t status = parser.GetStatus();
    StringMap &headers = parser.GetHeaders();

    if (http_status_is_empty(status)) {
        /* this response does not have a response body, as indicated
           by the HTTP status code */

        stopwatch_event(stopwatch, "empty");
        stopwatch_dump(stopwatch);

        buffer.Free(fb_pool_get());
        input.ClearAndClose();
        handler.InvokeResponse(status, std::move(headers), UnusedIstreamPtr());
        Destroy();
        return false;
    } else if (parser.IsEOF()) {
        /* the response body is empty */

        stopwatch_event(stopwatch, "empty");
        stopwatch_dump(stopwatch);

        buffer.Free(fb_pool_get());
        input.ClearAndClose();
        handler.InvokeResponse(status, std::move(headers),
                               istream_null_new(GetPool()));
        Destroy();
        return false;
    } else {
        stopwatch_event(stopwatch, "headers");

        const DestructObserver destructed(*this);

        in_response_callback = true;
        handler.InvokeResponse(status, std::move(headers),
                               UnusedIstreamPtr(this));
        if (destructed)
            return false;

        in_response_callback = false;
        return true;
    }
}

inline size_t
CGIClient::FeedHeaders(const void *data, size_t length)
try {
    assert(!parser.AreHeadersFinished());

    auto w = buffer.Write();
    assert(!w.empty());

    if (length > w.size)
        length = w.size;

    memcpy(w.data, data, length);
    buffer.Append(length);

    switch (parser.FeedHeaders(GetPool(), buffer)) {
    case Completion::DONE:
        /* the DONE status can only be triggered by new data that
           was just received; therefore, the amount of data still in
           the buffer (= response body) must be smaller */
        assert(buffer.GetAvailable() < length);

        if (!ReturnResponse())
            return 0;

        /* don't consider data still in the buffer (= response body)
           as "consumed"; the caller will attempt to submit it to the
           response body handler */
        return length - buffer.GetAvailable();

    case Completion::MORE:
        return length;

    case Completion::CLOSED:
        /* unreachable */
        assert(false);
        return 0;
    }

    /* unreachable */
    assert(false);
    return 0;
} catch (...) {
    buffer.Free(fb_pool_get());
    input.ClearAndClose();
    handler.InvokeError(std::current_exception());
    Destroy();
    return 0;
}

inline size_t
CGIClient::FeedHeadersLoop(const char *data, size_t length)
{
    assert(length > 0);
    assert(!parser.AreHeadersFinished());

    const DestructObserver destructed(*this);
    size_t consumed = 0;

    do {
        size_t nbytes = FeedHeaders(data + consumed, length - consumed);
        if (nbytes == 0)
            break;

        consumed += nbytes;
    } while (consumed < length && !parser.AreHeadersFinished());

    if (destructed)
        return 0;

    return consumed;
}

inline size_t
CGIClient::FeedHeadersCheck(const char *data, size_t length)
{
    size_t nbytes = FeedHeadersLoop(data, length);

    assert(nbytes == 0 || input.IsDefined());
    assert(nbytes == 0 ||
           !parser.AreHeadersFinished() ||
           !parser.IsEOF());

    return nbytes;
}

inline size_t
CGIClient::FeedBody(const char *data, size_t length)
{
    if (parser.IsTooMuch(length)) {
        stopwatch_event(stopwatch, "malformed");
        stopwatch_dump(stopwatch);

        buffer.Free(fb_pool_get());
        input.ClearAndClose();

        DestroyError(std::make_exception_ptr(CgiError("too much data from CGI script")));
        return 0;
    }

    had_output = true;

    size_t nbytes = InvokeData(data, length);
    if (nbytes > 0 && parser.BodyConsumed(nbytes)) {
        stopwatch_event(stopwatch, "end");
        stopwatch_dump(stopwatch);

        buffer.Free(fb_pool_get());
        input.ClearAndClose();
        DestroyEof();
        return 0;
    }

    return nbytes;
}

/*
 * input handler
 *
 */

inline size_t
CGIClient::OnData(const void *data, size_t length)
{
    assert(input.IsDefined());

    had_input = true;

    if (!parser.AreHeadersFinished()) {
        size_t nbytes = FeedHeadersCheck((const char *)data, length);

        if (nbytes > 0 && nbytes < length &&
            parser.AreHeadersFinished()) {
            /* the headers are finished; now begin sending the
               response body */
            const DestructObserver destructed(*this);
            size_t nbytes2 = FeedBody((const char *)data + nbytes,
                                      length - nbytes);
            if (nbytes2 > 0)
                /* more data was consumed */
                nbytes += nbytes2;
            else if (destructed)
                /* the connection was closed, must return 0 */
                nbytes = 0;
        }

        return nbytes;
    } else {
        return FeedBody((const char *)data, length);
    }
}

inline ssize_t
CGIClient::OnDirect(FdType type, int fd, size_t max_length)
{
    assert(parser.AreHeadersFinished());

    had_input = true;
    had_output = true;

    if (parser.KnownLength() &&
        (off_t)max_length > parser.GetAvailable())
        max_length = (size_t)parser.GetAvailable();

    ssize_t nbytes = InvokeDirect(type, fd, max_length);
    if (nbytes > 0 && parser.BodyConsumed(nbytes)) {
        stopwatch_event(stopwatch, "end");
        stopwatch_dump(stopwatch);

        buffer.Free(fb_pool_get());
        input.Close();
        DestroyEof();
        return ISTREAM_RESULT_CLOSED;
    }

    return nbytes;
}

void
CGIClient::OnEof() noexcept
{
    input.Clear();

    if (!parser.AreHeadersFinished()) {
        stopwatch_event(stopwatch, "malformed");
        stopwatch_dump(stopwatch);

        assert(!HasHandler());

        buffer.Free(fb_pool_get());

        handler.InvokeError(std::make_exception_ptr(CgiError("premature end of headers from CGI script")));
        Destroy();
    } else if (parser.DoesRequireMore()) {
        stopwatch_event(stopwatch, "malformed");
        stopwatch_dump(stopwatch);

        buffer.Free(fb_pool_get());

        DestroyError(std::make_exception_ptr(CgiError("premature end of response body from CGI script")));
    } else {
        stopwatch_event(stopwatch, "end");
        stopwatch_dump(stopwatch);

        buffer.Free(fb_pool_get());
        DestroyEof();
    }
}

void
CGIClient::OnError(std::exception_ptr ep) noexcept
{
    stopwatch_event(stopwatch, "abort");
    stopwatch_dump(stopwatch);

    input.Clear();

    if (!parser.AreHeadersFinished()) {
        /* the response hasn't been sent yet: notify the response
           handler */
        assert(!HasHandler());

        buffer.Free(fb_pool_get());

        handler.InvokeError(NestException(ep,
                                          std::runtime_error("CGI request body failed")));
        Destroy();
    } else {
        /* response has been sent: abort only the output stream */
        buffer.Free(fb_pool_get());
        DestroyError(ep);
    }
}

/*
 * istream implementation
 *
 */

off_t
CGIClient::_GetAvailable(bool partial) noexcept
{
    if (parser.KnownLength())
        return parser.GetAvailable();

    if (!input.IsDefined())
        return 0;

    if (in_response_callback)
        /* this condition catches the case in cgi_parse_headers():
           HttpResponseHandler::InvokeResponse() might
           recursively call istream_read(input) */
        return (off_t)-1;

    return input.GetAvailable(partial);
}

void
CGIClient::_Read() noexcept
{
    if (input.IsDefined()) {
        input.SetDirect(GetHandlerDirect());

        /* this condition catches the case in cgi_parse_headers():
           HttpResponseHandler::InvokeResponse() might
           recursively call input.Read() */
        if (in_response_callback) {
            return;
        }

        const DestructObserver destructed(*this);

        had_output = false;
        do {
            had_input = false;
            input.Read();
        } while (!destructed && input.IsDefined() && had_input && !had_output);
    }
}

void
CGIClient::_Close() noexcept
{
    buffer.Free(fb_pool_get());

    if (input.IsDefined())
        input.ClearAndClose();

    Destroy();
}

/*
 * async operation
 *
 */

void
CGIClient::Cancel() noexcept
{
    assert(input.IsDefined());

    buffer.Free(fb_pool_get());
    input.Close();
    Destroy();
}

/*
 * constructor
 *
 */

inline
CGIClient::CGIClient(struct pool &_pool, Stopwatch *_stopwatch,
                     UnusedIstreamPtr _input,
                     HttpResponseHandler &_handler,
                     CancellablePointer &cancel_ptr)
    :Istream(_pool),
     stopwatch(_stopwatch),
     input(std::move(_input), *this),
     buffer(fb_pool_get()),
     parser(_pool),
     handler(_handler)
{
    cancel_ptr = *this;

    input.Read();
}

void
cgi_client_new(struct pool &pool, Stopwatch *stopwatch,
               UnusedIstreamPtr input,
               HttpResponseHandler &handler,
               CancellablePointer &cancel_ptr)
{
    NewFromPool<CGIClient>(pool, pool, stopwatch, std::move(input),
                           handler, cancel_ptr);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <sstream>
#include <cstring>
#include <string>
using namespace std;

int stoi(string c)
{
    stringstream ss;
    ss << c;
    int i;
    ss >> i;
    ss.clear();
    ss.str("");
    return i;
}

string itos(int i)
{
    stringstream ss;
    ss << i;
    string s;
    ss >> s;
    ss.clear();
    ss.str("");
    return s;
}

int main()
{
	string dividend;int divisor;
	cin>>dividend>>divisor;
	string quotient = "";int remainder;
	bool (*isdivided) = new bool[dividend.length()];memset(isdivided,false,sizeof(bool)*dividend.length());
	for(int i = 0;i < dividend.length();i++)
    {
        if(!isdivided[i])
        {
            if(i != dividend.length()-2)
            {
                if(stoi(dividend.substr(i,1)) / divisor != 0)
                {
                    quotient += itos(stoi(dividend.substr(i,1)) / divisor);
                    if(stoi(dividend.substr(i,1)) % divisor != 0) dividend = itos(stoi(dividend.substr(i,1)) % divisor) + dividend.substr(i+1,dividend.length()-1);
                    else isdivided[i] = true;
                }
                else
                {
                    quotient += itos(stoi(dividend.substr(i,2)) / divisor);
                    if(stoi(dividend.substr(i,2)) % divisor != 0)
                    {
                        dividend = itos(stoi(dividend.substr(i,2)) % divisor) + dividend.substr(i+2,dividend.length()-2);
                        isdivided[i] = true;
                    }
                    else isdivided[i+1] = isdivided[i] = true;
                }
            }
            else
            {
                if(stoi(dividend.substr(i,1)) / divisor != 0)
                {
                    quotient += itos(stoi(dividend.substr(i,1)) / divisor);
                    quotient += itos(stoi(dividend.substr(i+1,1)) / divisor);
                    remainder = stoi(dividend.substr(i+1,1)) % divisor;
                    isdivided[i+1] = isdivided[i] = true;
                }
                else
                {
                    quotient += itos(stoi(dividend.substr(i,2)) / divisor);
                    remainder = stoi(dividend.substr(i,2)) % divisor;
                    isdivided[i+1] = isdivided[i] = true;
                }
            }
        }
    }
    delete [] isdivided;
    cout<<quotient<<" "<<remainder<<endl;
}
<commit_msg>Update 1017.cpp<commit_after>#include <iostream>
#include <sstream>
#include <string>
using namespace std;

string itos(int i)
{
    stringstream ss;
    ss << i;
    string s;
    ss >> s;
    ss.clear();
    ss.str("");
    return s;
}

int main()
{
    string dividend;int divisor;
    cin>>dividend>>divisor;
    string quotient = "";int remainder = 0;
    if(dividend.size() == 1)
    {
        quotient = itos(stoi(dividend) / divisor);
        remainder = stoi(dividend) % divisor;
    }
    else
    {
        for(int i = 0;i < dividend.size();i++)
        {
            remainder *= 10;
            remainder += stoi(dividend.substr(i,1));
            if(remainder / divisor)
            {
                quotient.append(itos(remainder / divisor));
                remainder %= divisor;
            }
            else quotient.append("0");
        }
        if(quotient.substr(0,1) == "0") quotient.erase(0,1);
    }
    cout<<quotient<<" "<<remainder<<endl;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <cstring>
using namespace std;

int jcu(char a)
{
    if(a >= 65 && a <= 90) return a-65;
    else return -1;
}

int jcd(char a)
{
    if(a >= 97 && a <= 122) return a-97;
    else return -1;
}

int jn(char a)
{
    if(a >= '0' && a <='9') return a-48;
    else return -1;
}

int main()
{
	string a,b;string u = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";string d = "abcdefghijklmnopqrstuvwxyz";
	cin>>a>>b;
	string c = "";
	bool (*pcu) = new bool[26];memset(pcu,false,sizeof(bool)*26);
	bool (*pcd) = new bool[26];memset(pcd,false,sizeof(bool)*26);
	bool (*pn) = new bool[10];memset(pn,false,sizeof(bool)*10);
	for(int i = 0;i < a.length();i++)
    {
        if(jcu(a[i]) != -1) pcu[jcu(a[i])] = true;
        else if(jcd(a[i]) != -1) pcd[jcd(a[i])] = true;
        else if(jn(a[i]) != -1) pn[jn(a[i])] = true;
    }
    /*for(int i = 0;i < a.length();i++)
    {
        if(jcu(a[i]) != -1)
        {
            if(u[jcu(a[i])] == a[i] && pcu[jcu(a[i])])
                c += a[i];
        }
        else if(jcd(a[i]) != -1)
        {
             if(d[jcd(a[i])] == a[i] && pcd[jcd(a[i])])
                c += a[i];
        }
        else if(jn(a[i]) != -1)
        {
            if((jn(a[i]) + 48) == a[i] && pn[jn(a[i])])
                c += a[i];
        }
    }*/
    for(int i = 0;i < 26;i++)
    {
        if(pcu[])
    }
    delete [] pcu;delete [] pcd;delete [] pn;u.~string();d.~string();
    cout<<c<<endl;
    for(int i = 0;i < c.length();i++)
    {
        if(b.find(c[i]) == b.npos)
        {
            if(jcd(c[i]) != -1) cout<<(char)(c[i]+32);
            else cout<<c[i];
        }
    }
    cout<<endl;
}
<commit_msg>Update 1029.cpp<commit_after>#include <iostream>
#include <algorithm>
#include <string>
#include <cctype>
#include <cstring>
using namespace std;

int main()
{
    string a,b;
    cin>>a>>b;
    string p = "";
    for(;a.size();)
    {
        if(a.front() != b.front())
        {
            if((p.find(toupper(a.front())) == string::npos) && (p.find(tolower(a.front())) == string::npos))
                p.push_back(*a.begin());
        }
        else b.erase(0,1);
        a.erase(0,1);
    }
    transform(p.begin(),p.end(),p.begin(),::toupper);
    cout<<p<<endl;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <osgGA/GUIActionAdapter>
#include <osgGA/GUIEventAdapter>
#include <osgGA/GUIEventHandler>

#include "control.h"
#include "../networks/client.h"
#include "../networks/netpacket.h"
#include "../networks/packetprotos.pb.h"
#include "../engines/physics/physics.h"

float ClientControl::UIEventHandler::get_prev_x() {
	return this->prev_x;
}

float ClientControl::UIEventHandler::get_prev_y() {
	return this->prev_y;
}

void ClientControl::UIEventHandler::set_prev_x(float x) {
	this->prev_x = x;
}

void ClientControl::UIEventHandler::set_prev_y(float y) {
	this->prev_y = y;
}

ClientControl::UIEventHandler::UIEventHandler(ClientNetUtils* net_utils) {
	this->net_utils = net_utils;
	this->is_pressing_accel = false;
	this->is_pressing_brake = false;
	this->prev_x = 0;
	this->prev_y = 0;
}

bool ClientControl::UIEventHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter&) {
	switch(ea.getEventType()) {
		case(osgGA::GUIEventAdapter::KEYDOWN):
			{
				switch(ea.getKey()) {
					case osgGA::GUIEventAdapter::KEY_Up:
					{
						if (this->is_pressing_accel == false) {
							this->is_pressing_accel = true;
							int action = Action::ACCEL;
							NetPacket packet;
							PacketUtils::make_packet(&packet, PacketType::CONTROL_INPUT, (void *) &action, NULL);
							if (net_utils->send_to_server(&packet))
								std::cout << "Sent accel control packet." << std::endl;
						}
					}
						return false;
						break;
					case osgGA::GUIEventAdapter::KEY_Down:
					{
						if (this->is_pressing_brake == false) {
							this->is_pressing_brake = true;
							int action = Action::BRAKE;
							NetPacket packet;
							PacketUtils::make_packet(&packet, PacketType::CONTROL_INPUT, (void *) &action, NULL);
							if (net_utils->send_to_server(&packet))
								std::cout << "Sent brake control packet." << std::endl;
						}
					}
						return false;
						break;
					case osgGA::GUIEventAdapter::KEY_Space:
					{
						int action = Action::BULLET;
						NetPacket packet;
						PacketUtils::make_packet(&packet, PacketType::CONTROL_INPUT, (void *) &action, NULL);
						if (net_utils->send_to_server(&packet))
							std::cout << "Sent bullet control packet." << std::endl;
					}
						return false;
						break;
					default:
						return false;
				}
			}
		case(osgGA::GUIEventAdapter::KEYUP):
			{
				switch(ea.getKey()) {
					case osgGA::GUIEventAdapter::KEY_Up:
					case osgGA::GUIEventAdapter::KEY_Down:
					{
						this->is_pressing_accel = false;
						this->is_pressing_brake = false;
						int action = Action::RESET_ACCEL;
						NetPacket packet;
						PacketUtils::make_packet(&packet, PacketType::CONTROL_INPUT, (void *) &action, NULL);
						if (net_utils->send_to_server(&packet))
							std::cout << "Sent reset acceleration control packet." << std::endl;
					}
						return false;
						break;
					default:
						return false;
				}
			}
		case(osgGA::GUIEventAdapter::MOVE):
			{
				int action = Action::ROLL_TILT;
				NetPacket packet;
				float prev_x = get_prev_x();
				float mouse_x = ea.getXnormalized();
				float bin_x = 0;

				if (-0.5 <= mouse_x <= 0.5) {
					bin_x = 0;
				} else if (mouse_x > 0.5) {
					bin_x = ((mouse_x - 0.5) * 2 * 100) % 10) * 0.1;
				} else {
					bin_x = ((mouse_x + 0.5) * 2 * 100) % 10) * 0.1;
				}

				if (bin_x != prev_x) {
					PacketUtils::make_packet(&packet, PacketType::CONTROL_INPUT, (void *) &action, (void *) &(mouse_x));
					if (net_utils->send_to_server(&packet))
						std::cout << "Sent roll tilt control packet." << std::endl;
				}
			}
			{
				int action = Action::PITCH_TILT;
				NetPacket packet;
				float prev_y = get_prev_y();
				float mouse_y = ea.getYnormalized();
				float bin_y = 0;

				if (-0.5 <= mouse_y <= 0.5) {
					bin_y = 0;
				} else if (mouse_y > 0.5) {
					bin_y = ((mouse_y - 0.5) * 2 * 100) % 10) * 0.1;
				} else {
					bin_y = ((mouse_y + 0.5) * 2 * 100) % 10) * 0.1;
				}

				if (bix_y != prev_y) {
					PacketUtils::make_packet(&packet, PacketType::CONTROL_INPUT, (void *) &action, (void *) &(mouse_y));
					if (net_utils->send_to_server(&packet))
						std::cout << "Sent pitch tilt control packet." << std::endl;
				}
			}
				return false;
				break;
		default:
			return false;
	}
}

void ClientControl::UIEventHandler::accept(osgGA::GUIEventHandlerVisitor& v) {
	v.visit(*this);
}

void ServerControl::update_physics(int obj_id, int action, void *action_arg, PhysicsEngine *p) {
	if (action == Action::ACCEL) {
		p->toggle_a(obj_id, 1);
	} else if (action == Action::RESET_ACCEL) {
		p->toggle_a(obj_id, 0);
	} else if (action == Action::BRAKE) {
		p->toggle_a(obj_id, -1);
	} else if (action == Action::ROLL_TILT) {
		float *tilt = (float *) action_arg;
		p->toggle_r_dot(obj_id, *tilt);
	} else if (action == Action::PITCH_TILT) {
		float *tilt = (float *) action_arg;
		p->toggle_p_dot(obj_id, *tilt);
	} else if (action == Action::ROLL_TILT) {
		float *tilt = (float *) action_arg;
		p->toggle_r_dot(obj_id, *tilt);
	}
/*
-1.0 : -1.0 -> -.95
-0.9 : -0.95 -> -0.90
-0.8 : -0.90 -> -0.85
-0.7 : -0.85 -> -0.80
-0.6 : -0.80 -> -0.75
-0.5 : -0.75 -> -0.70
-0.4 : -0.70 ->
-0.3 :
-0.2 :
-0.1 :
0 : -0.5 -> 0.5
0.1
0.2
*/
}
<commit_msg>hello<commit_after>#include <iostream>
#include <osgGA/GUIActionAdapter>
#include <osgGA/GUIEventAdapter>
#include <osgGA/GUIEventHandler>

#include "control.h"
#include "../networks/client.h"
#include "../networks/netpacket.h"
#include "../networks/packetprotos.pb.h"
#include "../engines/physics/physics.h"

float ClientControl::UIEventHandler::get_prev_x() {
	return this->prev_x;
}

float ClientControl::UIEventHandler::get_prev_y() {
	return this->prev_y;
}

void ClientControl::UIEventHandler::set_prev_x(float x) {
	this->prev_x = x;
}

void ClientControl::UIEventHandler::set_prev_y(float y) {
	this->prev_y = y;
}

ClientControl::UIEventHandler::UIEventHandler(ClientNetUtils* net_utils) {
	this->net_utils = net_utils;
	this->is_pressing_accel = false;
	this->is_pressing_brake = false;
	this->prev_x = 0;
	this->prev_y = 0;
}

bool ClientControl::UIEventHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter&) {
	switch(ea.getEventType()) {
		case(osgGA::GUIEventAdapter::KEYDOWN):
			{
				switch(ea.getKey()) {
					case osgGA::GUIEventAdapter::KEY_Up:
					{
						if (this->is_pressing_accel == false) {
							this->is_pressing_accel = true;
							int action = Action::ACCEL;
							NetPacket packet;
							PacketUtils::make_packet(&packet, PacketType::CONTROL_INPUT, (void *) &action, NULL);
							if (net_utils->send_to_server(&packet))
								std::cout << "Sent accel control packet." << std::endl;
						}
					}
						return false;
						break;
					case osgGA::GUIEventAdapter::KEY_Down:
					{
						if (this->is_pressing_brake == false) {
							this->is_pressing_brake = true;
							int action = Action::BRAKE;
							NetPacket packet;
							PacketUtils::make_packet(&packet, PacketType::CONTROL_INPUT, (void *) &action, NULL);
							if (net_utils->send_to_server(&packet))
								std::cout << "Sent brake control packet." << std::endl;
						}
					}
						return false;
						break;
					case osgGA::GUIEventAdapter::KEY_Space:
					{
						int action = Action::BULLET;
						NetPacket packet;
						PacketUtils::make_packet(&packet, PacketType::CONTROL_INPUT, (void *) &action, NULL);
						if (net_utils->send_to_server(&packet))
							std::cout << "Sent bullet control packet." << std::endl;
					}
						return false;
						break;
					default:
						return false;
				}
			}
		case(osgGA::GUIEventAdapter::KEYUP):
			{
				switch(ea.getKey()) {
					case osgGA::GUIEventAdapter::KEY_Up:
					case osgGA::GUIEventAdapter::KEY_Down:
					{
						this->is_pressing_accel = false;
						this->is_pressing_brake = false;
						int action = Action::RESET_ACCEL;
						NetPacket packet;
						PacketUtils::make_packet(&packet, PacketType::CONTROL_INPUT, (void *) &action, NULL);
						if (net_utils->send_to_server(&packet))
							std::cout << "Sent reset acceleration control packet." << std::endl;
					}
						return false;
						break;
					default:
						return false;
				}
			}
		case(osgGA::GUIEventAdapter::MOVE):
			{
				int action = Action::ROLL_TILT;
				NetPacket packet;
				float prev_x = get_prev_x();
				float mouse_x = ea.getXnormalized();
				float bin_x = 0;

				bin_x = ((int) (mouse_x * 100) % 10) * 0.1;

				if (bin_x != prev_x) {
					PacketUtils::make_packet(&packet, PacketType::CONTROL_INPUT, (void *) &action, (void *) &(mouse_x));
					if (net_utils->send_to_server(&packet))
						std::cout << "Sent roll tilt control packet." << std::endl;
				}
			}
			{
				int action = Action::PITCH_TILT;
				NetPacket packet;
				float prev_y = get_prev_y();
				float mouse_y = ea.getYnormalized();
				float bin_y = 0;

					bin_y = ((int) (mouse_y * 100) % 10) * 0.1;

				if (bin_y != prev_y) {
					PacketUtils::make_packet(&packet, PacketType::CONTROL_INPUT, (void *) &action, (void *) &(mouse_y));
					if (net_utils->send_to_server(&packet))
						std::cout << "Sent pitch tilt control packet." << std::endl;
				}
			}
				return false;
				break;
		default:
			return false;
	}
}

void ClientControl::UIEventHandler::accept(osgGA::GUIEventHandlerVisitor& v) {
	v.visit(*this);
}

void ServerControl::update_physics(int obj_id, int action, void *action_arg, PhysicsEngine *p) {
	if (action == Action::ACCEL) {
		p->toggle_a(obj_id, 1);
	} else if (action == Action::RESET_ACCEL) {
		p->toggle_a(obj_id, 0);
	} else if (action == Action::BRAKE) {
		p->toggle_a(obj_id, -1);
	} else if (action == Action::ROLL_TILT) {
		float *tilt = (float *) action_arg;
		p->toggle_r_dot(obj_id, *tilt);
	} else if (action == Action::PITCH_TILT) {
		float *tilt = (float *) action_arg;
		p->toggle_p_dot(obj_id, *tilt);
	} else if (action == Action::ROLL_TILT) {
		float *tilt = (float *) action_arg;
		p->toggle_r_dot(obj_id, *tilt);
	}
/*
-1.0 : -1.0 -> -.95
-0.9 : -0.95 -> -0.90
-0.8 : -0.90 -> -0.85
-0.7 : -0.85 -> -0.80
-0.6 : -0.80 -> -0.75
-0.5 : -0.75 -> -0.70
-0.4 : -0.70 ->
-0.3 :
-0.2 :
-0.1 :
0 : -0.5 -> 0.5
0.1
0.2
*/
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2003-2012, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_HASHER_HPP_INCLUDED
#define TORRENT_HASHER_HPP_INCLUDED

#include <boost/cstdint.hpp>

#include "libtorrent/peer_id.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"

#ifdef TORRENT_USE_GCRYPT
#include <gcrypt.h>
#elif defined TORRENT_USE_OPENSSL
extern "C"
{
#include <openssl/sha.h>
}
#else
// from sha1.cpp
namespace libtorrent
{

	struct TORRENT_EXTRA_EXPORT sha_ctx
	{
		boost::uint32_t state[5];
		boost::uint32_t count[2];
		boost::uint8_t buffer[64];
	};

	TORRENT_EXTRA_EXPORT void SHA1_init(sha_ctx* context);
	TORRENT_EXTRA_EXPORT void SHA1_update(sha_ctx* context, boost::uint8_t const* data, boost::uint32_t len);
	TORRENT_EXTRA_EXPORT void SHA1_final(boost::uint8_t* digest, sha_ctx* context);
} // namespace libtorrent

#endif

namespace libtorrent
{
	class hasher
	{
	public:

		hasher()
		{
#ifdef TORRENT_USE_GCRYPT
			gcry_md_open(&m_context, GCRY_MD_SHA1, 0);
#else
			SHA1_init(&m_context);
#endif
		}
		hasher(const char* data, int len)
		{
			TORRENT_ASSERT(data != 0);
			TORRENT_ASSERT(len > 0);
#ifdef TORRENT_USE_GCRYPT
			gcry_md_open(&m_context, GCRY_MD_SHA1, 0);
			gcry_md_write(m_context, data, len);
#else
			SHA1_init(&m_context);
			SHA1_update(&m_context, reinterpret_cast<unsigned char const*>(data), len);
#endif
		}

#ifdef TORRENT_USE_GCRYPT
		hasher(hasher const& h)
		{
			gcry_md_copy(&m_context, h.m_context);
		}

		hasher& operator=(hasher const& h)
		{
			gcry_md_close(m_context);
			gcry_md_copy(&m_context, h.m_context);
			return *this;
		}
#endif

		void update(std::string const& data) { update(data.c_str(), data.size()); }
		void update(const char* data, int len)
		{
			TORRENT_ASSERT(data != 0);
			TORRENT_ASSERT(len > 0);
#ifdef TORRENT_USE_GCRYPT
			gcry_md_write(m_context, data, len);
#else
			SHA1_update(&m_context, reinterpret_cast<unsigned char const*>(data), len);
#endif
		}

		sha1_hash final()
		{
			sha1_hash digest;
#ifdef TORRENT_USE_GCRYPT
			gcry_md_final(m_context);
			digest.assign((const char*)gcry_md_read(m_context, 0));
#else
			SHA1_final(digest.begin(), &m_context);
#endif
			return digest;
		}

		void reset()
		{
#ifdef TORRENT_USE_GCRYPT
			gcry_md_reset(m_context);
#else
			SHA1_init(&m_context);
#endif
		}

#ifdef TORRENT_USE_GCRYPT
		~hasher()
		{
			gcry_md_close(m_context);
		}
#endif

	private:

#ifdef TORRENT_USE_GCRYPT
		gcry_md_hd_t m_context;
#else
		sha_ctx m_context;
#endif
	};
}

#endif // TORRENT_HASHER_HPP_INCLUDED

<commit_msg>fix openssl build<commit_after>/*

Copyright (c) 2003-2012, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_HASHER_HPP_INCLUDED
#define TORRENT_HASHER_HPP_INCLUDED

#include <boost/cstdint.hpp>

#include "libtorrent/peer_id.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"

#ifdef TORRENT_USE_GCRYPT
#include <gcrypt.h>
#elif defined TORRENT_USE_OPENSSL
extern "C"
{
#include <openssl/sha.h>
}
#else
// from sha1.cpp
namespace libtorrent
{

	struct TORRENT_EXTRA_EXPORT sha_ctx
	{
		boost::uint32_t state[5];
		boost::uint32_t count[2];
		boost::uint8_t buffer[64];
	};

	TORRENT_EXTRA_EXPORT void SHA1_init(sha_ctx* context);
	TORRENT_EXTRA_EXPORT void SHA1_update(sha_ctx* context, boost::uint8_t const* data, boost::uint32_t len);
	TORRENT_EXTRA_EXPORT void SHA1_final(boost::uint8_t* digest, sha_ctx* context);
} // namespace libtorrent

#endif

namespace libtorrent
{
	class hasher
	{
	public:

		hasher()
		{
#ifdef TORRENT_USE_GCRYPT
			gcry_md_open(&m_context, GCRY_MD_SHA1, 0);
#elif defined TORRENT_USE_OPENSSL
			SHA1_Init(&m_context);
#else
			SHA1_init(&m_context);
#endif
		}
		hasher(const char* data, int len)
		{
			TORRENT_ASSERT(data != 0);
			TORRENT_ASSERT(len > 0);
#ifdef TORRENT_USE_GCRYPT
			gcry_md_open(&m_context, GCRY_MD_SHA1, 0);
			gcry_md_write(m_context, data, len);
#elif defined TORRENT_USE_OPENSSL
			SHA1_Init(&m_context);
			SHA1_Update(&m_context, reinterpret_cast<unsigned char const*>(data), len);
#else
			SHA1_init(&m_context);
			SHA1_update(&m_context, reinterpret_cast<unsigned char const*>(data), len);
#endif
		}

#ifdef TORRENT_USE_GCRYPT
		hasher(hasher const& h)
		{
			gcry_md_copy(&m_context, h.m_context);
		}

		hasher& operator=(hasher const& h)
		{
			gcry_md_close(m_context);
			gcry_md_copy(&m_context, h.m_context);
			return *this;
		}
#endif

		void update(std::string const& data) { update(data.c_str(), data.size()); }
		void update(const char* data, int len)
		{
			TORRENT_ASSERT(data != 0);
			TORRENT_ASSERT(len > 0);
#ifdef TORRENT_USE_GCRYPT
			gcry_md_write(m_context, data, len);
#elif defined TORRENT_USE_OPENSSL
			SHA1_Update(&m_context, reinterpret_cast<unsigned char const*>(data), len);
#else
			SHA1_update(&m_context, reinterpret_cast<unsigned char const*>(data), len);
#endif
		}

		sha1_hash final()
		{
			sha1_hash digest;
#ifdef TORRENT_USE_GCRYPT
			gcry_md_final(m_context);
			digest.assign((const char*)gcry_md_read(m_context, 0));
#elif defined TORRENT_USE_OPENSSL
			SHA1_Final(digest.begin(), &m_context);
#else
			SHA1_final(digest.begin(), &m_context);
#endif
			return digest;
		}

		void reset()
		{
#ifdef TORRENT_USE_GCRYPT
			gcry_md_reset(m_context);
#elif defined TORRENT_USE_OPENSSL
			SHA1_Init(&m_context);
#else
			SHA1_init(&m_context);
#endif
		}

#ifdef TORRENT_USE_GCRYPT
		~hasher()
		{
			gcry_md_close(m_context);
		}
#endif

	private:

#ifdef TORRENT_USE_GCRYPT
		gcry_md_hd_t m_context;
#elif defined TORRENT_USE_OPENSSL
		SHA_CTX m_context;
#else
		sha_ctx m_context;
#endif
	};
}

#endif // TORRENT_HASHER_HPP_INCLUDED

<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef ETL_EVALUATOR_HPP
#define ETL_EVALUATOR_HPP

#include "traits_lite.hpp"   //forward declaration of the traits
#include "visitor.hpp"   //forward declaration of the traits

namespace etl {

namespace detail {

struct temporary_allocator_static_visitor : etl_visitor<temporary_allocator_static_visitor> {
    template<typename E>
    using enabled = cpp::bool_constant<decay_traits<E>::needs_temporary_visitor>;

    using etl_visitor<temporary_allocator_static_visitor>::operator();

    template <typename T, typename AExpr, typename Op, typename Forced>
    void operator()(etl::temporary_unary_expr<T, AExpr, Op, Forced>& v) const {
        v.allocate_temporary();

        (*this)(v.a());
    }

    template <typename T, typename AExpr, typename BExpr, typename Op, typename Forced>
    void operator()(etl::temporary_binary_expr<T, AExpr, BExpr, Op, Forced>& v) const {
        v.allocate_temporary();

        (*this)(v.a());
        (*this)(v.b());
    }
};

struct evaluator_static_visitor : etl_visitor<evaluator_static_visitor> {
    template<typename E>
    using enabled = cpp::bool_constant<decay_traits<E>::needs_evaluator_visitor>;

    using etl_visitor<evaluator_static_visitor>::operator();

    template <typename T, typename AExpr, typename Op, typename Forced>
    void operator()(etl::temporary_unary_expr<T, AExpr, Op, Forced>& v) const {
        (*this)(v.a());

        v.evaluate();
    }

    template <typename T, typename AExpr, typename BExpr, typename Op, typename Forced>
    void operator()(etl::temporary_binary_expr<T, AExpr, BExpr, Op, Forced>& v) const {
        (*this)(v.a());
        (*this)(v.b());

        v.evaluate();
    }
};

} //end of namespace detail

template<typename Expr, typename Result>
struct standard_evaluator {
    template<typename E>
    static void evaluate_only(E&& expr){
        apply_visitor<detail::temporary_allocator_static_visitor>(expr);
        apply_visitor<detail::evaluator_static_visitor>(expr);
    }

    template<typename E, typename R>
    struct vectorized_assign : cpp::and_u<vectorize_expr, decay_traits<E>::vectorizable, intrinsic_traits<value_t<R>>::vectorizable, intrinsic_traits<value_t<E>>::vectorizable> {};

    template<typename E, typename R, cpp_enable_if(!vectorized_assign<E, R>::value && has_direct_access<E>::value && !is_temporary_expr<E>::value)>
    static void assign_evaluate(E&& expr, R&& result){
        evaluate_only(expr);

        auto m = result.memory_start();

        const std::size_t size = etl::size(result);

        std::size_t iend = 0;

        if(unroll_normal_loops){
            iend = size & std::size_t(-4);

            for(std::size_t i = 0; i < iend; i += 4){
                m[i] = expr[i];
                m[i+1] = expr[i+1];
                m[i+2] = expr[i+2];
                m[i+3] = expr[i+3];
            }
        }

        for(std::size_t i = iend; i < size; ++i){
            m[i] = expr[i];
        }
    }

    template<typename E, typename R, cpp_enable_if(!vectorized_assign<E, R>::value && !has_direct_access<E>::value && !is_temporary_expr<E>::value)>
    static void assign_evaluate(E&& expr, R&& result){
        evaluate_only(expr);

        const std::size_t size = etl::size(result);

        for(std::size_t i = 0; i < size; ++i){
            result[i] = expr[i];
        }
    }

    template<typename E, typename R, cpp_enable_if(vectorized_assign<E, R>::value && !is_temporary_expr<E>::value)>
    static void assign_evaluate(E&& expr, R&& result){
        evaluate_only(expr);

        using IT = intrinsic_traits<value_t<E>>;

        auto m = result.memory_start();

        const std::size_t size = etl::size(result);

        std::size_t iend = 0;

        if(unroll_vectorized_loops){
            iend = size & std::size_t(-IT::size * 4);

            for(std::size_t i = 0; i < iend; i += IT::size * 4){
                vec::store(m + i, expr.load(i));
                vec::store(m + i + 1 * IT::size, expr.load(i + 1 * IT::size));
                vec::store(m + i + 2 * IT::size, expr.load(i + 2 * IT::size));
                vec::store(m + i + 3 * IT::size, expr.load(i + 3 * IT::size));
            }
        } else {
            iend = size & std::size_t(-IT::size);

            for(std::size_t i = 0; i < iend; i += IT::size){
                vec::store(m + i, expr.load(i));
            }
        }

        //Finish the iterations in a non-vectorized fashion
        for(std::size_t i = iend; i < size; ++i){
            m[i] = expr[i];
        }
    }

    template<typename E, typename R, cpp_disable_if(is_temporary_expr<E>::value)>
    static void add_evaluate(E&& expr, R&& result){
        evaluate_only(expr);

        for(std::size_t i = 0; i < etl::size(result); ++i){
            result[i] += expr[i];
        }
    }

    template<typename E, typename R, cpp_disable_if(is_temporary_expr<E>::value)>
    static void sub_evaluate(E&& expr, R&& result){
        evaluate_only(expr);

        for(std::size_t i = 0; i < etl::size(result); ++i){
            result[i] -= expr[i];
        }
    }

    template<typename E, typename R, cpp_disable_if(is_temporary_expr<E>::value)>
    static void mul_evaluate(E&& expr, R&& result){
        evaluate_only(expr);

        for(std::size_t i = 0; i < etl::size(result); ++i){
            result[i] *= expr[i];
        }
    }

    template<typename E, typename R, cpp_disable_if(is_temporary_expr<E>::value)>
    static void div_evaluate(E&& expr, R&& result){
        evaluate_only(expr);

        for(std::size_t i = 0; i < etl::size(result); ++i){
            result[i] /= expr[i];
        }
    }

    template<typename E, typename R, cpp_disable_if(is_temporary_expr<E>::value)>
    static void mod_evaluate(E&& expr, R&& result){
        evaluate_only(expr);

        for(std::size_t i = 0; i < etl::size(result); ++i){
            result[i] %= expr[i];
        }
    }

    //Note: In case of direct evaluation, the temporary_expr itself must
    //not beevaluated by the static_visitor, otherwise, the result would
    //be evaluated twice and a temporary would be allocated for nothing

    template<typename E, typename R, cpp_enable_if(is_temporary_unary_expr<E>::value)>
    static void assign_evaluate(E&& expr, R&& result){
        apply_visitor<detail::temporary_allocator_static_visitor>(expr.a());
        apply_visitor<detail::evaluator_static_visitor>(expr.a());

        expr.direct_evaluate(result);
    }

    template<typename E, typename R, cpp_enable_if(is_temporary_binary_expr<E>::value)>
    static void assign_evaluate(E&& expr, R&& result){
        apply_visitor<detail::temporary_allocator_static_visitor>(expr.a());
        apply_visitor<detail::temporary_allocator_static_visitor>(expr.b());

        apply_visitor<detail::evaluator_static_visitor>(expr.a());
        apply_visitor<detail::evaluator_static_visitor>(expr.b());

        expr.direct_evaluate(result);
    }
};

template<typename Expr, typename Result>
void assign_evaluate(Expr&& expr, Result&& result){
    standard_evaluator<Expr, Result>::assign_evaluate(std::forward<Expr>(expr), std::forward<Result>(result));
}

template<typename Expr, typename Result>
void add_evaluate(Expr&& expr, Result&& result){
    standard_evaluator<Expr, Result>::add_evaluate(std::forward<Expr>(expr), std::forward<Result>(result));
}

template<typename Expr, typename Result>
void sub_evaluate(Expr&& expr, Result&& result){
    standard_evaluator<Expr, Result>::sub_evaluate(std::forward<Expr>(expr), std::forward<Result>(result));
}

template<typename Expr, typename Result>
void mul_evaluate(Expr&& expr, Result&& result){
    standard_evaluator<Expr, Result>::mul_evaluate(std::forward<Expr>(expr), std::forward<Result>(result));
}

template<typename Expr, typename Result>
void div_evaluate(Expr&& expr, Result&& result){
    standard_evaluator<Expr, Result>::div_evaluate(std::forward<Expr>(expr), std::forward<Result>(result));
}

template<typename Expr, typename Result>
void mod_evaluate(Expr&& expr, Result&& result){
    standard_evaluator<Expr, Result>::mod_evaluate(std::forward<Expr>(expr), std::forward<Result>(result));
}

/*!
 * \brief Force the internal evaluation of an expression
 */
template<typename Expr>
void force(Expr&& expr){
    standard_evaluator<Expr, void>::evaluate_only(std::forward<Expr>(expr));
}

} //end of namespace etl

#endif
<commit_msg>Fix the condition<commit_after>//=======================================================================
// Copyright (c) 2014-2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef ETL_EVALUATOR_HPP
#define ETL_EVALUATOR_HPP

#include "traits_lite.hpp"   //forward declaration of the traits
#include "visitor.hpp"   //forward declaration of the traits

namespace etl {

namespace detail {

struct temporary_allocator_static_visitor : etl_visitor<temporary_allocator_static_visitor> {
    template<typename E>
    using enabled = cpp::bool_constant<decay_traits<E>::needs_temporary_visitor>;

    using etl_visitor<temporary_allocator_static_visitor>::operator();

    template <typename T, typename AExpr, typename Op, typename Forced>
    void operator()(etl::temporary_unary_expr<T, AExpr, Op, Forced>& v) const {
        v.allocate_temporary();

        (*this)(v.a());
    }

    template <typename T, typename AExpr, typename BExpr, typename Op, typename Forced>
    void operator()(etl::temporary_binary_expr<T, AExpr, BExpr, Op, Forced>& v) const {
        v.allocate_temporary();

        (*this)(v.a());
        (*this)(v.b());
    }
};

struct evaluator_static_visitor : etl_visitor<evaluator_static_visitor> {
    template<typename E>
    using enabled = cpp::bool_constant<decay_traits<E>::needs_evaluator_visitor>;

    using etl_visitor<evaluator_static_visitor>::operator();

    template <typename T, typename AExpr, typename Op, typename Forced>
    void operator()(etl::temporary_unary_expr<T, AExpr, Op, Forced>& v) const {
        (*this)(v.a());

        v.evaluate();
    }

    template <typename T, typename AExpr, typename BExpr, typename Op, typename Forced>
    void operator()(etl::temporary_binary_expr<T, AExpr, BExpr, Op, Forced>& v) const {
        (*this)(v.a());
        (*this)(v.b());

        v.evaluate();
    }
};

} //end of namespace detail

template<typename Expr, typename Result>
struct standard_evaluator {
    template<typename E>
    static void evaluate_only(E&& expr){
        apply_visitor<detail::temporary_allocator_static_visitor>(expr);
        apply_visitor<detail::evaluator_static_visitor>(expr);
    }

    template<typename E, typename R>
    struct vectorized_assign : cpp::and_u<vectorize_expr, decay_traits<E>::vectorizable, intrinsic_traits<value_t<R>>::vectorizable, intrinsic_traits<value_t<E>>::vectorizable> {};

    template<typename E, typename R, cpp_enable_if(!vectorized_assign<E, R>::value && has_direct_access<R>::value && !is_temporary_expr<E>::value)>
    static void assign_evaluate(E&& expr, R&& result){
        evaluate_only(expr);

        auto m = result.memory_start();

        const std::size_t size = etl::size(result);
        std::cout << "diret" << std::endl;

        std::size_t iend = 0;

        if(unroll_normal_loops){
            iend = size & std::size_t(-4);

            for(std::size_t i = 0; i < iend; i += 4){
                m[i] = expr[i];
                m[i+1] = expr[i+1];
                m[i+2] = expr[i+2];
                m[i+3] = expr[i+3];
            }
        }

        for(std::size_t i = iend; i < size; ++i){
            m[i] = expr[i];
        }
    }

    template<typename E, typename R, cpp_enable_if(!vectorized_assign<E, R>::value && !has_direct_access<R>::value && !is_temporary_expr<E>::value)>
    static void assign_evaluate(E&& expr, R&& result){
        evaluate_only(expr);

        const std::size_t size = etl::size(result);
        std::cout << "Indiret" << std::endl;

        for(std::size_t i = 0; i < size; ++i){
            result[i] = expr[i];
        }
    }

    template<typename E, typename R, cpp_enable_if(vectorized_assign<E, R>::value && !is_temporary_expr<E>::value)>
    static void assign_evaluate(E&& expr, R&& result){
        evaluate_only(expr);

        using IT = intrinsic_traits<value_t<E>>;

        auto m = result.memory_start();

        const std::size_t size = etl::size(result);

        std::size_t iend = 0;

        std::cout << "Vectorized_assign" << std::endl;

        if(unroll_vectorized_loops){
            iend = size & std::size_t(-IT::size * 4);

            for(std::size_t i = 0; i < iend; i += IT::size * 4){
                vec::store(m + i, expr.load(i));
                vec::store(m + i + 1 * IT::size, expr.load(i + 1 * IT::size));
                vec::store(m + i + 2 * IT::size, expr.load(i + 2 * IT::size));
                vec::store(m + i + 3 * IT::size, expr.load(i + 3 * IT::size));
            }
        } else {
            iend = size & std::size_t(-IT::size);

            for(std::size_t i = 0; i < iend; i += IT::size){
                vec::store(m + i, expr.load(i));
            }
        }

        //Finish the iterations in a non-vectorized fashion
        for(std::size_t i = iend; i < size; ++i){
            m[i] = expr[i];
        }
    }

    template<typename E, typename R, cpp_disable_if(is_temporary_expr<E>::value)>
    static void add_evaluate(E&& expr, R&& result){
        evaluate_only(expr);

        for(std::size_t i = 0; i < etl::size(result); ++i){
            result[i] += expr[i];
        }
    }

    template<typename E, typename R, cpp_disable_if(is_temporary_expr<E>::value)>
    static void sub_evaluate(E&& expr, R&& result){
        evaluate_only(expr);

        for(std::size_t i = 0; i < etl::size(result); ++i){
            result[i] -= expr[i];
        }
    }

    template<typename E, typename R, cpp_disable_if(is_temporary_expr<E>::value)>
    static void mul_evaluate(E&& expr, R&& result){
        evaluate_only(expr);

        for(std::size_t i = 0; i < etl::size(result); ++i){
            result[i] *= expr[i];
        }
    }

    template<typename E, typename R, cpp_disable_if(is_temporary_expr<E>::value)>
    static void div_evaluate(E&& expr, R&& result){
        evaluate_only(expr);

        for(std::size_t i = 0; i < etl::size(result); ++i){
            result[i] /= expr[i];
        }
    }

    template<typename E, typename R, cpp_disable_if(is_temporary_expr<E>::value)>
    static void mod_evaluate(E&& expr, R&& result){
        evaluate_only(expr);

        for(std::size_t i = 0; i < etl::size(result); ++i){
            result[i] %= expr[i];
        }
    }

    //Note: In case of direct evaluation, the temporary_expr itself must
    //not beevaluated by the static_visitor, otherwise, the result would
    //be evaluated twice and a temporary would be allocated for nothing

    template<typename E, typename R, cpp_enable_if(is_temporary_unary_expr<E>::value)>
    static void assign_evaluate(E&& expr, R&& result){
        apply_visitor<detail::temporary_allocator_static_visitor>(expr.a());
        apply_visitor<detail::evaluator_static_visitor>(expr.a());

        expr.direct_evaluate(result);
    }

    template<typename E, typename R, cpp_enable_if(is_temporary_binary_expr<E>::value)>
    static void assign_evaluate(E&& expr, R&& result){
        apply_visitor<detail::temporary_allocator_static_visitor>(expr.a());
        apply_visitor<detail::temporary_allocator_static_visitor>(expr.b());

        apply_visitor<detail::evaluator_static_visitor>(expr.a());
        apply_visitor<detail::evaluator_static_visitor>(expr.b());

        expr.direct_evaluate(result);
    }
};

template<typename Expr, typename Result>
void assign_evaluate(Expr&& expr, Result&& result){
    standard_evaluator<Expr, Result>::assign_evaluate(std::forward<Expr>(expr), std::forward<Result>(result));
}

template<typename Expr, typename Result>
void add_evaluate(Expr&& expr, Result&& result){
    standard_evaluator<Expr, Result>::add_evaluate(std::forward<Expr>(expr), std::forward<Result>(result));
}

template<typename Expr, typename Result>
void sub_evaluate(Expr&& expr, Result&& result){
    standard_evaluator<Expr, Result>::sub_evaluate(std::forward<Expr>(expr), std::forward<Result>(result));
}

template<typename Expr, typename Result>
void mul_evaluate(Expr&& expr, Result&& result){
    standard_evaluator<Expr, Result>::mul_evaluate(std::forward<Expr>(expr), std::forward<Result>(result));
}

template<typename Expr, typename Result>
void div_evaluate(Expr&& expr, Result&& result){
    standard_evaluator<Expr, Result>::div_evaluate(std::forward<Expr>(expr), std::forward<Result>(result));
}

template<typename Expr, typename Result>
void mod_evaluate(Expr&& expr, Result&& result){
    standard_evaluator<Expr, Result>::mod_evaluate(std::forward<Expr>(expr), std::forward<Result>(result));
}

/*!
 * \brief Force the internal evaluation of an expression
 */
template<typename Expr>
void force(Expr&& expr){
    standard_evaluator<Expr, void>::evaluate_only(std::forward<Expr>(expr));
}

} //end of namespace etl

#endif
<|endoftext|>


<commit_before>#include "ogl.h"
#include "Connection.h"
#include "Object.h"
#include "Commands.h"
#include "JobProxy.h"

#include "Exception.h"

#include <algorithm>

namespace ogl
{

    Connection::~Connection()
    {
        // release JobProxys
        std::for_each(m_jobProxyList.begin(), m_jobProxyList.end(), releaseObject<JobProxy>);
        releaseObject<ACE_SOCK_Stream>(m_jmServer);
    }

    Connection::Connection()
    {
        /* Build ourselves a Stream socket. This is a connected socket that
           provides reliable end-to-end communications. We will use the
           server object to send data to the server we connect to.  */
        m_jmServer = new ACE_SOCK_Stream();

        /* And we need a connector object to establish that connection. The
           ACE_SOCK_Connector object provides all of the tools we need to
           establish a connection once we know the server's network
           address...  */
        ACE_SOCK_Connector connector;

        /* Which we create with an ACE_INET_Addr object. This object is
           given the TCP/IP port and hostname of the server we want to
           connect to.  */
        ACE_INET_Addr addr (Configuration::instance()->getMasterPort(),
                            Configuration::instance()->getMasterHost().c_str());

        /* So, we feed the Addr object and the Stream object to the
           connector's connect() member function. Given this information, it
           will establish the network connection to the server and attach
           that connection to the server object.  */

        if (connector.connect (*m_jmServer, addr) == -1)
        {
            char buf[BUFSIZ] = {0};
            snprintf(buf, BUFSIZ, "Failed to connection to target Job Manager Server at (%s:%d).",
                     Configuration::instance()->getMasterHost().c_str(),
                     Configuration::instance()->getMasterPort());

            throw Exception(buf);
        }
    }

    JobProxy* Connection::addJob(JobOption* jobOption)
    {
        return 0;
    }
};
<commit_msg>release m_jmServer when throw exception in Connection's constructor<commit_after>#include "ogl.h"
#include "Connection.h"
#include "Object.h"
#include "Commands.h"
#include "JobProxy.h"

#include "Exception.h"

#include <algorithm>

namespace ogl
{

    Connection::~Connection()
    {
        // release JobProxys
        std::for_each(m_jobProxyList.begin(), m_jobProxyList.end(), releaseObject<JobProxy>);
        if (m_jmServer)
        {
            m_jmServer->close();
        }
        releaseObject<ACE_SOCK_Stream>(m_jmServer);
    }

    Connection::Connection()
    {
        /* Build ourselves a Stream socket. This is a connected socket that
           provides reliable end-to-end communications. We will use the
           server object to send data to the server we connect to.  */
        m_jmServer = new ACE_SOCK_Stream();

        /* And we need a connector object to establish that connection. The
           ACE_SOCK_Connector object provides all of the tools we need to
           establish a connection once we know the server's network
           address...  */
        ACE_SOCK_Connector connector;

        /* Which we create with an ACE_INET_Addr object. This object is
           given the TCP/IP port and hostname of the server we want to
           connect to.  */
        ACE_INET_Addr addr (Configuration::instance()->getMasterPort(),
                            Configuration::instance()->getMasterHost().c_str());

        /* So, we feed the Addr object and the Stream object to the
           connector's connect() member function. Given this information, it
           will establish the network connection to the server and attach
           that connection to the server object.  */

        if (connector.connect (*m_jmServer, addr) == -1)
        {

            if (m_jmServer)
            {
                m_jmServer->close();
            }
            releaseObject<ACE_SOCK_Stream>(m_jmServer);

            char buf[BUFSIZ] = {0};
            snprintf(buf, BUFSIZ, "Failed to connection to target Job Manager Server at (%s:%d).",
                     Configuration::instance()->getMasterHost().c_str(),
                     Configuration::instance()->getMasterPort());

            throw Exception(buf);
        }
    }

    JobProxy* Connection::addJob(JobOption* jobOption)
    {
        return 0;
    }
};
<|endoftext|>