<commit_before>/*
 * Copyright 2007 Stephen Liu
 * For license terms, see the file COPYING along with this library.
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <signal.h>

#include "spporting.hpp"
#include "spthread.hpp"

#include "spdispatcher.hpp"

#include "speventcb.hpp"
#include "sphandler.hpp"
#include "spsession.hpp"
#include "spexecutor.hpp"
#include "sputils.hpp"
#include "spiochannel.hpp"
#include "spioutils.hpp"

#include "event_msgqueue.h"

SP_Dispatcher :: SP_Dispatcher( SP_CompletionHandler * completionHandler, int maxThreads )
{
#ifdef SIGPIPE
	/* Don't die with SIGPIPE on remote read shutdown. That's dumb. */
	signal( SIGPIPE, SIG_IGN );
#endif

	mIsShutdown = 0;
	mIsRunning = 0;

	mEventArg = new SP_EventArg( 600 );

	mMaxThreads = maxThreads > 0 ? maxThreads : 4;

	mCompletionHandler = completionHandler;

	mPushQueue = msgqueue_new( mEventArg->getEventBase(), 0, onPush, mEventArg );
}

SP_Dispatcher :: ~SP_Dispatcher()
{
	if( 0 == mIsRunning ) sleep( 1 );

	shutdown();

	for( ; mIsRunning; ) sleep( 1 );

	//msgqueue_destroy( (struct event_msgqueue*)mPushQueue );

	delete mEventArg;
	mEventArg = NULL;
}

void SP_Dispatcher :: setTimeout( int timeout )
{
	mEventArg->setTimeout( timeout );
}

void SP_Dispatcher :: shutdown()
{
	mIsShutdown = 1;
}

int SP_Dispatcher :: isRunning()
{
	return mIsRunning;
}

int SP_Dispatcher :: getSessionCount()
{
	return mEventArg->getSessionManager()->getCount();
}

int SP_Dispatcher :: getReqQueueLength()
{
	return mEventArg->getInputResultQueue()->getLength();
}

int SP_Dispatcher :: dispatch()
{
	int ret = -1;

	sp_thread_attr_t attr;
	sp_thread_attr_init( &attr );
	assert( sp_thread_attr_setstacksize( &attr, 1024 * 1024 ) == 0 );
	sp_thread_attr_setdetachstate( &attr, SP_THREAD_CREATE_DETACHED );

	sp_thread_t thread;
	ret = sp_thread_create( &thread, &attr, eventLoop, this );
	sp_thread_attr_destroy( &attr );
	if( 0 == ret ) {
		sp_syslog( LOG_NOTICE, "Thread #%ld has been created for dispatcher", thread );
	} else {
		mIsRunning = 0;
		sp_syslog( LOG_WARNING, "Unable to create a thread for dispatcher, %s",
			strerror( errno ) ) ;
	}

	return ret;
}

sp_thread_result_t SP_THREAD_CALL SP_Dispatcher :: eventLoop( void * arg )
{
	SP_Dispatcher * dispatcher = (SP_Dispatcher*)arg;

	dispatcher->mIsRunning = 1;

	dispatcher->start();

	dispatcher->mIsRunning = 0;

	return 0;
}

void SP_Dispatcher :: outputCompleted( void * arg )
{
	SP_CompletionHandler * handler = ( SP_CompletionHandler * ) ((void**)arg)[0];
	SP_Message * msg = ( SP_Message * ) ((void**)arg)[ 1 ];

	handler->completionMessage( msg );

	free( arg );
}

int SP_Dispatcher :: start()
{
	SP_Executor workerExecutor( mMaxThreads, "work" );
	SP_Executor actExecutor( 1, "act" );

	/* Start the event loop. */
	while( 0 == mIsShutdown ) {
		event_base_loop( mEventArg->getEventBase(), EVLOOP_ONCE );

		for( ; NULL != mEventArg->getInputResultQueue()->top(); ) {
			SP_Task * task = (SP_Task*)mEventArg->getInputResultQueue()->pop();
			workerExecutor.execute( task );
		}

		for( ; NULL != mEventArg->getOutputResultQueue()->top(); ) {
			SP_Message * msg = (SP_Message*)mEventArg->getOutputResultQueue()->pop();

			void ** arg = ( void** )malloc( sizeof( void * ) * 2 );
			arg[ 0 ] = (void*)mCompletionHandler;
			arg[ 1 ] = (void*)msg;

			actExecutor.execute( outputCompleted, arg );
		}
	}

	sp_syslog( LOG_NOTICE, "Dispatcher is shutdown." );

	return 0;
}

typedef struct tagSP_PushArg {
	int mType;      // 0 : fd, 1 : timer

	// for push fd
	int mFd;
	SP_Handler * mHandler;
	SP_IOChannel * mIOChannel;
	int mNeedStart;

	// for push timer
	struct timeval mTimeout;
	struct event mTimerEvent;
	SP_TimerHandler * mTimerHandler;
	SP_EventArg * mEventArg;
	void * mPushQueue;
} SP_PushArg_t;

void SP_Dispatcher :: onPush( void * queueData, void * arg )
{
	SP_PushArg_t * pushArg = (SP_PushArg_t*)queueData;
	SP_EventArg * eventArg = (SP_EventArg*)arg;

	if( 0 == pushArg->mType ) {
		SP_Sid_t sid;
		sid.mKey = eventArg->getSessionManager()->allocKey( &sid.mSeq );
		assert( sid.mKey > 0 );

		SP_Session * session = new SP_Session( sid );

		eventArg->getSessionManager()->put( sid.mKey, sid.mSeq, session );

		session->setHandler( pushArg->mHandler );
		session->setIOChannel( pushArg->mIOChannel );
		session->setArg( eventArg );

		event_set( session->getReadEvent(), pushArg->mFd, EV_READ,
				SP_EventCallback::onRead, session );
		event_set( session->getWriteEvent(), pushArg->mFd, EV_WRITE,
				SP_EventCallback::onWrite, session );

		if( pushArg->mNeedStart ) {
			SP_EventHelper::doStart( session );
		} else {
			SP_EventCallback::addEvent( session, EV_WRITE, pushArg->mFd );
			SP_EventCallback::addEvent( session, EV_READ, pushArg->mFd );
		}

		free( pushArg );
	} else {
		event_set( &( pushArg->mTimerEvent ), -1, 0, onTimer, pushArg );
		event_base_set( eventArg->getEventBase(), &( pushArg->mTimerEvent ) );
		event_add( &( pushArg->mTimerEvent ), &( pushArg->mTimeout ) );
	}
}

int SP_Dispatcher :: push( int fd, SP_Handler * handler, int needStart )
{
	SP_IOChannel * ioChannel = new SP_DefaultIOChannel();
	return push( fd, handler, ioChannel, needStart );
}

int SP_Dispatcher :: push( int fd, SP_Handler * handler,
		SP_IOChannel * ioChannel, int needStart )
{
	SP_PushArg_t * arg = (SP_PushArg_t*)malloc( sizeof( SP_PushArg_t ) );
	arg->mType = 0;
	arg->mFd = fd;
	arg->mHandler = handler;
	arg->mIOChannel = ioChannel;
	arg->mNeedStart = needStart;

	SP_IOUtils::setNonblock( fd );

	return msgqueue_push( (struct event_msgqueue*)mPushQueue, arg );
}

void SP_Dispatcher :: onTimer( int, short, void * arg )
{
	SP_PushArg_t * pushArg = (SP_PushArg_t*)arg;

	pushArg->mEventArg->getInputResultQueue()->push(
		new SP_SimpleTask( timer, pushArg, 1 ) );
}

void SP_Dispatcher :: timer( void * arg )
{
	SP_PushArg_t * pushArg = (SP_PushArg_t*)arg;
	SP_TimerHandler * handler = pushArg->mTimerHandler;
	SP_EventArg * eventArg = pushArg->mEventArg;

	SP_Sid_t sid;
	sid.mKey = SP_Sid_t::eTimerKey;
	sid.mSeq = SP_Sid_t::eTimerSeq;
	SP_Response * response = new SP_Response( sid );
	if( 0 == handler->handle( response, &( pushArg->mTimeout ) ) ) {
		msgqueue_push( (struct event_msgqueue*)pushArg->mPushQueue, arg );
	} else {
		delete pushArg->mTimerHandler;
		free( pushArg );
	}

	msgqueue_push( (struct event_msgqueue*)eventArg->getResponseQueue(), response );
}

int SP_Dispatcher :: push( const struct timeval * timeout, SP_TimerHandler * handler )
{
	SP_PushArg_t * arg = (SP_PushArg_t*)malloc( sizeof( SP_PushArg_t ) );

	arg->mType = 1;
	arg->mTimeout = *timeout;
	arg->mTimerHandler = handler;
	arg->mEventArg = mEventArg;
	arg->mPushQueue = mPushQueue;

	return msgqueue_push( (struct event_msgqueue*)mPushQueue, arg );
}

int SP_Dispatcher :: push( SP_Response * response )
{
	return msgqueue_push( (struct event_msgqueue*)mEventArg->getResponseQueue(), response );
}

<commit_msg>add client ip for request when using SP_Dispatcher<commit_after>/*
 * Copyright 2007 Stephen Liu
 * For license terms, see the file COPYING along with this library.
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <signal.h>

#include "spporting.hpp"
#include "spthread.hpp"

#include "spdispatcher.hpp"

#include "speventcb.hpp"
#include "sphandler.hpp"
#include "spsession.hpp"
#include "spexecutor.hpp"
#include "sputils.hpp"
#include "spiochannel.hpp"
#include "spioutils.hpp"
#include "sprequest.hpp"

#include "event_msgqueue.h"

SP_Dispatcher :: SP_Dispatcher( SP_CompletionHandler * completionHandler, int maxThreads )
{
#ifdef SIGPIPE
	/* Don't die with SIGPIPE on remote read shutdown. That's dumb. */
	signal( SIGPIPE, SIG_IGN );
#endif

	mIsShutdown = 0;
	mIsRunning = 0;

	mEventArg = new SP_EventArg( 600 );

	mMaxThreads = maxThreads > 0 ? maxThreads : 4;

	mCompletionHandler = completionHandler;

	mPushQueue = msgqueue_new( mEventArg->getEventBase(), 0, onPush, mEventArg );
}

SP_Dispatcher :: ~SP_Dispatcher()
{
	if( 0 == mIsRunning ) sleep( 1 );

	shutdown();

	for( ; mIsRunning; ) sleep( 1 );

	//msgqueue_destroy( (struct event_msgqueue*)mPushQueue );

	delete mEventArg;
	mEventArg = NULL;
}

void SP_Dispatcher :: setTimeout( int timeout )
{
	mEventArg->setTimeout( timeout );
}

void SP_Dispatcher :: shutdown()
{
	mIsShutdown = 1;
}

int SP_Dispatcher :: isRunning()
{
	return mIsRunning;
}

int SP_Dispatcher :: getSessionCount()
{
	return mEventArg->getSessionManager()->getCount();
}

int SP_Dispatcher :: getReqQueueLength()
{
	return mEventArg->getInputResultQueue()->getLength();
}

int SP_Dispatcher :: dispatch()
{
	int ret = -1;

	sp_thread_attr_t attr;
	sp_thread_attr_init( &attr );
	assert( sp_thread_attr_setstacksize( &attr, 1024 * 1024 ) == 0 );
	sp_thread_attr_setdetachstate( &attr, SP_THREAD_CREATE_DETACHED );

	sp_thread_t thread;
	ret = sp_thread_create( &thread, &attr, eventLoop, this );
	sp_thread_attr_destroy( &attr );
	if( 0 == ret ) {
		sp_syslog( LOG_NOTICE, "Thread #%ld has been created for dispatcher", thread );
	} else {
		mIsRunning = 0;
		sp_syslog( LOG_WARNING, "Unable to create a thread for dispatcher, %s",
			strerror( errno ) ) ;
	}

	return ret;
}

sp_thread_result_t SP_THREAD_CALL SP_Dispatcher :: eventLoop( void * arg )
{
	SP_Dispatcher * dispatcher = (SP_Dispatcher*)arg;

	dispatcher->mIsRunning = 1;

	dispatcher->start();

	dispatcher->mIsRunning = 0;

	return 0;
}

void SP_Dispatcher :: outputCompleted( void * arg )
{
	SP_CompletionHandler * handler = ( SP_CompletionHandler * ) ((void**)arg)[0];
	SP_Message * msg = ( SP_Message * ) ((void**)arg)[ 1 ];

	handler->completionMessage( msg );

	free( arg );
}

int SP_Dispatcher :: start()
{
	SP_Executor workerExecutor( mMaxThreads, "work" );
	SP_Executor actExecutor( 1, "act" );

	/* Start the event loop. */
	while( 0 == mIsShutdown ) {
		event_base_loop( mEventArg->getEventBase(), EVLOOP_ONCE );

		for( ; NULL != mEventArg->getInputResultQueue()->top(); ) {
			SP_Task * task = (SP_Task*)mEventArg->getInputResultQueue()->pop();
			workerExecutor.execute( task );
		}

		for( ; NULL != mEventArg->getOutputResultQueue()->top(); ) {
			SP_Message * msg = (SP_Message*)mEventArg->getOutputResultQueue()->pop();

			void ** arg = ( void** )malloc( sizeof( void * ) * 2 );
			arg[ 0 ] = (void*)mCompletionHandler;
			arg[ 1 ] = (void*)msg;

			actExecutor.execute( outputCompleted, arg );
		}
	}

	sp_syslog( LOG_NOTICE, "Dispatcher is shutdown." );

	return 0;
}

typedef struct tagSP_PushArg {
	int mType;      // 0 : fd, 1 : timer

	// for push fd
	int mFd;
	SP_Handler * mHandler;
	SP_IOChannel * mIOChannel;
	int mNeedStart;

	// for push timer
	struct timeval mTimeout;
	struct event mTimerEvent;
	SP_TimerHandler * mTimerHandler;
	SP_EventArg * mEventArg;
	void * mPushQueue;
} SP_PushArg_t;

void SP_Dispatcher :: onPush( void * queueData, void * arg )
{
	SP_PushArg_t * pushArg = (SP_PushArg_t*)queueData;
	SP_EventArg * eventArg = (SP_EventArg*)arg;

	if( 0 == pushArg->mType ) {
		SP_Sid_t sid;
		sid.mKey = eventArg->getSessionManager()->allocKey( &sid.mSeq );
		assert( sid.mKey > 0 );

		SP_Session * session = new SP_Session( sid );

		char clientIP[ 32 ] = { 0 };
		{
			struct sockaddr_in clientAddr;
			socklen_t clientLen = sizeof( clientAddr );
			getpeername( pushArg->mFd, (struct sockaddr *)&clientAddr, &clientLen );
			SP_IOUtils::inetNtoa( &( clientAddr.sin_addr ), clientIP, sizeof( clientIP ) );
		}
		session->getRequest()->setClientIP( clientIP );

		eventArg->getSessionManager()->put( sid.mKey, sid.mSeq, session );

		session->setHandler( pushArg->mHandler );
		session->setIOChannel( pushArg->mIOChannel );
		session->setArg( eventArg );

		event_set( session->getReadEvent(), pushArg->mFd, EV_READ,
				SP_EventCallback::onRead, session );
		event_set( session->getWriteEvent(), pushArg->mFd, EV_WRITE,
				SP_EventCallback::onWrite, session );

		if( pushArg->mNeedStart ) {
			SP_EventHelper::doStart( session );
		} else {
			SP_EventCallback::addEvent( session, EV_WRITE, pushArg->mFd );
			SP_EventCallback::addEvent( session, EV_READ, pushArg->mFd );
		}

		free( pushArg );
	} else {
		event_set( &( pushArg->mTimerEvent ), -1, 0, onTimer, pushArg );
		event_base_set( eventArg->getEventBase(), &( pushArg->mTimerEvent ) );
		event_add( &( pushArg->mTimerEvent ), &( pushArg->mTimeout ) );
	}
}

int SP_Dispatcher :: push( int fd, SP_Handler * handler, int needStart )
{
	SP_IOChannel * ioChannel = new SP_DefaultIOChannel();
	return push( fd, handler, ioChannel, needStart );
}

int SP_Dispatcher :: push( int fd, SP_Handler * handler,
		SP_IOChannel * ioChannel, int needStart )
{
	SP_PushArg_t * arg = (SP_PushArg_t*)malloc( sizeof( SP_PushArg_t ) );
	arg->mType = 0;
	arg->mFd = fd;
	arg->mHandler = handler;
	arg->mIOChannel = ioChannel;
	arg->mNeedStart = needStart;

	SP_IOUtils::setNonblock( fd );

	return msgqueue_push( (struct event_msgqueue*)mPushQueue, arg );
}

void SP_Dispatcher :: onTimer( int, short, void * arg )
{
	SP_PushArg_t * pushArg = (SP_PushArg_t*)arg;

	pushArg->mEventArg->getInputResultQueue()->push(
		new SP_SimpleTask( timer, pushArg, 1 ) );
}

void SP_Dispatcher :: timer( void * arg )
{
	SP_PushArg_t * pushArg = (SP_PushArg_t*)arg;
	SP_TimerHandler * handler = pushArg->mTimerHandler;
	SP_EventArg * eventArg = pushArg->mEventArg;

	SP_Sid_t sid;
	sid.mKey = SP_Sid_t::eTimerKey;
	sid.mSeq = SP_Sid_t::eTimerSeq;
	SP_Response * response = new SP_Response( sid );
	if( 0 == handler->handle( response, &( pushArg->mTimeout ) ) ) {
		msgqueue_push( (struct event_msgqueue*)pushArg->mPushQueue, arg );
	} else {
		delete pushArg->mTimerHandler;
		free( pushArg );
	}

	msgqueue_push( (struct event_msgqueue*)eventArg->getResponseQueue(), response );
}

int SP_Dispatcher :: push( const struct timeval * timeout, SP_TimerHandler * handler )
{
	SP_PushArg_t * arg = (SP_PushArg_t*)malloc( sizeof( SP_PushArg_t ) );

	arg->mType = 1;
	arg->mTimeout = *timeout;
	arg->mTimerHandler = handler;
	arg->mEventArg = mEventArg;
	arg->mPushQueue = mPushQueue;

	return msgqueue_push( (struct event_msgqueue*)mPushQueue, arg );
}

int SP_Dispatcher :: push( SP_Response * response )
{
	return msgqueue_push( (struct event_msgqueue*)mEventArg->getResponseQueue(), response );
}

<|endoftext|>


<commit_before>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "SurgSim/Blocks/ShadowMapping.h"

#include "SurgSim/Graphics/OsgCamera.h"
#include "SurgSim/Graphics/OsgScreenSpaceQuadRepresentation.h"
#include "SurgSim/Graphics/OsgMaterial.h"
#include "SurgSim/Graphics/OsgRenderTarget.h"
#include "SurgSim/Graphics/Program.h"
#include "SurgSim/Graphics/RenderPass.h"
#include "SurgSim/Graphics/OsgScreenSpacePass.h"
#include "SurgSim/Framework/Scene.h"
#include "SurgSim/Framework/BasicSceneElement.h"
#include "SurgSim/Framework/TransferPropertiesBehavior.h"
#include "SurgSim/Framework/PoseComponent.h"
#include "SurgSim/Blocks/GraphicsUtilities.h"
#include "SurgSim/Graphics/OsgLight.h"

#include <osg/PolygonMode>

namespace SurgSim
{

namespace Blocks
{

std::shared_ptr<Graphics::Camera> setupBlurPasses(
	std::shared_ptr<Graphics::RenderPass> previousPass,
	int textureSize,
	double blurRadius,
	bool debug,
	std::vector<std::shared_ptr<Framework::SceneElement>>* elements)
{
	std::vector<std::shared_ptr<Framework::SceneElement>> result;
	float shadowMapSize = static_cast<float>(textureSize);
	float floatRadius = static_cast<float>(blurRadius);

	std::shared_ptr<Graphics::Camera> previous = previousPass->getCamera();

	// Horizontal Pass
	{
		auto pass = std::make_shared<Graphics::RenderPass>("HorizontalBlurPass");
		pass->getCamera()->setOrthogonalProjection(0, textureSize, 0, textureSize, -1.0, 1.0);

		auto renderTarget = std::make_shared<Graphics::OsgRenderTarget2d>(textureSize, textureSize, 1.0, 1, false);
		pass->setRenderTarget(renderTarget);
		pass->setRenderOrder(Graphics::Camera::RENDER_ORDER_PRE_RENDER, 2);

		// Material
		auto material = Graphics::buildMaterial("Shaders/gauss_blur_horizontal.vert",
												"Shaders/gauss_blur.frag");
		material->getProgram()->setGlobalScope(true);
		material->addUniform("float", "width");
		material->setValue("width", shadowMapSize);
		material->addUniform("float", "blurRadius");
		material->setValue("blurRadius", floatRadius);
		pass->setMaterial(material);

		// Quad
		auto graphics = std::make_shared<Graphics::OsgScreenSpaceQuadRepresentation>("Quad");
		graphics->setSize(textureSize, textureSize);
		graphics->setLocation(0, 0);
		graphics->setTexture(previous->getRenderTarget()->getColorTarget(0));
		graphics->setGroupReference("HorizontalBlurPass");
		pass->addComponent(graphics);

		if (debug)
		{
			pass->showColorTarget(512, 0, 256, 256);
		}
		previous = pass->getCamera();
		elements->push_back(pass);
	}

	// Vertical Pass
	{
		auto pass = std::make_shared<Graphics::RenderPass>("VerticalBlurPass");
		pass->getCamera()->setOrthogonalProjection(0, textureSize, 0, textureSize, -1.0, 1.0);

		auto renderTarget = std::make_shared<Graphics::OsgRenderTarget2d>(textureSize, textureSize, 1.0, 1, false);
		pass->setRenderTarget(renderTarget);
		pass->setRenderOrder(Graphics::Camera::RENDER_ORDER_PRE_RENDER, 3);

		// Material
		auto material = Graphics::buildMaterial("Shaders/gauss_blur_vertical.vert",
												"Shaders/gauss_blur.frag");
		material->getProgram()->setGlobalScope(true);
		material->addUniform("float", "height");
		material->setValue("height", shadowMapSize);
		material->addUniform("float", "blurRadius");
		material->setValue("blurRadius", floatRadius);
		pass->setMaterial(material);

		// Quad
		auto graphics = std::make_shared<Graphics::OsgScreenSpaceQuadRepresentation>("Quad");
		graphics->setSize(textureSize, textureSize);
		graphics->setLocation(0, 0);
		graphics->setTexture(previous->getRenderTarget()->getColorTarget(0));
		graphics->setGroupReference("VerticalBlurPass");
		pass->addComponent(graphics);

		if (debug)
		{
			pass->showColorTarget(756, 0, 256, 256);
		}
		previous = pass->getCamera();
		elements->push_back(pass);
	}

	return previous;
}

/// Create the pass that renders the scene from the view of the light source
/// the identifier GROUP_SHADOW_CASTER is used in all graphic objects to mark them as used
/// in this pass
std::shared_ptr<Graphics::RenderPass> createLightMapPass(int textureSize, bool debug)
{
	auto pass = std::make_shared<Graphics::RenderPass>(GROUP_SHADOW_CASTER);
	auto renderTarget = std::make_shared<Graphics::OsgRenderTarget2d>(textureSize, textureSize, 1.0, 0, true);
	pass->setRenderTarget(renderTarget);
	pass->setRenderOrder(Graphics::Camera::RENDER_ORDER_PRE_RENDER, 0);

	auto material = Graphics::buildMaterial("Shaders/depth_map.vert", "Shaders/depth_map.frag");
	material->getProgram()->setGlobalScope(true);
	pass->setMaterial(material);

	if (debug)
	{
		pass->showDepthTarget(0, 0, 256, 256);
	}

	return pass;
}

/// Create the pass that renders shadowed pixels into the scene,
/// the identifier  GROUPD_SHADOW_RECEIVER is used in all graphics objects to mark them
/// as used in this pass
std::shared_ptr<Graphics::RenderPass> createShadowMapPass(int textureSize, bool debug)
{
	auto pass = std::make_shared<Graphics::RenderPass>(GROUP_SHADOW_RECEIVER);
	auto renderTarget = std::make_shared<Graphics::OsgRenderTarget2d>(textureSize, textureSize, 1.0, 1, false);
	pass->setRenderTarget(renderTarget);
	pass->setRenderOrder(Graphics::Camera::RENDER_ORDER_PRE_RENDER, 1);

	auto material = Graphics::buildMaterial("Shaders/shadow_map.vert", "Shaders/shadow_map.frag");
	material->getProgram()->setGlobalScope(true);
	pass->setMaterial(material);

	if (debug)
	{
		pass->showColorTarget(256, 0, 256, 256);
	}

	return pass;
}

std::vector<std::shared_ptr<Framework::SceneElement>> createShadowMapping(
			std::shared_ptr<Framework::Component> camera,
			std::shared_ptr<Framework::Component> light,
			int depthTextureSize,
			int shadowTextureSize,
			std::array<double, 6> lightCameraProjection,
			bool useBlur,
			double blurRadius,
			bool showDebug)
{
	SURGSIM_ASSERT(camera != nullptr) << "Camera can't be nullptr.";
	SURGSIM_ASSERT(light != nullptr) << "Light can't be nullptr.";

	std::vector<std::shared_ptr<Framework::SceneElement>> result;

	auto osgCamera = Framework::checkAndConvert<Graphics::OsgCamera>(camera, "SurgSim::Graphics::OsgCamera");
	auto osgLight = Framework::checkAndConvert<Graphics::OsgLight>(light, "SurgSim::Graphics::OsgLight");

	auto lightMapPass = createLightMapPass(depthTextureSize, showDebug);
	result.push_back(lightMapPass);

	lightMapPass->getCamera()->setValue("OrthogonalProjection", lightCameraProjection);

	auto cameraNode = std::dynamic_pointer_cast<Graphics::OsgCamera>(lightMapPass->getCamera())->getOsgCamera();
	cameraNode->getOrCreateStateSet()->setAttributeAndModes(
		new osg::PolygonMode(osg::PolygonMode::BACK, osg::PolygonMode::FILL), osg::StateAttribute::ON);

	auto copier = std::make_shared<Framework::TransferPropertiesBehavior>("Copier");
	copier->setTargetManagerType(Framework::MANAGER_TYPE_GRAPHICS);

	// connect the light pose and the light map camera pose, so when the light moves,
	// this camera will move as well
	// Stapling has the light and the camera on the same element, the view, take the view element and connect the pose
	// to the light map pass
	copier->connect(osgLight, "Pose", lightMapPass->getPoseComponent(), "Pose");

	auto shadowMapPass = createShadowMapPass(shadowTextureSize, showDebug);
	result.push_back(shadowMapPass);

	shadowMapPass->getMaterial()->addUniform("mat4", "lightViewMatrix");
	copier->connect(lightMapPass->getCamera(), "FloatViewMatrix",
					shadowMapPass->getMaterial(), "lightViewMatrix");

	auto shadowMaterial = shadowMapPass->getMaterial();
	// The projection matrix of the camera used to render the light map
	shadowMaterial->addUniform("mat4", "lightProjectionMatrix");
	copier->connect(lightMapPass->getCamera(), "FloatProjectionMatrix",
					shadowMaterial, "lightProjectionMatrix");

	// Get the result of the lightMapPass and pass it on to the shadowMapPass, because it is used
	// in a pass we ask the system to use a higher than normal texture unit (in this case 8) for
	// this texture, this prevents the texture from being overwritten by other textures

	shadowMaterial->addUniform("sampler2D", "depthMap");
	shadowMaterial->setValue("depthMap", lightMapPass->getRenderTarget()->getDepthTarget());
	shadowMaterial->getUniform("depthMap")->setValue("MinimumTextureUnit", static_cast<size_t>(8));

	// Make the camera in the shadowMapPass follow the main camera that is being used to render the
	// whole scene
	auto shadowCamera = shadowMapPass->getCamera();
	copier->connect(osgCamera, "ProjectionMatrix", shadowCamera , "ProjectionMatrix");
	copier->connect(osgCamera, "Pose", shadowMapPass->getPoseComponent(), "Pose");

	// Put the result of the last pass into the main camera to make it accessible
	auto material = std::make_shared<Graphics::OsgMaterial>("camera material");
	material->addUniform("sampler2D", "shadowMap");

	std::shared_ptr<Graphics::Texture> texture;

	if (useBlur)
	{
		auto blurrPass = setupBlurPasses(
							 shadowMapPass,
							 shadowTextureSize,
							 static_cast<float>(blurRadius),
							 showDebug,
							 &result);
		texture = blurrPass->getRenderTarget()->getColorTarget(0);
	}
	else
	{
		texture = shadowCamera->getRenderTarget()->getColorTarget(0);
	}

	material->setValue("shadowMap", texture);
	material->getUniform("shadowMap")->setValue("MinimumTextureUnit", static_cast<size_t>(8));

	osgCamera->getSceneElement()->addComponent(material);
	osgCamera->setMaterial(material);

	lightMapPass->addComponent(copier);

	return result;
}

}
}
<commit_msg>Some renames for clarity<commit_after>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "SurgSim/Blocks/ShadowMapping.h"

#include "SurgSim/Graphics/OsgCamera.h"
#include "SurgSim/Graphics/OsgScreenSpaceQuadRepresentation.h"
#include "SurgSim/Graphics/OsgMaterial.h"
#include "SurgSim/Graphics/OsgRenderTarget.h"
#include "SurgSim/Graphics/Program.h"
#include "SurgSim/Graphics/RenderPass.h"
#include "SurgSim/Graphics/OsgScreenSpacePass.h"
#include "SurgSim/Framework/Scene.h"
#include "SurgSim/Framework/BasicSceneElement.h"
#include "SurgSim/Framework/TransferPropertiesBehavior.h"
#include "SurgSim/Framework/PoseComponent.h"
#include "SurgSim/Blocks/GraphicsUtilities.h"
#include "SurgSim/Graphics/OsgLight.h"

#include <osg/PolygonMode>

namespace SurgSim
{

namespace Blocks
{

std::shared_ptr<Graphics::Camera> setupBlurPasses(
	std::shared_ptr<Graphics::RenderPass> shadowMapPass,
	int textureSize,
	double blurRadius,
	bool debug,
	std::vector<std::shared_ptr<Framework::SceneElement>>* elements)
{
	std::vector<std::shared_ptr<Framework::SceneElement>> result;
	float shadowMapSize = static_cast<float>(textureSize);
	float floatRadius = static_cast<float>(blurRadius);

	std::shared_ptr<Graphics::Camera> perviousCamera = shadowMapPass->getCamera();

	// Horizontal Pass
	{
		auto pass = std::make_shared<Graphics::RenderPass>("HorizontalBlurPass");
		pass->getCamera()->setOrthogonalProjection(0, textureSize, 0, textureSize, -1.0, 1.0);

		auto renderTarget = std::make_shared<Graphics::OsgRenderTarget2d>(textureSize, textureSize, 1.0, 1, false);
		pass->setRenderTarget(renderTarget);
		pass->setRenderOrder(Graphics::Camera::RENDER_ORDER_PRE_RENDER, 2);

		// Material
		auto material = Graphics::buildMaterial("Shaders/gauss_blur_horizontal.vert",
												"Shaders/gauss_blur.frag");
		material->getProgram()->setGlobalScope(true);
		material->addUniform("float", "width");
		material->setValue("width", shadowMapSize);
		material->addUniform("float", "blurRadius");
		material->setValue("blurRadius", floatRadius);
		pass->setMaterial(material);

		// Quad
		auto graphics = std::make_shared<Graphics::OsgScreenSpaceQuadRepresentation>("Quad");
		graphics->setSize(textureSize, textureSize);
		graphics->setLocation(0, 0);
		graphics->setTexture(perviousCamera->getRenderTarget()->getColorTarget(0));
		graphics->setGroupReference("HorizontalBlurPass");
		pass->addComponent(graphics);

		if (debug)
		{
			pass->showColorTarget(512, 0, 256, 256);
		}
		perviousCamera = pass->getCamera();
		elements->push_back(pass);
	}

	// Vertical Pass
	{
		auto pass = std::make_shared<Graphics::RenderPass>("VerticalBlurPass");
		pass->getCamera()->setOrthogonalProjection(0, textureSize, 0, textureSize, -1.0, 1.0);

		auto renderTarget = std::make_shared<Graphics::OsgRenderTarget2d>(textureSize, textureSize, 1.0, 1, false);
		pass->setRenderTarget(renderTarget);
		pass->setRenderOrder(Graphics::Camera::RENDER_ORDER_PRE_RENDER, 3);

		// Material
		auto material = Graphics::buildMaterial("Shaders/gauss_blur_vertical.vert",
												"Shaders/gauss_blur.frag");
		material->getProgram()->setGlobalScope(true);
		material->addUniform("float", "height");
		material->setValue("height", shadowMapSize);
		material->addUniform("float", "blurRadius");
		material->setValue("blurRadius", floatRadius);
		pass->setMaterial(material);

		// Quad
		auto graphics = std::make_shared<Graphics::OsgScreenSpaceQuadRepresentation>("Quad");
		graphics->setSize(textureSize, textureSize);
		graphics->setLocation(0, 0);
		graphics->setTexture(perviousCamera->getRenderTarget()->getColorTarget(0));
		graphics->setGroupReference("VerticalBlurPass");
		pass->addComponent(graphics);

		if (debug)
		{
			pass->showColorTarget(756, 0, 256, 256);
		}
		perviousCamera = pass->getCamera();
		elements->push_back(pass);
	}

	return perviousCamera;
}

/// Create the pass that renders the scene from the view of the light source
/// the identifier GROUP_SHADOW_CASTER is used in all graphic objects to mark them as used
/// in this pass
std::shared_ptr<Graphics::RenderPass> createLightMapPass(int textureSize, bool debug)
{
	auto pass = std::make_shared<Graphics::RenderPass>(GROUP_SHADOW_CASTER);
	auto renderTarget = std::make_shared<Graphics::OsgRenderTarget2d>(textureSize, textureSize, 1.0, 0, true);
	pass->setRenderTarget(renderTarget);
	pass->setRenderOrder(Graphics::Camera::RENDER_ORDER_PRE_RENDER, 0);

	auto material = Graphics::buildMaterial("Shaders/depth_map.vert", "Shaders/depth_map.frag");
	material->getProgram()->setGlobalScope(true);
	pass->setMaterial(material);

	if (debug)
	{
		pass->showDepthTarget(0, 0, 256, 256);
	}

	return pass;
}

/// Create the pass that renders shadowed pixels into the scene,
/// the identifier  GROUPD_SHADOW_RECEIVER is used in all graphics objects to mark them
/// as used in this pass
std::shared_ptr<Graphics::RenderPass> createShadowMapPass(int textureSize, bool debug)
{
	auto pass = std::make_shared<Graphics::RenderPass>(GROUP_SHADOW_RECEIVER);
	auto renderTarget = std::make_shared<Graphics::OsgRenderTarget2d>(textureSize, textureSize, 1.0, 1, false);
	pass->setRenderTarget(renderTarget);
	pass->setRenderOrder(Graphics::Camera::RENDER_ORDER_PRE_RENDER, 1);

	auto material = Graphics::buildMaterial("Shaders/shadow_map.vert", "Shaders/shadow_map.frag");
	material->getProgram()->setGlobalScope(true);
	pass->setMaterial(material);

	if (debug)
	{
		pass->showColorTarget(256, 0, 256, 256);
	}

	return pass;
}

std::vector<std::shared_ptr<Framework::SceneElement>> createShadowMapping(
			std::shared_ptr<Framework::Component> camera,
			std::shared_ptr<Framework::Component> light,
			int depthTextureSize,
			int shadowTextureSize,
			std::array<double, 6> lightCameraProjection,
			bool useBlur,
			double blurRadius,
			bool showDebug)
{
	SURGSIM_ASSERT(camera != nullptr) << "Camera can't be nullptr.";
	SURGSIM_ASSERT(light != nullptr) << "Light can't be nullptr.";

	std::vector<std::shared_ptr<Framework::SceneElement>> result;

	auto osgCamera = Framework::checkAndConvert<Graphics::OsgCamera>(camera, "SurgSim::Graphics::OsgCamera");
	auto osgLight = Framework::checkAndConvert<Graphics::OsgLight>(light, "SurgSim::Graphics::OsgLight");

	auto lightMapPass = createLightMapPass(depthTextureSize, showDebug);
	result.push_back(lightMapPass);

	lightMapPass->getCamera()->setValue("OrthogonalProjection", lightCameraProjection);

	auto cameraNode = std::dynamic_pointer_cast<Graphics::OsgCamera>(lightMapPass->getCamera())->getOsgCamera();
	cameraNode->getOrCreateStateSet()->setAttributeAndModes(
		new osg::PolygonMode(osg::PolygonMode::BACK, osg::PolygonMode::FILL), osg::StateAttribute::ON);

	auto copier = std::make_shared<Framework::TransferPropertiesBehavior>("Copier");
	copier->setTargetManagerType(Framework::MANAGER_TYPE_GRAPHICS);

	// connect the light pose and the light map camera pose, so when the light moves,
	// this camera will move as well
	// Stapling has the light and the camera on the same element, the view, take the view element and connect the pose
	// to the light map pass
	copier->connect(osgLight, "Pose", lightMapPass->getPoseComponent(), "Pose");

	auto shadowMapPass = createShadowMapPass(shadowTextureSize, showDebug);
	result.push_back(shadowMapPass);

	shadowMapPass->getMaterial()->addUniform("mat4", "lightViewMatrix");
	copier->connect(lightMapPass->getCamera(), "FloatViewMatrix",
					shadowMapPass->getMaterial(), "lightViewMatrix");

	auto shadowMaterial = shadowMapPass->getMaterial();
	// The projection matrix of the camera used to render the light map
	shadowMaterial->addUniform("mat4", "lightProjectionMatrix");
	copier->connect(lightMapPass->getCamera(), "FloatProjectionMatrix",
					shadowMaterial, "lightProjectionMatrix");

	// Get the result of the lightMapPass and pass it on to the shadowMapPass, because it is used
	// in a pass we ask the system to use a higher than normal texture unit (in this case 8) for
	// this texture, this prevents the texture from being overwritten by other textures

	shadowMaterial->addUniform("sampler2D", "depthMap");
	shadowMaterial->setValue("depthMap", lightMapPass->getRenderTarget()->getDepthTarget());
	shadowMaterial->getUniform("depthMap")->setValue("MinimumTextureUnit", static_cast<size_t>(8));

	// Make the camera in the shadowMapPass follow the main camera that is being used to render the
	// whole scene
	auto shadowCamera = shadowMapPass->getCamera();
	copier->connect(osgCamera, "ProjectionMatrix", shadowCamera , "ProjectionMatrix");
	copier->connect(osgCamera, "Pose", shadowMapPass->getPoseComponent(), "Pose");

	// Put the result of the last pass into the main camera to make it accessible
	auto material = std::make_shared<Graphics::OsgMaterial>("camera material");
	material->addUniform("sampler2D", "shadowMap");

	std::shared_ptr<Graphics::Texture> texture;

	if (useBlur)
	{
		auto blurrPass = setupBlurPasses(
							 shadowMapPass,
							 shadowTextureSize,
							 static_cast<float>(blurRadius),
							 showDebug,
							 &result);
		texture = blurrPass->getRenderTarget()->getColorTarget(0);
	}
	else
	{
		texture = shadowCamera->getRenderTarget()->getColorTarget(0);
	}

	material->setValue("shadowMap", texture);
	material->getUniform("shadowMap")->setValue("MinimumTextureUnit", static_cast<size_t>(8));

	osgCamera->getSceneElement()->addComponent(material);
	osgCamera->setMaterial(material);

	lightMapPass->addComponent(copier);

	return result;
}

}
}
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include <string>

#include "gtest/gtest.h"

#include "modules/common/configs/config_gflags.h"
#include "modules/planning/common/planning_gflags.h"
#include "modules/planning/integration_tests/planning_test_base.h"
#include "modules/planning/planning.h"

namespace apollo {
namespace planning {

/**
 * @class SunnyvaleLoopTest
 * @brief This is an integration test that uses the sunnyvale_loop map.
 */

class SunnyvaleLoopTest : public PlanningTestBase {
 public:
  virtual void SetUp() {
    FLAGS_map_dir = "modules/map/data/sunnyvale_loop";
    FLAGS_test_data_dir = "modules/planning/testdata/sunnyvale_loop_test";
    FLAGS_test_routing_response_file = "1_routing.pb.txt";
  }
};

/*
 * test stop for not-nudgable obstacle
 * A cruise test case
 */
TEST_F(SunnyvaleLoopTest, cruise) {
  std::string seq_num = "1";
  FLAGS_test_prediction_file = seq_num + "_prediction.pb.txt";
  FLAGS_test_localization_file = seq_num + "_localization.pb.txt";
  FLAGS_test_chassis_file = seq_num + "_chassis.pb.txt";
  PlanningTestBase::SetUp();
  RUN_GOLDEN_TEST;
}

/*
 * stop case to trigger QP ST failed to solve
 */
// TODO: fix this test.
TEST_F(SunnyvaleLoopTest, stop) {
  std::string seq_num = "2";
  FLAGS_test_prediction_file = seq_num + "_prediction.pb.txt";
  FLAGS_test_localization_file = seq_num + "_localization.pb.txt";
  FLAGS_test_chassis_file = seq_num + "_chassis.pb.txt";
  FLAGS_test_routing_response_file = seq_num + "_routing.pb.txt";
  PlanningTestBase::SetUp();
  bool run_planning_success = RunPlanning("sunnyvale_stop", 0);
  EXPECT_FALSE(run_planning_success);
}

}  // namespace planning
}  // namespace apollo
<commit_msg>Planning: force sunnyvale stop test to pass. TODO: fix this test.<commit_after>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include <string>

#include "gtest/gtest.h"

#include "modules/common/configs/config_gflags.h"
#include "modules/planning/common/planning_gflags.h"
#include "modules/planning/integration_tests/planning_test_base.h"
#include "modules/planning/planning.h"

namespace apollo {
namespace planning {

/**
 * @class SunnyvaleLoopTest
 * @brief This is an integration test that uses the sunnyvale_loop map.
 */

class SunnyvaleLoopTest : public PlanningTestBase {
 public:
  virtual void SetUp() {
    FLAGS_map_dir = "modules/map/data/sunnyvale_loop";
    FLAGS_test_data_dir = "modules/planning/testdata/sunnyvale_loop_test";
    FLAGS_test_routing_response_file = "1_routing.pb.txt";
  }
};

/*
 * test stop for not-nudgable obstacle
 * A cruise test case
 */
TEST_F(SunnyvaleLoopTest, cruise) {
  std::string seq_num = "1";
  FLAGS_test_prediction_file = seq_num + "_prediction.pb.txt";
  FLAGS_test_localization_file = seq_num + "_localization.pb.txt";
  FLAGS_test_chassis_file = seq_num + "_chassis.pb.txt";
  PlanningTestBase::SetUp();
  RUN_GOLDEN_TEST;
}

/*
 * stop case to trigger QP ST failed to solve
 */
TEST_F(SunnyvaleLoopTest, stop) {
  // TODO: fix this test.
  std::string seq_num = "2";
  FLAGS_test_prediction_file = seq_num + "_prediction.pb.txt";
  FLAGS_test_localization_file = seq_num + "_localization.pb.txt";
  FLAGS_test_chassis_file = seq_num + "_chassis.pb.txt";
  FLAGS_test_routing_response_file = seq_num + "_routing.pb.txt";
  PlanningTestBase::SetUp();
  bool run_planning_success = RunPlanning("sunnyvale_stop", 0);
  EXPECT_FALSE(run_planning_success);
}

}  // namespace planning
}  // namespace apollo
<|endoftext|>


<commit_before>/*
    Copyright (c) 2010 Tobias Koenig <tokoe@kde.org>

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 of the License, or (at your
    option) any later version.

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

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "dbconfig.h"

#include "dbconfigmysql.h"
#include "dbconfigmysqlembedded.h"
#include "dbconfigpostgresql.h"
#include "dbconfigsqlite.h"
#include "dbconfigvirtuoso.h"

#include <akdebug.h>
#include <libs/xdgbasedirs_p.h>

using namespace Akonadi;

//TODO: make me Q_GLOBAL_STATIC
static DbConfig *s_DbConfigInstance = 0;

DbConfig::DbConfig()
{
  const QString serverConfigFile = XdgBaseDirs::akonadiServerConfigFile( XdgBaseDirs::ReadWrite );
  QSettings settings( serverConfigFile, QSettings::IniFormat );

  mSizeThreshold = 4096;
  const QVariant value = settings.value( QLatin1String( "General/SizeThreshold" ), mSizeThreshold );
  if ( value.canConvert<qint64>() )
    mSizeThreshold = value.value<qint64>();
  else
    mSizeThreshold = 0;

  if ( mSizeThreshold < 0 )
    mSizeThreshold = 0;

  mUseExternalPayloadFile = true;
  mUseExternalPayloadFile = settings.value( QLatin1String( "General/ExternalPayload" ), mUseExternalPayloadFile ).toBool();
}

DbConfig::~DbConfig()
{
}

DbConfig* DbConfig::configuredDatabase()
{
  if ( !s_DbConfigInstance ) {
    const QString serverConfigFile = XdgBaseDirs::akonadiServerConfigFile( XdgBaseDirs::ReadWrite );
    QSettings settings( serverConfigFile, QSettings::IniFormat );

    // determine driver to use
#ifdef _WIN32_WCE
    // On Windows CE QSQLITE3 is the default driver for Akonadi
    const QString defaultDirver = QLatin1String( "QSQLITE3" );
#else
    const QString defaultDriver = QLatin1String( "QMYSQL" );
#endif
    QString driverName = settings.value( QLatin1String( "General/Driver" ), defaultDriver ).toString();
    if ( driverName.isEmpty() )
      driverName = defaultDriver;

    if ( driverName == QLatin1String( "QMYSQL" ) )
      s_DbConfigInstance = new DbConfigMysql;
    else if ( driverName == QLatin1String( "QMYSQL_EMBEDDED" ) )
      s_DbConfigInstance = new DbConfigMysqlEmbedded;
    else if ( driverName == QLatin1String( "QSQLITE" ) )
      s_DbConfigInstance = new DbConfigSqlite( DbConfigSqlite::Default );
    else if ( driverName == QLatin1String( "QSQLITE3" ) )
      s_DbConfigInstance = new DbConfigSqlite( DbConfigSqlite::Custom );
    else if ( driverName == QLatin1String( "QPSQL" ) )
      s_DbConfigInstance = new DbConfigPostgresql;
    else if ( driverName == QLatin1String( "QODBC" ) )
      s_DbConfigInstance = new DbConfigVirtuoso;
    else {
      akError() << "Unknown database driver: " << driverName;
      akError() << "Available drivers are: " << QSqlDatabase::drivers();
      akFatal();
    }
  }

  return s_DbConfigInstance;
}

void DbConfig::startInternalServer()
{
  // do nothing
}

void DbConfig::stopInternalServer()
{
  // do nothing
}

qint64 DbConfig::sizeThreshold() const
{
  return mSizeThreshold;
}

bool DbConfig::useExternalPayloadFile() const
{
  return mUseExternalPayloadFile;
}
<commit_msg>- fixed spelling error<commit_after>/*
    Copyright (c) 2010 Tobias Koenig <tokoe@kde.org>

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 of the License, or (at your
    option) any later version.

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

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "dbconfig.h"

#include "dbconfigmysql.h"
#include "dbconfigmysqlembedded.h"
#include "dbconfigpostgresql.h"
#include "dbconfigsqlite.h"
#include "dbconfigvirtuoso.h"

#include <akdebug.h>
#include <libs/xdgbasedirs_p.h>

using namespace Akonadi;

//TODO: make me Q_GLOBAL_STATIC
static DbConfig *s_DbConfigInstance = 0;

DbConfig::DbConfig()
{
  const QString serverConfigFile = XdgBaseDirs::akonadiServerConfigFile( XdgBaseDirs::ReadWrite );
  QSettings settings( serverConfigFile, QSettings::IniFormat );

  mSizeThreshold = 4096;
  const QVariant value = settings.value( QLatin1String( "General/SizeThreshold" ), mSizeThreshold );
  if ( value.canConvert<qint64>() )
    mSizeThreshold = value.value<qint64>();
  else
    mSizeThreshold = 0;

  if ( mSizeThreshold < 0 )
    mSizeThreshold = 0;

  mUseExternalPayloadFile = true;
  mUseExternalPayloadFile = settings.value( QLatin1String( "General/ExternalPayload" ), mUseExternalPayloadFile ).toBool();
}

DbConfig::~DbConfig()
{
}

DbConfig* DbConfig::configuredDatabase()
{
  if ( !s_DbConfigInstance ) {
    const QString serverConfigFile = XdgBaseDirs::akonadiServerConfigFile( XdgBaseDirs::ReadWrite );
    QSettings settings( serverConfigFile, QSettings::IniFormat );

    // determine driver to use
#ifdef _WIN32_WCE
    // On Windows CE QSQLITE3 is the default driver for Akonadi
    const QString defaultDriver = QLatin1String( "QSQLITE3" );
#else
    const QString defaultDriver = QLatin1String( "QMYSQL" );
#endif
    QString driverName = settings.value( QLatin1String( "General/Driver" ), defaultDriver ).toString();
    if ( driverName.isEmpty() )
      driverName = defaultDriver;

    if ( driverName == QLatin1String( "QMYSQL" ) )
      s_DbConfigInstance = new DbConfigMysql;
    else if ( driverName == QLatin1String( "QMYSQL_EMBEDDED" ) )
      s_DbConfigInstance = new DbConfigMysqlEmbedded;
    else if ( driverName == QLatin1String( "QSQLITE" ) )
      s_DbConfigInstance = new DbConfigSqlite( DbConfigSqlite::Default );
    else if ( driverName == QLatin1String( "QSQLITE3" ) )
      s_DbConfigInstance = new DbConfigSqlite( DbConfigSqlite::Custom );
    else if ( driverName == QLatin1String( "QPSQL" ) )
      s_DbConfigInstance = new DbConfigPostgresql;
    else if ( driverName == QLatin1String( "QODBC" ) )
      s_DbConfigInstance = new DbConfigVirtuoso;
    else {
      akError() << "Unknown database driver: " << driverName;
      akError() << "Available drivers are: " << QSqlDatabase::drivers();
      akFatal();
    }
  }

  return s_DbConfigInstance;
}

void DbConfig::startInternalServer()
{
  // do nothing
}

void DbConfig::stopInternalServer()
{
  // do nothing
}

qint64 DbConfig::sizeThreshold() const
{
  return mSizeThreshold;
}

bool DbConfig::useExternalPayloadFile() const
{
  return mUseExternalPayloadFile;
}
<|endoftext|>


<commit_before>//
//  test_http_client.cpp
//  fibio
//
//  Created by Chen Xu on 14-3-12.
//  Copyright (c) 2014 0d0a.com. All rights reserved.
//

#include <iostream>
#include <vector>
#include <sstream>
#include <fibio/fiber.hpp>
#include <fibio/http/client/client.hpp>
#include <fibio/fiberize.hpp>

using namespace fibio;
using namespace fibio::http;

void the_client() {
    client c;
    client::request req;
    req.url("/");
    req.headers.insert(std::make_pair("Host", "0d0a.com"));
    // Default method
    assert(req.method()==http_method::INVALID_METHOD);
    req.method(http_method::GET);
    // Default version
    assert(req.version()==http_version::INVALID_VERSION);
    req.version(http_version::HTTP_1_1);
    assert(req.content_length()==0);
    //c.set_auto_decompress(true);

    c.connect("0d0a.com");
    for(int i=0; i<10; i++) {
        client::response resp;
        if(c.send_request(req, resp)) {
            // This server returns a 200 response
            assert(resp.version==http_version::HTTP_1_1);
            assert(resp.status_code==http_status_code::OK);

            size_t cl=resp.content_length;
            std::string s;
            std::stringstream ss;
            ss << resp.body_stream().rdbuf();
            s=ss.str();
            assert(s.size()==cl);
            // Make sure we triggered EOF condition
            resp.body_stream().peek();
            assert(resp.body_stream().eof());
        }
    }
}

void the_url_client() {
    url_client uc;
    {
        client::response &resp=uc.request("http://0d0a.com/");
        assert(resp.status_code==http_status_code::OK);
    }
    {
        client::response &resp=uc.request("http://www.baidu.com/");
        assert(resp.status_code==http_status_code::OK);
    }
    {
        // http://github.com/ responses with 301, redirects to 'https://github.com/'
        client::response &resp=uc.request("http://github.com/");
        assert(resp.status_code==http_status_code::OK);
    }
}

int fibio::main(int argc, char *argv[]) {
    fiber_group fibers;
    for (int i=0; i<1; i++) {
        fibers.create_fiber(the_client);
        fibers.create_fiber(the_url_client);
    }
    fibers.join_all();
    std::cout << "main_fiber exiting" << std::endl;
    return 0;
}
<commit_msg>update test<commit_after>//
//  test_http_client.cpp
//  fibio
//
//  Created by Chen Xu on 14-3-12.
//  Copyright (c) 2014 0d0a.com. All rights reserved.
//

#include <iostream>
#include <vector>
#include <sstream>
#include <fibio/fiber.hpp>
#include <fibio/http/client/client.hpp>
#include <fibio/fiberize.hpp>

using namespace fibio;
using namespace fibio::http;

void the_client() {
    client c;
    client::request req;
    req.url("/");
    req.headers.insert(std::make_pair("Host", "0d0a.com"));
    // Default method
    assert(req.method()==http_method::INVALID_METHOD);
    req.method(http_method::GET);
    // Default version
    assert(req.version()==http_version::INVALID_VERSION);
    req.version(http_version::HTTP_1_1);
    assert(req.content_length()==0);
    //c.set_auto_decompress(true);

    c.connect("0d0a.com");
    for(int i=0; i<10; i++) {
        client::response resp;
        if(c.send_request(req, resp)) {
            // This server returns a 200 response
            assert(resp.version==http_version::HTTP_1_1);
            assert(resp.status_code==http_status_code::OK);

            size_t cl=resp.content_length;
            std::string s;
            std::stringstream ss;
            ss << resp.body_stream().rdbuf();
            s=ss.str();
            assert(s.size()==cl);
            // Make sure we triggered EOF condition
            resp.body_stream().peek();
            assert(resp.body_stream().eof());
        }
    }
}

void the_url_client() {
    url_client uc;
    if(0)
    {
        client::response &resp=uc.request("http://0d0a.com/");
        assert(resp.status_code==http_status_code::OK);
    }
    if(0)
    {
        client::response &resp=uc.request("http://www.baidu.com/");
        assert(resp.status_code==http_status_code::OK);
    }
    {
        // http://www.taobao.com/ responses with 302, redirects to 'https://www.taobao.com/'
        client::response &resp=uc.request("http://www.taobao.com/");
        assert(resp.status_code==http_status_code::OK);
    }
}

int fibio::main(int argc, char *argv[]) {
    fiber_group fibers;
    for (int i=0; i<1; i++) {
        //fibers.create_fiber(the_client);
        fibers.create_fiber(the_url_client);
    }
    fibers.join_all();
    std::cout << "main_fiber exiting" << std::endl;
    return 0;
}
<|endoftext|>


<commit_before>/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

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

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

/* create and drop of databases */

#include "mysql_priv.h"
#include "sql_acl.h"
#include <my_dir.h>
#include <m_ctype.h>
#ifdef __WIN__
#include <direct.h>
#endif

static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *path,
				 uint level);

/* db-name is already validated when we come here */

void mysql_create_db(THD *thd, char *db, uint create_options)
{
  char	 path[FN_REFLEN+16];
  MY_DIR *dirp;
  long result=1;
  DBUG_ENTER("mysql_create_db");

  VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
  VOID(pthread_mutex_lock(&LOCK_open));

  // do not create database if another thread is holding read lock
  if (global_read_lock)
  {
    if (thd->global_read_lock)
    {
      net_printf(&thd->net, ER_CREATE_DB_WITH_READ_LOCK);
      VOID(pthread_mutex_unlock(&LOCK_open));
      goto exit;
    }
    while (global_read_lock && ! thd->killed)
    {
      (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
    }

    if (thd->killed)
    {
      net_printf(&thd->net, ER_SERVER_SHUTDOWN);
      VOID(pthread_mutex_unlock(&LOCK_open));
      goto exit;
    }

  }

  VOID(pthread_mutex_unlock(&LOCK_open));

  /* Check directory */
  (void)sprintf(path,"%s/%s", mysql_data_home, db);
  unpack_dirname(path,path);			// Convert if not unix
  if ((dirp = my_dir(path,MYF(MY_DONT_SORT))))
  {
    my_dirend(dirp);
    if (!(create_options & HA_LEX_CREATE_IF_NOT_EXISTS))
    {
      net_printf(&thd->net,ER_DB_CREATE_EXISTS,db);
      goto exit;
    }
    result = 0;
  }
  else
  {
    strend(path)[-1]=0;				// Remove last '/' from path
    if (my_mkdir(path,0777,MYF(0)) < 0)
    {
      net_printf(&thd->net,ER_CANT_CREATE_DB,db,my_errno);
      goto exit;
    }
  }
  if (!thd->query)
  {
    thd->query = path;
    thd->query_length = (uint) (strxmov(path,"create database ", db, NullS)-
				path);
  }
  {
    mysql_update_log.write(thd,thd->query, thd->query_length);
    if (mysql_bin_log.is_open())
    {
      Query_log_event qinfo(thd, thd->query);
      mysql_bin_log.write(&qinfo);
    }
  }
  if (thd->query == path)
  {
    thd->query = 0; // just in case
    thd->query_length = 0;
  }
  send_ok(&thd->net, result);

exit:
  VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
  DBUG_VOID_RETURN;
}

const char *del_exts[]=
{".frm",".ISM",".ISD",".ISM",".HSH",".DAT",".MRG",".MYI",".MYD", ".db", ".BAK", NullS};
static TYPELIB deletable_extentions=
{array_elements(del_exts)-1,"del_exts", del_exts};

/* db-name is already validated when we come here */

void mysql_rm_db(THD *thd,char *db,bool if_exists)
{
  long deleted=0;
  char	path[FN_REFLEN+16];
  MY_DIR *dirp;
  DBUG_ENTER("mysql_rm_db");

  VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
  VOID(pthread_mutex_lock(&LOCK_open));

  // do not drop database if another thread is holding read lock
  if (global_read_lock)
  {
    if (thd->global_read_lock)
    {
      net_printf(&thd->net, ER_DROP_DB_WITH_READ_LOCK);
      goto exit;
    }
    while (global_read_lock && ! thd->killed)
    {
      (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
    }

    if (thd->killed)
    {
      net_printf(&thd->net, ER_SERVER_SHUTDOWN);
      goto exit;
    }
  }

  (void) sprintf(path,"%s/%s",mysql_data_home,db);
  unpack_dirname(path,path);			// Convert if not unix
  /* See if the directory exists */
  if (!(dirp = my_dir(path,MYF(MY_WME | MY_DONT_SORT))))
  {
    if (!if_exists)
      net_printf(&thd->net,ER_DB_DROP_EXISTS,db);
    else
      send_ok(&thd->net,0);
    goto exit;
  }
  remove_db_from_cache(db);

  if ((deleted=mysql_rm_known_files(thd, dirp, path,0)) >= 0)
  {
    /*
      If there are running queries on the tables, MySQL needs to get
      access to LOCK_open to end them. InnoDB on the other hand waits
      for the queries to end before dropping the database. That is why we
      must do the dropping with LOCK_open released.
    */
    VOID(pthread_mutex_unlock(&LOCK_open));
    ha_drop_database(path);
    VOID(pthread_mutex_lock(&LOCK_open));

    if (!thd->query)
    {
      thd->query = path;
      thd->query_length = (uint) (strxmov(path,"drop database ", db, NullS)-
				  path);
    }
    mysql_update_log.write(thd, thd->query, thd->query_length);
    if (mysql_bin_log.is_open())
    {
      Query_log_event qinfo(thd, thd->query);
      mysql_bin_log.write(&qinfo);
    }
    if (thd->query == path)
    {
      thd->query = 0; // just in case
      thd->query_length = 0;
    }
    send_ok(&thd->net,(ulong) deleted);
  }

exit:
  VOID(pthread_mutex_unlock(&LOCK_open));
  VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));

  DBUG_VOID_RETURN;
}

/*
  Removes files with known extensions plus all found subdirectories that
  are 2 digits (raid directories).
*/

static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *org_path,
				 uint level)
{
  long deleted=0;
  ulong found_other_files=0;
  char filePath[FN_REFLEN];
  DBUG_ENTER("mysql_rm_known_files");
  DBUG_PRINT("enter",("path: %s", org_path));
  /* remove all files with known extensions */

  for (uint idx=2 ;
       idx < (uint) dirp->number_off_files && !thd->killed ;
       idx++)
  {
    FILEINFO *file=dirp->dir_entry+idx;
    DBUG_PRINT("info",("Examining: %s", file->name));

    /* Check if file is a raid directory */
    if (isdigit(file->name[0]) && isdigit(file->name[1]) &&
	!file->name[2] && !level)
    {
      char newpath[FN_REFLEN];
      MY_DIR *new_dirp;
      strxmov(newpath,org_path,"/",file->name,NullS);
      unpack_filename(newpath,newpath);
      if ((new_dirp = my_dir(newpath,MYF(MY_DONT_SORT))))
      {
	DBUG_PRINT("my",("New subdir found: %s", newpath));
	if ((mysql_rm_known_files(thd,new_dirp,newpath,1)) < 0)
	{
	  my_dirend(dirp);
	  DBUG_RETURN(-1);
	}
      }
      continue;
    }
    if (find_type(fn_ext(file->name),&deletable_extentions,1+2) <= 0)
    {
      found_other_files++;
      continue;
    }
    strxmov(filePath,org_path,"/",file->name,NullS);
    unpack_filename(filePath,filePath);
    if (my_delete(filePath,MYF(MY_WME)))
    {
      net_printf(&thd->net,ER_DB_DROP_DELETE,filePath,my_error);
      my_dirend(dirp);
      DBUG_RETURN(-1);
    }
    deleted++;
  }

  my_dirend(dirp);

  if (thd->killed)
  {
    send_error(&thd->net,ER_SERVER_SHUTDOWN);
    DBUG_RETURN(-1);
  }

  /*
    If the directory is a symbolic link, remove the link first, then
    remove the directory the symbolic link pointed at
  */
  if (!found_other_files)
  {
    char tmp_path[FN_REFLEN], *pos;
    char *path=unpack_filename(tmp_path,org_path);
#ifdef HAVE_READLINK
    int error;

    /* Remove end FN_LIBCHAR as this causes problem on Linux in readlink */
    pos=strend(path);
    if (pos > path && pos[-1] == FN_LIBCHAR)
      *--pos=0;

    if ((error=my_readlink(filePath, path, MYF(MY_WME))) < 0)
      DBUG_RETURN(-1);
    if (!error)
    {
      if (my_delete(path,MYF(!level ? MY_WME : 0)))
      {
	/* Don't give errors if we can't delete 'RAID' directory */
	if (level)
	  DBUG_RETURN(deleted);
	send_error(&thd->net);
	DBUG_RETURN(-1);
      }
      /* Delete directory symbolic link pointed at */
      path= filePath;
    }
#endif
    /* Remove last FN_LIBCHAR to not cause a probelm on OS/2 */
    pos=strend(path);
    if (pos > path && pos[-1] == FN_LIBCHAR)
      *--pos=0;
    /* Don't give errors if we can't delete 'RAID' directory */
    if (rmdir(path) < 0 && !level)
    {
      net_printf(&thd->net,ER_DB_DROP_RMDIR, path,errno);
      DBUG_RETURN(-1);
    }
  }
  DBUG_RETURN(deleted);
}

bool mysql_change_db(THD *thd,const char *name)
{
  int length;
  char *dbname=my_strdup((char*) name,MYF(MY_WME));
  char	path[FN_REFLEN];
  uint db_access;
  DBUG_ENTER("mysql_change_db");

  if (!dbname || !(length=strip_sp(dbname)))
  {
    x_free(dbname);				/* purecov: inspected */
    send_error(&thd->net,ER_NO_DB_ERROR);	/* purecov: inspected */
    DBUG_RETURN(1);				/* purecov: inspected */
  }
  if ((length > NAME_LEN) || check_db_name(dbname))
  {
    net_printf(&thd->net,ER_WRONG_DB_NAME, dbname);
    x_free(dbname);
    DBUG_RETURN(1);
  }
  DBUG_PRINT("general",("Use database: %s", dbname));
  if (test_all_bits(thd->master_access,DB_ACLS))
    db_access=DB_ACLS;
  else
    db_access= (acl_get(thd->host,thd->ip,(char*) &thd->remote.sin_addr,
			thd->priv_user,dbname) |
		thd->master_access);
  if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname)))
  {
    net_printf(&thd->net,ER_DBACCESS_DENIED_ERROR,
	       thd->priv_user,
	       thd->host ? thd->host : thd->ip ? thd->ip : "unknown",
	       dbname);
    mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
		    thd->priv_user,
		    thd->host ? thd->host : thd->ip ? thd->ip : "unknown",
		    dbname);
    my_free(dbname,MYF(0));
    DBUG_RETURN(1);
  }

  (void) sprintf(path,"%s/%s",mysql_data_home,dbname);
  length=unpack_dirname(path,path);		// Convert if not unix
  if (length && path[length-1] == FN_LIBCHAR)
    path[length-1]=0;				// remove ending '\'
  if (access(path,F_OK))
  {
    net_printf(&thd->net,ER_BAD_DB_ERROR,dbname);
    my_free(dbname,MYF(0));
    DBUG_RETURN(1);
  }
  send_ok(&thd->net);
  x_free(thd->db);
  if (lower_case_table_names)
    casedn_str(dbname);
  thd->db=dbname;
  thd->db_access=db_access;
  DBUG_RETURN(0);
}
<commit_msg>Fix for a bug with mysql_select_db() on manually created database and lower case table names.<commit_after>/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

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

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

/* create and drop of databases */

#include "mysql_priv.h"
#include "sql_acl.h"
#include <my_dir.h>
#include <m_ctype.h>
#ifdef __WIN__
#include <direct.h>
#endif

static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *path,
				 uint level);

/* db-name is already validated when we come here */

void mysql_create_db(THD *thd, char *db, uint create_options)
{
  char	 path[FN_REFLEN+16];
  MY_DIR *dirp;
  long result=1;
  DBUG_ENTER("mysql_create_db");

  VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
  VOID(pthread_mutex_lock(&LOCK_open));

  // do not create database if another thread is holding read lock
  if (global_read_lock)
  {
    if (thd->global_read_lock)
    {
      net_printf(&thd->net, ER_CREATE_DB_WITH_READ_LOCK);
      VOID(pthread_mutex_unlock(&LOCK_open));
      goto exit;
    }
    while (global_read_lock && ! thd->killed)
    {
      (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
    }

    if (thd->killed)
    {
      net_printf(&thd->net, ER_SERVER_SHUTDOWN);
      VOID(pthread_mutex_unlock(&LOCK_open));
      goto exit;
    }

  }

  VOID(pthread_mutex_unlock(&LOCK_open));

  /* Check directory */
  (void)sprintf(path,"%s/%s", mysql_data_home, db);
  unpack_dirname(path,path);			// Convert if not unix
  if ((dirp = my_dir(path,MYF(MY_DONT_SORT))))
  {
    my_dirend(dirp);
    if (!(create_options & HA_LEX_CREATE_IF_NOT_EXISTS))
    {
      net_printf(&thd->net,ER_DB_CREATE_EXISTS,db);
      goto exit;
    }
    result = 0;
  }
  else
  {
    strend(path)[-1]=0;				// Remove last '/' from path
    if (my_mkdir(path,0777,MYF(0)) < 0)
    {
      net_printf(&thd->net,ER_CANT_CREATE_DB,db,my_errno);
      goto exit;
    }
  }
  if (!thd->query)
  {
    thd->query = path;
    thd->query_length = (uint) (strxmov(path,"create database ", db, NullS)-
				path);
  }
  {
    mysql_update_log.write(thd,thd->query, thd->query_length);
    if (mysql_bin_log.is_open())
    {
      Query_log_event qinfo(thd, thd->query);
      mysql_bin_log.write(&qinfo);
    }
  }
  if (thd->query == path)
  {
    thd->query = 0; // just in case
    thd->query_length = 0;
  }
  send_ok(&thd->net, result);

exit:
  VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
  DBUG_VOID_RETURN;
}

const char *del_exts[]=
{".frm",".ISM",".ISD",".ISM",".HSH",".DAT",".MRG",".MYI",".MYD", ".db", ".BAK", NullS};
static TYPELIB deletable_extentions=
{array_elements(del_exts)-1,"del_exts", del_exts};

/* db-name is already validated when we come here */

void mysql_rm_db(THD *thd,char *db,bool if_exists)
{
  long deleted=0;
  char	path[FN_REFLEN+16];
  MY_DIR *dirp;
  DBUG_ENTER("mysql_rm_db");

  VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
  VOID(pthread_mutex_lock(&LOCK_open));

  // do not drop database if another thread is holding read lock
  if (global_read_lock)
  {
    if (thd->global_read_lock)
    {
      net_printf(&thd->net, ER_DROP_DB_WITH_READ_LOCK);
      goto exit;
    }
    while (global_read_lock && ! thd->killed)
    {
      (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
    }

    if (thd->killed)
    {
      net_printf(&thd->net, ER_SERVER_SHUTDOWN);
      goto exit;
    }
  }

  (void) sprintf(path,"%s/%s",mysql_data_home,db);
  unpack_dirname(path,path);			// Convert if not unix
  /* See if the directory exists */
  if (!(dirp = my_dir(path,MYF(MY_WME | MY_DONT_SORT))))
  {
    if (!if_exists)
      net_printf(&thd->net,ER_DB_DROP_EXISTS,db);
    else
      send_ok(&thd->net,0);
    goto exit;
  }
  remove_db_from_cache(db);

  if ((deleted=mysql_rm_known_files(thd, dirp, path,0)) >= 0)
  {
    /*
      If there are running queries on the tables, MySQL needs to get
      access to LOCK_open to end them. InnoDB on the other hand waits
      for the queries to end before dropping the database. That is why we
      must do the dropping with LOCK_open released.
    */
    VOID(pthread_mutex_unlock(&LOCK_open));
    ha_drop_database(path);
    VOID(pthread_mutex_lock(&LOCK_open));

    if (!thd->query)
    {
      thd->query = path;
      thd->query_length = (uint) (strxmov(path,"drop database ", db, NullS)-
				  path);
    }
    mysql_update_log.write(thd, thd->query, thd->query_length);
    if (mysql_bin_log.is_open())
    {
      Query_log_event qinfo(thd, thd->query);
      mysql_bin_log.write(&qinfo);
    }
    if (thd->query == path)
    {
      thd->query = 0; // just in case
      thd->query_length = 0;
    }
    send_ok(&thd->net,(ulong) deleted);
  }

exit:
  VOID(pthread_mutex_unlock(&LOCK_open));
  VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));

  DBUG_VOID_RETURN;
}

/*
  Removes files with known extensions plus all found subdirectories that
  are 2 digits (raid directories).
*/

static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *org_path,
				 uint level)
{
  long deleted=0;
  ulong found_other_files=0;
  char filePath[FN_REFLEN];
  DBUG_ENTER("mysql_rm_known_files");
  DBUG_PRINT("enter",("path: %s", org_path));
  /* remove all files with known extensions */

  for (uint idx=2 ;
       idx < (uint) dirp->number_off_files && !thd->killed ;
       idx++)
  {
    FILEINFO *file=dirp->dir_entry+idx;
    DBUG_PRINT("info",("Examining: %s", file->name));

    /* Check if file is a raid directory */
    if (isdigit(file->name[0]) && isdigit(file->name[1]) &&
	!file->name[2] && !level)
    {
      char newpath[FN_REFLEN];
      MY_DIR *new_dirp;
      strxmov(newpath,org_path,"/",file->name,NullS);
      unpack_filename(newpath,newpath);
      if ((new_dirp = my_dir(newpath,MYF(MY_DONT_SORT))))
      {
	DBUG_PRINT("my",("New subdir found: %s", newpath));
	if ((mysql_rm_known_files(thd,new_dirp,newpath,1)) < 0)
	{
	  my_dirend(dirp);
	  DBUG_RETURN(-1);
	}
      }
      continue;
    }
    if (find_type(fn_ext(file->name),&deletable_extentions,1+2) <= 0)
    {
      found_other_files++;
      continue;
    }
    strxmov(filePath,org_path,"/",file->name,NullS);
    unpack_filename(filePath,filePath);
    if (my_delete(filePath,MYF(MY_WME)))
    {
      net_printf(&thd->net,ER_DB_DROP_DELETE,filePath,my_error);
      my_dirend(dirp);
      DBUG_RETURN(-1);
    }
    deleted++;
  }

  my_dirend(dirp);

  if (thd->killed)
  {
    send_error(&thd->net,ER_SERVER_SHUTDOWN);
    DBUG_RETURN(-1);
  }

  /*
    If the directory is a symbolic link, remove the link first, then
    remove the directory the symbolic link pointed at
  */
  if (!found_other_files)
  {
    char tmp_path[FN_REFLEN], *pos;
    char *path=unpack_filename(tmp_path,org_path);
#ifdef HAVE_READLINK
    int error;

    /* Remove end FN_LIBCHAR as this causes problem on Linux in readlink */
    pos=strend(path);
    if (pos > path && pos[-1] == FN_LIBCHAR)
      *--pos=0;

    if ((error=my_readlink(filePath, path, MYF(MY_WME))) < 0)
      DBUG_RETURN(-1);
    if (!error)
    {
      if (my_delete(path,MYF(!level ? MY_WME : 0)))
      {
	/* Don't give errors if we can't delete 'RAID' directory */
	if (level)
	  DBUG_RETURN(deleted);
	send_error(&thd->net);
	DBUG_RETURN(-1);
      }
      /* Delete directory symbolic link pointed at */
      path= filePath;
    }
#endif
    /* Remove last FN_LIBCHAR to not cause a probelm on OS/2 */
    pos=strend(path);
    if (pos > path && pos[-1] == FN_LIBCHAR)
      *--pos=0;
    /* Don't give errors if we can't delete 'RAID' directory */
    if (rmdir(path) < 0 && !level)
    {
      net_printf(&thd->net,ER_DB_DROP_RMDIR, path,errno);
      DBUG_RETURN(-1);
    }
  }
  DBUG_RETURN(deleted);
}

bool mysql_change_db(THD *thd,const char *name)
{
  int length;
  char *dbname=my_strdup((char*) name,MYF(MY_WME));
  char	path[FN_REFLEN];
  uint db_access;
  DBUG_ENTER("mysql_change_db");

  if (lower_case_table_names)
    casedn_str(dbname);

  if (!dbname || !(length=strip_sp(dbname)))
  {
    x_free(dbname);				/* purecov: inspected */
    send_error(&thd->net,ER_NO_DB_ERROR);	/* purecov: inspected */
    DBUG_RETURN(1);				/* purecov: inspected */
  }
  if ((length > NAME_LEN) || check_db_name(dbname))
  {
    net_printf(&thd->net,ER_WRONG_DB_NAME, dbname);
    x_free(dbname);
    DBUG_RETURN(1);
  }
  DBUG_PRINT("general",("Use database: %s", dbname));
  if (test_all_bits(thd->master_access,DB_ACLS))
    db_access=DB_ACLS;
  else
    db_access= (acl_get(thd->host,thd->ip,(char*) &thd->remote.sin_addr,
			thd->priv_user,dbname) |
		thd->master_access);
  if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname)))
  {
    net_printf(&thd->net,ER_DBACCESS_DENIED_ERROR,
	       thd->priv_user,
	       thd->host ? thd->host : thd->ip ? thd->ip : "unknown",
	       dbname);
    mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
		    thd->priv_user,
		    thd->host ? thd->host : thd->ip ? thd->ip : "unknown",
		    dbname);
    my_free(dbname,MYF(0));
    DBUG_RETURN(1);
  }

  (void) sprintf(path,"%s/%s",mysql_data_home,dbname);
  length=unpack_dirname(path,path);		// Convert if not unix
  if (length && path[length-1] == FN_LIBCHAR)
    path[length-1]=0;				// remove ending '\'
  if (access(path,F_OK))
  {
    net_printf(&thd->net,ER_BAD_DB_ERROR,dbname);
    my_free(dbname,MYF(0));
    DBUG_RETURN(1);
  }
  send_ok(&thd->net);
  x_free(thd->db);
  if (lower_case_table_names)
    casedn_str(dbname);
  thd->db=dbname;
  thd->db_access=db_access;
  DBUG_RETURN(0);
}
<|endoftext|>


<commit_before>#include "vaisseau_data.h"
#include "allegro_compatibility.h"
#include "option.h"
#include "platform_data.h"

int init_vaisseau_data(struct vaisseau_data *v, struct vaisseau_gfx *gfx,
                       float mass, float thrust_max, int anglestep,
                       int max_fuel, int speed_fuel_down, int speed_fuel_up,
                       int max_shield_force, int speed_shield_force_down,
                       int speed_shield_force_up) {
  v->thrust_max = ftofix(thrust_max);
  v->mass = ftofix(mass);
  v->anglestep = anglestep;

  v->max_fuel = max_fuel;
  v->speed_fuel_down = speed_fuel_down;
  v->speed_fuel_up = speed_fuel_up;
  v->max_shield_force = max_shield_force;
  v->speed_shield_force_down = speed_shield_force_down;
  v->speed_shield_force_up = speed_shield_force_down;
  int i;
  for (i = 0; i < MAX_TIR; i++) {
    v->tir[i].x = 0;
    v->tir[i].y = 0;
    v->tir[i].xposprecise = itofix(0);
    v->tir[i].yposprecise = itofix(0);
    v->tir[i].dx = itofix(0);
    v->tir[i].dy = itofix(0);
    v->tir[i].free = true;
  }

  for (i = 0; i < MAX_TIR; i++) {
    v->backtir[i].x = 0;
    v->backtir[i].y = 0;
    v->backtir[i].xposprecise = itofix(0);
    v->backtir[i].yposprecise = itofix(0);
    v->backtir[i].dx = itofix(0);
    v->backtir[i].dy = itofix(0);
    v->backtir[i].free = true;
  }

  for (i = 0; i < 8; i++) {
    v->debris[i].x = 0;
    v->debris[i].y = 0;
    v->debris[i].xposprecise = itofix(0);
    v->debris[i].yposprecise = itofix(0);
    v->debris[i].ax = itofix(0);
    v->debris[i].ay = itofix(0);
    v->debris[i].vx = itofix(0);
    v->debris[i].vy = itofix(0);
    v->debris[i].impultion = itofix(0);
    v->debris[i].angle = 0;
    v->debris[i].active = false;
  }

  v->gfx = gfx;
  v->sprite_buffer =
      al_create_bitmap(32, 32); // create ALLEGRO_BITMAP pour le sprite
  if (!v->sprite_buffer)
    return -1;
  clear_bitmap(v->sprite_buffer); // On nettoye
  blit(gfx->sprite, v->sprite_buffer, 0, 0, 0, 0, 32,
       32); // blit le sprite dans son buffer

  v->sprite_buffer_rota =
      al_create_bitmap(32, 32); // create ALLEGRO_BITMAP pour le sprite
  if (!v->sprite_buffer_rota)
    return -1;
  clear_bitmap(v->sprite_buffer_rota); // On nettoye

  int num_frames = 360 / VAISSEAU_ANGLESTEP;

  v->coll_map.init(32, 32, num_frames);

  for (int frame = 0; frame < num_frames; frame++) {
    double angle = v->anglestep * frame;
    clear_bitmap(v->sprite_buffer_rota);
    rotate_sprite(v->sprite_buffer_rota, v->sprite_buffer, 0, 0, angle);

    ALLEGRO_LOCKED_REGION *reg = al_lock_bitmap(
        v->sprite_buffer_rota, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READONLY);

    assert(reg);

    for (int y = 0; y < 32; y++) {
      for (int x = 0; x < 32; x++) {
        auto pixel = get_pixel(reg, x, y);
        v->coll_map.set_pixel(x, y, frame, is_nonblack_pixel(pixel));
      }
    }

    al_unlock_bitmap(v->sprite_buffer_rota);
  }

  return 0;
}

void clean_vaisseau_data(struct vaisseau_data *v) {
  if (v->sprite_buffer)
    al_destroy_bitmap(v->sprite_buffer); // On nettoye
  if (v->sprite_buffer_rota)
    al_destroy_bitmap(v->sprite_buffer_rota); // On nettoye
}

void init_ship_pos_from_platforms(struct vaisseau_data *v,
                                  struct platform_data *plats) {
  int xpos, ypos;
  xpos = (plats->xmin + plats->xmax) / 2 - 16;
  ypos = plats->yflat - 29;

  v->xpos = xpos;
  v->ypos = ypos;
  v->xposprecise = itofix(xpos);
  v->yposprecise = itofix(ypos);
  v->fuel = v->max_fuel;
  v->shield_force = v->max_shield_force;

  v->explode_count = 0;
  v->explode_tick = 0;
  v->explode = false;
  v->explode_appear_time_passed = false;

  v->option_type = OPT_NOOPTION;
  v->speed_shield_force_down = VAISSEAU_SPEED_SHIELD_FORCE_DOWN;
  v->thrust_max = ftofix(VAISSEAU_THRUST_MAX);

  v->impactx = 0;
  v->impacty = 0;
  v->ax = itofix(0);
  v->ay = itofix(0);
  v->vx = itofix(0);
  v->vy = itofix(0);
  v->thrust = itofix(0);
  v->shield = false;
  v->fire = false;
  v->fire_delay = false;
  v->landed = true;
  v->rebound = false;
  v->angle = 0;
  v->angle_precise = 0;
  v->refueling = false;
}

void fuel_shield_calcul(int nbvaisseau, struct vaisseau_data *v, double dt) {
  while (nbvaisseau--) {
    v->refueling = false;
    if (v->fire_delay)
      v->fuel -= 3 * (dt / 0.025);
    if (!(v->landed || v->rebound) && (v->thrust != itofix(0)) && (v->fuel > 0))
      v->fuel -= v->speed_fuel_down * (dt / 0.025);
    else if ((v->landed || v->rebound) && (v->thrust == itofix(0)) &&
             (v->fuel < v->max_fuel)) {
      v->fuel += v->speed_fuel_up * (dt / 0.025);
      v->refueling = true;
    }
    if (v->fuel < 0)
      v->fuel = 0;
    if (v->fuel > v->max_fuel)
      v->fuel = v->max_fuel;

    if (v->shield && v->shield_force > 0)
      v->shield_force -= v->speed_shield_force_down * (dt / 0.025);
    else if (!v->shield && v->shield_force < v->max_shield_force)
      v->shield_force += v->speed_shield_force_up * (dt / 0.025);

    if (v->shield_force < 0)
      v->shield_force = 0;
    if (v->shield_force > v->max_shield_force)
      v->shield_force = v->max_shield_force;

    v++;
  }
}

void collision_map::init(int width_in, int height_in, int num_frames_in) {
  width = width_in;
  height = height_in;
  num_frames = num_frames_in;
  int num_pixels = width * height * num_frames;
  coll_map = new bool[num_pixels];

  for (int i = 0; i < num_pixels; i++) {
    coll_map[i] = false;
  }
}

collision_map::~collision_map() { delete coll_map; }

bool collision_map::is_collide_pixel(int x, int y, int frame) {
  return coll_map[get_index(x, y, frame)];
}

void collision_map::set_pixel(int x, int y, int frame, bool value) {
  coll_map[get_index(x, y, frame)] = value;
}

int collision_map::get_index(int x, int y, int frame) {
  assert(x >= 0 && x < width);
  assert(y >= 0 && y < height);
  assert(frame >= 0 && frame < num_frames);

  int frame_offset = width * height * frame;
  int line_offset = width * y;
  int pos = frame_offset + line_offset + x;
  return pos;
}
<commit_msg>Fix crash due to missing one frame<commit_after>#include "vaisseau_data.h"
#include "allegro_compatibility.h"
#include "option.h"
#include "platform_data.h"

int init_vaisseau_data(struct vaisseau_data *v, struct vaisseau_gfx *gfx,
                       float mass, float thrust_max, int anglestep,
                       int max_fuel, int speed_fuel_down, int speed_fuel_up,
                       int max_shield_force, int speed_shield_force_down,
                       int speed_shield_force_up) {
  v->thrust_max = ftofix(thrust_max);
  v->mass = ftofix(mass);
  v->anglestep = anglestep;

  v->max_fuel = max_fuel;
  v->speed_fuel_down = speed_fuel_down;
  v->speed_fuel_up = speed_fuel_up;
  v->max_shield_force = max_shield_force;
  v->speed_shield_force_down = speed_shield_force_down;
  v->speed_shield_force_up = speed_shield_force_down;
  int i;
  for (i = 0; i < MAX_TIR; i++) {
    v->tir[i].x = 0;
    v->tir[i].y = 0;
    v->tir[i].xposprecise = itofix(0);
    v->tir[i].yposprecise = itofix(0);
    v->tir[i].dx = itofix(0);
    v->tir[i].dy = itofix(0);
    v->tir[i].free = true;
  }

  for (i = 0; i < MAX_TIR; i++) {
    v->backtir[i].x = 0;
    v->backtir[i].y = 0;
    v->backtir[i].xposprecise = itofix(0);
    v->backtir[i].yposprecise = itofix(0);
    v->backtir[i].dx = itofix(0);
    v->backtir[i].dy = itofix(0);
    v->backtir[i].free = true;
  }

  for (i = 0; i < 8; i++) {
    v->debris[i].x = 0;
    v->debris[i].y = 0;
    v->debris[i].xposprecise = itofix(0);
    v->debris[i].yposprecise = itofix(0);
    v->debris[i].ax = itofix(0);
    v->debris[i].ay = itofix(0);
    v->debris[i].vx = itofix(0);
    v->debris[i].vy = itofix(0);
    v->debris[i].impultion = itofix(0);
    v->debris[i].angle = 0;
    v->debris[i].active = false;
  }

  v->gfx = gfx;
  v->sprite_buffer =
      al_create_bitmap(32, 32); // create ALLEGRO_BITMAP pour le sprite
  if (!v->sprite_buffer)
    return -1;
  clear_bitmap(v->sprite_buffer); // On nettoye
  blit(gfx->sprite, v->sprite_buffer, 0, 0, 0, 0, 32,
       32); // blit le sprite dans son buffer

  v->sprite_buffer_rota =
      al_create_bitmap(32, 32); // create ALLEGRO_BITMAP pour le sprite
  if (!v->sprite_buffer_rota)
    return -1;
  clear_bitmap(v->sprite_buffer_rota); // On nettoye

  int num_frames = (360 / anglestep) + 1; // Add one frame for handling rounding errors

  v->coll_map.init(32, 32, num_frames);

  for (int frame = 0; frame < num_frames; frame++) {
    double angle = v->anglestep * frame;
    clear_bitmap(v->sprite_buffer_rota);
    rotate_sprite(v->sprite_buffer_rota, v->sprite_buffer, 0, 0, angle);

    ALLEGRO_LOCKED_REGION *reg = al_lock_bitmap(
        v->sprite_buffer_rota, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READONLY);

    assert(reg);

    for (int y = 0; y < 32; y++) {
      for (int x = 0; x < 32; x++) {
        auto pixel = get_pixel(reg, x, y);
        v->coll_map.set_pixel(x, y, frame, is_nonblack_pixel(pixel));
      }
    }

    al_unlock_bitmap(v->sprite_buffer_rota);
  }

  return 0;
}

void clean_vaisseau_data(struct vaisseau_data *v) {
  if (v->sprite_buffer)
    al_destroy_bitmap(v->sprite_buffer); // On nettoye
  if (v->sprite_buffer_rota)
    al_destroy_bitmap(v->sprite_buffer_rota); // On nettoye
}

void init_ship_pos_from_platforms(struct vaisseau_data *v,
                                  struct platform_data *plats) {
  int xpos, ypos;
  xpos = (plats->xmin + plats->xmax) / 2 - 16;
  ypos = plats->yflat - 29;

  v->xpos = xpos;
  v->ypos = ypos;
  v->xposprecise = itofix(xpos);
  v->yposprecise = itofix(ypos);
  v->fuel = v->max_fuel;
  v->shield_force = v->max_shield_force;

  v->explode_count = 0;
  v->explode_tick = 0;
  v->explode = false;
  v->explode_appear_time_passed = false;

  v->option_type = OPT_NOOPTION;
  v->speed_shield_force_down = VAISSEAU_SPEED_SHIELD_FORCE_DOWN;
  v->thrust_max = ftofix(VAISSEAU_THRUST_MAX);

  v->impactx = 0;
  v->impacty = 0;
  v->ax = itofix(0);
  v->ay = itofix(0);
  v->vx = itofix(0);
  v->vy = itofix(0);
  v->thrust = itofix(0);
  v->shield = false;
  v->fire = false;
  v->fire_delay = false;
  v->landed = true;
  v->rebound = false;
  v->angle = 0;
  v->angle_precise = 0;
  v->refueling = false;
}

void fuel_shield_calcul(int nbvaisseau, struct vaisseau_data *v, double dt) {
  while (nbvaisseau--) {
    v->refueling = false;
    if (v->fire_delay)
      v->fuel -= 3 * (dt / 0.025);
    if (!(v->landed || v->rebound) && (v->thrust != itofix(0)) && (v->fuel > 0))
      v->fuel -= v->speed_fuel_down * (dt / 0.025);
    else if ((v->landed || v->rebound) && (v->thrust == itofix(0)) &&
             (v->fuel < v->max_fuel)) {
      v->fuel += v->speed_fuel_up * (dt / 0.025);
      v->refueling = true;
    }
    if (v->fuel < 0)
      v->fuel = 0;
    if (v->fuel > v->max_fuel)
      v->fuel = v->max_fuel;

    if (v->shield && v->shield_force > 0)
      v->shield_force -= v->speed_shield_force_down * (dt / 0.025);
    else if (!v->shield && v->shield_force < v->max_shield_force)
      v->shield_force += v->speed_shield_force_up * (dt / 0.025);

    if (v->shield_force < 0)
      v->shield_force = 0;
    if (v->shield_force > v->max_shield_force)
      v->shield_force = v->max_shield_force;

    v++;
  }
}

void collision_map::init(int width_in, int height_in, int num_frames_in) {
  width = width_in;
  height = height_in;
  num_frames = num_frames_in;
  int num_pixels = width * height * num_frames;
  coll_map = new bool[num_pixels];

  for (int i = 0; i < num_pixels; i++) {
    coll_map[i] = false;
  }
}

collision_map::~collision_map() { delete coll_map; }

bool collision_map::is_collide_pixel(int x, int y, int frame) {
  return coll_map[get_index(x, y, frame)];
}

void collision_map::set_pixel(int x, int y, int frame, bool value) {
  coll_map[get_index(x, y, frame)] = value;
}

int collision_map::get_index(int x, int y, int frame) {
  assert(x >= 0 && x < width);
  assert(y >= 0 && y < height);
  assert(frame >= 0 && frame < num_frames);

  int frame_offset = width * height * frame;
  int line_offset = width * y;
  int pos = frame_offset + line_offset + x;
  return pos;
}
<|endoftext|>


<commit_before>/***************************************************************************
* Copyright (c) 2016, Johan Mabille and Sylvain Corlay                     *
*                                                                          *
* Distributed under the terms of the BSD 3-Clause License.                 *
*                                                                          *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#include "gtest/gtest.h"
#include "test_common.hpp"
#include "xtensor-python/pytensor.hpp"
#include "xtensor-python/pyvectorize.hpp"
#include "pybind11/pybind11.h"
#include "pybind11/numpy.h"

namespace xt
{

    double f1(double a, double b)
    {
        return a + b;
    }

    using shape_type = std::vector<std::size_t>;

    TEST(pyvectorize, function)
    {
        auto vecf1 = pyvectorize(f1);
        shape_type shape = { 3, 2 };
        pyarray<double> a(shape, 1.5);
        pyarray<double> b(shape, 2.3);
        pyarray<double> c = vecf1(a, b);
        EXPECT_EQ(a(0, 0) + b(0, 0), c(0, 0));
    }

    TEST(pyvectorize, lambda)
    {
        auto vecf1 = pyvectorize([](double a, double b) { return a + b; });
        shape_type shape = { 3, 2 };
        pyarray<double> a(shape, 1.5);
        pyarray<double> b(shape, 2.3);
        pyarray<double> c = vecf1(a, b);
        EXPECT_EQ(a(0, 0) + b(0, 0), c(0, 0));
    }

    TEST(pyvectorize, complex)
    {
        using complex_t = std::complex<double>;
        shape_type shape = { 3, 2 };
        pyarray<complex_t> a(shape, complex_t(1.2, 2.5));
        auto f = [](const pyarray<complex_t>& t) {
            return std::make_tuple(pyvectorize([](complex_t x) { return std::abs(x); })(t),
                                   pyvectorize([](complex_t x) { return std::arg(x); })(t));
        };

        auto res = f(a);
        double expected_abs = std::abs(a(1, 1));
        double expected_arg = std::arg(a(1, 1));
        EXPECT_EQ(expected_abs, std::get<0>(res)(1, 1));
        EXPECT_EQ(expected_arg, std::get<1>(res)(1, 1));
    }

    TEST(pyvectorize, complex_pybind)
    {
        using complex_t = std::complex<double>;
        shape_type shape = { 3, 2 };
        pyarray<complex_t> a(shape, complex_t(1.2, 2.5));
        auto f = [](const pyarray<complex_t>& t) {
            return pybind11::make_tuple(pyvectorize([](complex_t x) { return std::abs(x); })(t),
                                        pyvectorize([](complex_t x) { return std::arg(x); })(t));
        };

        auto res = f(a);
        double expected_abs = std::abs(a(1, 1));
        double expected_arg = std::arg(a(1, 1));

        EXPECT_EQ(expected_abs, res[0].cast<pyarray<double>>()(1, 1));
        EXPECT_EQ(expected_arg, res[1].cast<pyarray<double>>()(1, 1));
    }
}
<commit_msg>Remove pybind11 tuple test<commit_after>/***************************************************************************
* Copyright (c) 2016, Johan Mabille and Sylvain Corlay                     *
*                                                                          *
* Distributed under the terms of the BSD 3-Clause License.                 *
*                                                                          *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#include "gtest/gtest.h"
#include "test_common.hpp"
#include "xtensor-python/pytensor.hpp"
#include "xtensor-python/pyvectorize.hpp"
#include "pybind11/pybind11.h"
#include "pybind11/numpy.h"

namespace xt
{

    double f1(double a, double b)
    {
        return a + b;
    }

    using shape_type = std::vector<std::size_t>;

    TEST(pyvectorize, function)
    {
        auto vecf1 = pyvectorize(f1);
        shape_type shape = { 3, 2 };
        pyarray<double> a(shape, 1.5);
        pyarray<double> b(shape, 2.3);
        pyarray<double> c = vecf1(a, b);
        EXPECT_EQ(a(0, 0) + b(0, 0), c(0, 0));
    }

    TEST(pyvectorize, lambda)
    {
        auto vecf1 = pyvectorize([](double a, double b) { return a + b; });
        shape_type shape = { 3, 2 };
        pyarray<double> a(shape, 1.5);
        pyarray<double> b(shape, 2.3);
        pyarray<double> c = vecf1(a, b);
        EXPECT_EQ(a(0, 0) + b(0, 0), c(0, 0));
    }

    TEST(pyvectorize, complex)
    {
        using complex_t = std::complex<double>;
        shape_type shape = { 3, 2 };
        pyarray<complex_t> a(shape, complex_t(1.2, 2.5));
        auto f = pyvectorize([](complex_t x) { return std::abs(x); });
        auto res = f(a);
        double exp = std::abs(a(1, 1));
        EXPECT_EQ(exp, res(1, 1));
    }
}
<|endoftext|>