<commit_before>/*
    Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>

    This file is part of Magnum.

    Magnum is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License version 3
    only, as published by the Free Software Foundation.

    Magnum is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU Lesser General Public License version 3 for more details.
*/

#include <sstream>
#include <TestSuite/Tester.h>

#include "Math/Constants.h"
#include "Math/Matrix4.h"
#include "Math/Quaternion.h"

namespace Magnum { namespace Math { namespace Test {

class QuaternionTest: public Corrade::TestSuite::Tester {
    public:
        explicit QuaternionTest();

        void construct();
        void addSubtract();
        void negated();
        void multiplyDivideScalar();
        void multiply();
        void dot();
        void length();
        void normalized();
        void conjugated();
        void inverted();
        void invertedNormalized();
        void rotation();
        void matrix();
        void lerp();

        void debug();
};

typedef Math::Quaternion<float> Quaternion;
typedef Math::Vector3<float> Vector3;

QuaternionTest::QuaternionTest() {
    addTests(&QuaternionTest::construct,
             &QuaternionTest::addSubtract,
             &QuaternionTest::negated,
             &QuaternionTest::multiplyDivideScalar,
             &QuaternionTest::multiply,
             &QuaternionTest::dot,
             &QuaternionTest::length,
             &QuaternionTest::normalized,
             &QuaternionTest::conjugated,
             &QuaternionTest::inverted,
             &QuaternionTest::invertedNormalized,
             &QuaternionTest::rotation,
             &QuaternionTest::matrix,
             &QuaternionTest::lerp,
             &QuaternionTest::debug);
}

void QuaternionTest::construct() {
    Quaternion q({1.0f, 2.0f, 3.0f}, -4.0f);
    CORRADE_COMPARE(q.vector(), Vector3(1.0f, 2.0f, 3.0f));
    CORRADE_COMPARE(q.scalar(), -4.0f);

    CORRADE_COMPARE(Quaternion(), Quaternion({0.0f, 0.0f, 0.0f}, {1.0f}));
}

void QuaternionTest::addSubtract() {
    Quaternion a({1.0f, 3.0f, -2.0f}, -4.0f);
    Quaternion b({-0.5f, 1.4f, 3.0f}, 12.0f);
    Quaternion c({0.5f, 4.4f, 1.0f}, 8.0f);

    CORRADE_COMPARE(a+b, c);
    CORRADE_COMPARE(c-b, a);
}

void QuaternionTest::negated() {
    CORRADE_COMPARE(-Quaternion({1.0f, 2.0f, -3.0f}, -4.0f), Quaternion({-1.0f, -2.0f, 3.0f}, 4.0f));
}

void QuaternionTest::multiplyDivideScalar() {
    Quaternion a({1.0f, 3.0f, -2.0f}, -4.0f);
    Quaternion b({-1.5f, -4.5f, 3.0f}, 6.0f);

    CORRADE_COMPARE(a*-1.5f, b);
    CORRADE_COMPARE(-1.5f*a, b);
    CORRADE_COMPARE(b/-1.5f, a);

    CORRADE_COMPARE(2.0f/a, Quaternion({2.0f, 0.666666f, -1.0f}, -0.5f));
}

void QuaternionTest::multiply() {
    CORRADE_COMPARE(Quaternion({-6.0f, -9.0f, 15.0f}, 0.5f)*Quaternion({2.0f, 3.0f, -5.0f}, 2.0f),
                    Quaternion({-11.0f, -16.5f, 27.5f}, 115.0f));
}

void QuaternionTest::dot() {
    Quaternion a({1.0f, 3.0f, -2.0f}, -4.0f);
    Quaternion b({-0.5f, 1.5f, 3.0f}, 12.0f);

    CORRADE_COMPARE(Quaternion::dot(a, b), -50.0f);
}

void QuaternionTest::length() {
    CORRADE_COMPARE(Quaternion({1.0f, 3.0f, -2.0f}, -4.0f).length(), std::sqrt(30.0f));
}

void QuaternionTest::normalized() {
    Quaternion normalized = Quaternion({1.0f, 3.0f, -2.0f}, -4.0f).normalized();
    CORRADE_COMPARE(normalized.length(), 1.0f);
    CORRADE_COMPARE(normalized, Quaternion({1.0f, 3.0f, -2.0f}, -4.0f)/std::sqrt(30.0f));
}

void QuaternionTest::conjugated() {
    CORRADE_COMPARE(Quaternion({1.0f, 3.0f, -2.0f}, -4.0f).conjugated(),
                    Quaternion({-1.0f, -3.0f, 2.0f}, -4.0f));
}

void QuaternionTest::inverted() {
    Quaternion a = Quaternion({1.0f, 3.0f, -2.0f}, -4.0f);
    Quaternion inverted = a.inverted();

    CORRADE_COMPARE(a*inverted, Quaternion());
    CORRADE_COMPARE(inverted*a, Quaternion());
    CORRADE_COMPARE(inverted, Quaternion({-1.0f, -3.0f, 2.0f}, -4.0f)/30.0f);
}

void QuaternionTest::invertedNormalized() {
    Quaternion a = Quaternion({1.0f, 3.0f, -2.0f}, -4.0f);

    std::ostringstream o;
    Corrade::Utility::Error::setOutput(&o);
    Quaternion notInverted = a.invertedNormalized();
    CORRADE_COMPARE(notInverted.vector(), Vector3());
    CORRADE_COMPARE(notInverted.scalar(), std::numeric_limits<float>::quiet_NaN());
    CORRADE_COMPARE(o.str(), "Math::Quaternion::invertedNormalized(): quaternion must be normalized\n");

    Quaternion aNormalized = a.normalized();
    Quaternion inverted = aNormalized.invertedNormalized();
    CORRADE_COMPARE(aNormalized*inverted, Quaternion());
    CORRADE_COMPARE(inverted*aNormalized.normalized(), Quaternion());
    CORRADE_COMPARE(inverted, Quaternion({-1.0f, -3.0f, 2.0f}, -4.0f)/std::sqrt(30.0f));
}

void QuaternionTest::rotation() {
    float angle = deg(120.0f);
    Vector3 axis(1.0f/Constants<float>::sqrt3());
    Quaternion q = Quaternion::fromRotation(angle, axis);
    CORRADE_COMPARE(q, Quaternion(Vector3(0.5f, 0.5f, 0.5f), 0.5f));
    CORRADE_COMPARE(q.rotationAngle(), angle);
    CORRADE_COMPARE(q.rotationAxis(), axis);
    CORRADE_COMPARE(q.rotationAxis().length(), 1.0f);

    /* Verify negative angle */
    Quaternion q2 = Quaternion::fromRotation(deg(-120.0f), axis);
    CORRADE_COMPARE(q2, Quaternion(Vector3(-0.5f, -0.5f, -0.5f), 0.5f));
    CORRADE_COMPARE(q2.rotationAngle(), deg(120.0f));
    CORRADE_COMPARE(q2.rotationAxis(), -axis);
}

void QuaternionTest::matrix() {
    float angle = deg(37.0f);
    Vector3 axis(1.0f/Constants<float>::sqrt3());
    Quaternion q = Quaternion::fromRotation(angle, axis);
    Matrix<3, float> expected = Matrix4<float>::rotation(angle, axis).rotationScaling();
    CORRADE_COMPARE(q.matrix(), expected);

    /* Verify that negated quaternion gives the same rotation */
    CORRADE_COMPARE((-q).matrix(), expected);
}

void QuaternionTest::lerp() {
    Quaternion a = Quaternion::fromRotation(deg(15.0f), Vector3(1.0f/Constants<float>::sqrt3()));
    Quaternion b = Quaternion::fromRotation(deg(23.0f), Vector3::xAxis());

    std::ostringstream o;
    Corrade::Utility::Error::setOutput(&o);

    Quaternion notLerpA = Quaternion::lerp(a*3.0f, b, 0.35f);
    CORRADE_COMPARE(notLerpA.vector(), Vector3());
    CORRADE_COMPARE(notLerpA.scalar(), std::numeric_limits<float>::quiet_NaN());
    CORRADE_COMPARE(o.str(), "Math::Quaternion::lerp(): quaternions must be normalized\n");

    o.str("");
    Quaternion notLerpB = Quaternion::lerp(a, b*-3.0f, 0.35f);
    CORRADE_COMPARE(notLerpB.vector(), Vector3());
    CORRADE_COMPARE(notLerpB.scalar(), std::numeric_limits<float>::quiet_NaN());
    CORRADE_COMPARE(o.str(), "Math::Quaternion::lerp(): quaternions must be normalized\n");

    Quaternion lerp = Quaternion::lerp(a, b, 0.35f);
    CORRADE_COMPARE(lerp, Quaternion({0.119127f, 0.049134f, 0.049134f}, 0.990445f));
}

void QuaternionTest::debug() {
    std::ostringstream o;

    Corrade::Utility::Debug(&o) << Quaternion({1.0f, 2.0f, 3.0f}, -4.0f);
    CORRADE_COMPARE(o.str(), "Quaternion({1, 2, 3}, -4)\n");
}

}}}

CORRADE_TEST_MAIN(Magnum::Math::Test::QuaternionTest)
<commit_msg>Math: test also parameterless Quaternion::dot().<commit_after>/*
    Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>

    This file is part of Magnum.

    Magnum is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License version 3
    only, as published by the Free Software Foundation.

    Magnum is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU Lesser General Public License version 3 for more details.
*/

#include <sstream>
#include <TestSuite/Tester.h>

#include "Math/Constants.h"
#include "Math/Matrix4.h"
#include "Math/Quaternion.h"

namespace Magnum { namespace Math { namespace Test {

class QuaternionTest: public Corrade::TestSuite::Tester {
    public:
        explicit QuaternionTest();

        void construct();
        void addSubtract();
        void negated();
        void multiplyDivideScalar();
        void multiply();
        void dot();
        void dotSelf();
        void length();
        void normalized();
        void conjugated();
        void inverted();
        void invertedNormalized();
        void rotation();
        void matrix();
        void lerp();

        void debug();
};

typedef Math::Quaternion<float> Quaternion;
typedef Math::Vector3<float> Vector3;

QuaternionTest::QuaternionTest() {
    addTests(&QuaternionTest::construct,
             &QuaternionTest::addSubtract,
             &QuaternionTest::negated,
             &QuaternionTest::multiplyDivideScalar,
             &QuaternionTest::multiply,
             &QuaternionTest::dot,
             &QuaternionTest::dotSelf,
             &QuaternionTest::length,
             &QuaternionTest::normalized,
             &QuaternionTest::conjugated,
             &QuaternionTest::inverted,
             &QuaternionTest::invertedNormalized,
             &QuaternionTest::rotation,
             &QuaternionTest::matrix,
             &QuaternionTest::lerp,
             &QuaternionTest::debug);
}

void QuaternionTest::construct() {
    Quaternion q({1.0f, 2.0f, 3.0f}, -4.0f);
    CORRADE_COMPARE(q.vector(), Vector3(1.0f, 2.0f, 3.0f));
    CORRADE_COMPARE(q.scalar(), -4.0f);

    CORRADE_COMPARE(Quaternion(), Quaternion({0.0f, 0.0f, 0.0f}, {1.0f}));
}

void QuaternionTest::addSubtract() {
    Quaternion a({1.0f, 3.0f, -2.0f}, -4.0f);
    Quaternion b({-0.5f, 1.4f, 3.0f}, 12.0f);
    Quaternion c({0.5f, 4.4f, 1.0f}, 8.0f);

    CORRADE_COMPARE(a+b, c);
    CORRADE_COMPARE(c-b, a);
}

void QuaternionTest::negated() {
    CORRADE_COMPARE(-Quaternion({1.0f, 2.0f, -3.0f}, -4.0f), Quaternion({-1.0f, -2.0f, 3.0f}, 4.0f));
}

void QuaternionTest::multiplyDivideScalar() {
    Quaternion a({1.0f, 3.0f, -2.0f}, -4.0f);
    Quaternion b({-1.5f, -4.5f, 3.0f}, 6.0f);

    CORRADE_COMPARE(a*-1.5f, b);
    CORRADE_COMPARE(-1.5f*a, b);
    CORRADE_COMPARE(b/-1.5f, a);

    CORRADE_COMPARE(2.0f/a, Quaternion({2.0f, 0.666666f, -1.0f}, -0.5f));
}

void QuaternionTest::multiply() {
    CORRADE_COMPARE(Quaternion({-6.0f, -9.0f, 15.0f}, 0.5f)*Quaternion({2.0f, 3.0f, -5.0f}, 2.0f),
                    Quaternion({-11.0f, -16.5f, 27.5f}, 115.0f));
}

void QuaternionTest::dot() {
    Quaternion a({1.0f, 3.0f, -2.0f}, -4.0f);
    Quaternion b({-0.5f, 1.5f, 3.0f}, 12.0f);

    CORRADE_COMPARE(Quaternion::dot(a, b), -50.0f);
}

void QuaternionTest::dotSelf() {
    CORRADE_COMPARE(Quaternion({1.0f, 2.0f, -3.0f}, -4.0f).dot(), 30.0f);
}

void QuaternionTest::length() {
    CORRADE_COMPARE(Quaternion({1.0f, 3.0f, -2.0f}, -4.0f).length(), std::sqrt(30.0f));
}

void QuaternionTest::normalized() {
    Quaternion normalized = Quaternion({1.0f, 3.0f, -2.0f}, -4.0f).normalized();
    CORRADE_COMPARE(normalized.length(), 1.0f);
    CORRADE_COMPARE(normalized, Quaternion({1.0f, 3.0f, -2.0f}, -4.0f)/std::sqrt(30.0f));
}

void QuaternionTest::conjugated() {
    CORRADE_COMPARE(Quaternion({1.0f, 3.0f, -2.0f}, -4.0f).conjugated(),
                    Quaternion({-1.0f, -3.0f, 2.0f}, -4.0f));
}

void QuaternionTest::inverted() {
    Quaternion a = Quaternion({1.0f, 3.0f, -2.0f}, -4.0f);
    Quaternion inverted = a.inverted();

    CORRADE_COMPARE(a*inverted, Quaternion());
    CORRADE_COMPARE(inverted*a, Quaternion());
    CORRADE_COMPARE(inverted, Quaternion({-1.0f, -3.0f, 2.0f}, -4.0f)/30.0f);
}

void QuaternionTest::invertedNormalized() {
    Quaternion a = Quaternion({1.0f, 3.0f, -2.0f}, -4.0f);

    std::ostringstream o;
    Corrade::Utility::Error::setOutput(&o);
    Quaternion notInverted = a.invertedNormalized();
    CORRADE_COMPARE(notInverted.vector(), Vector3());
    CORRADE_COMPARE(notInverted.scalar(), std::numeric_limits<float>::quiet_NaN());
    CORRADE_COMPARE(o.str(), "Math::Quaternion::invertedNormalized(): quaternion must be normalized\n");

    Quaternion aNormalized = a.normalized();
    Quaternion inverted = aNormalized.invertedNormalized();
    CORRADE_COMPARE(aNormalized*inverted, Quaternion());
    CORRADE_COMPARE(inverted*aNormalized.normalized(), Quaternion());
    CORRADE_COMPARE(inverted, Quaternion({-1.0f, -3.0f, 2.0f}, -4.0f)/std::sqrt(30.0f));
}

void QuaternionTest::rotation() {
    float angle = deg(120.0f);
    Vector3 axis(1.0f/Constants<float>::sqrt3());
    Quaternion q = Quaternion::fromRotation(angle, axis);
    CORRADE_COMPARE(q, Quaternion(Vector3(0.5f, 0.5f, 0.5f), 0.5f));
    CORRADE_COMPARE(q.rotationAngle(), angle);
    CORRADE_COMPARE(q.rotationAxis(), axis);
    CORRADE_COMPARE(q.rotationAxis().length(), 1.0f);

    /* Verify negative angle */
    Quaternion q2 = Quaternion::fromRotation(deg(-120.0f), axis);
    CORRADE_COMPARE(q2, Quaternion(Vector3(-0.5f, -0.5f, -0.5f), 0.5f));
    CORRADE_COMPARE(q2.rotationAngle(), deg(120.0f));
    CORRADE_COMPARE(q2.rotationAxis(), -axis);
}

void QuaternionTest::matrix() {
    float angle = deg(37.0f);
    Vector3 axis(1.0f/Constants<float>::sqrt3());
    Quaternion q = Quaternion::fromRotation(angle, axis);
    Matrix<3, float> expected = Matrix4<float>::rotation(angle, axis).rotationScaling();
    CORRADE_COMPARE(q.matrix(), expected);

    /* Verify that negated quaternion gives the same rotation */
    CORRADE_COMPARE((-q).matrix(), expected);
}

void QuaternionTest::lerp() {
    Quaternion a = Quaternion::fromRotation(deg(15.0f), Vector3(1.0f/Constants<float>::sqrt3()));
    Quaternion b = Quaternion::fromRotation(deg(23.0f), Vector3::xAxis());

    std::ostringstream o;
    Corrade::Utility::Error::setOutput(&o);

    Quaternion notLerpA = Quaternion::lerp(a*3.0f, b, 0.35f);
    CORRADE_COMPARE(notLerpA.vector(), Vector3());
    CORRADE_COMPARE(notLerpA.scalar(), std::numeric_limits<float>::quiet_NaN());
    CORRADE_COMPARE(o.str(), "Math::Quaternion::lerp(): quaternions must be normalized\n");

    o.str("");
    Quaternion notLerpB = Quaternion::lerp(a, b*-3.0f, 0.35f);
    CORRADE_COMPARE(notLerpB.vector(), Vector3());
    CORRADE_COMPARE(notLerpB.scalar(), std::numeric_limits<float>::quiet_NaN());
    CORRADE_COMPARE(o.str(), "Math::Quaternion::lerp(): quaternions must be normalized\n");

    Quaternion lerp = Quaternion::lerp(a, b, 0.35f);
    CORRADE_COMPARE(lerp, Quaternion({0.119127f, 0.049134f, 0.049134f}, 0.990445f));
}

void QuaternionTest::debug() {
    std::ostringstream o;

    Corrade::Utility::Debug(&o) << Quaternion({1.0f, 2.0f, 3.0f}, -4.0f);
    CORRADE_COMPARE(o.str(), "Quaternion({1, 2, 3}, -4)\n");
}

}}}

CORRADE_TEST_MAIN(Magnum::Math::Test::QuaternionTest)
<|endoftext|>


<commit_before>// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Renderer/RenderWindow.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Thread.hpp>
#include <Nazara/Renderer/Context.hpp>
#include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/Texture.hpp>
#include <stdexcept>
#include <Nazara/Renderer/Debug.hpp>

NzRenderWindow::NzRenderWindow(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters)
{
	Create(mode, title, style, parameters);

	#ifdef NAZARA_DEBUG
	if (!m_impl)
	{
		NazaraError("Failed to create render window");
		throw std::runtime_error("Constructor failed");
	}
	#endif
}

NzRenderWindow::NzRenderWindow(NzWindowHandle handle, const NzContextParameters& parameters)
{
	Create(handle, parameters);

	#ifdef NAZARA_DEBUG
	if (!m_impl)
	{
		NazaraError("Failed to create render window");
		throw std::runtime_error("Constructor failed");
	}
	#endif
}

NzRenderWindow::~NzRenderWindow()
{
	// Nécessaire si NzWindow::Destroy est appelé par son destructeur
	OnWindowDestroy();
}

bool NzRenderWindow::CopyToImage(NzImage* image) const
{
	#if NAZARA_RENDERER_SAFE
	if (!m_context)
	{
		NazaraError("Window has not been created");
		return false;
	}

	if (!image)
	{
		NazaraError("Image must be valid");
		return false;
	}
	#endif

	const NzContext* currentContext = NzContext::GetCurrent();
	if (m_context != currentContext)
	{
		if (!m_context->SetActive(true))
		{
			NazaraError("Failed to activate context");
			return false;
		}
	}

	NzVector2ui size = GetSize();

	if (!image->Create(nzImageType_2D, nzPixelFormat_RGBA8, size.x, size.y, 1, 1))
	{
		NazaraError("Failed to create image");
		return false;
	}

	nzUInt8* pixels = image->GetPixels();
	glReadPixels(0, 0, size.x, size.y, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

	image->FlipVertically();

	if (m_context != currentContext)
	{
		if (currentContext)
		{
			if (!currentContext->SetActive(true))
				NazaraWarning("Failed to reset current context");
		}
		else
			m_context->SetActive(false);
	}

	return true;
}

bool NzRenderWindow::CopyToTexture(NzTexture* texture) const
{
	#if NAZARA_RENDERER_SAFE
	if (!m_context)
	{
		NazaraError("Window has not been created");
		return false;
	}

	if (!texture)
	{
		NazaraError("Texture must be valid");
		return false;
	}
	#endif

	const NzContext* currentContext = NzContext::GetCurrent();
	if (m_context != currentContext)
	{
		if (!m_context->SetActive(true))
		{
			NazaraError("Failed to activate context");
			return false;
		}
	}

	NzVector2ui size = GetSize();

	if (!texture->Create(nzImageType_2D, nzPixelFormat_RGBA8, size.x, size.y, 1, 1))
	{
		NazaraError("Failed to create texture");
		return false;
	}

	glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, size.x, size.y);

	if (m_context != currentContext)
	{
		if (currentContext)
		{
			if (!currentContext->SetActive(true))
				NazaraWarning("Failed to reset current context");
		}
		else
			m_context->SetActive(false);
	}

	return true;
}

bool NzRenderWindow::Create(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters)
{
    m_parameters = parameters;
    return NzWindow::Create(mode, title, style);
}

bool NzRenderWindow::Create(NzWindowHandle handle, const NzContextParameters& parameters)
{
    m_parameters = parameters;
    return NzWindow::Create(handle);
}

void NzRenderWindow::Display()
{
	if (m_framerateLimit > 0)
	{
		int remainingTime = 1000/static_cast<int>(m_framerateLimit) - static_cast<int>(m_clock.GetMilliseconds());
		if (remainingTime > 0)
			NzThread::Sleep(remainingTime);

		m_clock.Restart();
	}

	if (m_context && m_parameters.doubleBuffered)
		m_context->SwapBuffers();
}

void NzRenderWindow::EnableVerticalSync(bool enabled)
{
    if (m_context)
    {
		#if defined(NAZARA_PLATFORM_WINDOWS)
        if (!m_context->SetActive(true))
		{
			NazaraError("Failed to activate context");
			return;
		}

        if (wglSwapInterval)
            wglSwapInterval(enabled ? 1 : 0);
        else
		#elif defined(NAZARA_PLATFORM_LINUX)
        if (!m_context->SetActive(true))
        {
            NazaraError("Failed to activate context");
            return;
        }

        if (glXSwapInterval)
            glXSwapInterval(enabled ? 1 : 0);
        else
		#else
			#error Vertical Sync is not supported on this platform
		#endif
            NazaraError("Vertical Sync is not supported on this platform");
    }
    else
        NazaraError("No context");
}

unsigned int NzRenderWindow::GetHeight() const
{
	return NzWindow::GetHeight();
}

NzRenderTargetParameters NzRenderWindow::GetParameters() const
{
	if (m_context)
	{
		const NzContextParameters& parameters = m_context->GetParameters();
		return NzRenderTargetParameters(parameters.antialiasingLevel, parameters.depthBits, parameters.stencilBits);
	}
	else
	{
		NazaraError("Window not created/context not initialized");
		return NzRenderTargetParameters();
	}
}

unsigned int NzRenderWindow::GetWidth() const
{
	return NzWindow::GetWidth();
}

bool NzRenderWindow::IsRenderable() const
{
	return m_impl != nullptr; // Si m_impl est valide, alors m_context l'est aussi
}

bool NzRenderWindow::IsValid() const
{
	return m_impl != nullptr;
}

void NzRenderWindow::SetFramerateLimit(unsigned int limit)
{
	m_framerateLimit = limit;
}

NzContextParameters NzRenderWindow::GetContextParameters() const
{
	if (m_context)
		return m_context->GetParameters();
	else
	{
		NazaraError("Window not created/context not initialized");
		return NzContextParameters();
	}
}

bool NzRenderWindow::HasContext() const
{
	return true;
}

bool NzRenderWindow::Activate() const
{
	if (m_context->SetActive(true))
	{
		glDrawBuffer((m_parameters.doubleBuffered) ? GL_BACK : GL_FRONT);
		return true;
	}
	else
	{
		NazaraError("Failed to activate window's context");
		return false;
	}
}

void NzRenderWindow::EnsureTargetUpdated() const
{
	// Rien à faire
}

bool NzRenderWindow::OnWindowCreated()
{
	m_parameters.doubleBuffered = true;
    m_parameters.window = GetHandle();

    m_context = new NzContext;
    if (!m_context->Create(m_parameters))
    {
        NazaraError("Failed not create context");
        delete m_context;

        return false;
    }

	if (!SetActive(true)) // Les fenêtres s'activent à la création
		NazaraWarning("Failed to activate window");

    EnableVerticalSync(false);

	NzVector2ui size = GetSize();

	// Le scissorBox/viewport (à la création) est de la taille de la fenêtre
	// https://www.opengl.org/sdk/docs/man/xhtml/glGet.xml
	NzOpenGL::SetScissorBox(NzRecti(0, 0, size.x, size.y));
	NzOpenGL::SetViewport(NzRecti(0, 0, size.x, size.y));

	NotifyParametersChange();
	NotifySizeChange();

	m_clock.Restart();

    return true;
}

void NzRenderWindow::OnWindowDestroy()
{
	if (m_context)
	{
		if (IsActive())
			NzRenderer::SetTarget(nullptr);

		delete m_context;
		m_context = nullptr;
	}
}

void NzRenderWindow::OnWindowResized()
{
	NotifySizeChange();
}

<commit_msg>Fixed whitespaces<commit_after>// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Renderer/RenderWindow.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Thread.hpp>
#include <Nazara/Renderer/Context.hpp>
#include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/Texture.hpp>
#include <stdexcept>
#include <Nazara/Renderer/Debug.hpp>

NzRenderWindow::NzRenderWindow(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters)
{
	Create(mode, title, style, parameters);

	#ifdef NAZARA_DEBUG
	if (!m_impl)
	{
		NazaraError("Failed to create render window");
		throw std::runtime_error("Constructor failed");
	}
	#endif
}

NzRenderWindow::NzRenderWindow(NzWindowHandle handle, const NzContextParameters& parameters)
{
	Create(handle, parameters);

	#ifdef NAZARA_DEBUG
	if (!m_impl)
	{
		NazaraError("Failed to create render window");
		throw std::runtime_error("Constructor failed");
	}
	#endif
}

NzRenderWindow::~NzRenderWindow()
{
	// Nécessaire si NzWindow::Destroy est appelé par son destructeur
	OnWindowDestroy();
}

bool NzRenderWindow::CopyToImage(NzImage* image) const
{
	#if NAZARA_RENDERER_SAFE
	if (!m_context)
	{
		NazaraError("Window has not been created");
		return false;
	}

	if (!image)
	{
		NazaraError("Image must be valid");
		return false;
	}
	#endif

	const NzContext* currentContext = NzContext::GetCurrent();
	if (m_context != currentContext)
	{
		if (!m_context->SetActive(true))
		{
			NazaraError("Failed to activate context");
			return false;
		}
	}

	NzVector2ui size = GetSize();

	if (!image->Create(nzImageType_2D, nzPixelFormat_RGBA8, size.x, size.y, 1, 1))
	{
		NazaraError("Failed to create image");
		return false;
	}

	nzUInt8* pixels = image->GetPixels();
	glReadPixels(0, 0, size.x, size.y, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

	image->FlipVertically();

	if (m_context != currentContext)
	{
		if (currentContext)
		{
			if (!currentContext->SetActive(true))
				NazaraWarning("Failed to reset current context");
		}
		else
			m_context->SetActive(false);
	}

	return true;
}

bool NzRenderWindow::CopyToTexture(NzTexture* texture) const
{
	#if NAZARA_RENDERER_SAFE
	if (!m_context)
	{
		NazaraError("Window has not been created");
		return false;
	}

	if (!texture)
	{
		NazaraError("Texture must be valid");
		return false;
	}
	#endif

	const NzContext* currentContext = NzContext::GetCurrent();
	if (m_context != currentContext)
	{
		if (!m_context->SetActive(true))
		{
			NazaraError("Failed to activate context");
			return false;
		}
	}

	NzVector2ui size = GetSize();

	if (!texture->Create(nzImageType_2D, nzPixelFormat_RGBA8, size.x, size.y, 1, 1))
	{
		NazaraError("Failed to create texture");
		return false;
	}

	glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, size.x, size.y);

	if (m_context != currentContext)
	{
		if (currentContext)
		{
			if (!currentContext->SetActive(true))
				NazaraWarning("Failed to reset current context");
		}
		else
			m_context->SetActive(false);
	}

	return true;
}

bool NzRenderWindow::Create(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters)
{
    m_parameters = parameters;
    return NzWindow::Create(mode, title, style);
}

bool NzRenderWindow::Create(NzWindowHandle handle, const NzContextParameters& parameters)
{
    m_parameters = parameters;
    return NzWindow::Create(handle);
}

void NzRenderWindow::Display()
{
	if (m_framerateLimit > 0)
	{
		int remainingTime = 1000/static_cast<int>(m_framerateLimit) - static_cast<int>(m_clock.GetMilliseconds());
		if (remainingTime > 0)
			NzThread::Sleep(remainingTime);

		m_clock.Restart();
	}

	if (m_context && m_parameters.doubleBuffered)
		m_context->SwapBuffers();
}

void NzRenderWindow::EnableVerticalSync(bool enabled)
{
	if (m_context)
	{
		#if defined(NAZARA_PLATFORM_WINDOWS)
		if (!m_context->SetActive(true))
		{
			NazaraError("Failed to activate context");
			return;
		}

		if (wglSwapInterval)
			wglSwapInterval(enabled ? 1 : 0);
		else
		#elif defined(NAZARA_PLATFORM_LINUX)
		if (!m_context->SetActive(true))
		{
			NazaraError("Failed to activate context");
			return;
		}

		if (glXSwapInterval)
			glXSwapInterval(enabled ? 1 : 0);
		else
		#else
			#error Vertical Sync is not supported on this platform
		#endif
			NazaraError("Vertical Sync is not supported on this platform");
	}
	else
		NazaraError("No context");
}

unsigned int NzRenderWindow::GetHeight() const
{
	return NzWindow::GetHeight();
}

NzRenderTargetParameters NzRenderWindow::GetParameters() const
{
	if (m_context)
	{
		const NzContextParameters& parameters = m_context->GetParameters();
		return NzRenderTargetParameters(parameters.antialiasingLevel, parameters.depthBits, parameters.stencilBits);
	}
	else
	{
		NazaraError("Window not created/context not initialized");
		return NzRenderTargetParameters();
	}
}

unsigned int NzRenderWindow::GetWidth() const
{
	return NzWindow::GetWidth();
}

bool NzRenderWindow::IsRenderable() const
{
	return m_impl != nullptr; // Si m_impl est valide, alors m_context l'est aussi
}

bool NzRenderWindow::IsValid() const
{
	return m_impl != nullptr;
}

void NzRenderWindow::SetFramerateLimit(unsigned int limit)
{
	m_framerateLimit = limit;
}

NzContextParameters NzRenderWindow::GetContextParameters() const
{
	if (m_context)
		return m_context->GetParameters();
	else
	{
		NazaraError("Window not created/context not initialized");
		return NzContextParameters();
	}
}

bool NzRenderWindow::HasContext() const
{
	return true;
}

bool NzRenderWindow::Activate() const
{
	if (m_context->SetActive(true))
	{
		glDrawBuffer((m_parameters.doubleBuffered) ? GL_BACK : GL_FRONT);
		return true;
	}
	else
	{
		NazaraError("Failed to activate window's context");
		return false;
	}
}

void NzRenderWindow::EnsureTargetUpdated() const
{
	// Rien à faire
}

bool NzRenderWindow::OnWindowCreated()
{
	m_parameters.doubleBuffered = true;
    m_parameters.window = GetHandle();

    m_context = new NzContext;
    if (!m_context->Create(m_parameters))
    {
        NazaraError("Failed not create context");
        delete m_context;

        return false;
    }

	if (!SetActive(true)) // Les fenêtres s'activent à la création
		NazaraWarning("Failed to activate window");

    EnableVerticalSync(false);

	NzVector2ui size = GetSize();

	// Le scissorBox/viewport (à la création) est de la taille de la fenêtre
	// https://www.opengl.org/sdk/docs/man/xhtml/glGet.xml
	NzOpenGL::SetScissorBox(NzRecti(0, 0, size.x, size.y));
	NzOpenGL::SetViewport(NzRecti(0, 0, size.x, size.y));

	NotifyParametersChange();
	NotifySizeChange();

	m_clock.Restart();

    return true;
}

void NzRenderWindow::OnWindowDestroy()
{
	if (m_context)
	{
		if (IsActive())
			NzRenderer::SetTarget(nullptr);

		delete m_context;
		m_context = nullptr;
	}
}

void NzRenderWindow::OnWindowResized()
{
	NotifySizeChange();
}

<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

// This file contains the WebRTC suppressions for ThreadSanitizer.
// Please refer to
// http://dev.chromium.org/developers/testing/threadsanitizer-tsan-v2
// for more info.

#if defined(THREAD_SANITIZER)

// Please make sure the code below declares a single string variable
// kTSanDefaultSuppressions contains TSan suppressions delimited by newlines.
// See http://dev.chromium.org/developers/testing/threadsanitizer-tsan-v2
// for the instructions on writing suppressions.
char kTSanDefaultSuppressions[] =

// WebRTC specific suppressions.

// False positive in system wrappers.
// https://code.google.com/p/webrtc/issues/detail?id=300
"race:webrtc/system_wrappers/source/thread_posix.cc\n"

// Audio processing
// https://code.google.com/p/webrtc/issues/detail?id=2521 for details.
"race:webrtc/modules/audio_processing/aec/aec_core.c\n"
"race:webrtc/modules/audio_processing/aec/aec_rdft.c\n"

// libjingle_p2p_unittest
// https://code.google.com/p/webrtc/issues/detail?id=2079
"race:webrtc/base/messagequeue.cc\n"
"race:webrtc/base/testclient.cc\n"
"race:webrtc/base/virtualsocketserver.cc\n"
"race:talk/base/messagequeue.cc\n"
"race:talk/base/testclient.cc\n"
"race:talk/base/virtualsocketserver.cc\n"
"race:talk/p2p/base/stunserver_unittest.cc\n"

// libjingle_unittest
// https://code.google.com/p/webrtc/issues/detail?id=2080
"race:webrtc/base/logging.cc\n"
"race:webrtc/base/sharedexclusivelock_unittest.cc\n"
"race:webrtc/base/signalthread_unittest.cc\n"
"race:webrtc/base/thread.cc\n"
"race:talk/base/logging.cc\n"
"race:talk/base/sharedexclusivelock_unittest.cc\n"
"race:talk/base/signalthread_unittest.cc\n"
"race:talk/base/thread.cc\n"

// third_party/usrsctp
// TODO(jiayl): https://code.google.com/p/webrtc/issues/detail?id=3492
"race:third_party/usrsctp/usrsctplib/user_sctp_timer_iterate.c\n"

// Potential deadlocks detected after roll in r6516.
// https://code.google.com/p/webrtc/issues/detail?id=3509
"deadlock:cricket::WebRtcVideoChannel2::WebRtcVideoSendStream::InputFrame\n"
"deadlock:cricket::WebRtcVideoChannel2::WebRtcVideoSendStream::SetCapturer\n"
"deadlock:talk_base::AsyncResolver::~AsyncResolver\n"
"deadlock:webrtc::ProcessThreadImpl::RegisterModule\n"
"deadlock:webrtc::RTCPReceiver::SetSsrcs\n"
"deadlock:webrtc::RTPSenderAudio::RegisterAudioPayload\n"
"deadlock:webrtc::test::UdpSocketManagerPosixImpl::RemoveSocket\n"
"deadlock:webrtc::vcm::VideoReceiver::RegisterPacketRequestCallback\n"
"deadlock:webrtc::VideoSendStreamTest_SuspendBelowMinBitrate_Test::TestBody\n"
"deadlock:webrtc::ViECaptureImpl::ConnectCaptureDevice\n"
"deadlock:webrtc::ViEChannel::StartSend\n"
"deadlock:webrtc::ViECodecImpl::GetSendSideDelay\n"
"deadlock:webrtc::ViEEncoder::OnLocalSsrcChanged\n"
"deadlock:webrtc::ViESender::RegisterSendTransport\n"

// From Chromium's tsan_suppressions.cc file.

// False positives in libglib.so. Since we don't instrument them, we cannot
// reason about the synchronization in them.
"race:libglib*.so\n"

// Races in libevent, http://crbug.com/23244.
"race:libevent/event.c\n"

// http://crbug.com/84094.
"race:sqlite3StatusSet\n"
"race:pcache1EnforceMaxPage\n"
"race:pcache1AllocPage\n"

// http://crbug.com/157586
"race:third_party/libvpx/source/libvpx/vp8/decoder/threading.c\n"

// http://crbug.com/158922
"race:third_party/libvpx/source/libvpx/vp8/encoder/*\n"

// http://crbug.com/223352
"race:uprv_malloc_46\n"
"race:uprv_realloc_46\n"

// http://crbug.com/244385
"race:unixTempFileDir\n"

// http://crbug.com/244774
"race:webrtc::RTPReceiver::ProcessBitrate\n"
"race:webrtc::RTPSender::ProcessBitrate\n"
"race:webrtc::VideoCodingModuleImpl::Decode\n"
"race:webrtc::RTPSender::SendOutgoingData\n"
"race:webrtc::VP8EncoderImpl::GetEncodedPartitions\n"
"race:webrtc::VP8EncoderImpl::Encode\n"
"race:webrtc::ViEEncoder::DeliverFrame\n"
"race:webrtc::vcm::VideoReceiver::Decode\n"
"race:webrtc::VCMReceiver::FrameForDecoding\n"
"race:*trace_event_unique_catstatic*\n"

// http://crbug.com/244856
"race:AutoPulseLock\n"

// http://crbug.com/246968
"race:webrtc::VideoCodingModuleImpl::RegisterPacketRequestCallback\n"

// http://crbug.com/246970
"race:webrtc::EventPosix::StartTimer\n"

// http://crbug.com/258479
"race:SamplingStateScope\n"
"race:g_trace_state\n"

// http://crbug.com/270037
"race:gLibCleanupFunctions\n"

// http://crbug.com/272987
"race:webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>::set_enabled\n"

// http://crbug.com/345245
"race:jingle_glue::JingleThreadWrapper::~JingleThreadWrapper\n"
"race:webrtc::voe::Channel::UpdatePacketDelay\n"
"race:webrtc::voe::Channel::GetDelayEstimate\n"
"race:webrtc::VCMCodecDataBase::DeregisterReceiveCodec\n"
"race:webrtc::GainControlImpl::set_stream_analog_level\n"

// http://crbug.com/347538
"race:sctp_timer_start\n"

// http://crbug.com/347548
"race:cricket::WebRtcVideoMediaChannel::MaybeResetVieSendCodec\n"
"race:cricket::WebRtcVideoMediaChannel::SetSendCodec\n"

// http://crbug.com/348511
"race:webrtc::acm1::AudioCodingModuleImpl::PlayoutData10Ms\n"

// http://crbug.com/348982
"race:cricket::P2PTransportChannel::OnConnectionDestroyed\n"
"race:cricket::P2PTransportChannel::AddConnection\n"

// http://crbug.com/348984
"race:sctp_express_handle_sack\n"

// http://crbug.com/350982
"race:libvpx/vp9/decoder/vp9_thread.c\n"

// http://crbug.com/372807
"deadlock:net::X509Certificate::CreateCertificateListFromBytes\n"
"deadlock:net::X509Certificate::CreateFromBytes\n"
"deadlock:net::SSLClientSocketNSS::Core::DoHandshakeLoop\n"

// False positive in libc's tzset_internal, http://crbug.com/379738.
"race:tzset_internal\n"

// http://crbug.com/380554
"deadlock:g_type_add_interface_static\n"

// End of suppressions.
;  // Please keep this semicolon.

#endif  // THREAD_SANITIZER
<commit_msg>Tight data race suppressions around thread_posix.<commit_after>/*
 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

// This file contains the WebRTC suppressions for ThreadSanitizer.
// Please refer to
// http://dev.chromium.org/developers/testing/threadsanitizer-tsan-v2
// for more info.

#if defined(THREAD_SANITIZER)

// Please make sure the code below declares a single string variable
// kTSanDefaultSuppressions contains TSan suppressions delimited by newlines.
// See http://dev.chromium.org/developers/testing/threadsanitizer-tsan-v2
// for the instructions on writing suppressions.
char kTSanDefaultSuppressions[] =

// WebRTC specific suppressions.

// Usage of trace callback and trace level is racy in libjingle_media_unittests.
// https://code.google.com/p/webrtc/issues/detail?id=3372
"race:webrtc::TraceImpl::WriteToFile\n"
"race:webrtc::VideoEngine::SetTraceFilter\n"
"race:webrtc::VoiceEngine::SetTraceFilter\n"

// Audio processing
// https://code.google.com/p/webrtc/issues/detail?id=2521 for details.
"race:webrtc/modules/audio_processing/aec/aec_core.c\n"
"race:webrtc/modules/audio_processing/aec/aec_rdft.c\n"

// libjingle_p2p_unittest
// https://code.google.com/p/webrtc/issues/detail?id=2079
"race:webrtc/base/messagequeue.cc\n"
"race:webrtc/base/testclient.cc\n"
"race:webrtc/base/virtualsocketserver.cc\n"
"race:talk/base/messagequeue.cc\n"
"race:talk/base/testclient.cc\n"
"race:talk/base/virtualsocketserver.cc\n"
"race:talk/p2p/base/stunserver_unittest.cc\n"

// libjingle_unittest
// https://code.google.com/p/webrtc/issues/detail?id=2080
"race:webrtc/base/logging.cc\n"
"race:webrtc/base/sharedexclusivelock_unittest.cc\n"
"race:webrtc/base/signalthread_unittest.cc\n"
"race:webrtc/base/thread.cc\n"
"race:talk/base/logging.cc\n"
"race:talk/base/sharedexclusivelock_unittest.cc\n"
"race:talk/base/signalthread_unittest.cc\n"
"race:talk/base/thread.cc\n"

// third_party/usrsctp
// TODO(jiayl): https://code.google.com/p/webrtc/issues/detail?id=3492
"race:third_party/usrsctp/usrsctplib/user_sctp_timer_iterate.c\n"

// Potential deadlocks detected after roll in r6516.
// https://code.google.com/p/webrtc/issues/detail?id=3509
"deadlock:cricket::WebRtcVideoChannel2::WebRtcVideoSendStream::InputFrame\n"
"deadlock:cricket::WebRtcVideoChannel2::WebRtcVideoSendStream::SetCapturer\n"
"deadlock:talk_base::AsyncResolver::~AsyncResolver\n"
"deadlock:webrtc::ProcessThreadImpl::RegisterModule\n"
"deadlock:webrtc::RTCPReceiver::SetSsrcs\n"
"deadlock:webrtc::RTPSenderAudio::RegisterAudioPayload\n"
"deadlock:webrtc::test::UdpSocketManagerPosixImpl::RemoveSocket\n"
"deadlock:webrtc::vcm::VideoReceiver::RegisterPacketRequestCallback\n"
"deadlock:webrtc::VideoSendStreamTest_SuspendBelowMinBitrate_Test::TestBody\n"
"deadlock:webrtc::ViECaptureImpl::ConnectCaptureDevice\n"
"deadlock:webrtc::ViEChannel::StartSend\n"
"deadlock:webrtc::ViECodecImpl::GetSendSideDelay\n"
"deadlock:webrtc::ViEEncoder::OnLocalSsrcChanged\n"
"deadlock:webrtc::ViESender::RegisterSendTransport\n"

// From Chromium's tsan_suppressions.cc file.

// False positives in libglib.so. Since we don't instrument them, we cannot
// reason about the synchronization in them.
"race:libglib*.so\n"

// Races in libevent, http://crbug.com/23244.
"race:libevent/event.c\n"

// http://crbug.com/84094.
"race:sqlite3StatusSet\n"
"race:pcache1EnforceMaxPage\n"
"race:pcache1AllocPage\n"

// http://crbug.com/157586
"race:third_party/libvpx/source/libvpx/vp8/decoder/threading.c\n"

// http://crbug.com/158922
"race:third_party/libvpx/source/libvpx/vp8/encoder/*\n"

// http://crbug.com/223352
"race:uprv_malloc_46\n"
"race:uprv_realloc_46\n"

// http://crbug.com/244385
"race:unixTempFileDir\n"

// http://crbug.com/244774
"race:webrtc::RTPReceiver::ProcessBitrate\n"
"race:webrtc::RTPSender::ProcessBitrate\n"
"race:webrtc::VideoCodingModuleImpl::Decode\n"
"race:webrtc::RTPSender::SendOutgoingData\n"
"race:webrtc::VP8EncoderImpl::GetEncodedPartitions\n"
"race:webrtc::VP8EncoderImpl::Encode\n"
"race:webrtc::ViEEncoder::DeliverFrame\n"
"race:webrtc::vcm::VideoReceiver::Decode\n"
"race:webrtc::VCMReceiver::FrameForDecoding\n"
"race:*trace_event_unique_catstatic*\n"

// http://crbug.com/244856
"race:AutoPulseLock\n"

// http://crbug.com/246968
"race:webrtc::VideoCodingModuleImpl::RegisterPacketRequestCallback\n"

// http://crbug.com/246970
"race:webrtc::EventPosix::StartTimer\n"

// http://crbug.com/258479
"race:SamplingStateScope\n"
"race:g_trace_state\n"

// http://crbug.com/270037
"race:gLibCleanupFunctions\n"

// http://crbug.com/272987
"race:webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>::set_enabled\n"

// http://crbug.com/345245
"race:jingle_glue::JingleThreadWrapper::~JingleThreadWrapper\n"
"race:webrtc::voe::Channel::UpdatePacketDelay\n"
"race:webrtc::voe::Channel::GetDelayEstimate\n"
"race:webrtc::VCMCodecDataBase::DeregisterReceiveCodec\n"
"race:webrtc::GainControlImpl::set_stream_analog_level\n"

// http://crbug.com/347538
"race:sctp_timer_start\n"

// http://crbug.com/347548
"race:cricket::WebRtcVideoMediaChannel::MaybeResetVieSendCodec\n"
"race:cricket::WebRtcVideoMediaChannel::SetSendCodec\n"

// http://crbug.com/348511
"race:webrtc::acm1::AudioCodingModuleImpl::PlayoutData10Ms\n"

// http://crbug.com/348982
"race:cricket::P2PTransportChannel::OnConnectionDestroyed\n"
"race:cricket::P2PTransportChannel::AddConnection\n"

// http://crbug.com/348984
"race:sctp_express_handle_sack\n"

// http://crbug.com/350982
"race:libvpx/vp9/decoder/vp9_thread.c\n"

// http://crbug.com/372807
"deadlock:net::X509Certificate::CreateCertificateListFromBytes\n"
"deadlock:net::X509Certificate::CreateFromBytes\n"
"deadlock:net::SSLClientSocketNSS::Core::DoHandshakeLoop\n"

// False positive in libc's tzset_internal, http://crbug.com/379738.
"race:tzset_internal\n"

// http://crbug.com/380554
"deadlock:g_type_add_interface_static\n"

// End of suppressions.
;  // Please keep this semicolon.

#endif  // THREAD_SANITIZER
<|endoftext|>


<commit_before>// @(#)root/proof:$Id$
// Author: Sangsu Ryu 28/06/2011

/*************************************************************************
 * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TSelVerifyDataSet                                                    //
//                                                                      //
// Selector to verify dataset in parallel on workers                    //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#define TSelVerifyDataSet_cxx

#include "TSelVerifyDataSet.h"
#include "TDataSetManager.h"
#include "TDSet.h"
#include "TParameter.h"
#include "TTree.h"
#include "TFile.h"
#include "TNamed.h"
#include <unistd.h>
#include "TSystem.h"
#include "TROOT.h"
#include "TEnv.h"
#include "TFileStager.h"
#include "TProofDebug.h"
#include "TProofServ.h"
#include "TFileCollection.h"
#include "TFileInfo.h"

ClassImp(TSelVerifyDataSet)

//______________________________________________________________________________
TSelVerifyDataSet::TSelVerifyDataSet(TTree *)
{
   // Constructor
}

//______________________________________________________________________________
TSelVerifyDataSet::TSelVerifyDataSet()
{
   // Constructor
}

//______________________________________________________________________________
void TSelVerifyDataSet::Begin(TTree *)
{
   Init(0);
}

//______________________________________________________________________________
void TSelVerifyDataSet::SlaveBegin(TTree *)
{

   Init(0);

   TString dsname, opts;

   TNamed* par = dynamic_cast<TNamed*>(fInput->FindObject("PROOF_VerifyDataSet"));
   if (par) {
      dsname = par->GetTitle();
   } else {
      Abort("cannot find dataset name: cannot continue", kAbortProcess);
      return;
   }

   par = dynamic_cast<TNamed*>(fInput->FindObject("PROOF_VerifyDataSetOption"));
   if (par) {
      opts = par->GetTitle();
   } else {
      Abort("cannot find verify options: cannot continue", kAbortProcess);
      return;
   }

   par = dynamic_cast<TNamed*>(fInput->FindObject("PROOF_MSS"));
   if (par) {
      fMss = par->GetTitle();
      PDB(kSelector, 2) Info("SlaveBegin", "dataset MSS: '%s'", fMss.Data());
   }

   par = dynamic_cast<TNamed*>(fInput->FindObject("PROOF_StageOption"));
   if (par) {
      fStageopts = par->GetTitle();
      PDB(kSelector, 2) Info("SlaveBegin", "dataset stage options: '%s'", fStageopts.Data());
   }

   // Extract the directives
   UInt_t o = 0;
   if (!opts.IsNull()) {
      // Selection options
      if (strstr(opts, "allfiles:") || strchr(opts, 'A'))
         o |= TDataSetManager::kAllFiles;
      else if (strstr(opts, "staged:") || strchr(opts, 'D'))
         o |= TDataSetManager::kStagedFiles;
      // Pre-action options
      if (strstr(opts, "open:") || strchr(opts, 'O'))
         o |= TDataSetManager::kReopen;
      if (strstr(opts, "touch:") || strchr(opts, 'T'))
         o |= TDataSetManager::kTouch;
      if (strstr(opts, "nostagedcheck:") || strchr(opts, 'I'))
         o |= TDataSetManager::kNoStagedCheck;
      // Process options
      if (strstr(opts, "noaction:") || strchr(opts, 'N'))
         o |= TDataSetManager::kNoAction;
      if (strstr(opts, "locateonly:") || strchr(opts, 'L'))
         o |= TDataSetManager::kLocateOnly;
      if (strstr(opts, "stageonly:") || strchr(opts, 'S'))
         o |= TDataSetManager::kStageOnly;
      // Auxilliary options
      if (strstr(opts, "verbose:") || strchr(opts, 'V'))
         o |= TDataSetManager::kDebug;
   } else {
      // Default
      o = TDataSetManager::kReopen | TDataSetManager::kDebug;
   }

   PDB(kSelector, 1) Info("SlaveBegin", "o=%d", o);
   // File selection
   fFopt = ((o & TDataSetManager::kAllFiles)) ? -1 : 0;
   if (fFopt >= 0) {
      if ((o & TDataSetManager::kStagedFiles)) {
         fFopt = 10;
      } else {
         if ((o & TDataSetManager::kReopen)) fFopt++;
         if ((o & TDataSetManager::kTouch)) fFopt++;
      }
      if ((o & TDataSetManager::kNoStagedCheck)) fFopt += 100;
   } else {
      if ((o & TDataSetManager::kStagedFiles) || (o & TDataSetManager::kReopen) || (o & TDataSetManager::kTouch)) {
         Warning("SlaveBegin", "kAllFiles mode: ignoring kStagedFiles or kReopen"
                                " or kTouch requests");
      }
      if ((o & TDataSetManager::kNoStagedCheck)) fFopt -= 100;
   }
   PDB(kSelector, 1) Info("SlaveBegin", "fFopt=%d", fFopt);

   // Type of action
   fSopt = ((o & TDataSetManager::kNoAction)) ? -1 : 0;
   if (fSopt >= 0) {
      if ((o & TDataSetManager::kLocateOnly) && (o & TDataSetManager::kStageOnly)) {
         Error("SlaveBegin", "kLocateOnly and kStageOnly cannot be processed concurrently");
         return;
      }
      if ((o & TDataSetManager::kLocateOnly)) fSopt = 1;
      if ((o & TDataSetManager::kStageOnly)) fSopt = 2;
   } else if ((o & TDataSetManager::kLocateOnly) || (o & TDataSetManager::kStageOnly)) {
      Warning("SlaveBegin", "kNoAction mode: ignoring kLocateOnly or kStageOnly requests");
   }
   PDB(kSelector, 1) Info("SlaveBegin", "fSopt=%d", fSopt);

   fDbg = ((o & TDataSetManager::kDebug)) ? kTRUE : kFALSE;

   // File selection, Reopen and Touch options
   fAllf     = (fFopt == -1)               ? kTRUE : kFALSE;
   fCheckstg = (fFopt >= 100 || fFopt < -1) ? kFALSE : kTRUE;
   if (fFopt >= 0) fFopt %= 100;
   fNonStgf  = (fFopt >= 0 && fFopt < 10)   ? kTRUE : kFALSE;
   fReopen   = (fFopt >= 1 && fFopt < 10)   ? kTRUE : kFALSE;
   fTouch    = (fFopt >= 2 && fFopt < 10)   ? kTRUE : kFALSE;
   fStgf     = (fFopt == 10)               ? kTRUE : kFALSE;

   PDB(kSelector, 1) Info("SlaveBegin",
                          "fAllf=%d fCheckstg=%d fNonStgf=%d fReopen=%d fTouch=%d fStgf=%d",
                          fAllf, fCheckstg, fNonStgf, fReopen, fTouch, fStgf);

   // File processing options
   fNoaction   = (fSopt == -1) ? kTRUE : kFALSE;
   fFullproc   = (fSopt == 0)  ? kTRUE : kFALSE;
   fLocateonly = (fSopt == 1)  ? kTRUE : kFALSE;
   fStageonly  = (fSopt == 2)  ? kTRUE : kFALSE;

   PDB(kSelector, 1) Info("SlaveBegin",
                          "fNoaction=%d fFullproc=%d fLocateonly=%d fStageonly=%d",
                          fNoaction, fFullproc, fLocateonly, fStageonly);

   // Run options
   fDoall       = (fRopt == 0) ? kTRUE : kFALSE;
   fGetlistonly = (fRopt == 1) ? kTRUE : kFALSE;
   fScanlist    = (fRopt == 2) ? kTRUE : kFALSE;

   PDB(kSelector, 1) Info("SlaveBegin",
                          "fDoall=%d fGetlistonly=%d fScanlist=%d",
                          fDoall, fGetlistonly, fScanlist);

   TString hostname(TUrl(gSystem->HostName()).GetHostFQDN());
   TString thisordinal = gProofServ ? gProofServ->GetOrdinal() : "n.d";
   TString title =
      TString::Format("TSelVerifyDataSet_%s_%s", hostname.Data(), thisordinal.Data());
   fSubDataSet= new TFileCollection(dsname, title);
}

//______________________________________________________________________________
Bool_t TSelVerifyDataSet::Process(Long64_t entry)
{
   // Process a single entry

   TDSetElement *fCurrent = 0;
   TPair *elemPair = 0;
   if (fInput && (elemPair = dynamic_cast<TPair *>
                      (fInput->FindObject("PROOF_CurrentElement")))) {
      if ((fCurrent = dynamic_cast<TDSetElement *>(elemPair->Value()))) {
         Info("Process", "entry %lld: file: '%s'", entry, fCurrent->GetName());
      } else {
         Error("Process", "entry %lld: no file specified!", entry);
         return kFALSE;
      }
   }

   TFileInfo *fileInfo = dynamic_cast<TFileInfo*>(fCurrent->GetAssocObj(0));
   if (!fileInfo) {
      Error("Process", "can not get TFileInfo; returning");
      return kFALSE;
   }

   PDB(kSelector, 1) {
      Info("Process", "input fileinfo: ");
      fileInfo->Print("L");
   }

   TFileStager *stager = 0;
   Bool_t createStager = kFALSE;

   TFileInfo* newfileinfo = new TFileInfo(*fileInfo);
   newfileinfo->SetIndex(fileInfo->GetIndex());

   if (fDoall || fGetlistonly) {

      stager = (fMss && strlen(fMss) > 0) ? TFileStager::Open(fMss) : 0;
      createStager = (stager) ? kFALSE : kTRUE;

      // Check which files have been staged, this can be replaced by a bulk command,
      // once it exists in the xrdclient

      // For real time monitoring
      gSystem->DispatchOneEvent(kTRUE);

      Bool_t changed = kFALSE;
      Bool_t touched = kFALSE;
      Bool_t disappeared = kFALSE;

      TDataSetManager::CheckStagedStatus(newfileinfo, fFopt, -1, 0, stager, createStager,
                                         fDbg, changed, touched, disappeared);

      if (changed) fChangedDs = kTRUE;
      if (touched) fTouched++;
      if (disappeared) fDisappeared++;

      SafeDelete(stager);

      PDB(kSelector, 1) Info("Process",
                             "fChangedDs = %d, fTouched = %d disappeared = %d",
                              fChangedDs, fTouched, fDisappeared);

      // If required to only get the list we are done
      if (fGetlistonly) {
         Info("Process", "updated fileinfo: ");
         newfileinfo->Print("F");
         fSubDataSet->Add(newfileinfo);
         return kTRUE;
      }
   }

   if (!fNoaction && (fDoall || fScanlist)) {

      // Point to the fileinfo
      //newStagedFiles = (!fDoall && fScanlist && flist) ? flist : newStagedFiles;
      if (!fDoall && fScanlist) {
          SafeDelete(newfileinfo);
          newfileinfo = new TFileInfo(*fileInfo);
          newfileinfo->SetIndex(fileInfo->GetIndex());
      }

      // Loop over now staged files
      PDB(kSelector, 1) Info("Process",
                             "file appear to be newly staged; %s",
                             newfileinfo->GetFirstUrl()->GetUrl());

      // If staging files, prepare the stager
      if (fLocateonly || fStageonly) {
         stager = (fMss && strlen(fMss) > 0) ? TFileStager::Open(fMss) : 0;
         createStager = (stager) ? kFALSE : kTRUE;
      }

      // Process the file
      Bool_t changed = kFALSE;
      Bool_t opened = kFALSE;
      TDataSetManager::ProcessFile(newfileinfo, fSopt, fCheckstg, fDoall, stager, createStager, fStageopts,
                                   fDbg, changed, opened);

      if (changed) fChangedDs = kTRUE;
      if (opened) fOpened++;
   }

   PDB(kSelector, 1) {
      Info("Process", "updated fileinfo: ");
      newfileinfo->Print("L");
   }
   fSubDataSet->Add(newfileinfo);

   return kTRUE;
}

//______________________________________________________________________________
void TSelVerifyDataSet::SlaveTerminate()
{
   if (fSubDataSet) {
      fSubDataSet->Update();
      if (fSubDataSet->GetNFiles() > 0) {
         fOutput->Add(fSubDataSet);
         Info("SlaveTerminate",
              "sub-dataset '%s' added to the output list (%lld files)",
              fSubDataSet->GetTitle(), fSubDataSet->GetNFiles());
      }
      // Add information for registration
      fOutput->Add(new TNamed(TString::Format("DATASET_%s", fSubDataSet->GetName()).Data(),"OT:sortidx:"));
      fOutput->Add(new TNamed("PROOFSERV_RegisterDataSet", ""));
   }

   // Send the number of files disppeared, opened and mark 'changed'if any fileinfo in the dataset has changed
   TString hostname(TUrl(gSystem->HostName()).GetHostFQDN());
   TString thisordinal = gProofServ ? gProofServ->GetOrdinal() : "n.d";
   TString sfdisppeared= TString::Format("PROOF_NoFilesDisppeared_%s_%s", hostname.Data(), thisordinal.Data());
   fOutput->Add(new TParameter<Int_t>(sfdisppeared.Data(), fDisappeared));
   TString sfOpened= TString::Format("PROOF_NoFilesOpened_%s_%s", hostname.Data(), thisordinal.Data());
   fOutput->Add(new TParameter<Int_t>(sfOpened.Data(), fOpened));
   TString sfTouched = TString::Format("PROOF_NoFilesTouched_%s_%s", hostname.Data(), thisordinal.Data());
   fOutput->Add(new TParameter<Int_t>(sfTouched.Data(), fTouched));
   TString schanged= TString::Format("PROOF_DataSetChanged_%s_%s", hostname.Data(), thisordinal.Data());
   fOutput->Add(new TParameter<Bool_t>(schanged.Data(), fChangedDs));
}

//______________________________________________________________________________
void TSelVerifyDataSet::Terminate()
{}
<commit_msg>Remove unused include<commit_after>// @(#)root/proof:$Id$
// Author: Sangsu Ryu 28/06/2011

/*************************************************************************
 * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TSelVerifyDataSet                                                    //
//                                                                      //
// Selector to verify dataset in parallel on workers                    //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#define TSelVerifyDataSet_cxx

#include "TSelVerifyDataSet.h"
#include "TDataSetManager.h"
#include "TDSet.h"
#include "TParameter.h"
#include "TTree.h"
#include "TFile.h"
#include "TNamed.h"
#include "TSystem.h"
#include "TROOT.h"
#include "TEnv.h"
#include "TFileStager.h"
#include "TProofDebug.h"
#include "TProofServ.h"
#include "TFileCollection.h"
#include "TFileInfo.h"

ClassImp(TSelVerifyDataSet)

//______________________________________________________________________________
TSelVerifyDataSet::TSelVerifyDataSet(TTree *)
{
   // Constructor
}

//______________________________________________________________________________
TSelVerifyDataSet::TSelVerifyDataSet()
{
   // Constructor
}

//______________________________________________________________________________
void TSelVerifyDataSet::Begin(TTree *)
{
   Init(0);
}

//______________________________________________________________________________
void TSelVerifyDataSet::SlaveBegin(TTree *)
{

   Init(0);

   TString dsname, opts;

   TNamed* par = dynamic_cast<TNamed*>(fInput->FindObject("PROOF_VerifyDataSet"));
   if (par) {
      dsname = par->GetTitle();
   } else {
      Abort("cannot find dataset name: cannot continue", kAbortProcess);
      return;
   }

   par = dynamic_cast<TNamed*>(fInput->FindObject("PROOF_VerifyDataSetOption"));
   if (par) {
      opts = par->GetTitle();
   } else {
      Abort("cannot find verify options: cannot continue", kAbortProcess);
      return;
   }

   par = dynamic_cast<TNamed*>(fInput->FindObject("PROOF_MSS"));
   if (par) {
      fMss = par->GetTitle();
      PDB(kSelector, 2) Info("SlaveBegin", "dataset MSS: '%s'", fMss.Data());
   }

   par = dynamic_cast<TNamed*>(fInput->FindObject("PROOF_StageOption"));
   if (par) {
      fStageopts = par->GetTitle();
      PDB(kSelector, 2) Info("SlaveBegin", "dataset stage options: '%s'", fStageopts.Data());
   }

   // Extract the directives
   UInt_t o = 0;
   if (!opts.IsNull()) {
      // Selection options
      if (strstr(opts, "allfiles:") || strchr(opts, 'A'))
         o |= TDataSetManager::kAllFiles;
      else if (strstr(opts, "staged:") || strchr(opts, 'D'))
         o |= TDataSetManager::kStagedFiles;
      // Pre-action options
      if (strstr(opts, "open:") || strchr(opts, 'O'))
         o |= TDataSetManager::kReopen;
      if (strstr(opts, "touch:") || strchr(opts, 'T'))
         o |= TDataSetManager::kTouch;
      if (strstr(opts, "nostagedcheck:") || strchr(opts, 'I'))
         o |= TDataSetManager::kNoStagedCheck;
      // Process options
      if (strstr(opts, "noaction:") || strchr(opts, 'N'))
         o |= TDataSetManager::kNoAction;
      if (strstr(opts, "locateonly:") || strchr(opts, 'L'))
         o |= TDataSetManager::kLocateOnly;
      if (strstr(opts, "stageonly:") || strchr(opts, 'S'))
         o |= TDataSetManager::kStageOnly;
      // Auxilliary options
      if (strstr(opts, "verbose:") || strchr(opts, 'V'))
         o |= TDataSetManager::kDebug;
   } else {
      // Default
      o = TDataSetManager::kReopen | TDataSetManager::kDebug;
   }

   PDB(kSelector, 1) Info("SlaveBegin", "o=%d", o);
   // File selection
   fFopt = ((o & TDataSetManager::kAllFiles)) ? -1 : 0;
   if (fFopt >= 0) {
      if ((o & TDataSetManager::kStagedFiles)) {
         fFopt = 10;
      } else {
         if ((o & TDataSetManager::kReopen)) fFopt++;
         if ((o & TDataSetManager::kTouch)) fFopt++;
      }
      if ((o & TDataSetManager::kNoStagedCheck)) fFopt += 100;
   } else {
      if ((o & TDataSetManager::kStagedFiles) || (o & TDataSetManager::kReopen) || (o & TDataSetManager::kTouch)) {
         Warning("SlaveBegin", "kAllFiles mode: ignoring kStagedFiles or kReopen"
                                " or kTouch requests");
      }
      if ((o & TDataSetManager::kNoStagedCheck)) fFopt -= 100;
   }
   PDB(kSelector, 1) Info("SlaveBegin", "fFopt=%d", fFopt);

   // Type of action
   fSopt = ((o & TDataSetManager::kNoAction)) ? -1 : 0;
   if (fSopt >= 0) {
      if ((o & TDataSetManager::kLocateOnly) && (o & TDataSetManager::kStageOnly)) {
         Error("SlaveBegin", "kLocateOnly and kStageOnly cannot be processed concurrently");
         return;
      }
      if ((o & TDataSetManager::kLocateOnly)) fSopt = 1;
      if ((o & TDataSetManager::kStageOnly)) fSopt = 2;
   } else if ((o & TDataSetManager::kLocateOnly) || (o & TDataSetManager::kStageOnly)) {
      Warning("SlaveBegin", "kNoAction mode: ignoring kLocateOnly or kStageOnly requests");
   }
   PDB(kSelector, 1) Info("SlaveBegin", "fSopt=%d", fSopt);

   fDbg = ((o & TDataSetManager::kDebug)) ? kTRUE : kFALSE;

   // File selection, Reopen and Touch options
   fAllf     = (fFopt == -1)               ? kTRUE : kFALSE;
   fCheckstg = (fFopt >= 100 || fFopt < -1) ? kFALSE : kTRUE;
   if (fFopt >= 0) fFopt %= 100;
   fNonStgf  = (fFopt >= 0 && fFopt < 10)   ? kTRUE : kFALSE;
   fReopen   = (fFopt >= 1 && fFopt < 10)   ? kTRUE : kFALSE;
   fTouch    = (fFopt >= 2 && fFopt < 10)   ? kTRUE : kFALSE;
   fStgf     = (fFopt == 10)               ? kTRUE : kFALSE;

   PDB(kSelector, 1) Info("SlaveBegin",
                          "fAllf=%d fCheckstg=%d fNonStgf=%d fReopen=%d fTouch=%d fStgf=%d",
                          fAllf, fCheckstg, fNonStgf, fReopen, fTouch, fStgf);

   // File processing options
   fNoaction   = (fSopt == -1) ? kTRUE : kFALSE;
   fFullproc   = (fSopt == 0)  ? kTRUE : kFALSE;
   fLocateonly = (fSopt == 1)  ? kTRUE : kFALSE;
   fStageonly  = (fSopt == 2)  ? kTRUE : kFALSE;

   PDB(kSelector, 1) Info("SlaveBegin",
                          "fNoaction=%d fFullproc=%d fLocateonly=%d fStageonly=%d",
                          fNoaction, fFullproc, fLocateonly, fStageonly);

   // Run options
   fDoall       = (fRopt == 0) ? kTRUE : kFALSE;
   fGetlistonly = (fRopt == 1) ? kTRUE : kFALSE;
   fScanlist    = (fRopt == 2) ? kTRUE : kFALSE;

   PDB(kSelector, 1) Info("SlaveBegin",
                          "fDoall=%d fGetlistonly=%d fScanlist=%d",
                          fDoall, fGetlistonly, fScanlist);

   TString hostname(TUrl(gSystem->HostName()).GetHostFQDN());
   TString thisordinal = gProofServ ? gProofServ->GetOrdinal() : "n.d";
   TString title =
      TString::Format("TSelVerifyDataSet_%s_%s", hostname.Data(), thisordinal.Data());
   fSubDataSet= new TFileCollection(dsname, title);
}

//______________________________________________________________________________
Bool_t TSelVerifyDataSet::Process(Long64_t entry)
{
   // Process a single entry

   TDSetElement *fCurrent = 0;
   TPair *elemPair = 0;
   if (fInput && (elemPair = dynamic_cast<TPair *>
                      (fInput->FindObject("PROOF_CurrentElement")))) {
      if ((fCurrent = dynamic_cast<TDSetElement *>(elemPair->Value()))) {
         Info("Process", "entry %lld: file: '%s'", entry, fCurrent->GetName());
      } else {
         Error("Process", "entry %lld: no file specified!", entry);
         return kFALSE;
      }
   }

   TFileInfo *fileInfo = dynamic_cast<TFileInfo*>(fCurrent->GetAssocObj(0));
   if (!fileInfo) {
      Error("Process", "can not get TFileInfo; returning");
      return kFALSE;
   }

   PDB(kSelector, 1) {
      Info("Process", "input fileinfo: ");
      fileInfo->Print("L");
   }

   TFileStager *stager = 0;
   Bool_t createStager = kFALSE;

   TFileInfo* newfileinfo = new TFileInfo(*fileInfo);
   newfileinfo->SetIndex(fileInfo->GetIndex());

   if (fDoall || fGetlistonly) {

      stager = (fMss && strlen(fMss) > 0) ? TFileStager::Open(fMss) : 0;
      createStager = (stager) ? kFALSE : kTRUE;

      // Check which files have been staged, this can be replaced by a bulk command,
      // once it exists in the xrdclient

      // For real time monitoring
      gSystem->DispatchOneEvent(kTRUE);

      Bool_t changed = kFALSE;
      Bool_t touched = kFALSE;
      Bool_t disappeared = kFALSE;

      TDataSetManager::CheckStagedStatus(newfileinfo, fFopt, -1, 0, stager, createStager,
                                         fDbg, changed, touched, disappeared);

      if (changed) fChangedDs = kTRUE;
      if (touched) fTouched++;
      if (disappeared) fDisappeared++;

      SafeDelete(stager);

      PDB(kSelector, 1) Info("Process",
                             "fChangedDs = %d, fTouched = %d disappeared = %d",
                              fChangedDs, fTouched, fDisappeared);

      // If required to only get the list we are done
      if (fGetlistonly) {
         Info("Process", "updated fileinfo: ");
         newfileinfo->Print("F");
         fSubDataSet->Add(newfileinfo);
         return kTRUE;
      }
   }

   if (!fNoaction && (fDoall || fScanlist)) {

      // Point to the fileinfo
      //newStagedFiles = (!fDoall && fScanlist && flist) ? flist : newStagedFiles;
      if (!fDoall && fScanlist) {
          SafeDelete(newfileinfo);
          newfileinfo = new TFileInfo(*fileInfo);
          newfileinfo->SetIndex(fileInfo->GetIndex());
      }

      // Loop over now staged files
      PDB(kSelector, 1) Info("Process",
                             "file appear to be newly staged; %s",
                             newfileinfo->GetFirstUrl()->GetUrl());

      // If staging files, prepare the stager
      if (fLocateonly || fStageonly) {
         stager = (fMss && strlen(fMss) > 0) ? TFileStager::Open(fMss) : 0;
         createStager = (stager) ? kFALSE : kTRUE;
      }

      // Process the file
      Bool_t changed = kFALSE;
      Bool_t opened = kFALSE;
      TDataSetManager::ProcessFile(newfileinfo, fSopt, fCheckstg, fDoall, stager, createStager, fStageopts,
                                   fDbg, changed, opened);

      if (changed) fChangedDs = kTRUE;
      if (opened) fOpened++;
   }

   PDB(kSelector, 1) {
      Info("Process", "updated fileinfo: ");
      newfileinfo->Print("L");
   }
   fSubDataSet->Add(newfileinfo);

   return kTRUE;
}

//______________________________________________________________________________
void TSelVerifyDataSet::SlaveTerminate()
{
   if (fSubDataSet) {
      fSubDataSet->Update();
      if (fSubDataSet->GetNFiles() > 0) {
         fOutput->Add(fSubDataSet);
         Info("SlaveTerminate",
              "sub-dataset '%s' added to the output list (%lld files)",
              fSubDataSet->GetTitle(), fSubDataSet->GetNFiles());
      }
      // Add information for registration
      fOutput->Add(new TNamed(TString::Format("DATASET_%s", fSubDataSet->GetName()).Data(),"OT:sortidx:"));
      fOutput->Add(new TNamed("PROOFSERV_RegisterDataSet", ""));
   }

   // Send the number of files disppeared, opened and mark 'changed'if any fileinfo in the dataset has changed
   TString hostname(TUrl(gSystem->HostName()).GetHostFQDN());
   TString thisordinal = gProofServ ? gProofServ->GetOrdinal() : "n.d";
   TString sfdisppeared= TString::Format("PROOF_NoFilesDisppeared_%s_%s", hostname.Data(), thisordinal.Data());
   fOutput->Add(new TParameter<Int_t>(sfdisppeared.Data(), fDisappeared));
   TString sfOpened= TString::Format("PROOF_NoFilesOpened_%s_%s", hostname.Data(), thisordinal.Data());
   fOutput->Add(new TParameter<Int_t>(sfOpened.Data(), fOpened));
   TString sfTouched = TString::Format("PROOF_NoFilesTouched_%s_%s", hostname.Data(), thisordinal.Data());
   fOutput->Add(new TParameter<Int_t>(sfTouched.Data(), fTouched));
   TString schanged= TString::Format("PROOF_DataSetChanged_%s_%s", hostname.Data(), thisordinal.Data());
   fOutput->Add(new TParameter<Bool_t>(schanged.Data(), fChangedDs));
}

//______________________________________________________________________________
void TSelVerifyDataSet::Terminate()
{}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ximpgrp.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 13:58:58 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _XIMPGROUP_HXX
#define _XIMPGROUP_HXX

#ifndef _XMLOFF_XMLICTXT_HXX
#include "xmlictxt.hxx"
#endif

#ifndef _SDXMLIMP_IMPL_HXX
#include "sdxmlimp_impl.hxx"
#endif

#ifndef _XMLOFF_NMSPMAP_HXX
#include "nmspmap.hxx"
#endif

#ifndef _COM_SUN_STAR_DRAWING_XSHAPES_HPP_
#include <com/sun/star/drawing/XShapes.hpp>
#endif

#ifndef _RTTI_HXX
#include <tools/rtti.hxx>
#endif

#ifndef _XIMPSHAPE_HXX
#include "ximpshap.hxx"
#endif

//////////////////////////////////////////////////////////////////////////////
// draw:g context (RECURSIVE)

class SdXMLGroupShapeContext : public SdXMLShapeContext
{
    // the shape group this group is working on
    com::sun::star::uno::Reference< com::sun::star::drawing::XShapes > mxChilds;

protected:
    void SetLocalShapesContext(com::sun::star::uno::Reference< com::sun::star::drawing::XShapes >& rNew)
        { mxShapes = rNew; }

public:
    TYPEINFO();

    SdXMLGroupShapeContext( SvXMLImport& rImport, USHORT nPrfx, const rtl::OUString& rLocalName,
        const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList>& xAttrList,
        com::sun::star::uno::Reference< com::sun::star::drawing::XShapes >& rShapes,
        sal_Bool bTemporaryShape);
    virtual ~SdXMLGroupShapeContext();

    virtual SvXMLImportContext *CreateChildContext(
        USHORT nPrefix, const rtl::OUString& rLocalName,
        const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList>& xAttrList );
    virtual void StartElement(const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList>& xAttrList);
    virtual void EndElement();

    const com::sun::star::uno::Reference< com::sun::star::drawing::XShapes >& GetLocalShapesContext() const
        { return mxShapes; }
    com::sun::star::uno::Reference< com::sun::star::drawing::XShapes >& GetLocalShapesContext()
        { return mxShapes; }
};

#endif  //  _XIMPGROUP_HXX
<commit_msg>INTEGRATION: CWS vgbugs07 (1.6.274); FILE MERGED 2007/06/04 13:23:25 vg 1.6.274.1: #i76605# Remove -I .../inc/module hack introduced by hedaburemove01<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ximpgrp.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 15:10:19 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _XIMPGROUP_HXX
#define _XIMPGROUP_HXX

#ifndef _XMLOFF_XMLICTXT_HXX
#include <xmloff/xmlictxt.hxx>
#endif

#ifndef _SDXMLIMP_IMPL_HXX
#include "sdxmlimp_impl.hxx"
#endif

#ifndef _XMLOFF_NMSPMAP_HXX
#include <xmloff/nmspmap.hxx>
#endif

#ifndef _COM_SUN_STAR_DRAWING_XSHAPES_HPP_
#include <com/sun/star/drawing/XShapes.hpp>
#endif

#ifndef _RTTI_HXX
#include <tools/rtti.hxx>
#endif

#ifndef _XIMPSHAPE_HXX
#include "ximpshap.hxx"
#endif

//////////////////////////////////////////////////////////////////////////////
// draw:g context (RECURSIVE)

class SdXMLGroupShapeContext : public SdXMLShapeContext
{
    // the shape group this group is working on
    com::sun::star::uno::Reference< com::sun::star::drawing::XShapes > mxChilds;

protected:
    void SetLocalShapesContext(com::sun::star::uno::Reference< com::sun::star::drawing::XShapes >& rNew)
        { mxShapes = rNew; }

public:
    TYPEINFO();

    SdXMLGroupShapeContext( SvXMLImport& rImport, USHORT nPrfx, const rtl::OUString& rLocalName,
        const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList>& xAttrList,
        com::sun::star::uno::Reference< com::sun::star::drawing::XShapes >& rShapes,
        sal_Bool bTemporaryShape);
    virtual ~SdXMLGroupShapeContext();

    virtual SvXMLImportContext *CreateChildContext(
        USHORT nPrefix, const rtl::OUString& rLocalName,
        const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList>& xAttrList );
    virtual void StartElement(const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList>& xAttrList);
    virtual void EndElement();

    const com::sun::star::uno::Reference< com::sun::star::drawing::XShapes >& GetLocalShapesContext() const
        { return mxShapes; }
    com::sun::star::uno::Reference< com::sun::star::drawing::XShapes >& GetLocalShapesContext()
        { return mxShapes; }
};

#endif  //  _XIMPGROUP_HXX
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "TcpConn.hpp"
#include <geode/DistributedSystem.hpp>
#include <geode/SystemProperties.hpp>
#include <geode/Log.hpp>

#include <memory.h>

#include <ace/INET_Addr.h>
#include <ace/SOCK_IO.h>
#include <ace/SOCK_Connector.h>
#include <ace/SOCK_Acceptor.h>
#include <ace/OS.h>

using namespace apache::geode::client;

int TcpConn::m_chunkSize = TcpConn::setChunkSize();

void TcpConn::clearNagle(ACE_SOCKET sock) {
  int32_t val = 1;
#ifdef WIN32
  const char *param = (const char *)&val;
#else
  const void *param = (const void *)&val;
#endif
  int32_t plen = sizeof(val);

  if (0 != setsockopt(sock, IPPROTO_TCP, 1, param, plen)) {
    int32_t lastError = ACE_OS::last_error();
    LOGERROR("Failed to set TCP_NODELAY on socket. Errno: %d: %s", lastError,
             ACE_OS::strerror(lastError));
  }
}

int32_t TcpConn::maxSize(ACE_SOCKET sock, int32_t flag, int32_t size) {
  int32_t val = 0;
#ifdef _WIN32
  const char *cparam = (const char *)&val;
  char *param = (char *)&val;
#else
  const void *cparam = (const void *)&val;
  void *param = (void *)&val;
#endif
  socklen_t plen = sizeof(val);
  socklen_t clen = sizeof(val);

  static int32_t max = 32000;
  if (m_maxBuffSizePool <= 0) {
    SystemProperties *props = DistributedSystem::getSystemProperties();
    if (props != nullptr) {
      max = props->maxSocketBufferSize();
    }
  } else {
    max = m_maxBuffSizePool;
  }
  int32_t inc = 32120;
  val = size - (3 * inc);
  if (val < 0) val = 0;
  if (size == 0) size = max;
  int32_t red = 0;
  int32_t lastRed = -1;
  while (lastRed != red) {
    lastRed = red;
    val += inc;
    if (0 != setsockopt(sock, SOL_SOCKET, flag, cparam, clen)) {
      int32_t lastError = ACE_OS::last_error();
      LOGERROR("Failed to set socket options. Errno: %d : %s ", lastError,
               ACE_OS::strerror(lastError));
    }
    if (0 != getsockopt(sock, SOL_SOCKET, flag, param, &plen)) {
      int32_t lastError = ACE_OS::last_error();
      LOGERROR(
          "Failed to get buffer size for flag %d on socket. Errno: %d : %s",
          flag, lastError, ACE_OS::strerror(lastError));
    }
#ifdef _LINUX
    val /= 2;
#endif
    if ((val >= max) || (val >= size)) continue;
    red = val;
  }
  return val;
}

void TcpConn::createSocket(ACE_SOCKET sock) {
  LOGDEBUG("Creating plain socket stream");
  m_io = new ACE_SOCK_Stream((ACE_HANDLE)sock);
  // m_io->enable(ACE_NONBLOCK);
}

void TcpConn::init() {
  /* adongre
   * CID 28736: Improper use of negative value (NEGATIVE_RETURNS)
   * Function "socket(2, 1, 0)" returns a negative number.
   * Assigning: unsigned variable "sock" = "socket".
   *
   * CID 28737: Unsigned compared against 0 (NO_EFFECT)
   * This less-than-zero comparison of an unsigned value is never true. "sock <
   * 0U".
   */
  ACE_SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
  // if ( sock < 0 ) {
  if (sock == -1) {
    int32_t lastError = ACE_OS::last_error();
    LOGERROR("Failed to create socket. Errno: %d: %s", lastError,
             ACE_OS::strerror(lastError));
    char msg[256];
    ACE_OS::snprintf(msg, 256, "TcpConn::connect failed with errno: %d: %s",
                     lastError, ACE_OS::strerror(lastError));
    throw GeodeIOException(msg);
  }

  clearNagle(sock);

  static int32_t readSize = 0;
  static int32_t writeSize = 0;
  int32_t originalReadSize = readSize;
  readSize = maxSize(sock, SO_SNDBUF, readSize);
  if (originalReadSize != readSize) {
    // This should get logged once at startup and again only if it changes
    LOGINFO("Using socket send buffer size of %d.", readSize);
  }
  int32_t originalWriteSize = writeSize;
  writeSize = maxSize(sock, SO_RCVBUF, writeSize);
  if (originalWriteSize != writeSize) {
    // This should get logged once at startup and again only if it changes
    LOGINFO("Using socket receive buffer size of %d.", writeSize);
  }

  createSocket(sock);

  connect();
}

TcpConn::TcpConn() : m_io(nullptr), m_waitSeconds(0), m_maxBuffSizePool(0) {}

TcpConn::TcpConn(const char *ipaddr, uint32_t waitSeconds,
                 int32_t maxBuffSizePool)
    : m_io(nullptr),
      m_addr(ipaddr),
      m_waitSeconds(waitSeconds),
      m_maxBuffSizePool(maxBuffSizePool) {}

TcpConn::TcpConn(const char *hostname, int32_t port, uint32_t waitSeconds,
                 int32_t maxBuffSizePool)
    : m_io(nullptr),
      m_addr(port, hostname),
      m_waitSeconds(waitSeconds),
      m_maxBuffSizePool(maxBuffSizePool) {}

void TcpConn::listen(const char *hostname, int32_t port, uint32_t waitSeconds) {
  ACE_INET_Addr addr(port, hostname);
  listen(addr, waitSeconds);
}

void TcpConn::listen(const char *ipaddr, uint32_t waitSeconds) {
  ACE_INET_Addr addr(ipaddr);
  listen(addr, waitSeconds);
}

void TcpConn::listen(ACE_INET_Addr addr, uint32_t waitSeconds) {
  GF_DEV_ASSERT(m_io != nullptr);

  ACE_SOCK_Acceptor listener(addr, 1);
  int32_t retVal = 0;
  if (waitSeconds > 0) {
    ACE_Time_Value wtime(waitSeconds);
    retVal = listener.accept(*m_io, 0, &wtime);
  } else {
    retVal = listener.accept(*m_io, 0);
  }
  if (retVal == -1) {
    char msg[256];
    int32_t lastError = ACE_OS::last_error();
    if (lastError == ETIME || lastError == ETIMEDOUT) {
      /* adongre
       * Coverity - II
       * CID 29270: Calling risky function (SECURE_CODING)[VERY RISKY]. Using
       * "sprintf" can cause a
       * buffer overflow when done incorrectly. Because sprintf() assumes an
       * arbitrarily long string,
       * callers must be careful not to overflow the actual space of the
       * destination.
       * Use snprintf() instead, or correct precision specifiers.
       * Fix : using ACE_OS::snprintf
       */
      ACE_OS::snprintf(
          msg, 256,
          "TcpConn::listen Attempt to listen timed out after %d seconds.",
          waitSeconds);
      throw TimeoutException(msg);
    }
    ACE_OS::snprintf(msg, 256, "TcpConn::listen failed with errno: %d: %s",
                     lastError, ACE_OS::strerror(lastError));
    throw GeodeIOException(msg);
  }
}

void TcpConn::connect(const char *hostname, int32_t port,
                      uint32_t waitSeconds) {
  ACE_INET_Addr addr(port, hostname);
  m_addr = addr;
  m_waitSeconds = waitSeconds;
  connect();
}

void TcpConn::connect(const char *ipaddr, uint32_t waitSeconds) {
  ACE_INET_Addr addr(ipaddr);
  m_addr = addr;
  m_waitSeconds = waitSeconds;
  connect();
}

void TcpConn::connect() {
  GF_DEV_ASSERT(m_io != nullptr);

  ACE_INET_Addr ipaddr = m_addr;
  uint32_t waitSeconds = m_waitSeconds;

  ACE_OS::signal(SIGPIPE, SIG_IGN);  // Ignore broken pipe

  // passing waittime as microseconds
  if (DistributedSystem::getSystemProperties()->readTimeoutUnitInMillis()) {
    waitSeconds = waitSeconds * 1000;
  } else {
    waitSeconds = waitSeconds * (1000 * 1000);
  }

  LOGFINER("Connecting plain socket stream to %s:%d waiting %d micro sec",
           ipaddr.get_host_name(), ipaddr.get_port_number(), waitSeconds);

  ACE_SOCK_Connector conn;
  int32_t retVal = 0;
  if (waitSeconds > 0) {
    // passing waittime as microseconds
    ACE_Time_Value wtime(0, waitSeconds);
    retVal = conn.connect(*m_io, ipaddr, &wtime);
  } else {
    retVal = conn.connect(*m_io, ipaddr);
  }
  if (retVal == -1) {
    char msg[256];
    int32_t lastError = ACE_OS::last_error();
    if (lastError == ETIME || lastError == ETIMEDOUT) {
      ACE_OS::snprintf(
          msg, 256,
          "TcpConn::connect Attempt to connect timed out after %d seconds.",
          waitSeconds);
      //  this is only called by constructor, so we must delete m_io
      GF_SAFE_DELETE(m_io);
      throw TimeoutException(msg);
    }
    ACE_OS::snprintf(msg, 256, "TcpConn::connect failed with errno: %d: %s",
                     lastError, ACE_OS::strerror(lastError));
    //  this is only called by constructor, so we must delete m_io
    GF_SAFE_DELETE(m_io);
    throw GeodeIOException(msg);
  }
  int rc = this->m_io->enable(ACE_NONBLOCK);
  if (-1 == rc) {
    char msg[250];
    int32_t lastError = ACE_OS::last_error();
    ACE_OS::snprintf(msg, 256, "TcpConn::NONBLOCK: %d: %s", lastError,
                     ACE_OS::strerror(lastError));

    LOGINFO(msg);
  }
}

void TcpConn::close() {
  if (m_io != nullptr) {
    m_io->close();
    GF_SAFE_DELETE(m_io);
  }
}

int32_t TcpConn::receive(char *buff, int32_t len, uint32_t waitSeconds,
                         uint32_t waitMicroSeconds) {
  return socketOp(SOCK_READ, buff, len, waitSeconds);
}

int32_t TcpConn::send(const char *buff, int32_t len, uint32_t waitSeconds,
                      uint32_t waitMicroSeconds) {
  return socketOp(SOCK_WRITE, const_cast<char *>(buff), len, waitSeconds);
}

int32_t TcpConn::socketOp(TcpConn::SockOp op, char *buff, int32_t len,
                          uint32_t waitSeconds) {
  {
    /*{
      ACE_HANDLE handle = m_io->get_handle();
       int val = ACE::get_flags (handle);

      if (ACE_BIT_DISABLED (val, ACE_NONBLOCK))
      {
        //ACE::set_flags (handle, ACE_NONBLOCK);
        LOGINFO("Flag is not set");
      }else
      {
          LOGINFO("Flag is set");
      }
    }*/

    GF_DEV_ASSERT(m_io != nullptr);
    GF_DEV_ASSERT(buff != nullptr);

#if GF_DEVEL_ASSERTS == 1
    if (len <= 0) {
      LOGERROR(
          "TcpConn::socketOp called with a length of %d specified. "
          "No operation performed.",
          len);
      GF_DEV_ASSERT(false);
    }
#endif

    ACE_Time_Value waitTime(0, waitSeconds /*now its in microSeconds*/);
    ACE_Time_Value endTime(ACE_OS::gettimeofday() + waitTime);
    ACE_Time_Value sleepTime(0, 100);
    size_t readLen = 0;
    ssize_t retVal;
    bool errnoSet = false;

    int32_t sendlen = len;
    int32_t totalsend = 0;

    while (len > 0 && waitTime > ACE_Time_Value::zero) {
      if (len > m_chunkSize) {
        sendlen = m_chunkSize;
        len -= m_chunkSize;
      } else {
        sendlen = len;
        len = 0;
      }
      do {
        if (op == SOCK_READ) {
          retVal = m_io->recv_n(buff, sendlen, &waitTime, &readLen);
        } else {
          retVal = m_io->send_n(buff, sendlen, &waitTime, &readLen);
        }
        sendlen -= static_cast<int32_t>(readLen);
        totalsend += static_cast<int32_t>(readLen);
        if (retVal < 0) {
          int32_t lastError = ACE_OS::last_error();
          if (lastError == EAGAIN) {
            ACE_OS::sleep(sleepTime);
          } else {
            errnoSet = true;
            break;
          }
        } else if (retVal == 0 && readLen == 0) {
          ACE_OS::last_error(EPIPE);
          errnoSet = true;
          break;
        }

        buff += readLen;
        if (sendlen == 0) break;
        waitTime = endTime - ACE_OS::gettimeofday();
        if (waitTime <= ACE_Time_Value::zero) break;
      } while (sendlen > 0);
      if (errnoSet) break;
    }

    if (len > 0 && !errnoSet) {
      ACE_OS::last_error(ETIME);
    }

    GF_DEV_ASSERT(len >= 0);
    return totalsend;
  }
}

//  Return the local port for this TCP connection.
uint16_t TcpConn::getPort() {
  GF_DEV_ASSERT(m_io != nullptr);

  ACE_INET_Addr localAddr;
  m_io->get_local_addr(*(ACE_Addr *)&localAddr);
  return localAddr.get_port_number();
}
<commit_msg>GEODE-3143: Close socket before deleting it.<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "TcpConn.hpp"
#include <geode/DistributedSystem.hpp>
#include <geode/SystemProperties.hpp>
#include <geode/Log.hpp>

#include <memory.h>

#include <ace/INET_Addr.h>
#include <ace/SOCK_IO.h>
#include <ace/SOCK_Connector.h>
#include <ace/SOCK_Acceptor.h>
#include <ace/OS.h>

using namespace apache::geode::client;

int TcpConn::m_chunkSize = TcpConn::setChunkSize();

void TcpConn::clearNagle(ACE_SOCKET sock) {
  int32_t val = 1;
#ifdef WIN32
  const char *param = (const char *)&val;
#else
  const void *param = (const void *)&val;
#endif
  int32_t plen = sizeof(val);

  if (0 != setsockopt(sock, IPPROTO_TCP, 1, param, plen)) {
    int32_t lastError = ACE_OS::last_error();
    LOGERROR("Failed to set TCP_NODELAY on socket. Errno: %d: %s", lastError,
             ACE_OS::strerror(lastError));
  }
}

int32_t TcpConn::maxSize(ACE_SOCKET sock, int32_t flag, int32_t size) {
  int32_t val = 0;
#ifdef _WIN32
  const char *cparam = (const char *)&val;
  char *param = (char *)&val;
#else
  const void *cparam = (const void *)&val;
  void *param = (void *)&val;
#endif
  socklen_t plen = sizeof(val);
  socklen_t clen = sizeof(val);

  static int32_t max = 32000;
  if (m_maxBuffSizePool <= 0) {
    SystemProperties *props = DistributedSystem::getSystemProperties();
    if (props != nullptr) {
      max = props->maxSocketBufferSize();
    }
  } else {
    max = m_maxBuffSizePool;
  }
  int32_t inc = 32120;
  val = size - (3 * inc);
  if (val < 0) val = 0;
  if (size == 0) size = max;
  int32_t red = 0;
  int32_t lastRed = -1;
  while (lastRed != red) {
    lastRed = red;
    val += inc;
    if (0 != setsockopt(sock, SOL_SOCKET, flag, cparam, clen)) {
      int32_t lastError = ACE_OS::last_error();
      LOGERROR("Failed to set socket options. Errno: %d : %s ", lastError,
               ACE_OS::strerror(lastError));
    }
    if (0 != getsockopt(sock, SOL_SOCKET, flag, param, &plen)) {
      int32_t lastError = ACE_OS::last_error();
      LOGERROR(
          "Failed to get buffer size for flag %d on socket. Errno: %d : %s",
          flag, lastError, ACE_OS::strerror(lastError));
    }
#ifdef _LINUX
    val /= 2;
#endif
    if ((val >= max) || (val >= size)) continue;
    red = val;
  }
  return val;
}

void TcpConn::createSocket(ACE_SOCKET sock) {
  LOGDEBUG("Creating plain socket stream");
  m_io = new ACE_SOCK_Stream((ACE_HANDLE)sock);
  // m_io->enable(ACE_NONBLOCK);
}

void TcpConn::init() {
  /* adongre
   * CID 28736: Improper use of negative value (NEGATIVE_RETURNS)
   * Function "socket(2, 1, 0)" returns a negative number.
   * Assigning: unsigned variable "sock" = "socket".
   *
   * CID 28737: Unsigned compared against 0 (NO_EFFECT)
   * This less-than-zero comparison of an unsigned value is never true. "sock <
   * 0U".
   */
  ACE_SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
  // if ( sock < 0 ) {
  if (sock == -1) {
    int32_t lastError = ACE_OS::last_error();
    LOGERROR("Failed to create socket. Errno: %d: %s", lastError,
             ACE_OS::strerror(lastError));
    char msg[256];
    ACE_OS::snprintf(msg, 256, "TcpConn::connect failed with errno: %d: %s",
                     lastError, ACE_OS::strerror(lastError));
    throw GeodeIOException(msg);
  }

  clearNagle(sock);

  static int32_t readSize = 0;
  static int32_t writeSize = 0;
  int32_t originalReadSize = readSize;
  readSize = maxSize(sock, SO_SNDBUF, readSize);
  if (originalReadSize != readSize) {
    // This should get logged once at startup and again only if it changes
    LOGINFO("Using socket send buffer size of %d.", readSize);
  }
  int32_t originalWriteSize = writeSize;
  writeSize = maxSize(sock, SO_RCVBUF, writeSize);
  if (originalWriteSize != writeSize) {
    // This should get logged once at startup and again only if it changes
    LOGINFO("Using socket receive buffer size of %d.", writeSize);
  }

  createSocket(sock);

  connect();
}

TcpConn::TcpConn() : m_io(nullptr), m_waitSeconds(0), m_maxBuffSizePool(0) {}

TcpConn::TcpConn(const char *ipaddr, uint32_t waitSeconds,
                 int32_t maxBuffSizePool)
    : m_io(nullptr),
      m_addr(ipaddr),
      m_waitSeconds(waitSeconds),
      m_maxBuffSizePool(maxBuffSizePool) {}

TcpConn::TcpConn(const char *hostname, int32_t port, uint32_t waitSeconds,
                 int32_t maxBuffSizePool)
    : m_io(nullptr),
      m_addr(port, hostname),
      m_waitSeconds(waitSeconds),
      m_maxBuffSizePool(maxBuffSizePool) {}

void TcpConn::listen(const char *hostname, int32_t port, uint32_t waitSeconds) {
  ACE_INET_Addr addr(port, hostname);
  listen(addr, waitSeconds);
}

void TcpConn::listen(const char *ipaddr, uint32_t waitSeconds) {
  ACE_INET_Addr addr(ipaddr);
  listen(addr, waitSeconds);
}

void TcpConn::listen(ACE_INET_Addr addr, uint32_t waitSeconds) {
  GF_DEV_ASSERT(m_io != nullptr);

  ACE_SOCK_Acceptor listener(addr, 1);
  int32_t retVal = 0;
  if (waitSeconds > 0) {
    ACE_Time_Value wtime(waitSeconds);
    retVal = listener.accept(*m_io, 0, &wtime);
  } else {
    retVal = listener.accept(*m_io, 0);
  }
  if (retVal == -1) {
    char msg[256];
    int32_t lastError = ACE_OS::last_error();
    if (lastError == ETIME || lastError == ETIMEDOUT) {
      /* adongre
       * Coverity - II
       * CID 29270: Calling risky function (SECURE_CODING)[VERY RISKY]. Using
       * "sprintf" can cause a
       * buffer overflow when done incorrectly. Because sprintf() assumes an
       * arbitrarily long string,
       * callers must be careful not to overflow the actual space of the
       * destination.
       * Use snprintf() instead, or correct precision specifiers.
       * Fix : using ACE_OS::snprintf
       */
      ACE_OS::snprintf(
          msg, 256,
          "TcpConn::listen Attempt to listen timed out after %d seconds.",
          waitSeconds);
      throw TimeoutException(msg);
    }
    ACE_OS::snprintf(msg, 256, "TcpConn::listen failed with errno: %d: %s",
                     lastError, ACE_OS::strerror(lastError));
    throw GeodeIOException(msg);
  }
}

void TcpConn::connect(const char *hostname, int32_t port,
                      uint32_t waitSeconds) {
  ACE_INET_Addr addr(port, hostname);
  m_addr = addr;
  m_waitSeconds = waitSeconds;
  connect();
}

void TcpConn::connect(const char *ipaddr, uint32_t waitSeconds) {
  ACE_INET_Addr addr(ipaddr);
  m_addr = addr;
  m_waitSeconds = waitSeconds;
  connect();
}

void TcpConn::connect() {
  GF_DEV_ASSERT(m_io != nullptr);

  ACE_INET_Addr ipaddr = m_addr;
  uint32_t waitSeconds = m_waitSeconds;

  ACE_OS::signal(SIGPIPE, SIG_IGN);  // Ignore broken pipe

  // passing waittime as microseconds
  if (DistributedSystem::getSystemProperties()->readTimeoutUnitInMillis()) {
    waitSeconds = waitSeconds * 1000;
  } else {
    waitSeconds = waitSeconds * (1000 * 1000);
  }

  LOGFINER("Connecting plain socket stream to %s:%d waiting %d micro sec",
           ipaddr.get_host_name(), ipaddr.get_port_number(), waitSeconds);

  ACE_SOCK_Connector conn;
  int32_t retVal = 0;
  if (waitSeconds > 0) {
    // passing waittime as microseconds
    ACE_Time_Value wtime(0, waitSeconds);
    retVal = conn.connect(*m_io, ipaddr, &wtime);
  } else {
    retVal = conn.connect(*m_io, ipaddr);
  }
  if (retVal == -1) {
    char msg[256];
    int32_t lastError = ACE_OS::last_error();
    if (lastError == ETIME || lastError == ETIMEDOUT) {
      ACE_OS::snprintf(
          msg, 256,
          "TcpConn::connect Attempt to connect timed out after %d seconds.",
          waitSeconds);
      //  this is only called by constructor, so we must delete m_io
      GF_SAFE_DELETE(m_io);
      throw TimeoutException(msg);
    }
    ACE_OS::snprintf(msg, 256, "TcpConn::connect failed with errno: %d: %s",
                     lastError, ACE_OS::strerror(lastError));
    //  this is only called by constructor, so we must delete m_io
	close();
    throw GeodeIOException(msg);
  }
  int rc = this->m_io->enable(ACE_NONBLOCK);
  if (-1 == rc) {
    char msg[250];
    int32_t lastError = ACE_OS::last_error();
    ACE_OS::snprintf(msg, 256, "TcpConn::NONBLOCK: %d: %s", lastError,
                     ACE_OS::strerror(lastError));

    LOGINFO(msg);
  }
}

void TcpConn::close() {
  if (m_io != nullptr) {
    m_io->close();
    GF_SAFE_DELETE(m_io);
  }
}

int32_t TcpConn::receive(char *buff, int32_t len, uint32_t waitSeconds,
                         uint32_t waitMicroSeconds) {
  return socketOp(SOCK_READ, buff, len, waitSeconds);
}

int32_t TcpConn::send(const char *buff, int32_t len, uint32_t waitSeconds,
                      uint32_t waitMicroSeconds) {
  return socketOp(SOCK_WRITE, const_cast<char *>(buff), len, waitSeconds);
}

int32_t TcpConn::socketOp(TcpConn::SockOp op, char *buff, int32_t len,
                          uint32_t waitSeconds) {
  {
    /*{
      ACE_HANDLE handle = m_io->get_handle();
       int val = ACE::get_flags (handle);

      if (ACE_BIT_DISABLED (val, ACE_NONBLOCK))
      {
        //ACE::set_flags (handle, ACE_NONBLOCK);
        LOGINFO("Flag is not set");
      }else
      {
          LOGINFO("Flag is set");
      }
    }*/

    GF_DEV_ASSERT(m_io != nullptr);
    GF_DEV_ASSERT(buff != nullptr);

#if GF_DEVEL_ASSERTS == 1
    if (len <= 0) {
      LOGERROR(
          "TcpConn::socketOp called with a length of %d specified. "
          "No operation performed.",
          len);
      GF_DEV_ASSERT(false);
    }
#endif

    ACE_Time_Value waitTime(0, waitSeconds /*now its in microSeconds*/);
    ACE_Time_Value endTime(ACE_OS::gettimeofday() + waitTime);
    ACE_Time_Value sleepTime(0, 100);
    size_t readLen = 0;
    ssize_t retVal;
    bool errnoSet = false;

    int32_t sendlen = len;
    int32_t totalsend = 0;

    while (len > 0 && waitTime > ACE_Time_Value::zero) {
      if (len > m_chunkSize) {
        sendlen = m_chunkSize;
        len -= m_chunkSize;
      } else {
        sendlen = len;
        len = 0;
      }
      do {
        if (op == SOCK_READ) {
          retVal = m_io->recv_n(buff, sendlen, &waitTime, &readLen);
        } else {
          retVal = m_io->send_n(buff, sendlen, &waitTime, &readLen);
        }
        sendlen -= static_cast<int32_t>(readLen);
        totalsend += static_cast<int32_t>(readLen);
        if (retVal < 0) {
          int32_t lastError = ACE_OS::last_error();
          if (lastError == EAGAIN) {
            ACE_OS::sleep(sleepTime);
          } else {
            errnoSet = true;
            break;
          }
        } else if (retVal == 0 && readLen == 0) {
          ACE_OS::last_error(EPIPE);
          errnoSet = true;
          break;
        }

        buff += readLen;
        if (sendlen == 0) break;
        waitTime = endTime - ACE_OS::gettimeofday();
        if (waitTime <= ACE_Time_Value::zero) break;
      } while (sendlen > 0);
      if (errnoSet) break;
    }

    if (len > 0 && !errnoSet) {
      ACE_OS::last_error(ETIME);
    }

    GF_DEV_ASSERT(len >= 0);
    return totalsend;
  }
}

//  Return the local port for this TCP connection.
uint16_t TcpConn::getPort() {
  GF_DEV_ASSERT(m_io != nullptr);

  ACE_INET_Addr localAddr;
  m_io->get_local_addr(*(ACE_Addr *)&localAddr);
  return localAddr.get_port_number();
}
<|endoftext|>


<commit_before><commit_msg>Use the boundary_pos parameter passed to the MultiPartResponseClient::didReceiveData function as the length of the data. At times HTTP byte range requests return responses which specify invalid content ranges as per the spec, i.e. the last byte position is smaller than the first byte position, etc. I looked into Firefox's byte range parsing code and it always calculates the length based on the boundary position.<commit_after><|endoftext|>