<commit_before>/**
 * @file llupdaterservice.cpp
 *
 * $LicenseInfo:firstyear=2010&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include "linden_common.h"
#include <stdexcept>
#include <boost/format.hpp>
#include "llhttpclient.h"
#include "llsd.h"
#include "llupdatechecker.h"
#include "lluri.h"
#if LL_DARWIN
#include <CoreServices/CoreServices.h>
#endif

#if LL_WINDOWS
#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
#endif

class LLUpdateChecker::CheckError:
	public std::runtime_error
{
public:
	CheckError(const char * message):
		std::runtime_error(message)
	{
		; // No op.
	}
};

// LLUpdateChecker
//-----------------------------------------------------------------------------

LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client):
	mImplementation(new LLUpdateChecker::Implementation(client))
{
	; // No op.
}

void LLUpdateChecker::checkVersion(std::string const & hostUrl,
								   std::string const & servicePath,
								   std::string const & channel,
								   std::string const & version,
								   std::string const & platform_version,
								   unsigned char       uniqueid[MD5HEX_STR_SIZE],
								   bool                willing_to_test)
{
	mImplementation->checkVersion(hostUrl, servicePath, channel, version, platform_version, uniqueid, willing_to_test);
}

// LLUpdateChecker::Implementation
//-----------------------------------------------------------------------------

const char * LLUpdateChecker::Implementation::sLegacyProtocolVersion = "v1.0";
const char * LLUpdateChecker::Implementation::sProtocolVersion = "v1.1";

LLUpdateChecker::Implementation::Implementation(LLUpdateChecker::Client & client):
	mClient(client),
	mInProgress(false),
	mProtocol(sProtocolVersion)
{
	; // No op.
}

LLUpdateChecker::Implementation::~Implementation()
{
	; // No op.
}

void LLUpdateChecker::Implementation::checkVersion(std::string const & hostUrl,
												   std::string const & servicePath,
												   std::string const & channel,
												   std::string const & version,
												   std::string const & platform_version,
												   unsigned char       uniqueid[MD5HEX_STR_SIZE],
												   bool                willing_to_test)
{
	llassert(!mInProgress);

	mInProgress = true;

	mHostUrl     	 = hostUrl;
	mServicePath 	 = servicePath;
	mChannel     	 = channel;
	mVersion     	 = version;
	mPlatformVersion = platform_version;
	memcpy(mUniqueId, uniqueid, MD5HEX_STR_SIZE);
	mWillingToTest   = willing_to_test;

	mProtocol = sProtocolVersion;

	std::string checkUrl = buildUrl(hostUrl, servicePath, channel, version, platform_version, uniqueid, willing_to_test);
	LL_INFOS("UpdaterService") << "checking for updates at " << checkUrl << LL_ENDL;

	mHttpClient.get(checkUrl, this);
}

void LLUpdateChecker::Implementation::completed(U32 status,
												const std::string & reason,
												const LLSD & content)
{
	mInProgress = false;

	if(status != 200)
	{
		if (status == 404)
		{
			if (mProtocol == sProtocolVersion)
			{
				mProtocol = sLegacyProtocolVersion;
				std::string retryUrl = buildUrl(mHostUrl, mServicePath, mChannel, mVersion, mPlatformVersion, mUniqueId, mWillingToTest);

				LL_WARNS("UpdaterService")
					<< "update response using " << sProtocolVersion
					<< " was 404... retry with legacy protocol" << mProtocol
					<< "\n at " << retryUrl
					<< LL_ENDL;

				mHttpClient.get(retryUrl, this);
			}
			else
			{
				LL_WARNS("UpdaterService")
					<< "update response using " << sLegacyProtocolVersion
					<< " was 404; request failed"
					<< LL_ENDL;
				mClient.error(reason);
			}
		}
		else
		{
			LL_WARNS("UpdaterService") << "response error " << status << " (" << reason << ")" << LL_ENDL;
			mClient.error(reason);
		}
	}
	else
	{
		mClient.response(content);
	}
}

void LLUpdateChecker::Implementation::error(U32 status, const std::string & reason)
{
	mInProgress = false;
	LL_WARNS("UpdaterService") << "update check failed; " << reason << LL_ENDL;
	mClient.error(reason);
}

std::string LLUpdateChecker::Implementation::buildUrl(std::string const & hostUrl,
													  std::string const & servicePath,
													  std::string const & channel,
													  std::string const & version,
													  std::string const & platform_version,
													  unsigned char       uniqueid[MD5HEX_STR_SIZE],
													  bool                willing_to_test)
{
#ifdef LL_WINDOWS
	static const char * platform = "win";
#elif LL_DARWIN
    long versMin;
    Gestalt(gestaltSystemVersionMinor, &versMin);

    static const char *platform;
    if (versMin == 5) //OS 10.5
    {
        platform = "mac_legacy";
    }
    else
    {
        platform = "mac";
    }
#elif LL_LINUX
	static const char * platform = "lnx";
#else
#   error "unsupported platform"
#endif

	LLSD path;
	path.append(servicePath);
	path.append(mProtocol);
	path.append(channel);
	path.append(version);
	path.append(platform);
	if (mProtocol != sLegacyProtocolVersion)
	{
		path.append(platform_version);
		path.append(willing_to_test ? "testok" : "testno");
		path.append((char*)uniqueid);
	}
	return LLURI::buildHTTP(hostUrl, path).asString();
}
<commit_msg>remove old hack for legacy mac updates (no system that needed that will run this version anyway)<commit_after>/**
 * @file llupdaterservice.cpp
 *
 * $LicenseInfo:firstyear=2010&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include "linden_common.h"
#include <stdexcept>
#include <boost/format.hpp>
#include "llhttpclient.h"
#include "llsd.h"
#include "llupdatechecker.h"
#include "lluri.h"
#if LL_DARWIN
#include <CoreServices/CoreServices.h>
#endif

#if LL_WINDOWS
#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
#endif

class LLUpdateChecker::CheckError:
	public std::runtime_error
{
public:
	CheckError(const char * message):
		std::runtime_error(message)
	{
		; // No op.
	}
};

// LLUpdateChecker
//-----------------------------------------------------------------------------

LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client):
	mImplementation(new LLUpdateChecker::Implementation(client))
{
	; // No op.
}

void LLUpdateChecker::checkVersion(std::string const & hostUrl,
								   std::string const & servicePath,
								   std::string const & channel,
								   std::string const & version,
								   std::string const & platform_version,
								   unsigned char       uniqueid[MD5HEX_STR_SIZE],
								   bool                willing_to_test)
{
	mImplementation->checkVersion(hostUrl, servicePath, channel, version, platform_version, uniqueid, willing_to_test);
}

// LLUpdateChecker::Implementation
//-----------------------------------------------------------------------------

const char * LLUpdateChecker::Implementation::sLegacyProtocolVersion = "v1.0";
const char * LLUpdateChecker::Implementation::sProtocolVersion = "v1.1";

LLUpdateChecker::Implementation::Implementation(LLUpdateChecker::Client & client):
	mClient(client),
	mInProgress(false),
	mProtocol(sProtocolVersion)
{
	; // No op.
}

LLUpdateChecker::Implementation::~Implementation()
{
	; // No op.
}

void LLUpdateChecker::Implementation::checkVersion(std::string const & hostUrl,
												   std::string const & servicePath,
												   std::string const & channel,
												   std::string const & version,
												   std::string const & platform_version,
												   unsigned char       uniqueid[MD5HEX_STR_SIZE],
												   bool                willing_to_test)
{
	llassert(!mInProgress);

	mInProgress = true;

	mHostUrl     	 = hostUrl;
	mServicePath 	 = servicePath;
	mChannel     	 = channel;
	mVersion     	 = version;
	mPlatformVersion = platform_version;
	memcpy(mUniqueId, uniqueid, MD5HEX_STR_SIZE);
	mWillingToTest   = willing_to_test;

	mProtocol = sProtocolVersion;

	std::string checkUrl = buildUrl(hostUrl, servicePath, channel, version, platform_version, uniqueid, willing_to_test);
	LL_INFOS("UpdaterService") << "checking for updates at " << checkUrl << LL_ENDL;

	mHttpClient.get(checkUrl, this);
}

void LLUpdateChecker::Implementation::completed(U32 status,
												const std::string & reason,
												const LLSD & content)
{
	mInProgress = false;

	if(status != 200)
	{
		if (status == 404)
		{
			if (mProtocol == sProtocolVersion)
			{
				mProtocol = sLegacyProtocolVersion;
				std::string retryUrl = buildUrl(mHostUrl, mServicePath, mChannel, mVersion, mPlatformVersion, mUniqueId, mWillingToTest);

				LL_WARNS("UpdaterService")
					<< "update response using " << sProtocolVersion
					<< " was 404... retry with legacy protocol" << mProtocol
					<< "\n at " << retryUrl
					<< LL_ENDL;

				mHttpClient.get(retryUrl, this);
			}
			else
			{
				LL_WARNS("UpdaterService")
					<< "update response using " << sLegacyProtocolVersion
					<< " was 404; request failed"
					<< LL_ENDL;
				mClient.error(reason);
			}
		}
		else
		{
			LL_WARNS("UpdaterService") << "response error " << status << " (" << reason << ")" << LL_ENDL;
			mClient.error(reason);
		}
	}
	else
	{
		mClient.response(content);
	}
}

void LLUpdateChecker::Implementation::error(U32 status, const std::string & reason)
{
	mInProgress = false;
	LL_WARNS("UpdaterService") << "update check failed; " << reason << LL_ENDL;
	mClient.error(reason);
}

std::string LLUpdateChecker::Implementation::buildUrl(std::string const & hostUrl,
													  std::string const & servicePath,
													  std::string const & channel,
													  std::string const & version,
													  std::string const & platform_version,
													  unsigned char       uniqueid[MD5HEX_STR_SIZE],
													  bool                willing_to_test)
{
#ifdef LL_WINDOWS
	static const char * platform = "win";
#elif LL_DARWIN
    static const char *platform = "mac";
#elif LL_LINUX
	static const char * platform = "lnx";
#else
#   error "unsupported platform"
#endif

	LLSD path;
	path.append(servicePath);
	path.append(mProtocol);
	path.append(channel);
	path.append(version);
	path.append(platform);
	if (mProtocol != sLegacyProtocolVersion)
	{
		path.append(platform_version);
		path.append(willing_to_test ? "testok" : "testno");
		path.append((char*)uniqueid);
	}
	return LLURI::buildHTTP(hostUrl, path).asString();
}
<|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
*                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#ifndef SOFA_COMPONENT_INTERACTIONFORCEFIELD_ConstantForceField_INL
#define SOFA_COMPONENT_INTERACTIONFORCEFIELD_ConstantForceField_INL

#include <sofa/core/componentmodel/behavior/ForceField.inl>
#include "RestShapeSpringsForceField.h"
#include <sofa/helper/system/config.h>
#include <sofa/defaulttype/VecTypes.h>
#include <sofa/defaulttype/RigidTypes.h>
#include <sofa/helper/gl/template.h>
#include <assert.h>
#include <iostream>

namespace sofa
{

namespace component
{

namespace forcefield
{

template<class DataTypes>
RestShapeSpringsForceField<DataTypes>::RestShapeSpringsForceField()
    : points(initData(&points, "points", "points where the forces are applied"))
    , stiffness(initData(&stiffness, "stiffness", "stiffness values between the actual position and the rest shape position"))
{}

template<class DataTypes>
void RestShapeSpringsForceField<DataTypes>::init()
{

    core::componentmodel::behavior::ForceField<DataTypes>::init();

    if (points.getValue().size()==0)
    {
        VecIndex indices; // = points.getValue();
        std::cout<<"in RestShapeSpringsForceField no point is defined, default case: points = all points "<<std::endl;

        for (unsigned int i=0; i<(unsigned)this->mstate->getSize(); i++)
        {
            //int &toto = i;
            indices.push_back(i);
        }
        points.setValue(indices);

    }
    if(stiffness.getValue()s.size() == 0)
    {
        VecReal stiffs;
        stiffs.push_back(100.0);
        std::cout<<"in RestShapeSpringsForceField no stiffness is defined, assuming equal stiffness on each node, k = 100.0 "<<std::endl;
        stiffness.setValue(stiffs);
    }

}

template<class DataTypes>
void RestShapeSpringsForceField<DataTypes>::addForce(VecDeriv& f, const VecCoord& p, const VecDeriv& )
{
    const VecCoord& p_0 = *this->mstate->getX0();

    f.resize(p.size());

    const VecIndex& indices = points.getValue();
    const VecReal& k = stiffness.getValue();

    if ( k.size()!= indices.size() )
    {
        sout << "WARNING : stiffness is not defined on each point, first stiffness is used" << sendl;

        for (unsigned int i=0; i<indices.size(); i++)
        {
            const unsigned int index = indices[i];

            Deriv dx = p[index] - p_0[index];
            f[index] -=  dx * k[0] ;

            //	Deriv dx = p[i] - p_0[i];
            //	f[ indices[i] ] -=  dx * k[0] ;
        }
    }
    else
    {
        for (unsigned int i=0; i<indices.size(); i++)
        {
            const unsigned int index = indices[i];

            Deriv dx = p[index] - p_0[index];
            f[index] -=  dx * k[index] ;

            //	Deriv dx = p[i] - p_0[i];
            //	f[ indices[i] ] -=  dx * k[i] ;
        }
    }
}

template<class DataTypes>
void RestShapeSpringsForceField<DataTypes>::addDForce(VecDeriv& df, const VecDeriv &dx, double kFactor, double )
{
    const VecIndex& indices = points.getValue();
    const VecReal& k = stiffness.getValue();

    if (k.size()!= indices.size() )
    {
        sout << "WARNING : stiffness is not defined on each point, first stiffness is used" << sendl;

        for (unsigned int i=0; i<indices.size(); i++)
        {
            df[indices[i]] -=  dx[indices[i]] * k[0] * kFactor;
        }
    }
    else
    {
        for (unsigned int i=0; i<indices.size(); i++)
        {
            //	df[ indices[i] ] -=  dx[indices[i]] * k[i] * kFactor ;
            df[indices[i]] -=  dx[indices[i]] * k[indices[i]] * kFactor ;
        }
    }
}

template<class DataTypes>
void RestShapeSpringsForceField<DataTypes>::addKToMatrix(sofa::defaulttype::BaseMatrix * mat, double kFact, unsigned int &offset)
{
    const VecIndex& indices = points.getValue();
    const VecReal& k = stiffness.getValue();
    const int N = Coord::static_size;

    unsigned int curIndex = 0;

    if (k.size()!= indices.size() )
    {
        for (unsigned int index = 0; index < indices.size(); index++)
        {
            curIndex = indices[index];

            for(int i = 0; i < N; i++)
            {

                //	for (unsigned int j = 0; j < N; j++)
                //	{
                //		mat->add(offset + N * curIndex + i, offset + N * curIndex + j, kFact * k[0]);
                //	}

                mat->add(offset + N * curIndex + i, offset + N * curIndex + i, kFact * k[0]);
            }
        }
    }
    else
    {
        for (unsigned int index = 0; index < indices.size(); index++)
        {
            curIndex = indices[index];

            for(int i = 0; i < N; i++)
            {

                //	for (unsigned int j = 0; j < N; j++)
                //	{
                //		mat->add(offset + N * curIndex + i, offset + N * curIndex + j, kFact * k[curIndex]);
                //	}

                mat->add(offset + N * curIndex + i, offset + N * curIndex + i, kFact * k[curIndex]);
            }
        }
    }
}

//template <class DataTypes>
//double RestShapeSpringsForceField<DataTypes>::getPotentialEnergy(const VecCoord& x)
//{
//	const VecIndex& indices = points.getValue();
//	const VecDeriv& f = forces.getValue();
//	double e=0;
//	unsigned int i = 0;
//	for (; i<f.size(); i++)
//	{
//		e -= f[i]*x[indices[i]];
//	}
//	for (; i<indices.size(); i++)
//	{
//		e -= f[f.size()-1]*x[indices[i]];
//	}
//	return e;
//}

//template <class DataTypes>
//void RestShapeSpringsForceField<DataTypes>::setForce( unsigned i, const Deriv& force )
//{
//	VecIndex& indices = *points.beginEdit();
//	VecDeriv& f = *forces.beginEdit();
//	indices.push_back(i);
//	f.push_back( force );
//	points.endEdit();
//	forces.endEdit();
//}

template<class DataTypes>
void RestShapeSpringsForceField<DataTypes>::draw()
{
    /*
    if (!getContext()->getShowForceFields())
    	return;  /// \todo put this in the parent class
    const VecIndex& indices = points.getValue();
    const VecDeriv& f = forces.getValue();
    const VecCoord& x = *this->mstate->getX();
    glDisable(GL_LIGHTING);
    glBegin(GL_LINES);
    glColor3f(0,1,0);
    for (unsigned int i=0; i<indices.size(); i++)
    {
    	Real xx,xy,xz,fx,fy,fz;
    	DataTypes::get(xx,xy,xz,x[indices[i]]);
    	DataTypes::get(fx,fy,fz,f[(i<f.size()) ? i : f.size()-1]);
    	glVertex3f( (GLfloat)xx, (GLfloat)xy, (GLfloat)xz );
    	glVertex3f( (GLfloat)(xx+fx), (GLfloat)(xy+fy), (GLfloat)(xz+fz) );
    }
    glEnd();
    */
}

template <class DataTypes>
bool RestShapeSpringsForceField<DataTypes>::addBBox(double*, double* )
{
    return false;
}

} // namespace forcefield

} // namespace component

} // namespace sofa

#endif

<commit_msg>r4007/sofa-dev : Compilation Fix<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
*                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#ifndef SOFA_COMPONENT_INTERACTIONFORCEFIELD_ConstantForceField_INL
#define SOFA_COMPONENT_INTERACTIONFORCEFIELD_ConstantForceField_INL

#include <sofa/core/componentmodel/behavior/ForceField.inl>
#include "RestShapeSpringsForceField.h"
#include <sofa/helper/system/config.h>
#include <sofa/defaulttype/VecTypes.h>
#include <sofa/defaulttype/RigidTypes.h>
#include <sofa/helper/gl/template.h>
#include <assert.h>
#include <iostream>

namespace sofa
{

namespace component
{

namespace forcefield
{

template<class DataTypes>
RestShapeSpringsForceField<DataTypes>::RestShapeSpringsForceField()
    : points(initData(&points, "points", "points where the forces are applied"))
    , stiffness(initData(&stiffness, "stiffness", "stiffness values between the actual position and the rest shape position"))
{}

template<class DataTypes>
void RestShapeSpringsForceField<DataTypes>::init()
{

    core::componentmodel::behavior::ForceField<DataTypes>::init();

    if (points.getValue().size()==0)
    {
        VecIndex indices; // = points.getValue();
        std::cout<<"in RestShapeSpringsForceField no point is defined, default case: points = all points "<<std::endl;

        for (unsigned int i=0; i<(unsigned)this->mstate->getSize(); i++)
        {
            //int &toto = i;
            indices.push_back(i);
        }
        points.setValue(indices);

    }
    if(stiffness.getValue().size() == 0)
    {
        VecReal stiffs;
        stiffs.push_back(100.0);
        std::cout<<"in RestShapeSpringsForceField no stiffness is defined, assuming equal stiffness on each node, k = 100.0 "<<std::endl;
        stiffness.setValue(stiffs);
    }

}

template<class DataTypes>
void RestShapeSpringsForceField<DataTypes>::addForce(VecDeriv& f, const VecCoord& p, const VecDeriv& )
{
    const VecCoord& p_0 = *this->mstate->getX0();

    f.resize(p.size());

    const VecIndex& indices = points.getValue();
    const VecReal& k = stiffness.getValue();

    if ( k.size()!= indices.size() )
    {
        sout << "WARNING : stiffness is not defined on each point, first stiffness is used" << sendl;

        for (unsigned int i=0; i<indices.size(); i++)
        {
            const unsigned int index = indices[i];

            Deriv dx = p[index] - p_0[index];
            f[index] -=  dx * k[0] ;

            //	Deriv dx = p[i] - p_0[i];
            //	f[ indices[i] ] -=  dx * k[0] ;
        }
    }
    else
    {
        for (unsigned int i=0; i<indices.size(); i++)
        {
            const unsigned int index = indices[i];

            Deriv dx = p[index] - p_0[index];
            f[index] -=  dx * k[index] ;

            //	Deriv dx = p[i] - p_0[i];
            //	f[ indices[i] ] -=  dx * k[i] ;
        }
    }
}

template<class DataTypes>
void RestShapeSpringsForceField<DataTypes>::addDForce(VecDeriv& df, const VecDeriv &dx, double kFactor, double )
{
    const VecIndex& indices = points.getValue();
    const VecReal& k = stiffness.getValue();

    if (k.size()!= indices.size() )
    {
        sout << "WARNING : stiffness is not defined on each point, first stiffness is used" << sendl;

        for (unsigned int i=0; i<indices.size(); i++)
        {
            df[indices[i]] -=  dx[indices[i]] * k[0] * kFactor;
        }
    }
    else
    {
        for (unsigned int i=0; i<indices.size(); i++)
        {
            //	df[ indices[i] ] -=  dx[indices[i]] * k[i] * kFactor ;
            df[indices[i]] -=  dx[indices[i]] * k[indices[i]] * kFactor ;
        }
    }
}

template<class DataTypes>
void RestShapeSpringsForceField<DataTypes>::addKToMatrix(sofa::defaulttype::BaseMatrix * mat, double kFact, unsigned int &offset)
{
    const VecIndex& indices = points.getValue();
    const VecReal& k = stiffness.getValue();
    const int N = Coord::static_size;

    unsigned int curIndex = 0;

    if (k.size()!= indices.size() )
    {
        for (unsigned int index = 0; index < indices.size(); index++)
        {
            curIndex = indices[index];

            for(int i = 0; i < N; i++)
            {

                //	for (unsigned int j = 0; j < N; j++)
                //	{
                //		mat->add(offset + N * curIndex + i, offset + N * curIndex + j, kFact * k[0]);
                //	}

                mat->add(offset + N * curIndex + i, offset + N * curIndex + i, kFact * k[0]);
            }
        }
    }
    else
    {
        for (unsigned int index = 0; index < indices.size(); index++)
        {
            curIndex = indices[index];

            for(int i = 0; i < N; i++)
            {

                //	for (unsigned int j = 0; j < N; j++)
                //	{
                //		mat->add(offset + N * curIndex + i, offset + N * curIndex + j, kFact * k[curIndex]);
                //	}

                mat->add(offset + N * curIndex + i, offset + N * curIndex + i, kFact * k[curIndex]);
            }
        }
    }
}

//template <class DataTypes>
//double RestShapeSpringsForceField<DataTypes>::getPotentialEnergy(const VecCoord& x)
//{
//	const VecIndex& indices = points.getValue();
//	const VecDeriv& f = forces.getValue();
//	double e=0;
//	unsigned int i = 0;
//	for (; i<f.size(); i++)
//	{
//		e -= f[i]*x[indices[i]];
//	}
//	for (; i<indices.size(); i++)
//	{
//		e -= f[f.size()-1]*x[indices[i]];
//	}
//	return e;
//}

//template <class DataTypes>
//void RestShapeSpringsForceField<DataTypes>::setForce( unsigned i, const Deriv& force )
//{
//	VecIndex& indices = *points.beginEdit();
//	VecDeriv& f = *forces.beginEdit();
//	indices.push_back(i);
//	f.push_back( force );
//	points.endEdit();
//	forces.endEdit();
//}

template<class DataTypes>
void RestShapeSpringsForceField<DataTypes>::draw()
{
    /*
    if (!getContext()->getShowForceFields())
    	return;  /// \todo put this in the parent class
    const VecIndex& indices = points.getValue();
    const VecDeriv& f = forces.getValue();
    const VecCoord& x = *this->mstate->getX();
    glDisable(GL_LIGHTING);
    glBegin(GL_LINES);
    glColor3f(0,1,0);
    for (unsigned int i=0; i<indices.size(); i++)
    {
    	Real xx,xy,xz,fx,fy,fz;
    	DataTypes::get(xx,xy,xz,x[indices[i]]);
    	DataTypes::get(fx,fy,fz,f[(i<f.size()) ? i : f.size()-1]);
    	glVertex3f( (GLfloat)xx, (GLfloat)xy, (GLfloat)xz );
    	glVertex3f( (GLfloat)(xx+fx), (GLfloat)(xy+fy), (GLfloat)(xz+fz) );
    }
    glEnd();
    */
}

template <class DataTypes>
bool RestShapeSpringsForceField<DataTypes>::addBBox(double*, double* )
{
    return false;
}

} // namespace forcefield

} // namespace component

} // namespace sofa

#endif

<|endoftext|>


<commit_before>
#pragma once

#include "exceptions.hh"

template <typename ELEMENT>
class FixedVector {
public:
  FixedVector(int capacity) throw(ArgumentException) {
    if (capacity <= 0)
      throw ArgumentException("capacity must be positive");

    _capacity = capacity;
    _array = new ELEMENT[_capacity];
  }

  ~FixedVector() {
    delete [] _array;
  }

  int capacity() { return _capacity; }

  ELEMENT get(int index) {
    check_index(index);
    return _array[index];
  }

  void set(int index, ELEMENT value) {
    check_index(index);
    _array[index] = value;
  }

private:
  int _capacity;
  ELEMENT* _array;

  void check_index(int i) {
    if ((i < 0) || (i >= _capacity))
      throw IndexException(_capacity, i);
  }
};
<commit_msg>whitespace formatting<commit_after>
#pragma once

#include "exceptions.hh"

template <typename ELEMENT>
class FixedVector {
public:
  FixedVector(int capacity) throw(ArgumentException) {
    if (capacity <= 0)
      throw ArgumentException("capacity must be positive");

    _capacity = capacity;
    _array = new ELEMENT[_capacity];
  }

  ~FixedVector() {
    delete [] _array;
  }

  int capacity() {
    return _capacity;
  }

  ELEMENT get(int index) {
    check_index(index);
    return _array[index];
  }

  void set(int index, ELEMENT value) {
    check_index(index);
    _array[index] = value;
  }

private:
  int _capacity;
  ELEMENT* _array;

  void check_index(int i) {
    if ((i < 0) || (i >= _capacity))
      throw IndexException(_capacity, i);
  }
};
<|endoftext|>


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

#include "boost/format.hpp"

#include "PRM/PRM_Default.h"
#include "PRM/PRM_Template.h"

#include "IECore/CompoundObject.h"
#include "IECore/VectorTypedData.h"

#include "Convert.h"
#include "ToHoudiniAttribConverter.h"
#include "SOP_InterpolatedCacheReader.h"

using namespace IECore;
using namespace IECoreHoudini;

static PRM_Name parameterNames[] = {
	PRM_Name( "cacheSequence", "Cache Sequence" ),
	PRM_Name( "objectFixes", "Object Prefix/Suffix" ),
	PRM_Name( "attributeFixes", "Attribute Prefix/Suffix" ),
	PRM_Name( "frameMultiplier", "Frame Multiplier" ),
};

static PRM_Default frameMultiplierDefault( 1 );

PRM_Template SOP_InterpolatedCacheReader::parameters[] = {
	PRM_Template( PRM_FILE, 1, &parameterNames[0] ),
	PRM_Template( PRM_STRING, 2, &parameterNames[1] ),
	PRM_Template( PRM_STRING, 2, &parameterNames[2] ),
	PRM_Template( PRM_INT, 1, &parameterNames[3], &frameMultiplierDefault ),
	PRM_Template(),
};

SOP_InterpolatedCacheReader::SOP_InterpolatedCacheReader( OP_Network *net, const char *name, OP_Operator *op )
	: SOP_Node( net, name, op ), m_cache( 0 ), m_cacheFileName(), m_frameMultiplier( -1 )
{
	flags().setTimeDep( true );
}

SOP_InterpolatedCacheReader::~SOP_InterpolatedCacheReader()
{
}

OP_Node *SOP_InterpolatedCacheReader::create( OP_Network *net, const char *name, OP_Operator *op )
{
	return new SOP_InterpolatedCacheReader( net, name, op );
}

OP_ERROR SOP_InterpolatedCacheReader::cookMySop( OP_Context &context )
{
	flags().setTimeDep( true );

	if ( lockInputs( context ) >= UT_ERROR_ABORT )
	{
		return error();
	}

	gdp->stashAll();

	duplicatePointSource( 0, context );

	float time = context.getTime();
	float frame = context.getFloatFrame();

	UT_String paramVal;

	evalString( paramVal, "cacheSequence", 0, time );
	std::string cacheFileName = paramVal.toStdString();

	evalString( paramVal, "objectFixes", 0, time );
	std::string objectPrefix = paramVal.toStdString();
	evalString( paramVal, "objectFixes", 1, time );
	std::string objectSuffix = paramVal.toStdString();

	evalString( paramVal, "attributeFixes", 0, time );
	std::string attributePrefix = paramVal.toStdString();
	evalString( paramVal, "attributeFixes", 1, time );
	std::string attributeSuffix = paramVal.toStdString();

	int frameMultiplier = evalInt( "frameMultiplier", 0, time );

	// create the InterpolatedCache
	if ( cacheFileName.compare( m_cacheFileName ) != 0 || frameMultiplier != m_frameMultiplier )
	{
		try
		{
			OversamplesCalculator calc( 24.0, 1, 24 * frameMultiplier );
			m_cache = new InterpolatedCache( cacheFileName, InterpolatedCache::Linear, calc );
		}
		catch ( IECore::InvalidArgumentException e )
		{
			addError( SOP_ATTRIBUTE_INVALID, e.what() );
			unlockInputs();
			return error();
		}

		m_cacheFileName = cacheFileName;
		m_frameMultiplier = frameMultiplier;
	}

	if ( !m_cache )
	{
		addWarning( SOP_MESSAGE, "SOP_InterpolatedCacheReader: Cache Sequence not found" );
		unlockInputs();
		return error();
	}

	std::vector<InterpolatedCache::ObjectHandle> objects;
	std::vector<InterpolatedCache::AttributeHandle> attrs;

	try
	{
		m_cache->objects( frame, objects );
	}
	catch ( IECore::Exception e )
	{
		addError( SOP_ATTRIBUTE_INVALID, e.what() );
		unlockInputs();
		return error();
	}

	GB_Group *group;
	const GB_GroupList &pointGroups = gdp->pointGroups();
	for ( group=pointGroups.head(); group; group = (GB_Group *)group->next() )
	{
		if ( !group->entries() )
		{
			continue;
		}

		// match GB_PointGroup name to InterpolatedCache::ObjectHandle
		std::string searchName = objectPrefix + group->getName().toStdString() + objectSuffix;
		std::vector<InterpolatedCache::ObjectHandle>::iterator oIt = find( objects.begin(), objects.end(), searchName );
		if ( oIt == objects.end() )
		{
			continue;
		}

		// gather the points for this group
		GEO_PointList points;
		for ( GEO_Point *p = gdp->points().head( *(GB_PointGroup*)group ); p; p = gdp->points().next( p, *(GB_PointGroup*)group ) )
		{
			points.append( p );
		}

		CompoundObjectPtr attributes = 0;

		try
		{
			m_cache->attributes( frame, *oIt, attrs );
			attributes = m_cache->read( frame, *oIt );
		}
		catch ( IECore::Exception e )
		{
			addError( SOP_ATTRIBUTE_INVALID, e.what() );
			unlockInputs();
			return error();
		}

		const CompoundObject::ObjectMap &attributeMap = attributes->members();

		// transfer the InterpolatedCache::Attributes onto the GB_PointGroup
		/// \todo: this does not account for detail, prim, or vertex attribs...
		for ( CompoundObject::ObjectMap::const_iterator aIt=attributeMap.begin(); aIt != attributeMap.end(); aIt++ )
		{
			const Data *data = IECore::runTimeCast<const Data>( aIt->second );
			if ( !data )
			{
				continue;
			}

			ToHoudiniAttribConverterPtr converter = ToHoudiniAttribConverter::create( data );
			if ( !converter )
 			{
 				continue;
 			}

			// strip the prefix/suffix from the GB_Attribute name
			std::string attrName = aIt->first.value();
			size_t prefixLength = attributePrefix.length();
			if ( prefixLength && ( search( attrName.begin(), attrName.begin()+prefixLength, attributePrefix.begin(), attributePrefix.end() ) == attrName.begin() ) )
			{
				attrName.erase( attrName.begin(), attrName.begin() + prefixLength );
			}

			size_t suffixLength = attributeSuffix.length();
			if ( suffixLength && ( search( attrName.end() - suffixLength, attrName.end(), attributeSuffix.begin(), attributeSuffix.end() ) == ( attrName.end() - suffixLength ) ) )
			{
				attrName.erase( attrName.end() - suffixLength, attrName.end() );
			}

			if ( attrName == "P" )
			{
				const V3fVectorData *positions = IECore::runTimeCast<const V3fVectorData>( data );
				if ( !positions )
				{
					converter->convert( attrName, gdp, &points );
					continue;
				}

				const std::vector<Imath::V3f> &pos = positions->readable();
				if ( pos.size() != points.entries() )
				{
					addError( SOP_ATTRIBUTE_INVALID, ( boost::format( "Geometry/Cache mismatch: Geometry contains %d points, while cache expects %d." ) % points.entries() % pos.size() ).str().c_str() );
					unlockInputs();
					return error();
				}

				for ( size_t i=0; i < pos.size(); i++ )
				{
					points[i]->setPos( IECore::convert<UT_Vector3>( pos[i] ) );
				}
			}
			else
			{
				converter->convert( attrName, gdp, &points );
			}
		}
	}

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

#include "boost/format.hpp"

#include "OP/OP_Director.h"
#include "PRM/PRM_Default.h"
#include "PRM/PRM_Template.h"

#include "IECore/CompoundObject.h"
#include "IECore/VectorTypedData.h"

#include "Convert.h"
#include "ToHoudiniAttribConverter.h"
#include "SOP_InterpolatedCacheReader.h"

using namespace IECore;
using namespace IECoreHoudini;

static PRM_Name parameterNames[] = {
	PRM_Name( "cacheSequence", "Cache Sequence" ),
	PRM_Name( "objectFixes", "Object Prefix/Suffix" ),
	PRM_Name( "attributeFixes", "Attribute Prefix/Suffix" ),
	PRM_Name( "frameMultiplier", "Frame Multiplier" ),
};

static PRM_Default frameMultiplierDefault( 1 );

PRM_Template SOP_InterpolatedCacheReader::parameters[] = {
	PRM_Template( PRM_FILE, 1, &parameterNames[0] ),
	PRM_Template( PRM_STRING, 2, &parameterNames[1] ),
	PRM_Template( PRM_STRING, 2, &parameterNames[2] ),
	PRM_Template( PRM_INT, 1, &parameterNames[3], &frameMultiplierDefault ),
	PRM_Template(),
};

SOP_InterpolatedCacheReader::SOP_InterpolatedCacheReader( OP_Network *net, const char *name, OP_Operator *op )
	: SOP_Node( net, name, op ), m_cache( 0 ), m_cacheFileName(), m_frameMultiplier( -1 )
{
	flags().setTimeDep( true );
}

SOP_InterpolatedCacheReader::~SOP_InterpolatedCacheReader()
{
}

OP_Node *SOP_InterpolatedCacheReader::create( OP_Network *net, const char *name, OP_Operator *op )
{
	return new SOP_InterpolatedCacheReader( net, name, op );
}

OP_ERROR SOP_InterpolatedCacheReader::cookMySop( OP_Context &context )
{
	flags().setTimeDep( true );

	if ( lockInputs( context ) >= UT_ERROR_ABORT )
	{
		return error();
	}

	gdp->stashAll();

	duplicatePointSource( 0, context );

	float time = context.getTime();
	float frame = context.getFloatFrame();

	UT_String paramVal;

	evalString( paramVal, "cacheSequence", 0, time );
	std::string cacheFileName = paramVal.toStdString();

	evalString( paramVal, "objectFixes", 0, time );
	std::string objectPrefix = paramVal.toStdString();
	evalString( paramVal, "objectFixes", 1, time );
	std::string objectSuffix = paramVal.toStdString();

	evalString( paramVal, "attributeFixes", 0, time );
	std::string attributePrefix = paramVal.toStdString();
	evalString( paramVal, "attributeFixes", 1, time );
	std::string attributeSuffix = paramVal.toStdString();

	int frameMultiplier = evalInt( "frameMultiplier", 0, time );

	// create the InterpolatedCache
	if ( cacheFileName.compare( m_cacheFileName ) != 0 || frameMultiplier != m_frameMultiplier )
	{
		try
		{
			float fps = OPgetDirector()->getChannelManager()->getSamplesPerSec();
			OversamplesCalculator calc( fps, 1, (int)fps * frameMultiplier );
			m_cache = new InterpolatedCache( cacheFileName, InterpolatedCache::Linear, calc );
		}
		catch ( IECore::InvalidArgumentException e )
		{
			addError( SOP_ATTRIBUTE_INVALID, e.what() );
			unlockInputs();
			return error();
		}

		m_cacheFileName = cacheFileName;
		m_frameMultiplier = frameMultiplier;
	}

	if ( !m_cache )
	{
		addWarning( SOP_MESSAGE, "SOP_InterpolatedCacheReader: Cache Sequence not found" );
		unlockInputs();
		return error();
	}

	std::vector<InterpolatedCache::ObjectHandle> objects;
	std::vector<InterpolatedCache::AttributeHandle> attrs;

	try
	{
		m_cache->objects( frame, objects );
	}
	catch ( IECore::Exception e )
	{
		addError( SOP_ATTRIBUTE_INVALID, e.what() );
		unlockInputs();
		return error();
	}

	GB_Group *group;
	const GB_GroupList &pointGroups = gdp->pointGroups();
	for ( group=pointGroups.head(); group; group = (GB_Group *)group->next() )
	{
		if ( !group->entries() )
		{
			continue;
		}

		// match GB_PointGroup name to InterpolatedCache::ObjectHandle
		std::string searchName = objectPrefix + group->getName().toStdString() + objectSuffix;
		std::vector<InterpolatedCache::ObjectHandle>::iterator oIt = find( objects.begin(), objects.end(), searchName );
		if ( oIt == objects.end() )
		{
			continue;
		}

		// gather the points for this group
		GEO_PointList points;
		for ( GEO_Point *p = gdp->points().head( *(GB_PointGroup*)group ); p; p = gdp->points().next( p, *(GB_PointGroup*)group ) )
		{
			points.append( p );
		}

		CompoundObjectPtr attributes = 0;

		try
		{
			m_cache->attributes( frame, *oIt, attrs );
			attributes = m_cache->read( frame, *oIt );
		}
		catch ( IECore::Exception e )
		{
			addError( SOP_ATTRIBUTE_INVALID, e.what() );
			unlockInputs();
			return error();
		}

		const CompoundObject::ObjectMap &attributeMap = attributes->members();

		// transfer the InterpolatedCache::Attributes onto the GB_PointGroup
		/// \todo: this does not account for detail, prim, or vertex attribs...
		for ( CompoundObject::ObjectMap::const_iterator aIt=attributeMap.begin(); aIt != attributeMap.end(); aIt++ )
		{
			const Data *data = IECore::runTimeCast<const Data>( aIt->second );
			if ( !data )
			{
				continue;
			}

			ToHoudiniAttribConverterPtr converter = ToHoudiniAttribConverter::create( data );
			if ( !converter )
 			{
 				continue;
 			}

			// strip the prefix/suffix from the GB_Attribute name
			std::string attrName = aIt->first.value();
			size_t prefixLength = attributePrefix.length();
			if ( prefixLength && ( search( attrName.begin(), attrName.begin()+prefixLength, attributePrefix.begin(), attributePrefix.end() ) == attrName.begin() ) )
			{
				attrName.erase( attrName.begin(), attrName.begin() + prefixLength );
			}

			size_t suffixLength = attributeSuffix.length();
			if ( suffixLength && ( search( attrName.end() - suffixLength, attrName.end(), attributeSuffix.begin(), attributeSuffix.end() ) == ( attrName.end() - suffixLength ) ) )
			{
				attrName.erase( attrName.end() - suffixLength, attrName.end() );
			}

			if ( attrName == "P" )
			{
				const V3fVectorData *positions = IECore::runTimeCast<const V3fVectorData>( data );
				if ( !positions )
				{
					converter->convert( attrName, gdp, &points );
					continue;
				}

				const std::vector<Imath::V3f> &pos = positions->readable();
				if ( pos.size() != points.entries() )
				{
					addError( SOP_ATTRIBUTE_INVALID, ( boost::format( "Geometry/Cache mismatch: Geometry contains %d points, while cache expects %d." ) % points.entries() % pos.size() ).str().c_str() );
					unlockInputs();
					return error();
				}

				for ( size_t i=0; i < pos.size(); i++ )
				{
					points[i]->setPos( IECore::convert<UT_Vector3>( pos[i] ) );
				}
			}
			else
			{
				converter->convert( attrName, gdp, &points );
			}
		}
	}

	unlockInputs();
	return error();
}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
//------------------------------------------------------------------------------

#include "DeclCollector.h"

#include "cling/Interpreter/Transaction.h"

#include "clang/AST/Decl.h"
#include "clang/AST/DeclGroup.h"

using namespace clang;

namespace cling {

  // pin the vtable here.
  DeclCollector::~DeclCollector() {
  }

  bool DeclCollector::HandleTopLevelDecl(DeclGroupRef DGR) {
    m_CurTransaction->appendUnique(DGR);
    return true;
  }

  void DeclCollector::HandleInterestingDecl(DeclGroupRef DGR) {
    assert("Not implemented yet!");
  }

  // Does more than we want:
  // if there is class A {enum E {kEnum = 1};};
  // we get two different tag decls one for A and one for E. This is not that
  // bad because esentially it has no effect on codegen but it differs from what
  // one'd expect. For now rely on the HandleTopLevelDecl to provide all the
  // declarations in the transaction.
  void DeclCollector::HandleTagDeclDefinition(TagDecl* TD) {
    // Intentional no-op.
  }

  void DeclCollector::HandleVTable(CXXRecordDecl* RD, bool DefinitionRequired) {
    assert(0 && "Not implemented yet!");
  }

  void DeclCollector::CompleteTentativeDefinition(VarDecl* VD) {
    assert(0 && "Not implemented yet!");
  }

  void DeclCollector::HandleTranslationUnit(ASTContext& Ctx) {
  }
} // namespace cling
<commit_msg>HandleVTable assert is far too intrusive to stay.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
//------------------------------------------------------------------------------

#include "DeclCollector.h"

#include "cling/Interpreter/Transaction.h"

#include "clang/AST/Decl.h"
#include "clang/AST/DeclGroup.h"

using namespace clang;

namespace cling {

  // pin the vtable here.
  DeclCollector::~DeclCollector() {
  }

  bool DeclCollector::HandleTopLevelDecl(DeclGroupRef DGR) {
    m_CurTransaction->appendUnique(DGR);
    return true;
  }

  void DeclCollector::HandleInterestingDecl(DeclGroupRef DGR) {
    assert(0 && "Not implemented yet!");
  }

  // Does more than we want:
  // if there is class A {enum E {kEnum = 1};};
  // we get two different tag decls one for A and one for E. This is not that
  // bad because esentially it has no effect on codegen but it differs from what
  // one'd expect. For now rely on the HandleTopLevelDecl to provide all the
  // declarations in the transaction.
  void DeclCollector::HandleTagDeclDefinition(TagDecl* TD) {
    // Intentional no-op.
  }

  void DeclCollector::HandleVTable(CXXRecordDecl* RD, bool DefinitionRequired) {
    // Intentional no-op. It comes through Sema::DefineUsedVTables, which
    // comes either Sema::ActOnEndOfTranslationUnit or while instantiating a
    // template. In our case we will do it on transaction commit, without
    // keeping track of used vtables, because we have cases where we bypass the
    // clang/AST and directly ask the module so that we have to generate
    // everything without extra smartness.
  }

  void DeclCollector::CompleteTentativeDefinition(VarDecl* VD) {
    assert(0 && "Not implemented yet!");
  }

  void DeclCollector::HandleTranslationUnit(ASTContext& Ctx) {
  }
} // namespace cling
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief Aql, query context
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2014 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "Aql/Query.h"
#include "Aql/ExecutionBlock.h"
#include "Aql/ExecutionEngine.h"
#include "Aql/ExecutionPlan.h"
#include "Aql/Executor.h"
#include "Aql/Parser.h"
#include "Aql/ExecutionEngine.h"
#include "Aql/Optimizer.h"
#include "Basics/JsonHelper.h"
#include "BasicsC/json.h"
#include "BasicsC/tri-strings.h"
#include "Utils/AqlTransaction.h"
#include "Utils/Exception.h"
#include "Utils/V8TransactionContext.h"
#include "VocBase/vocbase.h"

using namespace triagens::aql;

// -----------------------------------------------------------------------------
// --SECTION--                                        constructors / destructors
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief creates a query
////////////////////////////////////////////////////////////////////////////////

Query::Query (TRI_vocbase_t* vocbase,
              char const* queryString,
              size_t queryLength,
              TRI_json_t* bindParameters,
              TRI_json_t* options)
  : _vocbase(vocbase),
    _executor(nullptr),
    _queryString(queryString),
    _queryLength(queryLength),
    _queryJson(),
    _type(AQL_QUERY_READ),
    _bindParameters(bindParameters),
    _options(options),
    _collections(vocbase),
    _strings() {

  TRI_ASSERT(_vocbase != nullptr);

  _strings.reserve(32);
}

Query::Query (TRI_vocbase_t* vocbase,
              triagens::basics::Json queryStruct,
              QueryType Type)
  : _vocbase(vocbase),
    _executor(nullptr),
    _queryString(nullptr),
    _queryLength(0),
    _queryJson(queryStruct),
    _type(Type),
    _bindParameters(nullptr),
    _collections(vocbase),
    _strings() {

  TRI_ASSERT(_vocbase != nullptr);

  _strings.reserve(32);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief destroys a query
////////////////////////////////////////////////////////////////////////////////

Query::~Query () {
  if (_options != nullptr) {
    TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, _options);
  }

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

  // free strings
  for (auto it = _strings.begin(); it != _strings.end(); ++it) {
    TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, const_cast<char*>(*it));
  }
}

// -----------------------------------------------------------------------------
// --SECTION--                                                    public methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief extract a region from the query
////////////////////////////////////////////////////////////////////////////////

std::string Query::extractRegion (int line,
                                  int column) const {
  // note: line numbers reported by bison/flex start at 1, columns start at 0
  int currentLine   = 1;
  int currentColumn = 0;

  char c;
  char const* p = _queryString;

  while ((c = *p)) {
    if (currentLine > line ||
        (currentLine >= line && currentColumn >= column)) {
      break;
    }

    if (c == '\n') {
      ++p;
      ++currentLine;
      currentColumn = 0;
    }
    else if (c == '\r') {
      ++p;
      ++currentLine;
      currentColumn = 0;

      // eat a following newline
      if (*p == '\n') {
        ++p;
      }
    }
    else {
      ++currentColumn;
      ++p;
    }
  }

  // p is pointing at the position in the query the parse error occurred at
  TRI_ASSERT(p >= _queryString);

  size_t offset = static_cast<size_t>(p - _queryString);

  static int const   SNIPPET_LENGTH = 32;
  static char const* SNIPPET_SUFFIX = "...";

  if (_queryLength < offset + SNIPPET_LENGTH) {
    // return a copy of the region
    return std::string(_queryString + offset, _queryLength - offset);
  }

  // copy query part
  std::string result(_queryString + offset, SNIPPET_LENGTH);
  result.append(SNIPPET_SUFFIX);

  return result;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief register an error
////////////////////////////////////////////////////////////////////////////////

void Query::registerError (int code,
                           char const* details) {

  TRI_ASSERT(code != TRI_ERROR_NO_ERROR);

  if (details == nullptr) {
    THROW_ARANGO_EXCEPTION(code);
  }
  else {
    THROW_ARANGO_EXCEPTION_PARAMS(code, details);
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief execute an AQL query
////////////////////////////////////////////////////////////////////////////////

QueryResult Query::execute () {
  try {
    ExecutionPlan* plan;
    Parser parser(this);

    if (_queryString != nullptr) {
      parser.parse();
      // put in bind parameters
      parser.ast()->injectBindParameters(_bindParameters);
      // optimize the ast
      parser.ast()->optimize();
      // std::cout << "AST: " << triagens::basics::JsonHelper::toString(parser.ast()->toJson(TRI_UNKNOWN_MEM_ZONE, false)) << "\n";
    }

    // create the transaction object, but do not start it yet
    AQL_TRANSACTION_V8 trx(_vocbase, _collections.collections());

    if (_queryString != nullptr) {
      // we have an AST
      int res = trx.begin();

      if (res != TRI_ERROR_NO_ERROR) {
        return QueryResult(res, TRI_errno_string(res));
      }

      plan = ExecutionPlan::instanciateFromAst(parser.ast());
      if (plan == nullptr) {
        // oops
        return QueryResult(TRI_ERROR_INTERNAL);
      }
    }
    else {
      // we have an execution plan in JSON format
      plan = ExecutionPlan::instanciateFromJson(parser.ast(), _queryJson);
      if (plan == nullptr) {
        // oops
        return QueryResult(TRI_ERROR_INTERNAL);
      }

      // creating the plan may have produced some collections
      // we need to add them to the transaction now (otherwise the query will fail)
      trx.addCollections(_collections.collections());

      int res = trx.begin();

      if (res != TRI_ERROR_NO_ERROR) {
        return QueryResult(res, TRI_errno_string(res));
      }
    }

    // Run the query optimiser:
    triagens::aql::Optimizer opt;
    opt.createPlans(plan, std::vector<std::string>());
    // Now plan and all derived plans belong to the optimizer
    plan = opt.stealBest(); // Now we own the best one again
    TRI_ASSERT(plan != nullptr);
    /* // for debugging of serialisation/deserialisation . . .
    auto JsonPlan = plan->toJson(TRI_UNKNOWN_MEM_ZONE, true);
    auto JsonString = JsonPlan.toString();
    std::cout << "original plan: \n" << JsonString << "\n";

    auto otherPlan = ExecutionPlan::instanciateFromJson (parser.ast(),
                                                         JsonPlan);
    otherPlan->getCost();
    auto otherJsonString =
      otherPlan->toJson(TRI_UNKNOWN_MEM_ZONE, true).toString();
    std::cout << "deserialised plan: \n" << otherJsonString << "\n";
    TRI_ASSERT(otherJsonString == JsonString);*/

    triagens::basics::Json json(triagens::basics::Json::List);
    triagens::basics::Json stats;

    try {
      auto engine = ExecutionEngine::instanciateFromPlan(&trx, plan);

      try {
        AqlItemBlock* value;

        while (nullptr != (value = engine->getSome(1, ExecutionBlock::DefaultBatchSize))) {
          auto doc = value->getDocumentCollection(0);
          size_t const n = value->size();
          for (size_t i = 0; i < n; ++i) {
            AqlValue val = value->getValue(i, 0);

            if (! val.isEmpty()) {
              json.add(val.toJson(&trx, doc));
            }
          }
          delete value;
        }

        stats = engine->_stats.toJson();

        delete engine;
      }
      catch (...) {
        delete engine;
        throw;
      }
    }
    catch (...) {
      delete plan;
      throw;
    }

    delete plan;
    trx.commit();

    QueryResult result(TRI_ERROR_NO_ERROR);
    result.json  = json.steal();
    result.stats = stats.steal();
    return result;
  }
  catch (triagens::arango::Exception const& ex) {
    return QueryResult(ex.code(), ex.message());
  }
  catch (std::bad_alloc const& ex) {
    return QueryResult(TRI_ERROR_OUT_OF_MEMORY, TRI_errno_string(TRI_ERROR_OUT_OF_MEMORY));
  }
  catch (std::exception const& ex) {
    return QueryResult(TRI_ERROR_INTERNAL, ex.what());
  }
  catch (...) {
    return QueryResult(TRI_ERROR_INTERNAL, TRI_errno_string(TRI_ERROR_INTERNAL));
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief parse an AQL query
////////////////////////////////////////////////////////////////////////////////

QueryResult Query::parse () {
  try {
    Parser parser(this);
    return parser.parse();
  }
  catch (triagens::arango::Exception const& ex) {
    return QueryResult(ex.code(), ex.message());
  }
  catch (...) {
    return QueryResult(TRI_ERROR_OUT_OF_MEMORY, TRI_errno_string(TRI_ERROR_OUT_OF_MEMORY));
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief explain an AQL query
////////////////////////////////////////////////////////////////////////////////

QueryResult Query::explain () {
  try {
    ExecutionPlan* plan;
    Parser parser(this);

    parser.parse();
    // put in bind parameters
    parser.ast()->injectBindParameters(_bindParameters);
    // optimize the ast
    parser.ast()->optimize();
    // std::cout << "AST: " << triagens::basics::JsonHelper::toString(parser.ast()->toJson(TRI_UNKNOWN_MEM_ZONE)) << "\n";

    // create the transaction object, but do not start it yet
    AQL_TRANSACTION_V8 trx(_vocbase, _collections.collections());

    // we have an AST
    int res = trx.begin();

    if (res != TRI_ERROR_NO_ERROR) {
      return QueryResult(res, TRI_errno_string(res));
    }

    plan = ExecutionPlan::instanciateFromAst(parser.ast());
    if (plan == nullptr) {
      // oops
      return QueryResult(TRI_ERROR_INTERNAL);
    }

    // Run the query optimiser:
    triagens::aql::Optimizer opt;

    // get enabled/disabled rules
    std::vector<std::string> rules(getRulesFromOptions());

    opt.createPlans(plan, rules);
    // Now plan and all derived plans belong to the optimizer
    plan = opt.stealBest(); // Now we own the best one again
    TRI_ASSERT(plan != nullptr);

    trx.commit();

    QueryResult result(TRI_ERROR_NO_ERROR);
    result.json = plan->toJson(TRI_UNKNOWN_MEM_ZONE, false).steal(); //json();

    delete plan;

    return result;
  }
  catch (triagens::arango::Exception const& ex) {
    return QueryResult(ex.code(), ex.message());
  }
  catch (std::bad_alloc const& ex) {
    return QueryResult(TRI_ERROR_OUT_OF_MEMORY, TRI_errno_string(TRI_ERROR_OUT_OF_MEMORY));
  }
  catch (std::exception const& ex) {
    return QueryResult(TRI_ERROR_INTERNAL, ex.what());
  }
  catch (...) {
    return QueryResult(TRI_ERROR_INTERNAL, TRI_errno_string(TRI_ERROR_INTERNAL));
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get v8 executor
////////////////////////////////////////////////////////////////////////////////

Executor* Query::executor () {
  if (_executor == nullptr) {
    // the executor is a singleton per query
    _executor = new Executor;
  }

  TRI_ASSERT(_executor != nullptr);
  return _executor;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief register a string
/// the string is freed when the query is destroyed
////////////////////////////////////////////////////////////////////////////////

char* Query::registerString (char const* p,
                             size_t length,
                             bool mustUnescape) {

  if (p == nullptr) {
    THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
  }

  if (length == 0) {
    static char const* empty = "";
    // optimisation for the empty string
    return const_cast<char*>(empty);
  }

  char* copy = nullptr;
  if (mustUnescape) {
    size_t outLength;
    copy = TRI_UnescapeUtf8StringZ(TRI_UNKNOWN_MEM_ZONE, p, length, &outLength);
  }
  else {
    copy = TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, p, length);
  }

  if (copy == nullptr) {
    THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
  }

  try {
    _strings.push_back(copy);
  }
  catch (...) {
    THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
  }

  return copy;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief register a string
/// the string is freed when the query is destroyed
////////////////////////////////////////////////////////////////////////////////

char* Query::registerString (std::string const& p,
                             bool mustUnescape) {

  return registerString(p.c_str(), p.length(), mustUnescape);
}

// -----------------------------------------------------------------------------
// --SECTION--                                                   private methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief read the "optimizer.rules" section from the options
////////////////////////////////////////////////////////////////////////////////

std::vector<std::string> Query::getRulesFromOptions () const {
  std::vector<std::string> rules;

  if (TRI_IsArrayJson(_options)) {
    TRI_json_t const* optJson = TRI_LookupArrayJson(_options, "optimizer");

    if (TRI_IsArrayJson(optJson)) {
      TRI_json_t const* rulesJson = TRI_LookupArrayJson(optJson, "rules");

      if (TRI_IsListJson(rulesJson)) {
        size_t const n = TRI_LengthListJson(rulesJson);

        for (size_t i = 0; i < n; ++i) {
          TRI_json_t const* rule = static_cast<TRI_json_t const*>(TRI_AtVector(&rulesJson->_value._objects, i));

          if (TRI_IsStringJson(rule)) {
            rules.emplace_back(rule->_value._string.data, rule->_value._string.length - 1);
          }
        }
      }
    }
  }

  return rules;
}

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<commit_msg>added optimizer flags for AQL_EXECUTE<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief Aql, query context
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2014 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "Aql/Query.h"
#include "Aql/ExecutionBlock.h"
#include "Aql/ExecutionEngine.h"
#include "Aql/ExecutionPlan.h"
#include "Aql/Executor.h"
#include "Aql/Parser.h"
#include "Aql/ExecutionEngine.h"
#include "Aql/Optimizer.h"
#include "Basics/JsonHelper.h"
#include "BasicsC/json.h"
#include "BasicsC/tri-strings.h"
#include "Utils/AqlTransaction.h"
#include "Utils/Exception.h"
#include "Utils/V8TransactionContext.h"
#include "VocBase/vocbase.h"

using namespace triagens::aql;

// -----------------------------------------------------------------------------
// --SECTION--                                        constructors / destructors
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief creates a query
////////////////////////////////////////////////////////////////////////////////

Query::Query (TRI_vocbase_t* vocbase,
              char const* queryString,
              size_t queryLength,
              TRI_json_t* bindParameters,
              TRI_json_t* options)
  : _vocbase(vocbase),
    _executor(nullptr),
    _queryString(queryString),
    _queryLength(queryLength),
    _queryJson(),
    _type(AQL_QUERY_READ),
    _bindParameters(bindParameters),
    _options(options),
    _collections(vocbase),
    _strings() {

  TRI_ASSERT(_vocbase != nullptr);

  _strings.reserve(32);
}

Query::Query (TRI_vocbase_t* vocbase,
              triagens::basics::Json queryStruct,
              QueryType Type)
  : _vocbase(vocbase),
    _executor(nullptr),
    _queryString(nullptr),
    _queryLength(0),
    _queryJson(queryStruct),
    _type(Type),
    _bindParameters(nullptr),
    _collections(vocbase),
    _strings() {

  TRI_ASSERT(_vocbase != nullptr);

  _strings.reserve(32);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief destroys a query
////////////////////////////////////////////////////////////////////////////////

Query::~Query () {
  if (_options != nullptr) {
    TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, _options);
  }

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

  // free strings
  for (auto it = _strings.begin(); it != _strings.end(); ++it) {
    TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, const_cast<char*>(*it));
  }
}

// -----------------------------------------------------------------------------
// --SECTION--                                                    public methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief extract a region from the query
////////////////////////////////////////////////////////////////////////////////

std::string Query::extractRegion (int line,
                                  int column) const {
  // note: line numbers reported by bison/flex start at 1, columns start at 0
  int currentLine   = 1;
  int currentColumn = 0;

  char c;
  char const* p = _queryString;

  while ((c = *p)) {
    if (currentLine > line ||
        (currentLine >= line && currentColumn >= column)) {
      break;
    }

    if (c == '\n') {
      ++p;
      ++currentLine;
      currentColumn = 0;
    }
    else if (c == '\r') {
      ++p;
      ++currentLine;
      currentColumn = 0;

      // eat a following newline
      if (*p == '\n') {
        ++p;
      }
    }
    else {
      ++currentColumn;
      ++p;
    }
  }

  // p is pointing at the position in the query the parse error occurred at
  TRI_ASSERT(p >= _queryString);

  size_t offset = static_cast<size_t>(p - _queryString);

  static int const   SNIPPET_LENGTH = 32;
  static char const* SNIPPET_SUFFIX = "...";

  if (_queryLength < offset + SNIPPET_LENGTH) {
    // return a copy of the region
    return std::string(_queryString + offset, _queryLength - offset);
  }

  // copy query part
  std::string result(_queryString + offset, SNIPPET_LENGTH);
  result.append(SNIPPET_SUFFIX);

  return result;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief register an error
////////////////////////////////////////////////////////////////////////////////

void Query::registerError (int code,
                           char const* details) {

  TRI_ASSERT(code != TRI_ERROR_NO_ERROR);

  if (details == nullptr) {
    THROW_ARANGO_EXCEPTION(code);
  }
  else {
    THROW_ARANGO_EXCEPTION_PARAMS(code, details);
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief execute an AQL query
////////////////////////////////////////////////////////////////////////////////

QueryResult Query::execute () {
  try {
    ExecutionPlan* plan;
    Parser parser(this);

    if (_queryString != nullptr) {
      parser.parse();
      // put in bind parameters
      parser.ast()->injectBindParameters(_bindParameters);
      // optimize the ast
      parser.ast()->optimize();
      // std::cout << "AST: " << triagens::basics::JsonHelper::toString(parser.ast()->toJson(TRI_UNKNOWN_MEM_ZONE, false)) << "\n";
    }

    // create the transaction object, but do not start it yet
    AQL_TRANSACTION_V8 trx(_vocbase, _collections.collections());

    if (_queryString != nullptr) {
      // we have an AST
      int res = trx.begin();

      if (res != TRI_ERROR_NO_ERROR) {
        return QueryResult(res, TRI_errno_string(res));
      }

      plan = ExecutionPlan::instanciateFromAst(parser.ast());
      if (plan == nullptr) {
        // oops
        return QueryResult(TRI_ERROR_INTERNAL);
      }
    }
    else {
      // we have an execution plan in JSON format
      plan = ExecutionPlan::instanciateFromJson(parser.ast(), _queryJson);
      if (plan == nullptr) {
        // oops
        return QueryResult(TRI_ERROR_INTERNAL);
      }

      // creating the plan may have produced some collections
      // we need to add them to the transaction now (otherwise the query will fail)
      trx.addCollections(_collections.collections());

      int res = trx.begin();

      if (res != TRI_ERROR_NO_ERROR) {
        return QueryResult(res, TRI_errno_string(res));
      }
    }

    // get enabled/disabled rules
    std::vector<std::string> rules(getRulesFromOptions());

    // Run the query optimiser:
    triagens::aql::Optimizer opt;
    opt.createPlans(plan, rules);

    // Now plan and all derived plans belong to the optimizer
    plan = opt.stealBest(); // Now we own the best one again
    TRI_ASSERT(plan != nullptr);
    /* // for debugging of serialisation/deserialisation . . .
    auto JsonPlan = plan->toJson(TRI_UNKNOWN_MEM_ZONE, true);
    auto JsonString = JsonPlan.toString();
    std::cout << "original plan: \n" << JsonString << "\n";

    auto otherPlan = ExecutionPlan::instanciateFromJson (parser.ast(),
                                                         JsonPlan);
    otherPlan->getCost();
    auto otherJsonString =
      otherPlan->toJson(TRI_UNKNOWN_MEM_ZONE, true).toString();
    std::cout << "deserialised plan: \n" << otherJsonString << "\n";
    TRI_ASSERT(otherJsonString == JsonString);*/

    triagens::basics::Json json(triagens::basics::Json::List);
    triagens::basics::Json stats;

    try {
      auto engine = ExecutionEngine::instanciateFromPlan(&trx, plan);

      try {
        AqlItemBlock* value;

        while (nullptr != (value = engine->getSome(1, ExecutionBlock::DefaultBatchSize))) {
          auto doc = value->getDocumentCollection(0);
          size_t const n = value->size();
          for (size_t i = 0; i < n; ++i) {
            AqlValue val = value->getValue(i, 0);

            if (! val.isEmpty()) {
              json.add(val.toJson(&trx, doc));
            }
          }
          delete value;
        }

        stats = engine->_stats.toJson();

        delete engine;
      }
      catch (...) {
        delete engine;
        throw;
      }
    }
    catch (...) {
      delete plan;
      throw;
    }

    delete plan;
    trx.commit();

    QueryResult result(TRI_ERROR_NO_ERROR);
    result.json  = json.steal();
    result.stats = stats.steal();
    return result;
  }
  catch (triagens::arango::Exception const& ex) {
    return QueryResult(ex.code(), ex.message());
  }
  catch (std::bad_alloc const& ex) {
    return QueryResult(TRI_ERROR_OUT_OF_MEMORY, TRI_errno_string(TRI_ERROR_OUT_OF_MEMORY));
  }
  catch (std::exception const& ex) {
    return QueryResult(TRI_ERROR_INTERNAL, ex.what());
  }
  catch (...) {
    return QueryResult(TRI_ERROR_INTERNAL, TRI_errno_string(TRI_ERROR_INTERNAL));
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief parse an AQL query
////////////////////////////////////////////////////////////////////////////////

QueryResult Query::parse () {
  try {
    Parser parser(this);
    return parser.parse();
  }
  catch (triagens::arango::Exception const& ex) {
    return QueryResult(ex.code(), ex.message());
  }
  catch (...) {
    return QueryResult(TRI_ERROR_OUT_OF_MEMORY, TRI_errno_string(TRI_ERROR_OUT_OF_MEMORY));
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief explain an AQL query
////////////////////////////////////////////////////////////////////////////////

QueryResult Query::explain () {
  try {
    ExecutionPlan* plan;
    Parser parser(this);

    parser.parse();
    // put in bind parameters
    parser.ast()->injectBindParameters(_bindParameters);
    // optimize the ast
    parser.ast()->optimize();
    // std::cout << "AST: " << triagens::basics::JsonHelper::toString(parser.ast()->toJson(TRI_UNKNOWN_MEM_ZONE)) << "\n";

    // create the transaction object, but do not start it yet
    AQL_TRANSACTION_V8 trx(_vocbase, _collections.collections());

    // we have an AST
    int res = trx.begin();

    if (res != TRI_ERROR_NO_ERROR) {
      return QueryResult(res, TRI_errno_string(res));
    }

    plan = ExecutionPlan::instanciateFromAst(parser.ast());
    if (plan == nullptr) {
      // oops
      return QueryResult(TRI_ERROR_INTERNAL);
    }

    // Run the query optimiser:
    triagens::aql::Optimizer opt;

    // get enabled/disabled rules
    std::vector<std::string> rules(getRulesFromOptions());

    opt.createPlans(plan, rules);
    // Now plan and all derived plans belong to the optimizer
    plan = opt.stealBest(); // Now we own the best one again
    TRI_ASSERT(plan != nullptr);

    trx.commit();

    QueryResult result(TRI_ERROR_NO_ERROR);
    result.json = plan->toJson(TRI_UNKNOWN_MEM_ZONE, false).steal(); //json();

    delete plan;

    return result;
  }
  catch (triagens::arango::Exception const& ex) {
    return QueryResult(ex.code(), ex.message());
  }
  catch (std::bad_alloc const& ex) {
    return QueryResult(TRI_ERROR_OUT_OF_MEMORY, TRI_errno_string(TRI_ERROR_OUT_OF_MEMORY));
  }
  catch (std::exception const& ex) {
    return QueryResult(TRI_ERROR_INTERNAL, ex.what());
  }
  catch (...) {
    return QueryResult(TRI_ERROR_INTERNAL, TRI_errno_string(TRI_ERROR_INTERNAL));
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get v8 executor
////////////////////////////////////////////////////////////////////////////////

Executor* Query::executor () {
  if (_executor == nullptr) {
    // the executor is a singleton per query
    _executor = new Executor;
  }

  TRI_ASSERT(_executor != nullptr);
  return _executor;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief register a string
/// the string is freed when the query is destroyed
////////////////////////////////////////////////////////////////////////////////

char* Query::registerString (char const* p,
                             size_t length,
                             bool mustUnescape) {

  if (p == nullptr) {
    THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
  }

  if (length == 0) {
    static char const* empty = "";
    // optimisation for the empty string
    return const_cast<char*>(empty);
  }

  char* copy = nullptr;
  if (mustUnescape) {
    size_t outLength;
    copy = TRI_UnescapeUtf8StringZ(TRI_UNKNOWN_MEM_ZONE, p, length, &outLength);
  }
  else {
    copy = TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, p, length);
  }

  if (copy == nullptr) {
    THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
  }

  try {
    _strings.push_back(copy);
  }
  catch (...) {
    THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
  }

  return copy;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief register a string
/// the string is freed when the query is destroyed
////////////////////////////////////////////////////////////////////////////////

char* Query::registerString (std::string const& p,
                             bool mustUnescape) {

  return registerString(p.c_str(), p.length(), mustUnescape);
}

// -----------------------------------------------------------------------------
// --SECTION--                                                   private methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief read the "optimizer.rules" section from the options
////////////////////////////////////////////////////////////////////////////////

std::vector<std::string> Query::getRulesFromOptions () const {
  std::vector<std::string> rules;

  if (TRI_IsArrayJson(_options)) {
    TRI_json_t const* optJson = TRI_LookupArrayJson(_options, "optimizer");

    if (TRI_IsArrayJson(optJson)) {
      TRI_json_t const* rulesJson = TRI_LookupArrayJson(optJson, "rules");

      if (TRI_IsListJson(rulesJson)) {
        size_t const n = TRI_LengthListJson(rulesJson);

        for (size_t i = 0; i < n; ++i) {
          TRI_json_t const* rule = static_cast<TRI_json_t const*>(TRI_AtVector(&rulesJson->_value._objects, i));

          if (TRI_IsStringJson(rule)) {
            rules.emplace_back(rule->_value._string.data, rule->_value._string.length - 1);
          }
        }
      }
    }
  }

  return rules;
}

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: registry.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 16:36:22 $
 *
 *  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 _REGISTRY_HXX_
#include "registry.hxx"
#endif

#include <assert.h>
#include <algorithm>

#pragma warning(disable : 4786)

//-----------------------------------------------------
/** Create instance and open the specified Registry key

    @throws  RegistryWriteAccessDenyException
             RegistryAccessDenyException
             RegistryKeyNotFoundException
*/
RegistryKeyImpl::RegistryKeyImpl(HKEY RootKey, const std::wstring& KeyName) :
    m_hRootKey(RootKey),
    m_hSubKey(0),
    m_KeyName(KeyName),
    m_IsWriteable(false)
{
}

//-----------------------------------------------------
/** Create instance and open the specified Registry key

    @throws  RegistryWriteAccessDenyException
             RegistryAccessDenyException
             RegistryKeyNotFoundException
*/
RegistryKeyImpl::RegistryKeyImpl(HKEY RootKey) :
    m_hRootKey(RootKey),
    m_hSubKey(0),
    m_IsWriteable(false)
{
}

//-----------------------------------------------------
/** Create an instances of the specified Registry key,
    the key is assumed to be already opened.
*/
RegistryKeyImpl::RegistryKeyImpl(HKEY RootKey, HKEY SubKey, const std::wstring& KeyName, bool Writeable) :
    m_hRootKey(RootKey),
    m_hSubKey(SubKey),
    m_KeyName(KeyName),
    m_IsWriteable(Writeable)
{
}

//-----------------------------------------------------
/**
*/
RegistryKeyImpl::~RegistryKeyImpl()
{
    if (IsOpen())
        Close();
}

//############################################
// Queries
//############################################

//-----------------------------------------------------
/** The name of the key at hand, maybe empty
    if this is any of the root keys
*/
std::wstring RegistryKeyImpl::GetName() const
{
    return m_KeyName;
}

//-----------------------------------------------------
/**
*/
bool RegistryKeyImpl::IsOpen() const
{
    return m_hSubKey != 0;
}

//-----------------------------------------------------
/** Is this one of the root keys
    HKEY_CLASSES_ROOT
    HKEY_CURRENT_USER
    etc.
*/
bool RegistryKeyImpl::IsRootKey() const
{
    return (0 == m_KeyName.length());
}

//-----------------------------------------------------
/** Do we have write access on the key at hand
*/
bool RegistryKeyImpl::IsWriteable() const
{
    return m_IsWriteable;
}

//-----------------------------------------------------
/** Convenience function to determine if the
    Registry key at hand has the specified
    value

    @precond IsOpen = true

    throws RegistryAccessDenyException
*/
bool RegistryKeyImpl::HasValue(const std::wstring& Name) const
{
    StringListPtr names = GetSubValueNames();

    StringList::iterator iter_end = names->end();
    StringList::iterator iter = std::find(names->begin(), iter_end, Name);

    return (iter != iter_end);
}

//-----------------------------------------------------
/** Convenience function to determine if the
    Registry key at hand has the specified
    sub-key

    @precond IsOpen = true

    throws RegistryAccessDenyException
*/
bool RegistryKeyImpl::HasSubKey(const std::wstring& Name) const
{
    StringListPtr names = GetSubKeyNames();

    StringList::iterator iter_end = names->end();
    StringList::iterator iter = std::find(names->begin(), iter_end, Name);

    return (iter != iter_end);
}

//-----------------------------------------------------
/**
*/
void RegistryKeyImpl::Close()
{
    LONG rc = RegCloseKey(m_hSubKey);
    assert(ERROR_SUCCESS == rc);

    m_hSubKey = 0;
    m_IsWriteable = false;
}

//-----------------------------------------------------
/** Copies the specified value from RegistryKey to
    the registry key at hand, if a value with this
    name already exist under the registry key at hand
    it will be overwritten

    @precond IsOpen = true
             IsWriteable = true
             RegistryKey.HasSubValue(Name) = true

    @throws RegistryIOException
            RegistryWriteAccessDeniedException
            RegistryValueNotFoundException
*/
void RegistryKeyImpl::CopyValue(const RegistryKey& RegistryKey, const std::wstring& Name)
{
    assert(RegistryKey->HasValue(Name));
    SetValue(RegistryKey->GetValue(Name));
    assert(HasValue(Name));
}

/** Copies the specified value from RegistryKey to
    the registry key at hand under a new name,
    if a value with this name already exist there
    it will be overwritten

    @precond IsOpen = true
             IsWriteable = true
             RegistryKey.HasSubValue(Name) = true

    @throws RegistryIOException
            RegistryWriteAccessDeniedException
            RegistryValueNotFoundException
*/
void RegistryKeyImpl::CopyValue(const RegistryKey& RegistryKey, const std::wstring& Name, const std::wstring& NewName)
{
    assert(RegistryKey->HasValue(Name));

    RegistryValue RegVal = RegistryKey->GetValue(Name);
    RegVal->SetName(NewName);
    SetValue(RegVal);

    assert(HasValue(NewName));
}
<commit_msg>INTEGRATION: CWS native34 (1.2.38); FILE MERGED 2005/12/22 13:25:42 is 1.2.38.1: #i57587# case insensitive registry search<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: registry.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: kz $ $Date: 2006-01-06 11:20: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 _REGISTRY_HXX_
#include "registry.hxx"
#endif

#include <Shlwapi.h>
#include <assert.h>
#include <algorithm>

#pragma warning(disable : 4786)

//-----------------------------------------------------
/** Create instance and open the specified Registry key

    @throws  RegistryWriteAccessDenyException
             RegistryAccessDenyException
             RegistryKeyNotFoundException
*/
RegistryKeyImpl::RegistryKeyImpl(HKEY RootKey, const std::wstring& KeyName) :
    m_hRootKey(RootKey),
    m_hSubKey(0),
    m_KeyName(KeyName),
    m_IsWriteable(false)
{
}

//-----------------------------------------------------
/** Create instance and open the specified Registry key

    @throws  RegistryWriteAccessDenyException
             RegistryAccessDenyException
             RegistryKeyNotFoundException
*/
RegistryKeyImpl::RegistryKeyImpl(HKEY RootKey) :
    m_hRootKey(RootKey),
    m_hSubKey(0),
    m_IsWriteable(false)
{
}

//-----------------------------------------------------
/** Create an instances of the specified Registry key,
    the key is assumed to be already opened.
*/
RegistryKeyImpl::RegistryKeyImpl(HKEY RootKey, HKEY SubKey, const std::wstring& KeyName, bool Writeable) :
    m_hRootKey(RootKey),
    m_hSubKey(SubKey),
    m_KeyName(KeyName),
    m_IsWriteable(Writeable)
{
}

//-----------------------------------------------------
/**
*/
RegistryKeyImpl::~RegistryKeyImpl()
{
    if (IsOpen())
        Close();
}

//############################################
// Queries
//############################################

//-----------------------------------------------------
/** The name of the key at hand, maybe empty
    if this is any of the root keys
*/
std::wstring RegistryKeyImpl::GetName() const
{
    return m_KeyName;
}

//-----------------------------------------------------
/**
*/
bool RegistryKeyImpl::IsOpen() const
{
    return m_hSubKey != 0;
}

//-----------------------------------------------------
/** Is this one of the root keys
    HKEY_CLASSES_ROOT
    HKEY_CURRENT_USER
    etc.
*/
bool RegistryKeyImpl::IsRootKey() const
{
    return (0 == m_KeyName.length());
}

//-----------------------------------------------------
/** Do we have write access on the key at hand
*/
bool RegistryKeyImpl::IsWriteable() const
{
    return m_IsWriteable;
}

//-----------------------------------------------------
/** Convenience function to determine if the
    Registry key at hand has the specified
    value

    @precond IsOpen = true

    throws RegistryAccessDenyException
*/
bool RegistryKeyImpl::HasValue(const std::wstring& Name) const
{
    StringListPtr names = GetSubValueNames();

    StringList::iterator iter_end = names->end();
    StringList::iterator iter = std::find(names->begin(), iter_end, Name);

    return (iter != iter_end);
}

struct CompareNamesCaseInsensitive
{
    CompareNamesCaseInsensitive(const std::wstring& Name) :
        name_(Name)
    {}

    bool operator() (const std::wstring& value)
    {
        return (0 == StrCmpI(value.c_str(), name_.c_str()));
    }

    std::wstring name_;
};

//-----------------------------------------------------
/** Convenience function to determine if the
    Registry key at hand has the specified
    sub-key

    @precond IsOpen = true

    throws RegistryAccessDenyException
*/
bool RegistryKeyImpl::HasSubKey(const std::wstring& Name) const
{
    StringListPtr names = GetSubKeyNames();

    StringList::iterator iter_end = names->end();
    StringList::iterator iter = std::find_if(names->begin(), iter_end, CompareNamesCaseInsensitive(Name));

    return (iter != iter_end);
}

//-----------------------------------------------------
/**
*/
void RegistryKeyImpl::Close()
{
    LONG rc = RegCloseKey(m_hSubKey);
    assert(ERROR_SUCCESS == rc);

    m_hSubKey = 0;
    m_IsWriteable = false;
}

//-----------------------------------------------------
/** Copies the specified value from RegistryKey to
    the registry key at hand, if a value with this
    name already exist under the registry key at hand
    it will be overwritten

    @precond IsOpen = true
             IsWriteable = true
             RegistryKey.HasSubValue(Name) = true

    @throws RegistryIOException
            RegistryWriteAccessDeniedException
            RegistryValueNotFoundException
*/
void RegistryKeyImpl::CopyValue(const RegistryKey& RegistryKey, const std::wstring& Name)
{
    assert(RegistryKey->HasValue(Name));
    SetValue(RegistryKey->GetValue(Name));
    assert(HasValue(Name));
}

/** Copies the specified value from RegistryKey to
    the registry key at hand under a new name,
    if a value with this name already exist there
    it will be overwritten

    @precond IsOpen = true
             IsWriteable = true
             RegistryKey.HasSubValue(Name) = true

    @throws RegistryIOException
            RegistryWriteAccessDeniedException
            RegistryValueNotFoundException
*/
void RegistryKeyImpl::CopyValue(const RegistryKey& RegistryKey, const std::wstring& Name, const std::wstring& NewName)
{
    assert(RegistryKey->HasValue(Name));

    RegistryValue RegVal = RegistryKey->GetValue(Name);
    RegVal->SetName(NewName);
    SetValue(RegVal);

    assert(HasValue(NewName));
}
<|endoftext|>