<commit_before>/******************************************************************************
  2016 SVPA Flood Sensor Prototype Firmware
  by Tom Sayles <TSayles@Soot-n-Smoke.com>

*******************************************************************************/
#include "checkUpdateOTA.h"

STARTUP(System.enableFeature(FEATURE_RETAINED_MEMORY));

retained int nextUpdateCheck;
int updateDelayOTA = 60000; //miliseconds, aka 1 minute
int updateCadanceOTA = 25; //hours, aka once per day

int runTimeAdjSec = -118; // adjustment time from wake-up to publish

void checkUpdateOTA(){
  //@TODO Add routine to ensure that OTA updates are receivable once per day.

  //Check the current time
  int nowTime = Time.now();

  // Set time zone to Pacific USA standard time
  Time.zone(-8);

  if (nextUpdateCheck < nowTime){
    // Wait for an over the air update
    nextUpdateCheck = nowTime + (updateCadanceOTA * 3600);

    Particle.publish("UpdateOTA:",
      "Wait for next OTA Update after: " + Time.format(nextUpdateCheck, TIME_FORMAT_DEFAULT)
      );

    delay(updateDelayOTA);

  } else {
    //@TODO Comment this publish event, once done debugging
    Particle.publish("UpdateOTA:",
      "Next OTA Update planned after: " + Time.format(nextUpdateCheck, TIME_FORMAT_DEFAULT)
      );

  }

};

long getSecUntilUpdate(){
  //Publish data events only once every 15 minutes

  int minute = 0;
  int nextPublishTime = 0;
  long secUntilUpdate = 900; // aka 15 minutes

  //Check the current time, in minutes
  minute = Time.minute();
  //@TODO Fix time check to account for runTimeAdjSec

  // Compute the next publish time
  //@TODO Refactor to work with an actual target time
  //@TODO Impliment runTimeAdjSec
  if (minute > 45) {
    minute = minute - 60;
    nextPublishTime = 0;
  } else if (minute > 30) {
    nextPublishTime = 45;
  } else if (minute > 15) {
    nextPublishTime = 30;
  } else if (minute > 0) {
    nextPublishTime = 15;
  }

  // compute the number of minuted until the next publish time
  secUntilUpdate = (nextPublishTime - minute) * 60;

  //@TODO Adjust secUntilUpdate by a random amount to reduce network contention

  return secUntilUpdate;
};
<commit_msg>Debugged and tuned getSecUntilUpdate based on testing<commit_after>/******************************************************************************
  2016 SVPA Flood Sensor Prototype Firmware
  by Tom Sayles <TSayles@Soot-n-Smoke.com>

*******************************************************************************/
#include "checkUpdateOTA.h"

STARTUP(System.enableFeature(FEATURE_RETAINED_MEMORY));

retained int nextUpdateCheck;
int updateDelayOTA = 60000; //miliseconds, aka 1 minute
int updateCadanceOTA = 25; //hours, aka once per day

int runTimeAdjSec = -60; // adjustment time from wake-up to publish

void checkUpdateOTA(){
  //@TODO Add routine to ensure that OTA updates are receivable once per day.

  //Check the current time
  int nowTime = Time.now();

  // Set time zone to Pacific USA standard time
  Time.zone(-8);

  if (nextUpdateCheck < nowTime){
    // Wait for an over the air update
    nextUpdateCheck = nowTime + (updateCadanceOTA * 3600);

    Particle.publish("UpdateOTA:",
      "Wait for next OTA Update after: " + Time.format(nextUpdateCheck, TIME_FORMAT_DEFAULT)
      );

    delay(updateDelayOTA);

  } else {
    //@TODO Comment this publish event, once done debugging
    Particle.publish("UpdateOTA:",
      "Next OTA Update planned after: " + Time.format(nextUpdateCheck, TIME_FORMAT_DEFAULT)
      );

  }

};

long getSecUntilUpdate(){
  //Publish data events only once every 15 minutes

  int minute = 0;
  int nextPublishTime = 0;
  long secUntilUpdate = 900; // aka 15 minutes

  //Check the current time, in minutes
  minute = Time.minute() + 2;
  //@TODO Fix time check to account for runTimeAdjSec

  // Compute the next publish time
  //@TODO Refactor to work with an actual target time
  //@TODO Impliment runTimeAdjSec
  if (minute > 45) {
    minute = minute - 60;
    nextPublishTime = 0;
  } else if (minute > 30) {
    nextPublishTime = 45;
  } else if (minute > 15) {
    nextPublishTime = 30;
  } else if (minute > 0) {
    nextPublishTime = 15;
  }

  // compute the number of minuted until the next publish time
  secUntilUpdate = ((nextPublishTime - minute) * 60) + runTimeAdjSec;

  //@TODO Adjust secUntilUpdate by a random amount to reduce network contention

  // check that getSecUntilUpdate is in a reasonable range 60 to 3600 seconds
  if (secUntilUpdate < 60){secUntilUpdate = 60;}
  if (secUntilUpdate > 3600){secUntilUpdate = 3600;}

  return secUntilUpdate;
};
<|endoftext|>


<commit_before>/**
 * Clever programming language
 * Copyright (c) Clever Team
 *
 * This file is distributed under the MIT license. See LICENSE for details.
 */

#include <fstream>
#include "core/value.h"
#include "core/clever.h"
#include "modules/std/file/cfile.h"
#include "types/type.h"
#include "modules/std/core/function.h"

// @TODO(muriloadriano): make this available and use in all Clever API
#define CLEVER_CAST(Type, obj) (static_cast<Type*>(obj))

using ::std::fstream;

namespace clever { namespace packages { namespace std {

namespace detail {

// Given a mode string returns the according ios flag
::std::ios::openmode convert_open_mode(const CString& mode)
{
	// @TODO(muriloadriano): support binary modes.
	if (mode == "r") {
		return ::std::ios_base::in;
	} else if (mode == "w") {
		return ::std::ios_base::out | ::std::ios_base::trunc;
	} else if (mode == "a") {
		return ::std::ios_base::out | ::std::ios_base::app;
	} else if (mode == "r+") {
		return ::std::ios_base::in | ::std::ios_base::out;
	} else if (mode == "w+") {
		return ::std::ios_base::in | ::std::ios_base::out |
				::std::ios_base::trunc;
	} else if (mode == "a+") {
		return ::std::ios_base::in | ::std::ios_base::out |
				::std::ios_base::app;
	} else {
		// @TODO(muriloadriano): return some kind of error here.
		return ::std::ios_base::in;
	}
}

}

void CFile::dump(const void* data) const
{
	dump(data, ::std::cout);
}

void CFile::dump(const void* data, ::std::ostream& out) const
{
	out << "File class (" << data << ")";
}

// File.new(string fileName, string openMode)
void* CFile::allocData(CLEVER_TYPE_CTOR_ARGS) const
{
	// @TODO(muriloadriano): allow object construction with a single argument
	// and check the argument's type.
	return new fstream(args->at(0)->getStr()->c_str(),
		static_cast< ::std::ios_base::openmode>(args->at(1)->getInt()));
}

void CFile::deallocData(CLEVER_TYPE_DTOR_ARGS)
{
	delete CLEVER_CAST(fstream*, data);
}

CLEVER_METHOD(CFile::ctor)
{
	if (!clever_check_args("si")) {
		return;
	}

	result->setObj(this, allocData(&args));
}

// string File.read()
// Return the next token from the current stream
CLEVER_METHOD(CFile::read)
{
	if (!clever_check_no_args()) {
		return;
	}

	fstream* file = CLEVER_GET_OBJECT(fstream*, CLEVER_THIS());

	CString* token = new CString;
	*file >> *token;

	result->setStr(token);
}

// string File.readLine()
// Return the contents from the current positon until the next line
CLEVER_METHOD(CFile::readLine)
{
	if (!clever_check_no_args()) {
		return;
	}

	fstream* file = CLEVER_GET_OBJECT(fstream*, CLEVER_THIS());

	CString* token = new CString;
	::std::getline(*file, *token);

	result->setStr(token);
}

// void File.write(String)
// Return the contents from the current positon until the next line
// TODO(muriloadriano): allow use other primitive types as argument
CLEVER_METHOD(CFile::write)
{
	if (!clever_check_args("s")) {
		return;
	}

	fstream* file = CLEVER_GET_OBJECT(fstream*, CLEVER_THIS());

	*file << *(args[0]->getStr());
}

// void File.open(string fileName, Int openMode)
CLEVER_METHOD(CFile::open)
{
	if (!clever_check_args("si")) {
		return;
	}

	fstream* file = CLEVER_GET_OBJECT(fstream*, CLEVER_THIS());

	file->open(args[0]->getStr()->c_str(),
		static_cast< ::std::ios_base::openmode>(args[1]->getInt()));
}

// void File.close()
CLEVER_METHOD(CFile::close)
{
	if (!clever_check_no_args()) {
		return;
	}

	fstream* file = CLEVER_GET_OBJECT(fstream*, CLEVER_THIS());
	file->close();
}

// bool File.isOpen()
CLEVER_METHOD(CFile::isOpen)
{
	if (!clever_check_no_args()) {
		return;
	}

	fstream* file = CLEVER_GET_OBJECT(fstream*, CLEVER_THIS());
	result->setBool(file->is_open());
}

CLEVER_TYPE_INIT(CFile::init)
{
	Function* ctor = new Function("File", (MethodPtr)&CFile::ctor);

	setConstructor(ctor);
	addMethod(ctor);
	addMethod(new Function("read",		(MethodPtr)&CFile::read));
	addMethod(new Function("readLine",	(MethodPtr)&CFile::readLine));
	addMethod(new Function("write",		(MethodPtr)&CFile::write));
	addMethod(new Function("open",		(MethodPtr)&CFile::open));
	addMethod(new Function("close",		(MethodPtr)&CFile::close));
	addMethod(new Function("isOpen",	(MethodPtr)&CFile::isOpen));

	addProperty(CSTRING("IN"), new Value(long(::std::ios_base::in), true));
	addProperty(CSTRING("OUT"), new Value(long(::std::ios_base::out), true));
	addProperty(CSTRING("TRUNC"),
		new Value(long(::std::ios_base::trunc), true));
	addProperty(CSTRING("APP"), new Value(long(::std::ios_base::app), true));
	addProperty(CSTRING("ATE"), new Value(long(::std::ios_base::ate), true));
	addProperty(CSTRING("BIN"), new Value(long(::std::ios_base::binary), true));
}

}}} // clever::packages::std
<commit_msg>- Cosmetics<commit_after>/**
 * Clever programming language
 * Copyright (c) Clever Team
 *
 * This file is distributed under the MIT license. See LICENSE for details.
 */

#include <fstream>
#include "core/value.h"
#include "core/clever.h"
#include "modules/std/file/cfile.h"
#include "types/type.h"
#include "modules/std/core/function.h"

// @TODO(muriloadriano): make this available and use in all Clever API
#define CLEVER_CAST(Type, obj) (static_cast<Type*>(obj))

using ::std::fstream;

namespace clever { namespace packages { namespace std {

namespace detail {

// Given a mode string returns the according ios flag
::std::ios::openmode convert_open_mode(const CString& mode)
{
	// @TODO(muriloadriano): support binary modes.
	if (mode == "r") {
		return ::std::ios_base::in;
	} else if (mode == "w") {
		return ::std::ios_base::out | ::std::ios_base::trunc;
	} else if (mode == "a") {
		return ::std::ios_base::out | ::std::ios_base::app;
	} else if (mode == "r+") {
		return ::std::ios_base::in | ::std::ios_base::out;
	} else if (mode == "w+") {
		return ::std::ios_base::in | ::std::ios_base::out |
				::std::ios_base::trunc;
	} else if (mode == "a+") {
		return ::std::ios_base::in | ::std::ios_base::out |
				::std::ios_base::app;
	} else {
		// @TODO(muriloadriano): return some kind of error here.
		return ::std::ios_base::in;
	}
}

}

void CFile::dump(const void* data) const
{
	dump(data, ::std::cout);
}

void CFile::dump(const void* data, ::std::ostream& out) const
{
	out << "File class (" << data << ")";
}

// File.new(string fileName, string openMode)
void* CFile::allocData(CLEVER_TYPE_CTOR_ARGS) const
{
	// @TODO(muriloadriano): allow object construction with a single argument
	// and check the argument's type.
	return new fstream(args->at(0)->getStr()->c_str(),
		static_cast< ::std::ios_base::openmode>(args->at(1)->getInt()));
}

void CFile::deallocData(CLEVER_TYPE_DTOR_ARGS)
{
	delete CLEVER_CAST(fstream*, data);
}

CLEVER_METHOD(CFile::ctor)
{
	if (!clever_check_args("si")) {
		return;
	}

	result->setObj(this, allocData(&args));
}

// string File.read()
// Return the next token from the current stream
CLEVER_METHOD(CFile::read)
{
	if (!clever_check_no_args()) {
		return;
	}

	fstream* file = CLEVER_GET_OBJECT(fstream*, CLEVER_THIS());

	CString* token = new CString;
	*file >> *token;

	result->setStr(token);
}

// string File.readLine()
// Return the contents from the current positon until the next line
CLEVER_METHOD(CFile::readLine)
{
	if (!clever_check_no_args()) {
		return;
	}

	fstream* file = CLEVER_GET_OBJECT(fstream*, CLEVER_THIS());

	CString* token = new CString;
	::std::getline(*file, *token);

	result->setStr(token);
}

// void File.write(String)
// Return the contents from the current positon until the next line
// TODO(muriloadriano): allow use other primitive types as argument
CLEVER_METHOD(CFile::write)
{
	if (!clever_check_args("s")) {
		return;
	}

	fstream* file = CLEVER_GET_OBJECT(fstream*, CLEVER_THIS());

	*file << *(args[0]->getStr());
}

// void File.open(string fileName, Int openMode)
CLEVER_METHOD(CFile::open)
{
	if (!clever_check_args("si")) {
		return;
	}

	fstream* file = CLEVER_GET_OBJECT(fstream*, CLEVER_THIS());

	file->open(args[0]->getStr()->c_str(),
		static_cast< ::std::ios_base::openmode>(args[1]->getInt()));
}

// void File.close()
CLEVER_METHOD(CFile::close)
{
	if (!clever_check_no_args()) {
		return;
	}

	fstream* file = CLEVER_GET_OBJECT(fstream*, CLEVER_THIS());
	file->close();
}

// bool File.isOpen()
CLEVER_METHOD(CFile::isOpen)
{
	if (!clever_check_no_args()) {
		return;
	}

	fstream* file = CLEVER_GET_OBJECT(fstream*, CLEVER_THIS());
	result->setBool(file->is_open());
}

CLEVER_TYPE_INIT(CFile::init)
{
	Function* ctor = new Function("File", (MethodPtr)&CFile::ctor);

	setConstructor(ctor);
	addMethod(ctor);
	addMethod(new Function("read",		(MethodPtr)&CFile::read));
	addMethod(new Function("readLine",	(MethodPtr)&CFile::readLine));
	addMethod(new Function("write",		(MethodPtr)&CFile::write));
	addMethod(new Function("open",		(MethodPtr)&CFile::open));
	addMethod(new Function("close",		(MethodPtr)&CFile::close));
	addMethod(new Function("isOpen",	(MethodPtr)&CFile::isOpen));

	addProperty(CSTRING("IN"),    new Value(long(::std::ios_base::in),     true));
	addProperty(CSTRING("OUT"),   new Value(long(::std::ios_base::out),    true));
	addProperty(CSTRING("TRUNC"), new Value(long(::std::ios_base::trunc),  true));
	addProperty(CSTRING("APP"),   new Value(long(::std::ios_base::app),    true));
	addProperty(CSTRING("ATE"),   new Value(long(::std::ios_base::ate),    true));
	addProperty(CSTRING("BIN"),   new Value(long(::std::ios_base::binary), true));
}

}}} // clever::packages::std
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: spriteredrawmanager.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2006-05-04 07:47:27 $
 *
 *  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 INCLUDED_CANVAS_SPRITEREDRAWMANAGER_HXX
#define INCLUDED_CANVAS_SPRITEREDRAWMANAGER_HXX

#ifndef _BGFX_RANGE_B2DCONNECTEDRANGES_HXX
#include <basegfx/range/b2dconnectedranges.hxx>
#endif
#ifndef _BGFX_POINT_B2DPOINT_HXX
#include <basegfx/point/b2dpoint.hxx>
#endif
#ifndef _BGFX_VECTOR_B2DVECTOR_HXX
#include <basegfx/vector/b2dvector.hxx>
#endif
#ifndef _BGFX_RANGE_B2DRANGE_HXX
#include <basegfx/range/b2drange.hxx>
#endif
#ifndef _BGFX_RANGE_B2IRANGE_HXX
#include <basegfx/range/b2irange.hxx>
#endif
#ifndef _BGFX_MATRIX_B2DHOMMATRIX_HXX
#include <basegfx/matrix/b2dhommatrix.hxx>
#endif

#ifndef INCLUDED_CANVAS_SPRITESURFACE_HXX
#include <canvas/base/spritesurface.hxx>
#endif

#include <list>
#include <vector>
#include <algorithm>

#include <boost/utility.hpp>
#include <boost/bind.hpp>

/* Definition of SpriteRedrawManager class */

namespace canvas
{
    /** This class manages smooth SpriteCanvas updates

        Use this class to handle the ::canvas::SpriteSurface methods,
        that track and process sprite update events. Recorded update
        events are later grouped by connected areas (i.e. all sprites
        that somehow overlap over a rectangular area are grouped
        together); the forEachSpriteArea() method calls the passed
        functor for each of those connected areas.

        Note that, although this class generally works with IEEE
        doubles, the calculation of connected areas happens in the
        integer domain - it is generally expected that repaints can
        only be divided at pixel boundaries, without causing visible
        artifacts. Therefore, sprites that touch the same pixel (but
        don't necessarily have the same floating point coordinates
        there) will reside in a common sprite area and handled
        together in the forEachSpriteArea functor call.
     */
    class SpriteRedrawManager : private ::boost::noncopyable
    {
    public:
        /** Data container for the connected components list
         */
        class SpriteInfo
        {
        public:
            ~SpriteInfo() {}

            /** Create sprite info

                @param rRef
                Sprite this info represents (might be the NULL ref)

                @param rTrueUpdateArea
                True (un-rounded) update area this sprite has recorded

                @param bNeedsUpdate
                When false, this sprite is not a member of the change
                record list. Thus, it only needs redraw if within the
                update area of other, changed sprites.

                @internal
             */
            SpriteInfo( const Sprite::Reference&    rRef,
                        const ::basegfx::B2DRange&  rTrueUpdateArea,
                        bool                        bNeedsUpdate ) :
                mpSprite( rRef ),
                maTrueUpdateArea( rTrueUpdateArea ),
                mbNeedsUpdate( bNeedsUpdate ),
                mbIsPureMove( false )
            {
            }

            /** Create sprite info, specify move type

                @param rRef
                Sprite this info represents (might be the NULL ref)

                @param rTrueUpdateArea
                True (un-rounded) update area this sprite has recorded

                @param bNeedsUpdate
                When false, this sprite is not a member of the change
                record list. Thus, it only needs redraw if within the
                update area of other, changed sprites.

                @param bIsPureMove
                When true, this sprite is _only_ moved, no other
                changes happened.

                @internal
             */
            SpriteInfo( const Sprite::Reference&    rRef,
                        const ::basegfx::B2DRange&  rTrueUpdateArea,
                        bool                        bNeedsUpdate,
                        bool                        bIsPureMove ) :
                mpSprite( rRef ),
                maTrueUpdateArea( rTrueUpdateArea ),
                mbNeedsUpdate( bNeedsUpdate ),
                mbIsPureMove( bIsPureMove )
            {
            }

            const Sprite::Reference&    getSprite() const { return mpSprite; }

            // #i61843# need to return by value here, to be used safely from bind
            ::basegfx::B2DRange         getUpdateArea() const { return maTrueUpdateArea; }
            bool                        needsUpdate() const { return mbNeedsUpdate; }
            bool                        isPureMove() const { return mbIsPureMove; }

        private:
            Sprite::Reference       mpSprite;
            ::basegfx::B2DRange     maTrueUpdateArea;
            bool                    mbNeedsUpdate;
            bool                    mbIsPureMove;
        };

        /** Helper struct for SpriteTracer template

            This struct stores change information to a sprite's visual
            appearance (move, content updated, and the like).
         */
        struct SpriteChangeRecord
        {
            typedef enum{ none=0, move, update } ChangeType;

            SpriteChangeRecord() :
                meChangeType( none ),
                mpAffectedSprite(),
                maOldPos(),
                maUpdateArea()
            {
            }

            SpriteChangeRecord( const Sprite::Reference&    rSprite,
                                const ::basegfx::B2DPoint&  rOldPos,
                                const ::basegfx::B2DPoint&  rNewPos,
                                const ::basegfx::B2DVector& rSpriteSize ) :
                meChangeType( move ),
                mpAffectedSprite( rSprite ),
                maOldPos( rOldPos ),
                maUpdateArea( rNewPos.getX(),
                              rNewPos.getY(),
                              rNewPos.getX() + rSpriteSize.getX(),
                              rNewPos.getY() + rSpriteSize.getY() )
            {
            }

            SpriteChangeRecord( const Sprite::Reference&    rSprite,
                                const ::basegfx::B2DPoint&  rPos,
                                const ::basegfx::B2DRange&  rUpdateArea ) :
                meChangeType( update ),
                mpAffectedSprite( rSprite ),
                maOldPos( rPos ),
                maUpdateArea( rUpdateArea )
            {
            }

            Sprite::Reference getSprite() const { return mpAffectedSprite; }

            ChangeType          meChangeType;
            Sprite::Reference   mpAffectedSprite;
            ::basegfx::B2DPoint maOldPos;
            ::basegfx::B2DRange maUpdateArea;
        };

        typedef ::std::vector< SpriteChangeRecord >             VectorOfChangeRecords;
        typedef ::std::list< Sprite::Reference >                ListOfSprites;
        typedef ::basegfx::B2DConnectedRanges< SpriteInfo >     SpriteConnectedRanges;
        typedef SpriteConnectedRanges::ComponentType            AreaComponent;
        typedef SpriteConnectedRanges::ConnectedComponents      UpdateArea;
        typedef ::std::vector< Sprite::Reference >              VectorOfSprites;

        SpriteRedrawManager();

        /** Must be called when user of this object gets
            disposed. Frees all internal references.
         */
        void disposing();

        /** Functor, to be used from forEachSpriteArea
         */
        template< typename Functor > struct AreaUpdateCaller
        {
            AreaUpdateCaller( Functor&                      rFunc,
                              const SpriteRedrawManager&    rManager ) :
                mrFunc( rFunc ),
                mrManager( rManager )
            {
            }

            void operator()( const UpdateArea& rUpdateArea )
            {
                mrManager.handleArea( mrFunc, rUpdateArea );
            }

            Functor&                    mrFunc;
            const SpriteRedrawManager&  mrManager;
        };

        /** Call given functor for each sprite area that needs an
            update.

            This method calls the given functor for each update area
            (calculated from the sprite change records).

            @tpl Functor
            Must provide the following four methods:
            <pre>
            void backgroundPaint( ::basegfx::B2DRange aUpdateRect );
            void scrollUpdate( ::basegfx::B2DRange& o_rMoveStart,
                               ::basegfx::B2DRange& o_rMoveEnd,
                               UpdateArea           aUpdateArea );
            void opaqueUpdate( const ::basegfx::B2DRange&                          rTotalArea,
                               const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites );
            void genericUpdate( const ::basegfx::B2DRange&                          rTotalArea,
                                const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites );
            </pre>
            The backgroundPaint() method is called to simply repaint
            background content, the scrollUpdate() method is used to
            scroll a given area, and paint background in the uncovered
            areas, the opaqueUpdate() method is called when a sprite
            can be painted in the given area without taking background
            content into account, and finally, genericUpdate() is
            called for complex updates, where first the background and
            then all sprites consecutively have to be repainted.
         */
        template< typename Functor > void forEachSpriteArea( Functor& rFunc ) const
        {
            SpriteConnectedRanges aUpdateAreas;

            setupUpdateAreas( aUpdateAreas );

            aUpdateAreas.forEachAggregate(
                AreaUpdateCaller< Functor >( rFunc, *this ) );
        }

        /** Call given functor for each active sprite.

            This method calls the given functor for each active
            sprite, in the order of sprite priority.

            @tpl Functor
            Must provide a Functor::operator( Sprite::Reference& )
            method.
         */
        template< typename Functor > void forEachSprite( const Functor& rFunc ) const
        {
            ::std::for_each( maSprites.begin(),
                             maSprites.end(),
                             rFunc );
        }

        /// Clear sprite change records (typically directly after a screen update)
        void clearChangeRecords();

        // SpriteSurface interface, is delegated to e.g. from SpriteCanvas
        void showSprite( const Sprite::Reference& rSprite );
        void hideSprite( const Sprite::Reference& rSprite );
        void moveSprite( const Sprite::Reference&       rSprite,
                         const ::basegfx::B2DPoint&     rOldPos,
                         const ::basegfx::B2DPoint&     rNewPos,
                         const ::basegfx::B2DVector&    rSpriteSize );
        void updateSprite( const Sprite::Reference&     rSprite,
                           const ::basegfx::B2DPoint&   rPos,
                           const ::basegfx::B2DRange&   rUpdateArea );

        /** Internal, handles each distinct component for forEachAggregate()

            The reason why this must be public is that it needs to be
            accessible from the AreaUpdateCaller functor.

            @internal
         */
        template< typename Functor > void handleArea( Functor&          rFunc,
                                                      const UpdateArea& rUpdateArea ) const
        {
            // check whether this area contains changed sprites at all
            // (if not, just ignore it)
            if( areSpritesChanged( rUpdateArea ) )
            {
                // at least one of the sprites actually needs an
                // update - process whole area.

                // check whether this area could be handled special
                // (background paint, direct update, scroll, etc.)
                ::basegfx::B2DRange aMoveStart;
                ::basegfx::B2DRange aMoveEnd;
                if( rUpdateArea.maComponentList.empty() )
                {
                    rFunc.backgroundPaint( rUpdateArea.maTotalBounds );
                }
                else
                {
                    // cache number of sprites in this area (it's a
                    // list, and both isAreaUpdateScroll() and
                    // isAreaUpdateOpaque() need it).
                    const ::std::size_t nNumSprites(
                        rUpdateArea.maComponentList.size() );

                    if( isAreaUpdateScroll( aMoveStart,
                                            aMoveEnd,
                                            rUpdateArea,
                                            nNumSprites ) )
                    {
                        rFunc.scrollUpdate( aMoveStart,
                                            aMoveEnd,
                                            rUpdateArea );
                    }
                    else
                    {
                        // potentially, more than a single sprite
                        // involved. Have to sort component lists for
                        // sprite prio.
                        VectorOfSprites aSortedUpdateSprites;
                        SpriteConnectedRanges::ComponentListType::const_iterator aCurr(
                            rUpdateArea.maComponentList.begin() );
                        const SpriteConnectedRanges::ComponentListType::const_iterator aEnd(
                            rUpdateArea.maComponentList.end() );
                        while( aCurr != aEnd )
                        {
                            const Sprite::Reference& rSprite( aCurr->second.getSprite() );
                            if( rSprite.is() )
                                aSortedUpdateSprites.push_back( rSprite );

                            ++aCurr;
                        }

                        ::std::sort( aSortedUpdateSprites.begin(),
                                     aSortedUpdateSprites.end(),
                                     SpriteComparator() );

                        if( isAreaUpdateOpaque( rUpdateArea,
                                                nNumSprites ) )
                        {
                            rFunc.opaqueUpdate( rUpdateArea.maTotalBounds,
                                                aSortedUpdateSprites );
                        }
                        else
                        {
                            rFunc.genericUpdate( rUpdateArea.maTotalBounds,
                                                 aSortedUpdateSprites );
                        }
                    }
                }
            }
        }

    private:
        /** Central method of this class. Calculates the set of
            disjunct components that need an update.
         */
        void setupUpdateAreas( SpriteConnectedRanges& rUpdateAreas ) const;

        bool areSpritesChanged( const UpdateArea& rUpdateArea ) const;

        bool isAreaUpdateNotOpaque( const ::basegfx::B2DRange&  rUpdateRect,
                                    const AreaComponent&        rComponent ) const;

        bool isAreaUpdateOpaque( const UpdateArea&  rUpdateArea,
                                 ::std::size_t      nNumSprites ) const;

        /** Check whether given update area can be handled by a simple
            scroll

            @param o_rMoveStart
            Start rect of the move

            @param o_rMoveEnd
            End rect of the move. The content must be moved from start
            to end rect

            @param rUpdateArea
            Area to check for scroll update optimization
         */
        bool isAreaUpdateScroll( ::basegfx::B2DRange&   o_rMoveStart,
                                 ::basegfx::B2DRange&   o_rMoveEnd,
                                 const UpdateArea&      rUpdateArea,
                                 ::std::size_t          nNumSprites ) const;

        ListOfSprites                   maSprites; // list of active
                                                   // sprite
                                                   // objects. this
                                                   // list is only
                                                   // used for full
                                                   // repaints,
                                                   // otherwise, we
                                                   // rely on the
                                                   // active sprites
                                                   // itself to notify
                                                   // us.

        VectorOfChangeRecords           maChangeRecords; // vector of
                                                         // sprites
                                                         // changes
                                                         // since last
                                                         // updateScreen()
                                                         // call
    };
}

#endif /* INCLUDED_CANVAS_SPRITEREDRAWMANAGER_HXX */
<commit_msg>INTEGRATION: CWS changefileheader (1.4.112); FILE MERGED 2008/04/01 15:03:01 thb 1.4.112.3: #i85898# Stripping all external header guards 2008/04/01 10:49:24 thb 1.4.112.2: #i85898# Stripping all external header guards 2008/03/28 16:34:52 rt 1.4.112.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: spriteredrawmanager.hxx,v $
 * $Revision: 1.5 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef INCLUDED_CANVAS_SPRITEREDRAWMANAGER_HXX
#define INCLUDED_CANVAS_SPRITEREDRAWMANAGER_HXX

#include <basegfx/range/b2dconnectedranges.hxx>
#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/vector/b2dvector.hxx>
#include <basegfx/range/b2drange.hxx>
#include <basegfx/range/b2irange.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <canvas/base/spritesurface.hxx>

#include <list>
#include <vector>
#include <algorithm>

#include <boost/utility.hpp>
#include <boost/bind.hpp>

/* Definition of SpriteRedrawManager class */

namespace canvas
{
    /** This class manages smooth SpriteCanvas updates

        Use this class to handle the ::canvas::SpriteSurface methods,
        that track and process sprite update events. Recorded update
        events are later grouped by connected areas (i.e. all sprites
        that somehow overlap over a rectangular area are grouped
        together); the forEachSpriteArea() method calls the passed
        functor for each of those connected areas.

        Note that, although this class generally works with IEEE
        doubles, the calculation of connected areas happens in the
        integer domain - it is generally expected that repaints can
        only be divided at pixel boundaries, without causing visible
        artifacts. Therefore, sprites that touch the same pixel (but
        don't necessarily have the same floating point coordinates
        there) will reside in a common sprite area and handled
        together in the forEachSpriteArea functor call.
     */
    class SpriteRedrawManager : private ::boost::noncopyable
    {
    public:
        /** Data container for the connected components list
         */
        class SpriteInfo
        {
        public:
            ~SpriteInfo() {}

            /** Create sprite info

                @param rRef
                Sprite this info represents (might be the NULL ref)

                @param rTrueUpdateArea
                True (un-rounded) update area this sprite has recorded

                @param bNeedsUpdate
                When false, this sprite is not a member of the change
                record list. Thus, it only needs redraw if within the
                update area of other, changed sprites.

                @internal
             */
            SpriteInfo( const Sprite::Reference&    rRef,
                        const ::basegfx::B2DRange&  rTrueUpdateArea,
                        bool                        bNeedsUpdate ) :
                mpSprite( rRef ),
                maTrueUpdateArea( rTrueUpdateArea ),
                mbNeedsUpdate( bNeedsUpdate ),
                mbIsPureMove( false )
            {
            }

            /** Create sprite info, specify move type

                @param rRef
                Sprite this info represents (might be the NULL ref)

                @param rTrueUpdateArea
                True (un-rounded) update area this sprite has recorded

                @param bNeedsUpdate
                When false, this sprite is not a member of the change
                record list. Thus, it only needs redraw if within the
                update area of other, changed sprites.

                @param bIsPureMove
                When true, this sprite is _only_ moved, no other
                changes happened.

                @internal
             */
            SpriteInfo( const Sprite::Reference&    rRef,
                        const ::basegfx::B2DRange&  rTrueUpdateArea,
                        bool                        bNeedsUpdate,
                        bool                        bIsPureMove ) :
                mpSprite( rRef ),
                maTrueUpdateArea( rTrueUpdateArea ),
                mbNeedsUpdate( bNeedsUpdate ),
                mbIsPureMove( bIsPureMove )
            {
            }

            const Sprite::Reference&    getSprite() const { return mpSprite; }

            // #i61843# need to return by value here, to be used safely from bind
            ::basegfx::B2DRange         getUpdateArea() const { return maTrueUpdateArea; }
            bool                        needsUpdate() const { return mbNeedsUpdate; }
            bool                        isPureMove() const { return mbIsPureMove; }

        private:
            Sprite::Reference       mpSprite;
            ::basegfx::B2DRange     maTrueUpdateArea;
            bool                    mbNeedsUpdate;
            bool                    mbIsPureMove;
        };

        /** Helper struct for SpriteTracer template

            This struct stores change information to a sprite's visual
            appearance (move, content updated, and the like).
         */
        struct SpriteChangeRecord
        {
            typedef enum{ none=0, move, update } ChangeType;

            SpriteChangeRecord() :
                meChangeType( none ),
                mpAffectedSprite(),
                maOldPos(),
                maUpdateArea()
            {
            }

            SpriteChangeRecord( const Sprite::Reference&    rSprite,
                                const ::basegfx::B2DPoint&  rOldPos,
                                const ::basegfx::B2DPoint&  rNewPos,
                                const ::basegfx::B2DVector& rSpriteSize ) :
                meChangeType( move ),
                mpAffectedSprite( rSprite ),
                maOldPos( rOldPos ),
                maUpdateArea( rNewPos.getX(),
                              rNewPos.getY(),
                              rNewPos.getX() + rSpriteSize.getX(),
                              rNewPos.getY() + rSpriteSize.getY() )
            {
            }

            SpriteChangeRecord( const Sprite::Reference&    rSprite,
                                const ::basegfx::B2DPoint&  rPos,
                                const ::basegfx::B2DRange&  rUpdateArea ) :
                meChangeType( update ),
                mpAffectedSprite( rSprite ),
                maOldPos( rPos ),
                maUpdateArea( rUpdateArea )
            {
            }

            Sprite::Reference getSprite() const { return mpAffectedSprite; }

            ChangeType          meChangeType;
            Sprite::Reference   mpAffectedSprite;
            ::basegfx::B2DPoint maOldPos;
            ::basegfx::B2DRange maUpdateArea;
        };

        typedef ::std::vector< SpriteChangeRecord >             VectorOfChangeRecords;
        typedef ::std::list< Sprite::Reference >                ListOfSprites;
        typedef ::basegfx::B2DConnectedRanges< SpriteInfo >     SpriteConnectedRanges;
        typedef SpriteConnectedRanges::ComponentType            AreaComponent;
        typedef SpriteConnectedRanges::ConnectedComponents      UpdateArea;
        typedef ::std::vector< Sprite::Reference >              VectorOfSprites;

        SpriteRedrawManager();

        /** Must be called when user of this object gets
            disposed. Frees all internal references.
         */
        void disposing();

        /** Functor, to be used from forEachSpriteArea
         */
        template< typename Functor > struct AreaUpdateCaller
        {
            AreaUpdateCaller( Functor&                      rFunc,
                              const SpriteRedrawManager&    rManager ) :
                mrFunc( rFunc ),
                mrManager( rManager )
            {
            }

            void operator()( const UpdateArea& rUpdateArea )
            {
                mrManager.handleArea( mrFunc, rUpdateArea );
            }

            Functor&                    mrFunc;
            const SpriteRedrawManager&  mrManager;
        };

        /** Call given functor for each sprite area that needs an
            update.

            This method calls the given functor for each update area
            (calculated from the sprite change records).

            @tpl Functor
            Must provide the following four methods:
            <pre>
            void backgroundPaint( ::basegfx::B2DRange aUpdateRect );
            void scrollUpdate( ::basegfx::B2DRange& o_rMoveStart,
                               ::basegfx::B2DRange& o_rMoveEnd,
                               UpdateArea           aUpdateArea );
            void opaqueUpdate( const ::basegfx::B2DRange&                          rTotalArea,
                               const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites );
            void genericUpdate( const ::basegfx::B2DRange&                          rTotalArea,
                                const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites );
            </pre>
            The backgroundPaint() method is called to simply repaint
            background content, the scrollUpdate() method is used to
            scroll a given area, and paint background in the uncovered
            areas, the opaqueUpdate() method is called when a sprite
            can be painted in the given area without taking background
            content into account, and finally, genericUpdate() is
            called for complex updates, where first the background and
            then all sprites consecutively have to be repainted.
         */
        template< typename Functor > void forEachSpriteArea( Functor& rFunc ) const
        {
            SpriteConnectedRanges aUpdateAreas;

            setupUpdateAreas( aUpdateAreas );

            aUpdateAreas.forEachAggregate(
                AreaUpdateCaller< Functor >( rFunc, *this ) );
        }

        /** Call given functor for each active sprite.

            This method calls the given functor for each active
            sprite, in the order of sprite priority.

            @tpl Functor
            Must provide a Functor::operator( Sprite::Reference& )
            method.
         */
        template< typename Functor > void forEachSprite( const Functor& rFunc ) const
        {
            ::std::for_each( maSprites.begin(),
                             maSprites.end(),
                             rFunc );
        }

        /// Clear sprite change records (typically directly after a screen update)
        void clearChangeRecords();

        // SpriteSurface interface, is delegated to e.g. from SpriteCanvas
        void showSprite( const Sprite::Reference& rSprite );
        void hideSprite( const Sprite::Reference& rSprite );
        void moveSprite( const Sprite::Reference&       rSprite,
                         const ::basegfx::B2DPoint&     rOldPos,
                         const ::basegfx::B2DPoint&     rNewPos,
                         const ::basegfx::B2DVector&    rSpriteSize );
        void updateSprite( const Sprite::Reference&     rSprite,
                           const ::basegfx::B2DPoint&   rPos,
                           const ::basegfx::B2DRange&   rUpdateArea );

        /** Internal, handles each distinct component for forEachAggregate()

            The reason why this must be public is that it needs to be
            accessible from the AreaUpdateCaller functor.

            @internal
         */
        template< typename Functor > void handleArea( Functor&          rFunc,
                                                      const UpdateArea& rUpdateArea ) const
        {
            // check whether this area contains changed sprites at all
            // (if not, just ignore it)
            if( areSpritesChanged( rUpdateArea ) )
            {
                // at least one of the sprites actually needs an
                // update - process whole area.

                // check whether this area could be handled special
                // (background paint, direct update, scroll, etc.)
                ::basegfx::B2DRange aMoveStart;
                ::basegfx::B2DRange aMoveEnd;
                if( rUpdateArea.maComponentList.empty() )
                {
                    rFunc.backgroundPaint( rUpdateArea.maTotalBounds );
                }
                else
                {
                    // cache number of sprites in this area (it's a
                    // list, and both isAreaUpdateScroll() and
                    // isAreaUpdateOpaque() need it).
                    const ::std::size_t nNumSprites(
                        rUpdateArea.maComponentList.size() );

                    if( isAreaUpdateScroll( aMoveStart,
                                            aMoveEnd,
                                            rUpdateArea,
                                            nNumSprites ) )
                    {
                        rFunc.scrollUpdate( aMoveStart,
                                            aMoveEnd,
                                            rUpdateArea );
                    }
                    else
                    {
                        // potentially, more than a single sprite
                        // involved. Have to sort component lists for
                        // sprite prio.
                        VectorOfSprites aSortedUpdateSprites;
                        SpriteConnectedRanges::ComponentListType::const_iterator aCurr(
                            rUpdateArea.maComponentList.begin() );
                        const SpriteConnectedRanges::ComponentListType::const_iterator aEnd(
                            rUpdateArea.maComponentList.end() );
                        while( aCurr != aEnd )
                        {
                            const Sprite::Reference& rSprite( aCurr->second.getSprite() );
                            if( rSprite.is() )
                                aSortedUpdateSprites.push_back( rSprite );

                            ++aCurr;
                        }

                        ::std::sort( aSortedUpdateSprites.begin(),
                                     aSortedUpdateSprites.end(),
                                     SpriteComparator() );

                        if( isAreaUpdateOpaque( rUpdateArea,
                                                nNumSprites ) )
                        {
                            rFunc.opaqueUpdate( rUpdateArea.maTotalBounds,
                                                aSortedUpdateSprites );
                        }
                        else
                        {
                            rFunc.genericUpdate( rUpdateArea.maTotalBounds,
                                                 aSortedUpdateSprites );
                        }
                    }
                }
            }
        }

    private:
        /** Central method of this class. Calculates the set of
            disjunct components that need an update.
         */
        void setupUpdateAreas( SpriteConnectedRanges& rUpdateAreas ) const;

        bool areSpritesChanged( const UpdateArea& rUpdateArea ) const;

        bool isAreaUpdateNotOpaque( const ::basegfx::B2DRange&  rUpdateRect,
                                    const AreaComponent&        rComponent ) const;

        bool isAreaUpdateOpaque( const UpdateArea&  rUpdateArea,
                                 ::std::size_t      nNumSprites ) const;

        /** Check whether given update area can be handled by a simple
            scroll

            @param o_rMoveStart
            Start rect of the move

            @param o_rMoveEnd
            End rect of the move. The content must be moved from start
            to end rect

            @param rUpdateArea
            Area to check for scroll update optimization
         */
        bool isAreaUpdateScroll( ::basegfx::B2DRange&   o_rMoveStart,
                                 ::basegfx::B2DRange&   o_rMoveEnd,
                                 const UpdateArea&      rUpdateArea,
                                 ::std::size_t          nNumSprites ) const;

        ListOfSprites                   maSprites; // list of active
                                                   // sprite
                                                   // objects. this
                                                   // list is only
                                                   // used for full
                                                   // repaints,
                                                   // otherwise, we
                                                   // rely on the
                                                   // active sprites
                                                   // itself to notify
                                                   // us.

        VectorOfChangeRecords           maChangeRecords; // vector of
                                                         // sprites
                                                         // changes
                                                         // since last
                                                         // updateScreen()
                                                         // call
    };
}

#endif /* INCLUDED_CANVAS_SPRITEREDRAWMANAGER_HXX */
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkOptImageToImageMetricsTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "itkImage.h"
#include "itkTranslationTransform.h"
#include "itkAffineTransform.h"
#include "itkRigid2DTransform.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

#include "itkLinearInterpolateImageFunction.h"

#include "itkMeanSquaresImageToImageMetric.h"
#include "itkMattesMutualInformationImageToImageMetric.h"
#include "itkMutualInformationImageToImageMetric.h"
#include "itkMersenneTwisterRandomVariateGenerator.h"

#include "itkOptImageToImageMetricsTest.h"

int itkOptImageToImageMetricsTest(int , char* argv[])
{
#ifdef ITK_USE_OPTIMIZED_REGISTRATION_METHODS
  std::cout << "OPTIMIZED ON" << std::endl;
#else
  std::cout << "OPTIMIZED OFF" << std::endl;
#endif

  std::cout << "Default number of threads : "
            << itk::MultiThreader::GetGlobalDefaultNumberOfThreads()
            << std::endl;

  typedef itk::Image< unsigned int > FixedImageType;
  typedef itk::Image< unsigned int > MovingImageType;

  typedef itk::ImageFileReader< FixedImageType  > FixedImageReaderType;
  typedef itk::ImageFileReader< MovingImageType > MovingImageReaderType;

  FixedImageReaderType::Pointer  fixedImageReader  = FixedImageReaderType::New();
  MovingImageReaderType::Pointer movingImageReader = MovingImageReaderType::New();

  fixedImageReader->SetFileName(  argv[1] );
  movingImageReader->SetFileName( argv[2] );

  TranslationLinearTest( fixedImageReader.GetPointer(),
                    movingImageReader.GetPointer() );

  RigidLinearTest( fixedImageReader.GetPointer(),
                    movingImageReader.GetPointer() );

  AffineLinearTest( fixedImageReader.GetPointer(),
                    movingImageReader.GetPointer() );

#ifdef ITK_USE_OPTIMIZED_REGISTRATION_METHODS
  std::cout << "OPTIMIZED ON" << std::endl;
#else
  std::cout << "OPTIMIZED OFF" << std::endl;
#endif

  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  // DO EXPERIMENTS WITH NUMBER OF THREADS SET TO 1!!!
  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl;
  std::cout << "Running tests with : " << std::endl;
  std::cout << "\t itk::MultiThreader::SetGlobalDefaultNumberOfThreads(1); " << std::endl;
  std::cout << "\t itk::MultiThreader::SetGlobalMaximumNumberOfThreads(1); " << std::endl;
  std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl;
  std::cout << std::endl;

  itk::MultiThreader::SetGlobalDefaultNumberOfThreads(1);
  itk::MultiThreader::SetGlobalMaximumNumberOfThreads(1);

  TranslationLinearTest( fixedImageReader.GetPointer(),
                    movingImageReader.GetPointer() );

  RigidLinearTest( fixedImageReader.GetPointer(),
                    movingImageReader.GetPointer() );

  AffineLinearTest( fixedImageReader.GetPointer(),
                    movingImageReader.GetPointer() );

#ifdef ITK_USE_OPTIMIZED_REGISTRATION_METHODS
  std::cout << "OPTIMIZED ON" << std::endl;
#else
  std::cout << "OPTIMIZED OFF" << std::endl;
#endif

  return EXIT_SUCCESS;
}
<commit_msg>BUG: missing itk:: namespace qualifiers.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkOptImageToImageMetricsTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "itkImage.h"
#include "itkTranslationTransform.h"
#include "itkAffineTransform.h"
#include "itkRigid2DTransform.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

#include "itkLinearInterpolateImageFunction.h"

#include "itkMeanSquaresImageToImageMetric.h"
#include "itkMattesMutualInformationImageToImageMetric.h"
#include "itkMutualInformationImageToImageMetric.h"
#include "itkMersenneTwisterRandomVariateGenerator.h"

#include "itkOptImageToImageMetricsTest.h"

int itkOptImageToImageMetricsTest(int , char* argv[])
{
#ifdef ITK_USE_OPTIMIZED_REGISTRATION_METHODS
  std::cout << "OPTIMIZED ON" << std::endl;
#else
  std::cout << "OPTIMIZED OFF" << std::endl;
#endif

  std::cout << "Default number of threads : "
            << itk::MultiThreader::GetGlobalDefaultNumberOfThreads()
            << std::endl;

  typedef itk::Image< unsigned int > FixedImageType;
  typedef itk::Image< unsigned int > MovingImageType;

  typedef itk::ImageFileReader< FixedImageType  > FixedImageReaderType;
  typedef itk::ImageFileReader< MovingImageType > MovingImageReaderType;

  FixedImageReaderType::Pointer  fixedImageReader  = FixedImageReaderType::New();
  MovingImageReaderType::Pointer movingImageReader = MovingImageReaderType::New();

  fixedImageReader->SetFileName(  argv[1] );
  movingImageReader->SetFileName( argv[2] );

  itk::TranslationLinearTest( fixedImageReader.GetPointer(),
                              movingImageReader.GetPointer() );

  itk::RigidLinearTest( fixedImageReader.GetPointer(),
                        movingImageReader.GetPointer() );

  itk::AffineLinearTest( fixedImageReader.GetPointer(),
                         movingImageReader.GetPointer() );

#ifdef ITK_USE_OPTIMIZED_REGISTRATION_METHODS
  std::cout << "OPTIMIZED ON" << std::endl;
#else
  std::cout << "OPTIMIZED OFF" << std::endl;
#endif

  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  // DO EXPERIMENTS WITH NUMBER OF THREADS SET TO 1!!!
  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl;
  std::cout << "Running tests with : " << std::endl;
  std::cout << "\t itk::MultiThreader::SetGlobalDefaultNumberOfThreads(1); " << std::endl;
  std::cout << "\t itk::MultiThreader::SetGlobalMaximumNumberOfThreads(1); " << std::endl;
  std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl;
  std::cout << std::endl;

  itk::MultiThreader::SetGlobalDefaultNumberOfThreads(1);
  itk::MultiThreader::SetGlobalMaximumNumberOfThreads(1);

  itk::TranslationLinearTest( fixedImageReader.GetPointer(),
                              movingImageReader.GetPointer() );

  itk::RigidLinearTest( fixedImageReader.GetPointer(),
                        movingImageReader.GetPointer() );

  itk::AffineLinearTest( fixedImageReader.GetPointer(),
                         movingImageReader.GetPointer() );

#ifdef ITK_USE_OPTIMIZED_REGISTRATION_METHODS
  std::cout << "OPTIMIZED ON" << std::endl;
#else
  std::cout << "OPTIMIZED OFF" << std::endl;
#endif

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before><commit_msg>Add missing newline at end of file. BUG=none TEST=none<commit_after><|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief arango benchmark tool
///
/// @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 Dr. Frank Celler
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "Basics/Common.h"

#include "ArangoShell/ArangoClient.h"
#include "Basics/Mutex.h"
#include "Basics/MutexLocker.h"
#include "Basics/ProgramOptions.h"
#include "Basics/ProgramOptionsDescription.h"
#include "Basics/StringUtils.h"
#include "Basics/init.h"
#include "Basics/logging.h"
#include "Basics/random.h"
#include "Basics/tri-strings.h"
#include "Basics/string-buffer.h"
#include "Basics/terminal-utils.h"
#include "Rest/Endpoint.h"
#include "Rest/HttpRequest.h"
#include "Rest/InitialiseRest.h"
#include "SimpleHttpClient/SimpleHttpClient.h"
#include "SimpleHttpClient/SimpleHttpResult.h"
#include "Benchmark/BenchmarkCounter.h"
#include "Benchmark/BenchmarkOperation.h"
#include "Benchmark/BenchmarkThread.h"

using namespace std;
using namespace triagens::basics;
using namespace triagens::httpclient;
using namespace triagens::rest;
using namespace triagens::arango;
using namespace triagens::arangob;

// -----------------------------------------------------------------------------
// --SECTION--                                                 private variables
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief base class for clients
////////////////////////////////////////////////////////////////////////////////

ArangoClient BaseClient("arangob");

////////////////////////////////////////////////////////////////////////////////
/// @brief started counter
////////////////////////////////////////////////////////////////////////////////

static atomic<int> Started;

////////////////////////////////////////////////////////////////////////////////
/// @brief mutex for start counter
////////////////////////////////////////////////////////////////////////////////

Mutex StartMutex;

////////////////////////////////////////////////////////////////////////////////
/// @brief send asychronous requests
////////////////////////////////////////////////////////////////////////////////

static bool Async = false;

////////////////////////////////////////////////////////////////////////////////
/// @brief number of operations in one batch
////////////////////////////////////////////////////////////////////////////////

static int BatchSize = 0;

////////////////////////////////////////////////////////////////////////////////
/// @brief collection to use
////////////////////////////////////////////////////////////////////////////////

static string Collection = "ArangoBenchmark";

////////////////////////////////////////////////////////////////////////////////
/// @brief complexity parameter for tests
////////////////////////////////////////////////////////////////////////////////

static uint64_t Complexity = 1;

////////////////////////////////////////////////////////////////////////////////
/// @brief concurrency
////////////////////////////////////////////////////////////////////////////////

static int Concurrency = 1;

////////////////////////////////////////////////////////////////////////////////
/// @brief use a startup delay
////////////////////////////////////////////////////////////////////////////////

static bool Delay = false;

////////////////////////////////////////////////////////////////////////////////
/// @brief use HTTP keep-alive
////////////////////////////////////////////////////////////////////////////////

static bool KeepAlive = true;

////////////////////////////////////////////////////////////////////////////////
/// @brief number of operations to perform
////////////////////////////////////////////////////////////////////////////////

static int Operations = 1000;

////////////////////////////////////////////////////////////////////////////////
/// @brief display progress
////////////////////////////////////////////////////////////////////////////////

static bool Progress = true;

////////////////////////////////////////////////////////////////////////////////
/// @brief test case to use
////////////////////////////////////////////////////////////////////////////////

static string TestCase = "version";

////////////////////////////////////////////////////////////////////////////////
/// @brief print out replies on error
////////////////////////////////////////////////////////////////////////////////

static bool verbose = false;

////////////////////////////////////////////////////////////////////////////////
/// @brief includes all the test cases
////////////////////////////////////////////////////////////////////////////////

#include "Benchmark/test-cases.h"

// -----------------------------------------------------------------------------
// --SECTION--                                                 private functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief update the number of ready threads. this is a callback function
/// that is called by each thread after it is created
////////////////////////////////////////////////////////////////////////////////

static void UpdateStartCounter () {
  ++Started;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get the value of the number of started threads counter
////////////////////////////////////////////////////////////////////////////////

static int GetStartCounter () {
  return Started;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief print a status line (if ! quiet)
////////////////////////////////////////////////////////////////////////////////

static void Status (const string& value) {
  if (! BaseClient.quiet()) {
    cout << value << endl;
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief parses the program options
////////////////////////////////////////////////////////////////////////////////

static void ParseProgramOptions (int argc, char* argv[]) {
  ProgramOptionsDescription description("STANDARD options");

  description
    ("async", &Async, "send asychronous requests")
    ("concurrency", &Concurrency, "number of parallel connections")
    ("requests", &Operations, "total number of operations")
    ("batch-size", &BatchSize, "number of operations in one batch (0 disables batching)")
    ("keep-alive", &KeepAlive, "use HTTP keep-alive")
    ("collection", &Collection, "collection name to use in tests")
    ("test-case", &TestCase, "test case to use (possible values: version, document, collection, import-document, hash, skiplist, edge, shapes, shapes-append, random-shapes, crud, crud-append, crud-write-read, aqltrx, counttrx, multitrx, multi-collection, aqlinsert)")
    ("complexity", &Complexity, "complexity parameter for the test")
    ("delay", &Delay, "use a startup delay (necessary only when run in series)")
    ("progress", &Progress, "show progress")
    ("verbose", &verbose, "print out replies if the http-header indicates db-errors")
  ;

  BaseClient.setupGeneral(description);
  BaseClient.setupServer(description);

  vector<string> arguments;
  description.arguments(&arguments);

  ProgramOptions options;
  BaseClient.parse(options, description, "--concurrency <concurrency> --requests <request> --test-case <case> ...", argc, argv, "arangob.conf");
}

// -----------------------------------------------------------------------------
// --SECTION--                                                  public functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief startup and exit functions
////////////////////////////////////////////////////////////////////////////////

static void arangobEntryFunction ();
static void arangobExitFunction (int, void*);

#ifdef _WIN32

// .............................................................................
// Call this function to do various initialisations for windows only
// .............................................................................

void arangobEntryFunction () {
  int maxOpenFiles = 1024;
  int res = 0;

  // ...........................................................................
  // Uncomment this to call this for extended debug information.
  // If you familiar with valgrind ... then this is not like that, however
  // you do get some similar functionality.
  // ...........................................................................
  //res = initialiseWindows(TRI_WIN_INITIAL_SET_DEBUG_FLAG, 0);

  res = initialiseWindows(TRI_WIN_INITIAL_SET_INVALID_HANLE_HANDLER, 0);
  if (res != 0) {
    _exit(1);
  }

  res = initialiseWindows(TRI_WIN_INITIAL_SET_MAX_STD_IO,(const char*)(&maxOpenFiles));
  if (res != 0) {
    _exit(1);
  }

  res = initialiseWindows(TRI_WIN_INITIAL_WSASTARTUP_FUNCTION_CALL, 0);
  if (res != 0) {
    _exit(1);
  }

  TRI_Application_Exit_SetExit(arangobExitFunction);
}

static void arangobExitFunction (int exitCode, void* data) {
  int res = 0;
  // ...........................................................................
  // TODO: need a terminate function for windows to be called and cleanup
  // any windows specific stuff.
  // ...........................................................................

  res = finaliseWindows(TRI_WIN_FINAL_WSASTARTUP_FUNCTION_CALL, 0);

  if (res != 0) {
    exit(1);
  }

  exit(exitCode);
}
#else

static void arangobEntryFunction () {
}

static void arangobExitFunction (int exitCode, void* data) {
}

#endif

////////////////////////////////////////////////////////////////////////////////
/// @brief main
////////////////////////////////////////////////////////////////////////////////

int main (int argc, char* argv[]) {
  int ret = EXIT_SUCCESS;

  arangobEntryFunction();

  TRIAGENS_C_INITIALISE(argc, argv);
  TRIAGENS_REST_INITIALISE(argc, argv);

  TRI_InitialiseLogging(false);

  BaseClient.setEndpointString(Endpoint::getDefaultEndpoint());

  // .............................................................................
  // parse the program options
  // .............................................................................

  ParseProgramOptions(argc, argv);

  // .............................................................................
  // set-up client connection
  // .............................................................................

  BaseClient.createEndpoint();

  if (BaseClient.endpointServer() == nullptr) {
    LOG_FATAL_AND_EXIT("invalid value for --server.endpoint ('%s')", BaseClient.endpointString().c_str());
  }

  BenchmarkOperation* testCase = GetTestCase(TestCase);

  if (testCase == nullptr) {
    LOG_FATAL_AND_EXIT("invalid test case name '%s'", TestCase.c_str());
    return EXIT_FAILURE; // will not be reached
  }

  Status("starting threads...");

  BenchmarkCounter<unsigned long> operationsCounter(0, (unsigned long) Operations);
  ConditionVariable startCondition;

  vector<Endpoint*> endpoints;
  vector<BenchmarkThread*> threads;

  const double stepSize = (double) Operations / (double) Concurrency;
  int64_t realStep = (int64_t) stepSize;
  if (stepSize - (double) ((int64_t) stepSize) > 0.0) {
    realStep++;
  }
  if (realStep % 1000 != 0) {
    realStep += 1000 - (realStep % 1000);
  }
  // add some more offset so we don't get into trouble with threads of different speed
  realStep += 10000;

  // start client threads
  for (int i = 0; i < Concurrency; ++i) {
    Endpoint* endpoint = Endpoint::clientFactory(BaseClient.endpointString());
    endpoints.push_back(endpoint);

    BenchmarkThread* thread = new BenchmarkThread(testCase,
        &startCondition,
        &UpdateStartCounter,
        i,
        (unsigned long) BatchSize,
        &operationsCounter,
        endpoint,
        BaseClient.databaseName(),
        BaseClient.username(),
        BaseClient.password(),
        BaseClient.requestTimeout(),
        BaseClient.connectTimeout(),
        BaseClient.sslProtocol(),
        KeepAlive,
        Async,
        verbose);

    threads.push_back(thread);
    thread->setOffset((size_t) (i * realStep));
    thread->start();
  }

  // give all threads a chance to start so they will not miss the broadcast
  while (GetStartCounter() < Concurrency) {
    usleep(5000);
  }

  if (Delay) {
    Status("sleeping (startup delay)...");
    sleep(10);
  }
  Status("executing tests...");

  double start = TRI_microtime();

  // broadcast the start signal to all threads
  {
    ConditionLocker guard(&startCondition);
    guard.broadcast();
  }

  const size_t stepValue = (Operations / 20);
  size_t nextReportValue = stepValue;

  if (nextReportValue < 100) {
    nextReportValue = 100;
  }

  while (1) {
    const size_t numOperations = operationsCounter.getDone();

    if (numOperations >= (size_t) Operations) {
      break;
    }

    if (Progress && numOperations >= nextReportValue) {
      LOG_INFO("number of operations: %d", (int) nextReportValue);
      nextReportValue += stepValue;
    }

    usleep(20000);
  }

  double time = TRI_microtime() - start;
  double requestTime = 0.0;

  for (int i = 0; i < Concurrency; ++i) {
    requestTime += threads[i]->getTime();
  }

  size_t failures = operationsCounter.failures();
  size_t incomplete = operationsCounter.incompleteFailures();

  cout << endl;
  cout << "Total number of operations: " << Operations <<
          ", keep alive: " << (KeepAlive ? "yes" : "no") <<
          ", async: " << (Async ? "yes" : "no")  <<
          ", batch size: " << BatchSize <<
          ", concurrency level (threads): " << Concurrency <<
          endl;

  cout << "Test case: " << TestCase <<
          ", complexity: " << Complexity <<
          ", database: '" << BaseClient.databaseName() <<
          "', collection: '" << Collection << "'" <<
          endl;

  cout << "Total request/response duration (sum of all threads): " << fixed << requestTime << " s" << endl;
  cout << "Request/response duration (per thread): " << fixed << (requestTime / (double) Concurrency) << " s" << endl;
  cout << "Time needed per operation: " << fixed << (time / Operations) << " s" << endl;
  cout << "Time needed per operation per thread: " << fixed << (time / (double) Operations * (double) Concurrency) << " s" << endl;
  cout << "Operations per second rate: " << fixed << ((double) Operations / time) << endl;
  cout << "Elapsed time since start: " << fixed << time << " s" << endl << endl;

  if (failures > 0) {
    cerr << "WARNING: " << failures << " arangob request(s) failed!!" << endl;
  }
  if (incomplete > 0) {
    cerr << "WARNING: " << incomplete << " arangob requests with incomplete results!!" << endl;
  }

  testCase->tearDown();

  for (int i = 0; i < Concurrency; ++i) {
    threads[i]->join();
    delete threads[i];
    delete endpoints[i];
  }

  delete testCase;

  TRIAGENS_REST_SHUTDOWN;

  if (failures > 0) {
    ret = EXIT_FAILURE;
  }

  arangobExitFunction(ret, nullptr);

  return ret;
}

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

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<commit_msg>resolve conflict with namespace "Concurrency", introduced by MS on top-level...<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief arango benchmark tool
///
/// @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 Dr. Frank Celler
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "Basics/Common.h"

#include "ArangoShell/ArangoClient.h"
#include "Basics/Mutex.h"
#include "Basics/MutexLocker.h"
#include "Basics/ProgramOptions.h"
#include "Basics/ProgramOptionsDescription.h"
#include "Basics/StringUtils.h"
#include "Basics/init.h"
#include "Basics/logging.h"
#include "Basics/random.h"
#include "Basics/tri-strings.h"
#include "Basics/string-buffer.h"
#include "Basics/terminal-utils.h"
#include "Rest/Endpoint.h"
#include "Rest/HttpRequest.h"
#include "Rest/InitialiseRest.h"
#include "SimpleHttpClient/SimpleHttpClient.h"
#include "SimpleHttpClient/SimpleHttpResult.h"
#include "Benchmark/BenchmarkCounter.h"
#include "Benchmark/BenchmarkOperation.h"
#include "Benchmark/BenchmarkThread.h"

using namespace std;
using namespace triagens::basics;
using namespace triagens::httpclient;
using namespace triagens::rest;
using namespace triagens::arango;
using namespace triagens::arangob;

// -----------------------------------------------------------------------------
// --SECTION--                                                 private variables
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief base class for clients
////////////////////////////////////////////////////////////////////////////////

ArangoClient BaseClient("arangob");

////////////////////////////////////////////////////////////////////////////////
/// @brief started counter
////////////////////////////////////////////////////////////////////////////////

static atomic<int> Started;

////////////////////////////////////////////////////////////////////////////////
/// @brief mutex for start counter
////////////////////////////////////////////////////////////////////////////////

Mutex StartMutex;

////////////////////////////////////////////////////////////////////////////////
/// @brief send asychronous requests
////////////////////////////////////////////////////////////////////////////////

static bool Async = false;

////////////////////////////////////////////////////////////////////////////////
/// @brief number of operations in one batch
////////////////////////////////////////////////////////////////////////////////

static int BatchSize = 0;

////////////////////////////////////////////////////////////////////////////////
/// @brief collection to use
////////////////////////////////////////////////////////////////////////////////

static string Collection = "ArangoBenchmark";

////////////////////////////////////////////////////////////////////////////////
/// @brief complexity parameter for tests
////////////////////////////////////////////////////////////////////////////////

static uint64_t Complexity = 1;

////////////////////////////////////////////////////////////////////////////////
/// @brief concurrency
////////////////////////////////////////////////////////////////////////////////

static int ThreadConcurrency = 1;

////////////////////////////////////////////////////////////////////////////////
/// @brief use a startup delay
////////////////////////////////////////////////////////////////////////////////

static bool Delay = false;

////////////////////////////////////////////////////////////////////////////////
/// @brief use HTTP keep-alive
////////////////////////////////////////////////////////////////////////////////

static bool KeepAlive = true;

////////////////////////////////////////////////////////////////////////////////
/// @brief number of operations to perform
////////////////////////////////////////////////////////////////////////////////

static int Operations = 1000;

////////////////////////////////////////////////////////////////////////////////
/// @brief display progress
////////////////////////////////////////////////////////////////////////////////

static bool Progress = true;

////////////////////////////////////////////////////////////////////////////////
/// @brief test case to use
////////////////////////////////////////////////////////////////////////////////

static string TestCase = "version";

////////////////////////////////////////////////////////////////////////////////
/// @brief print out replies on error
////////////////////////////////////////////////////////////////////////////////

static bool verbose = false;

////////////////////////////////////////////////////////////////////////////////
/// @brief includes all the test cases
////////////////////////////////////////////////////////////////////////////////

#include "Benchmark/test-cases.h"

// -----------------------------------------------------------------------------
// --SECTION--                                                 private functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief update the number of ready threads. this is a callback function
/// that is called by each thread after it is created
////////////////////////////////////////////////////////////////////////////////

static void UpdateStartCounter () {
  ++Started;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get the value of the number of started threads counter
////////////////////////////////////////////////////////////////////////////////

static int GetStartCounter () {
  return Started;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief print a status line (if ! quiet)
////////////////////////////////////////////////////////////////////////////////

static void Status (const string& value) {
  if (! BaseClient.quiet()) {
    cout << value << endl;
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief parses the program options
////////////////////////////////////////////////////////////////////////////////

static void ParseProgramOptions (int argc, char* argv[]) {
  ProgramOptionsDescription description("STANDARD options");

  description
    ("async", &Async, "send asychronous requests")
    ("concurrency", &ThreadConcurrency, "number of parallel connections")
    ("requests", &Operations, "total number of operations")
    ("batch-size", &BatchSize, "number of operations in one batch (0 disables batching)")
    ("keep-alive", &KeepAlive, "use HTTP keep-alive")
    ("collection", &Collection, "collection name to use in tests")
    ("test-case", &TestCase, "test case to use (possible values: version, document, collection, import-document, hash, skiplist, edge, shapes, shapes-append, random-shapes, crud, crud-append, crud-write-read, aqltrx, counttrx, multitrx, multi-collection, aqlinsert)")
    ("complexity", &Complexity, "complexity parameter for the test")
    ("delay", &Delay, "use a startup delay (necessary only when run in series)")
    ("progress", &Progress, "show progress")
    ("verbose", &verbose, "print out replies if the http-header indicates db-errors")
  ;

  BaseClient.setupGeneral(description);
  BaseClient.setupServer(description);

  vector<string> arguments;
  description.arguments(&arguments);

  ProgramOptions options;
  BaseClient.parse(options, description, "--concurrency <concurrency> --requests <request> --test-case <case> ...", argc, argv, "arangob.conf");
}

// -----------------------------------------------------------------------------
// --SECTION--                                                  public functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief startup and exit functions
////////////////////////////////////////////////////////////////////////////////

static void arangobEntryFunction ();
static void arangobExitFunction (int, void*);

#ifdef _WIN32

// .............................................................................
// Call this function to do various initialisations for windows only
// .............................................................................

void arangobEntryFunction () {
  int maxOpenFiles = 1024;
  int res = 0;

  // ...........................................................................
  // Uncomment this to call this for extended debug information.
  // If you familiar with valgrind ... then this is not like that, however
  // you do get some similar functionality.
  // ...........................................................................
  //res = initialiseWindows(TRI_WIN_INITIAL_SET_DEBUG_FLAG, 0);

  res = initialiseWindows(TRI_WIN_INITIAL_SET_INVALID_HANLE_HANDLER, 0);
  if (res != 0) {
    _exit(1);
  }

  res = initialiseWindows(TRI_WIN_INITIAL_SET_MAX_STD_IO,(const char*)(&maxOpenFiles));
  if (res != 0) {
    _exit(1);
  }

  res = initialiseWindows(TRI_WIN_INITIAL_WSASTARTUP_FUNCTION_CALL, 0);
  if (res != 0) {
    _exit(1);
  }

  TRI_Application_Exit_SetExit(arangobExitFunction);
}

static void arangobExitFunction (int exitCode, void* data) {
  int res = 0;
  // ...........................................................................
  // TODO: need a terminate function for windows to be called and cleanup
  // any windows specific stuff.
  // ...........................................................................

  res = finaliseWindows(TRI_WIN_FINAL_WSASTARTUP_FUNCTION_CALL, 0);

  if (res != 0) {
    exit(1);
  }

  exit(exitCode);
}
#else

static void arangobEntryFunction () {
}

static void arangobExitFunction (int exitCode, void* data) {
}

#endif

////////////////////////////////////////////////////////////////////////////////
/// @brief main
////////////////////////////////////////////////////////////////////////////////

int main (int argc, char* argv[]) {
  int ret = EXIT_SUCCESS;

  arangobEntryFunction();

  TRIAGENS_C_INITIALISE(argc, argv);
  TRIAGENS_REST_INITIALISE(argc, argv);

  TRI_InitialiseLogging(false);

  BaseClient.setEndpointString(Endpoint::getDefaultEndpoint());

  // .............................................................................
  // parse the program options
  // .............................................................................

  ParseProgramOptions(argc, argv);

  // .............................................................................
  // set-up client connection
  // .............................................................................

  BaseClient.createEndpoint();

  if (BaseClient.endpointServer() == nullptr) {
    LOG_FATAL_AND_EXIT("invalid value for --server.endpoint ('%s')", BaseClient.endpointString().c_str());
  }

  BenchmarkOperation* testCase = GetTestCase(TestCase);

  if (testCase == nullptr) {
    LOG_FATAL_AND_EXIT("invalid test case name '%s'", TestCase.c_str());
    return EXIT_FAILURE; // will not be reached
  }

  Status("starting threads...");

  BenchmarkCounter<unsigned long> operationsCounter(0, (unsigned long) Operations);
  ConditionVariable startCondition;

  vector<Endpoint*> endpoints;
  vector<BenchmarkThread*> threads;

  const double stepSize = (double) Operations / (double) ThreadConcurrency;
  int64_t realStep = (int64_t) stepSize;
  if (stepSize - (double) ((int64_t) stepSize) > 0.0) {
    realStep++;
  }
  if (realStep % 1000 != 0) {
    realStep += 1000 - (realStep % 1000);
  }
  // add some more offset so we don't get into trouble with threads of different speed
  realStep += 10000;

  // start client threads
  for (int i = 0; i < ThreadConcurrency; ++i) {
    Endpoint* endpoint = Endpoint::clientFactory(BaseClient.endpointString());
    endpoints.push_back(endpoint);

    BenchmarkThread* thread = new BenchmarkThread(testCase,
        &startCondition,
        &UpdateStartCounter,
        i,
        (unsigned long) BatchSize,
        &operationsCounter,
        endpoint,
        BaseClient.databaseName(),
        BaseClient.username(),
        BaseClient.password(),
        BaseClient.requestTimeout(),
        BaseClient.connectTimeout(),
        BaseClient.sslProtocol(),
        KeepAlive,
        Async,
        verbose);

    threads.push_back(thread);
    thread->setOffset((size_t) (i * realStep));
    thread->start();
  }

  // give all threads a chance to start so they will not miss the broadcast
  while (GetStartCounter() < ThreadConcurrency) {
    usleep(5000);
  }

  if (Delay) {
    Status("sleeping (startup delay)...");
    sleep(10);
  }
  Status("executing tests...");

  double start = TRI_microtime();

  // broadcast the start signal to all threads
  {
    ConditionLocker guard(&startCondition);
    guard.broadcast();
  }

  const size_t stepValue = (Operations / 20);
  size_t nextReportValue = stepValue;

  if (nextReportValue < 100) {
    nextReportValue = 100;
  }

  while (1) {
    const size_t numOperations = operationsCounter.getDone();

    if (numOperations >= (size_t) Operations) {
      break;
    }

    if (Progress && numOperations >= nextReportValue) {
      LOG_INFO("number of operations: %d", (int) nextReportValue);
      nextReportValue += stepValue;
    }

    usleep(20000);
  }

  double time = TRI_microtime() - start;
  double requestTime = 0.0;

  for (int i = 0; i < ThreadConcurrency; ++i) {
    requestTime += threads[i]->getTime();
  }

  size_t failures = operationsCounter.failures();
  size_t incomplete = operationsCounter.incompleteFailures();

  cout << endl;
  cout << "Total number of operations: " << Operations <<
          ", keep alive: " << (KeepAlive ? "yes" : "no") <<
          ", async: " << (Async ? "yes" : "no")  <<
          ", batch size: " << BatchSize <<
          ", concurrency level (threads): " << ThreadConcurrency <<
          endl;

  cout << "Test case: " << TestCase <<
          ", complexity: " << Complexity <<
          ", database: '" << BaseClient.databaseName() <<
          "', collection: '" << Collection << "'" <<
          endl;

  cout << "Total request/response duration (sum of all threads): " << fixed << requestTime << " s" << endl;
  cout << "Request/response duration (per thread): " << fixed << (requestTime / (double) ThreadConcurrency) << " s" << endl;
  cout << "Time needed per operation: " << fixed << (time / Operations) << " s" << endl;
  cout << "Time needed per operation per thread: " << fixed << (time / (double) Operations * (double) ThreadConcurrency) << " s" << endl;
  cout << "Operations per second rate: " << fixed << ((double) Operations / time) << endl;
  cout << "Elapsed time since start: " << fixed << time << " s" << endl << endl;

  if (failures > 0) {
    cerr << "WARNING: " << failures << " arangob request(s) failed!!" << endl;
  }
  if (incomplete > 0) {
    cerr << "WARNING: " << incomplete << " arangob requests with incomplete results!!" << endl;
  }

  testCase->tearDown();

  for (int i = 0; i < ThreadConcurrency; ++i) {
    threads[i]->join();
    delete threads[i];
    delete endpoints[i];
  }

  delete testCase;

  TRIAGENS_REST_SHUTDOWN;

  if (failures > 0) {
    ret = EXIT_FAILURE;
  }

  arangobExitFunction(ret, nullptr);

  return ret;
}

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

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


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Run all of our test shell tests.  This is just an entry point
// to kick off gTest's RUN_ALL_TESTS().

#include "base/basictypes.h"

#if defined(OS_WIN)
#include <windows.h>
#include <commctrl.h>
#elif defined(OS_LINUX)
#include <gtk/gtk.h>
#endif

#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/icu_util.h"
#include "base/message_loop.h"
#include "base/process_util.h"
#include "webkit/tools/test_shell/simple_resource_loader_bridge.h"
#include "webkit/tools/test_shell/test_shell.h"
#include "webkit/tools/test_shell/test_shell_test.h"
#include "testing/gtest/include/gtest/gtest.h"

const char* TestShellTest::kJavascriptDelayExitScript =
  "<script>"
    "window.layoutTestController.waitUntilDone();"
    "window.addEventListener('load', function() {"
    "  var x = document.body.clientWidth;"  // Force a document layout
    "  window.layoutTestController.notifyDone();"
    "});"
  "</script>";

int main(int argc, char* argv[]) {
  base::EnableTerminationOnHeapCorruption();
  // Some unittests may use base::Singleton<>, thus we need to instanciate
  // the AtExitManager or else we will leak objects.
  base::AtExitManager at_exit_manager;

#if defined(OS_LINUX)
  gtk_init(&argc, &argv);
#endif

#if defined(OS_POSIX)
  CommandLine::SetArgcArgv(argc, argv);
#endif

  TestShell::InitLogging(true, false);  // suppress error dialogs

#if defined(OS_WIN)
  // Some of the individual tests wind up calling TestShell::WaitTestFinished
  // which has a timeout in it.  For these tests, we don't care about a timeout
  // so just set it to be a really large number.  This is necessary because
  // when running under Purify, we were hitting those timeouts.
  TestShell::SetFileTestTimeout(USER_TIMER_MAXIMUM);
#endif

  // Initialize test shell in non-interactive mode, which will let us load one
  // request than automatically quit.
  TestShell::InitializeTestShell(false);

  // Allocate a message loop for this thread.  Although it is not used
  // directly, its constructor sets up some necessary state.
  MessageLoop main_message_loop;

  // Load ICU data tables
  icu_util::Initialize();

#if defined(OS_WIN)
  INITCOMMONCONTROLSEX InitCtrlEx;

  InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
  InitCtrlEx.dwICC  = ICC_STANDARD_CLASSES;
  InitCommonControlsEx(&InitCtrlEx);
#endif

  // Run the actual tests
  testing::InitGoogleTest(&argc, argv);
  int result = RUN_ALL_TESTS();

  TestShell::ShutdownTestShell();
  TestShell::CleanupLogging();

  return result;
}
<commit_msg>Fixed broken build - missing parameter to TestShell::InitLogging in test shell tests.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Run all of our test shell tests.  This is just an entry point
// to kick off gTest's RUN_ALL_TESTS().

#include "base/basictypes.h"

#if defined(OS_WIN)
#include <windows.h>
#include <commctrl.h>
#elif defined(OS_LINUX)
#include <gtk/gtk.h>
#endif

#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/icu_util.h"
#include "base/message_loop.h"
#include "base/process_util.h"
#include "webkit/tools/test_shell/simple_resource_loader_bridge.h"
#include "webkit/tools/test_shell/test_shell.h"
#include "webkit/tools/test_shell/test_shell_test.h"
#include "testing/gtest/include/gtest/gtest.h"

const char* TestShellTest::kJavascriptDelayExitScript =
  "<script>"
    "window.layoutTestController.waitUntilDone();"
    "window.addEventListener('load', function() {"
    "  var x = document.body.clientWidth;"  // Force a document layout
    "  window.layoutTestController.notifyDone();"
    "});"
  "</script>";

int main(int argc, char* argv[]) {
  base::EnableTerminationOnHeapCorruption();
  // Some unittests may use base::Singleton<>, thus we need to instanciate
  // the AtExitManager or else we will leak objects.
  base::AtExitManager at_exit_manager;

#if defined(OS_LINUX)
  gtk_init(&argc, &argv);
#endif

#if defined(OS_POSIX)
  CommandLine::SetArgcArgv(argc, argv);
#endif

  // Suppress error dialogs and do not show GP fault error box on Windows.
  TestShell::InitLogging(true, false, false);

#if defined(OS_WIN)
  // Some of the individual tests wind up calling TestShell::WaitTestFinished
  // which has a timeout in it.  For these tests, we don't care about a timeout
  // so just set it to be a really large number.  This is necessary because
  // when running under Purify, we were hitting those timeouts.
  TestShell::SetFileTestTimeout(USER_TIMER_MAXIMUM);
#endif

  // Initialize test shell in non-interactive mode, which will let us load one
  // request than automatically quit.
  TestShell::InitializeTestShell(false);

  // Allocate a message loop for this thread.  Although it is not used
  // directly, its constructor sets up some necessary state.
  MessageLoop main_message_loop;

  // Load ICU data tables
  icu_util::Initialize();

#if defined(OS_WIN)
  INITCOMMONCONTROLSEX InitCtrlEx;

  InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
  InitCtrlEx.dwICC  = ICC_STANDARD_CLASSES;
  InitCommonControlsEx(&InitCtrlEx);
#endif

  // Run the actual tests
  testing::InitGoogleTest(&argc, argv);
  int result = RUN_ALL_TESTS();

  TestShell::ShutdownTestShell();
  TestShell::CleanupLogging();

  return result;
}
<|endoftext|>