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

#include <set>

#include "openvdb/openvdb.h"

#include "IECore/ExternalProcedural.h"
#include "IECore/CompoundData.h"

#include "Gaffer/StringPlug.h"
#include "Gaffer/StringAlgo.h"

#include "GafferArnold/ArnoldVDB.h"

using namespace Imath;
using namespace IECore;
using namespace Gaffer;
using namespace GafferScene;
using namespace GafferArnold;

//////////////////////////////////////////////////////////////////////////
// Internal utilities
//////////////////////////////////////////////////////////////////////////

namespace
{

Box3f boundAndAutoStepSize( const std::string &fileName, const std::set<std::string> &sets, float &autoStepSize )
{
	openvdb::initialize();
	openvdb::io::File file( fileName );
	file.open();

	autoStepSize = Imath::limits<float>::max();

	openvdb::BBoxd result;
	for( std::set<std::string>::const_iterator it = sets.begin(), eIt = sets.end(); it != eIt; ++it )
	{
		openvdb::GridBase::Ptr grid = file.readGridMetadata( *it );
		const openvdb::Vec3i &min = grid->metaValue<openvdb::Vec3i>( openvdb::GridBase::META_FILE_BBOX_MIN );
		const openvdb::Vec3i &max = grid->metaValue<openvdb::Vec3i>( openvdb::GridBase::META_FILE_BBOX_MAX );
		result.expand( grid->transform().indexToWorld( openvdb::BBoxd( min - 0.5, max + 0.5 ) ) );

		const openvdb::Vec3d voxelSize = grid->voxelSize();
		autoStepSize = std::min( std::min( (double)autoStepSize, voxelSize.x() ), std::min( voxelSize.y(), voxelSize.z() ) );
	}

	return Box3f(
		V3f( result.min().x(), result.min().y(), result.min().z() ),
		V3f( result.max().x(), result.max().y(), result.max().z() )
	);
}

} // namespace

//////////////////////////////////////////////////////////////////////////
// ArnoldVDB
//////////////////////////////////////////////////////////////////////////

IE_CORE_DEFINERUNTIMETYPED( ArnoldVDB );

size_t ArnoldVDB::g_firstPlugIndex = 0;

ArnoldVDB::ArnoldVDB( const std::string &name )
	:	ObjectSource( name, "volume" )
{
	storeIndexOfNextChild( g_firstPlugIndex );
	addChild( new StringPlug( "fileName" ) );
	addChild( new StringPlug( "grids", Plug::In, "density" ) );
	addChild( new StringPlug( "velocityGrids" ) );
	addChild( new FloatPlug( "velocityScale", Plug::In, 1.0f ) );
	addChild( new FloatPlug( "stepSize", Plug::In, 0.0f, 0.0f ) );
	addChild( new FloatPlug( "stepScale", Plug::In, 1.0f, 0.0f ) );
	addChild( new StringPlug( "dso", Plug::In, "volume_vdb.so" ) );
}

ArnoldVDB::~ArnoldVDB()
{
}

Gaffer::StringPlug *ArnoldVDB::fileNamePlug()
{
	return getChild<StringPlug>( g_firstPlugIndex );
}

const Gaffer::StringPlug *ArnoldVDB::fileNamePlug() const
{
	return getChild<StringPlug>( g_firstPlugIndex );
}

Gaffer::StringPlug *ArnoldVDB::gridsPlug()
{
	return getChild<StringPlug>( g_firstPlugIndex + 1 );
}

const Gaffer::StringPlug *ArnoldVDB::gridsPlug() const
{
	return getChild<StringPlug>( g_firstPlugIndex + 1 );
}

Gaffer::StringPlug *ArnoldVDB::velocityGridsPlug()
{
	return getChild<StringPlug>( g_firstPlugIndex + 2 );
}

const Gaffer::StringPlug *ArnoldVDB::velocityGridsPlug() const
{
	return getChild<StringPlug>( g_firstPlugIndex + 2 );
}

Gaffer::FloatPlug *ArnoldVDB::velocityScalePlug()
{
	return getChild<FloatPlug>( g_firstPlugIndex + 3 );
}

const Gaffer::FloatPlug *ArnoldVDB::velocityScalePlug() const
{
	return getChild<FloatPlug>( g_firstPlugIndex + 3 );
}

Gaffer::FloatPlug *ArnoldVDB::stepSizePlug()
{
	return getChild<FloatPlug>( g_firstPlugIndex + 4 );
}

const Gaffer::FloatPlug *ArnoldVDB::stepSizePlug() const
{
	return getChild<FloatPlug>( g_firstPlugIndex + 4 );
}

Gaffer::FloatPlug *ArnoldVDB::stepScalePlug()
{
	return getChild<FloatPlug>( g_firstPlugIndex + 5 );
}

const Gaffer::FloatPlug *ArnoldVDB::stepScalePlug() const
{
	return getChild<FloatPlug>( g_firstPlugIndex + 5 );
}

Gaffer::StringPlug *ArnoldVDB::dsoPlug()
{
	return getChild<StringPlug>( g_firstPlugIndex + 6 );
}

const Gaffer::StringPlug *ArnoldVDB::dsoPlug() const
{
	return getChild<StringPlug>( g_firstPlugIndex + 6 );
}

void ArnoldVDB::affects( const Gaffer::Plug *input, AffectedPlugsContainer &outputs ) const
{
	ObjectSource::affects( input, outputs );

	if(
		input == fileNamePlug() ||
		input == gridsPlug() ||
		input == velocityGridsPlug() ||
		input == velocityScalePlug() ||
		input == stepSizePlug() ||
		input == stepScalePlug() ||
		input == dsoPlug()
	)
	{
		outputs.push_back( sourcePlug() );
	}
}

void ArnoldVDB::hashSource( const Gaffer::Context *context, IECore::MurmurHash &h ) const
{
	fileNamePlug()->hash( h );
	gridsPlug()->hash( h );
	velocityGridsPlug()->hash( h );
	velocityScalePlug()->hash( h );
	stepSizePlug()->hash( h );
	stepScalePlug()->hash( h );
	dsoPlug()->hash( h );
	h.append( context->getFramesPerSecond() );
}

IECore::ConstObjectPtr ArnoldVDB::computeSource( const Context *context ) const
{
	IECore::ExternalProceduralPtr result = new ExternalProcedural( dsoPlug()->getValue() );
	const std::string fileName = fileNamePlug()->getValue();
	const std::string gridsString = gridsPlug()->getValue();
	if( fileName.empty() || gridsString.empty() )
	{
		result->setBound( Box3f( V3f( -0.5 ), V3f( 0.5 ) ) );
		return result;
	}

	CompoundDataMap &parameters = result->parameters()->writable();

	parameters["ai:nodeType"] = new StringData( "volume" );
	parameters["filename"] = new StringData( fileNamePlug()->getValue() );

	StringVectorDataPtr grids = new StringVectorData();
	tokenize( gridsString, ' ', grids->writable() );
	parameters["grids"] = grids;

	StringVectorDataPtr velocityGrids = new StringVectorData();
	tokenize( velocityGridsPlug()->getValue(), ' ', velocityGrids->writable() );
	parameters["velocity_grids"] = velocityGrids;

	parameters["velocity_scale"] = new FloatData( velocityScalePlug()->getValue() );
	parameters["velocity_fps"] = new FloatData( context->getFramesPerSecond() );

	std::set<std::string> allGrids;
	allGrids.insert( grids->readable().begin(), grids->readable().end() );
	allGrids.insert( velocityGrids->readable().begin(), velocityGrids->readable().end() );

	float autoStepSize = 0;
	const Box3f bound = boundAndAutoStepSize( fileName, allGrids, autoStepSize );

	result->setBound( bound );

	const float stepSize = stepSizePlug()->getValue();
	const float stepScale = stepScalePlug()->getValue();
	parameters["step_size"] = new FloatData(
		( stepSize <= 0.0f ? autoStepSize : stepSize ) * stepScale
	);

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

#include <set>

#include "openvdb/openvdb.h"

#include "IECore/ExternalProcedural.h"
#include "IECore/CompoundData.h"

#include "Gaffer/StringPlug.h"
#include "Gaffer/StringAlgo.h"

#include "GafferArnold/ArnoldVDB.h"

using namespace Imath;
using namespace IECore;
using namespace Gaffer;
using namespace GafferScene;
using namespace GafferArnold;

//////////////////////////////////////////////////////////////////////////
// Internal utilities
//////////////////////////////////////////////////////////////////////////

namespace
{

Box3f boundAndAutoStepSize( const std::string &fileName, const std::set<std::string> &sets, float &autoStepSize )
{
	openvdb::initialize();
	openvdb::io::File file( fileName );
	// VDB has the crazy default behaviour of making a local
	// copy of the file and then opening that instead. Even if
	// the file is local already. Even if all you do is query
	// metadata. Restore sanity!
	file.setCopyMaxBytes( 0 );
	file.open();

	autoStepSize = Imath::limits<float>::max();

	openvdb::BBoxd result;
	for( std::set<std::string>::const_iterator it = sets.begin(), eIt = sets.end(); it != eIt; ++it )
	{
		openvdb::GridBase::Ptr grid = file.readGridMetadata( *it );
		const openvdb::Vec3i &min = grid->metaValue<openvdb::Vec3i>( openvdb::GridBase::META_FILE_BBOX_MIN );
		const openvdb::Vec3i &max = grid->metaValue<openvdb::Vec3i>( openvdb::GridBase::META_FILE_BBOX_MAX );
		result.expand( grid->transform().indexToWorld( openvdb::BBoxd( min - 0.5, max + 0.5 ) ) );

		const openvdb::Vec3d voxelSize = grid->voxelSize();
		autoStepSize = std::min( std::min( (double)autoStepSize, voxelSize.x() ), std::min( voxelSize.y(), voxelSize.z() ) );
	}

	return Box3f(
		V3f( result.min().x(), result.min().y(), result.min().z() ),
		V3f( result.max().x(), result.max().y(), result.max().z() )
	);
}

} // namespace

//////////////////////////////////////////////////////////////////////////
// ArnoldVDB
//////////////////////////////////////////////////////////////////////////

IE_CORE_DEFINERUNTIMETYPED( ArnoldVDB );

size_t ArnoldVDB::g_firstPlugIndex = 0;

ArnoldVDB::ArnoldVDB( const std::string &name )
	:	ObjectSource( name, "volume" )
{
	storeIndexOfNextChild( g_firstPlugIndex );
	addChild( new StringPlug( "fileName" ) );
	addChild( new StringPlug( "grids", Plug::In, "density" ) );
	addChild( new StringPlug( "velocityGrids" ) );
	addChild( new FloatPlug( "velocityScale", Plug::In, 1.0f ) );
	addChild( new FloatPlug( "stepSize", Plug::In, 0.0f, 0.0f ) );
	addChild( new FloatPlug( "stepScale", Plug::In, 1.0f, 0.0f ) );
	addChild( new StringPlug( "dso", Plug::In, "volume_vdb.so" ) );
}

ArnoldVDB::~ArnoldVDB()
{
}

Gaffer::StringPlug *ArnoldVDB::fileNamePlug()
{
	return getChild<StringPlug>( g_firstPlugIndex );
}

const Gaffer::StringPlug *ArnoldVDB::fileNamePlug() const
{
	return getChild<StringPlug>( g_firstPlugIndex );
}

Gaffer::StringPlug *ArnoldVDB::gridsPlug()
{
	return getChild<StringPlug>( g_firstPlugIndex + 1 );
}

const Gaffer::StringPlug *ArnoldVDB::gridsPlug() const
{
	return getChild<StringPlug>( g_firstPlugIndex + 1 );
}

Gaffer::StringPlug *ArnoldVDB::velocityGridsPlug()
{
	return getChild<StringPlug>( g_firstPlugIndex + 2 );
}

const Gaffer::StringPlug *ArnoldVDB::velocityGridsPlug() const
{
	return getChild<StringPlug>( g_firstPlugIndex + 2 );
}

Gaffer::FloatPlug *ArnoldVDB::velocityScalePlug()
{
	return getChild<FloatPlug>( g_firstPlugIndex + 3 );
}

const Gaffer::FloatPlug *ArnoldVDB::velocityScalePlug() const
{
	return getChild<FloatPlug>( g_firstPlugIndex + 3 );
}

Gaffer::FloatPlug *ArnoldVDB::stepSizePlug()
{
	return getChild<FloatPlug>( g_firstPlugIndex + 4 );
}

const Gaffer::FloatPlug *ArnoldVDB::stepSizePlug() const
{
	return getChild<FloatPlug>( g_firstPlugIndex + 4 );
}

Gaffer::FloatPlug *ArnoldVDB::stepScalePlug()
{
	return getChild<FloatPlug>( g_firstPlugIndex + 5 );
}

const Gaffer::FloatPlug *ArnoldVDB::stepScalePlug() const
{
	return getChild<FloatPlug>( g_firstPlugIndex + 5 );
}

Gaffer::StringPlug *ArnoldVDB::dsoPlug()
{
	return getChild<StringPlug>( g_firstPlugIndex + 6 );
}

const Gaffer::StringPlug *ArnoldVDB::dsoPlug() const
{
	return getChild<StringPlug>( g_firstPlugIndex + 6 );
}

void ArnoldVDB::affects( const Gaffer::Plug *input, AffectedPlugsContainer &outputs ) const
{
	ObjectSource::affects( input, outputs );

	if(
		input == fileNamePlug() ||
		input == gridsPlug() ||
		input == velocityGridsPlug() ||
		input == velocityScalePlug() ||
		input == stepSizePlug() ||
		input == stepScalePlug() ||
		input == dsoPlug()
	)
	{
		outputs.push_back( sourcePlug() );
	}
}

void ArnoldVDB::hashSource( const Gaffer::Context *context, IECore::MurmurHash &h ) const
{
	fileNamePlug()->hash( h );
	gridsPlug()->hash( h );
	velocityGridsPlug()->hash( h );
	velocityScalePlug()->hash( h );
	stepSizePlug()->hash( h );
	stepScalePlug()->hash( h );
	dsoPlug()->hash( h );
	h.append( context->getFramesPerSecond() );
}

IECore::ConstObjectPtr ArnoldVDB::computeSource( const Context *context ) const
{
	IECore::ExternalProceduralPtr result = new ExternalProcedural( dsoPlug()->getValue() );
	const std::string fileName = fileNamePlug()->getValue();
	const std::string gridsString = gridsPlug()->getValue();
	if( fileName.empty() || gridsString.empty() )
	{
		result->setBound( Box3f( V3f( -0.5 ), V3f( 0.5 ) ) );
		return result;
	}

	CompoundDataMap &parameters = result->parameters()->writable();

	parameters["ai:nodeType"] = new StringData( "volume" );
	parameters["filename"] = new StringData( fileNamePlug()->getValue() );

	StringVectorDataPtr grids = new StringVectorData();
	tokenize( gridsString, ' ', grids->writable() );
	parameters["grids"] = grids;

	StringVectorDataPtr velocityGrids = new StringVectorData();
	tokenize( velocityGridsPlug()->getValue(), ' ', velocityGrids->writable() );
	parameters["velocity_grids"] = velocityGrids;

	parameters["velocity_scale"] = new FloatData( velocityScalePlug()->getValue() );
	parameters["velocity_fps"] = new FloatData( context->getFramesPerSecond() );

	std::set<std::string> allGrids;
	allGrids.insert( grids->readable().begin(), grids->readable().end() );
	allGrids.insert( velocityGrids->readable().begin(), velocityGrids->readable().end() );

	float autoStepSize = 0;
	const Box3f bound = boundAndAutoStepSize( fileName, allGrids, autoStepSize );

	result->setBound( bound );

	const float stepSize = stepSizePlug()->getValue();
	const float stepScale = stepScalePlug()->getValue();
	parameters["step_size"] = new FloatData(
		( stepSize <= 0.0f ? autoStepSize : stepSize ) * stepScale
	);

	return result;
}
<|endoftext|>


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

#include <folly/system/MemoryMapping.h>

#include <algorithm>
#include <cerrno>
#include <functional>
#include <utility>

#include <glog/logging.h>

#include <folly/Format.h>
#include <folly/portability/GFlags.h>
#include <folly/portability/SysMman.h>
#include <folly/portability/SysSyscall.h>

#ifdef __linux__
#include <folly/experimental/io/HugePages.h> // @manual
#endif

#include <fcntl.h>
#include <sys/types.h>
#include <system_error>

static constexpr ssize_t kDefaultMlockChunkSize =
#ifndef _MSC_VER
    // Linux implementations of unmap/mlock/munlock take a kernel
    // semaphore and block other threads from doing other memory
    // operations. Split the operations in chunks.
    (1 << 20) // 1MB
#else // _MSC_VER
    // MSVC doesn't have this problem, and calling munmap many times
    // with the same address is a bad idea with the windows implementation.
    (-1)
#endif // _MSC_VER
    ;

DEFINE_int64(
    mlock_chunk_size,
    kDefaultMlockChunkSize,
    "Maximum bytes to mlock/munlock/munmap at once "
    "(will be rounded up to PAGESIZE). Ignored if negative.");

namespace folly {

namespace {

enum mmap_flags : int {
#ifdef MAP_POPULATE
  populate = MAP_POPULATE,
#else
  populate = 0,
#endif
};

} // namespace

MemoryMapping::MemoryMapping(MemoryMapping&& other) noexcept {
  swap(other);
}

MemoryMapping::MemoryMapping(
    File file,
    off_t offset,
    off_t length,
    Options options)
    : file_(std::move(file)), options_(std::move(options)) {
  CHECK(file_);
  init(offset, length);
}

MemoryMapping::MemoryMapping(
    const char* name,
    off_t offset,
    off_t length,
    Options options)
    : MemoryMapping(
          File(name, options.writable ? O_RDWR : O_RDONLY),
          offset,
          length,
          options) {}

MemoryMapping::MemoryMapping(
    int fd,
    off_t offset,
    off_t length,
    Options options)
    : MemoryMapping(File(fd), offset, length, options) {}

MemoryMapping::MemoryMapping(AnonymousType, off_t length, Options options)
    : options_(std::move(options)) {
  init(0, length);
}

namespace {

#ifdef __linux__
void getDeviceOptions(dev_t device, off_t& pageSize, bool& autoExtend) {
  auto ps = getHugePageSizeForDevice(device);
  if (ps) {
    pageSize = ps->size;
    autoExtend = true;
  }
}
#else
inline void getDeviceOptions(dev_t, off_t&, bool&) {}
#endif

} // namespace

void MemoryMapping::init(off_t offset, off_t length) {
  const bool grow = options_.grow;
  const bool anon = !file_;
  CHECK(!(grow && anon));

  off_t& pageSize = options_.pageSize;

  struct stat st;

  // On Linux, hugetlbfs file systems don't require ftruncate() to grow the
  // file, and (on kernels before 2.6.24) don't even allow it. Also, the file
  // size is always a multiple of the page size.
  bool autoExtend = false;

  if (!anon) {
    // Stat the file
    CHECK_ERR(fstat(file_.fd(), &st));

    if (pageSize == 0) {
      getDeviceOptions(st.st_dev, pageSize, autoExtend);
    }
  } else {
    DCHECK(!file_);
    DCHECK_EQ(offset, 0);
    CHECK_EQ(pageSize, 0);
    CHECK_GE(length, 0);
  }

  if (pageSize == 0) {
    pageSize = off_t(sysconf(_SC_PAGESIZE));
  }

  CHECK_GT(pageSize, 0);
  CHECK_EQ(pageSize & (pageSize - 1), 0); // power of two
  CHECK_GE(offset, 0);

  // Round down the start of the mapped region
  off_t skipStart = offset % pageSize;
  offset -= skipStart;

  mapLength_ = length;
  if (mapLength_ != -1) {
    mapLength_ += skipStart;

    // Round up the end of the mapped region
    mapLength_ = (mapLength_ + pageSize - 1) / pageSize * pageSize;
  }

  off_t remaining = anon ? length : st.st_size - offset;

  if (mapLength_ == -1) {
    length = mapLength_ = remaining;
  } else {
    if (length > remaining) {
      if (grow) {
        if (!autoExtend) {
          PCHECK(0 == ftruncate(file_.fd(), offset + length))
              << "ftruncate() failed, couldn't grow file to "
              << offset + length;
          remaining = length;
        } else {
          // Extend mapping to multiple of page size, don't use ftruncate
          remaining = mapLength_;
        }
      } else {
        length = remaining;
      }
    }
    if (mapLength_ > remaining) {
      mapLength_ = remaining;
    }
  }

  if (length == 0) {
    mapLength_ = 0;
    mapStart_ = nullptr;
  } else {
    int flags = options_.shared ? MAP_SHARED : MAP_PRIVATE;
    if (anon) {
      flags |= MAP_ANONYMOUS;
    }
    if (options_.prefault) {
      flags |= mmap_flags::populate;
    }

    // The standard doesn't actually require PROT_NONE to be zero...
    int prot = PROT_NONE;
    if (options_.readable || options_.writable) {
      prot =
          ((options_.readable ? PROT_READ : 0) |
           (options_.writable ? PROT_WRITE : 0));
    }

    unsigned char* start = static_cast<unsigned char*>(mmap(
        options_.address, size_t(mapLength_), prot, flags, file_.fd(), offset));
    PCHECK(start != MAP_FAILED)
        << " offset=" << offset << " length=" << mapLength_;
    mapStart_ = start;
    data_.reset(start + skipStart, size_t(length));
  }
}

namespace {

off_t memOpChunkSize(off_t length, off_t pageSize) {
  off_t chunkSize = length;
  if (FLAGS_mlock_chunk_size <= 0) {
    return chunkSize;
  }

  chunkSize = off_t(FLAGS_mlock_chunk_size);
  off_t r = chunkSize % pageSize;
  if (r) {
    chunkSize += (pageSize - r);
  }
  return chunkSize;
}

/**
 * Run @op in chunks over the buffer @mem of @bufSize length.
 *
 * Return:
 * - success: true + amountSucceeded == bufSize (op success on whole buffer)
 * - failure: false + amountSucceeded == nr bytes on which op succeeded.
 */
bool memOpInChunks(
    std::function<int(void*, size_t)> op,
    void* mem,
    size_t bufSize,
    off_t pageSize,
    size_t& amountSucceeded) {
  // Linux' unmap/mlock/munlock take a kernel semaphore and block other threads
  // from doing other memory operations. If the size of the buffer is big the
  // semaphore can be down for seconds (for benchmarks see
  // http://kostja-osipov.livejournal.com/42963.html).  Doing the operations in
  // chunks breaks the locking into intervals and lets other threads do memory
  // operations of their own.

  size_t chunkSize = size_t(memOpChunkSize(off_t(bufSize), pageSize));

  char* addr = static_cast<char*>(mem);
  amountSucceeded = 0;

  while (amountSucceeded < bufSize) {
    size_t size = std::min(chunkSize, bufSize - amountSucceeded);
    if (op(addr + amountSucceeded, size) != 0) {
      return false;
    }
    amountSucceeded += size;
  }

  return true;
}

/**
 * mlock2 is Linux-only and exists since Linux 4.4
 * On Linux pre-4.4 and other platforms fail with ENOSYS.
 * glibc added the mlock2 wrapper in 2.27
 * https://lists.gnu.org/archive/html/info-gnu/2018-02/msg00000.html
 */
int mlock2wrapper(
    const void* addr,
    size_t len,
    MemoryMapping::LockFlags flags) {
  int intFlags = 0;
  if (flags.lockOnFault) {
    // MLOCK_ONFAULT, only available in non-portable headers.
    intFlags |= 0x01;
  }

#if defined(__GLIBC__) && !defined(__APPLE__)
#if __GLIBC_PREREQ(2, 27)
  return mlock2(addr, len, intFlags);
#elif defined(SYS_mlock2)
  // SYS_mlock2 is defined in Linux headers since 4.4
  return syscall(SYS_mlock2, addr, len, intFlags);
#else // !__GLIBC_PREREQ(2, 27) && !defined(SYS_mlock2)
  errno = ENOSYS;
  return -1;
#endif
#else // !defined(__GLIBC__) || defined(__APPLE__)
  errno = ENOSYS;
  return -1;
#endif
}

} // namespace

bool MemoryMapping::mlock(LockMode mode, LockFlags flags) {
  size_t amountSucceeded = 0;
  locked_ = memOpInChunks(
      [flags](void* addr, size_t len) -> int {
        // If no flags are set, mlock2() behaves exactly the same as
        // mlock(). Prefer the portable variant.
        return flags == LockFlags{} ? ::mlock(addr, len)
                                    : mlock2wrapper(addr, len, flags);
      },
      mapStart_,
      size_t(mapLength_),
      options_.pageSize,
      amountSucceeded);
  if (locked_) {
    return true;
  }

  auto msg =
      folly::format("mlock({}) failed at {}", mapLength_, amountSucceeded);
  if (mode == LockMode::TRY_LOCK && errno == EPERM) {
    PLOG(WARNING) << msg;
  } else if (mode == LockMode::TRY_LOCK && errno == ENOMEM) {
    VLOG(1) << msg;
  } else {
    PLOG(FATAL) << msg;
  }

  // only part of the buffer was mlocked, unlock it back
  if (!memOpInChunks(
          ::munlock,
          mapStart_,
          amountSucceeded,
          options_.pageSize,
          amountSucceeded)) {
    PLOG(WARNING) << "munlock()";
  }

  return false;
}

void MemoryMapping::munlock(bool dontneed) {
  if (!locked_) {
    return;
  }

  size_t amountSucceeded = 0;
  if (!memOpInChunks(
          ::munlock,
          mapStart_,
          size_t(mapLength_),
          options_.pageSize,
          amountSucceeded)) {
    PLOG(WARNING) << "munlock()";
  }
  if (mapLength_ && dontneed &&
      ::madvise(mapStart_, size_t(mapLength_), MADV_DONTNEED)) {
    PLOG(WARNING) << "madvise()";
  }
  locked_ = false;
}

void MemoryMapping::hintLinearScan() {
  advise(MADV_SEQUENTIAL);
}

MemoryMapping::~MemoryMapping() {
  if (mapLength_) {
    size_t amountSucceeded = 0;
    if (!memOpInChunks(
            ::munmap,
            mapStart_,
            size_t(mapLength_),
            options_.pageSize,
            amountSucceeded)) {
      PLOG(FATAL) << folly::format(
          "munmap({}) failed at {}", mapLength_, amountSucceeded);
    }
  }
}

void MemoryMapping::advise(int advice) const {
  advise(advice, 0, size_t(mapLength_));
}

void MemoryMapping::advise(int advice, size_t offset, size_t length) const {
  CHECK_LE(offset + length, size_t(mapLength_))
      << " offset: " << offset << " length: " << length
      << " mapLength_: " << mapLength_;

  // Include the entire start page: round down to page boundary.
  const auto offMisalign = offset % options_.pageSize;
  offset -= offMisalign;
  length += offMisalign;

  // Round the last page down to page boundary.
  if (offset + length != size_t(mapLength_)) {
    length -= length % options_.pageSize;
  }

  if (length == 0) {
    return;
  }

  char* mapStart = static_cast<char*>(mapStart_) + offset;
  PLOG_IF(WARNING, ::madvise(mapStart, length, advice)) << "madvise";
}

MemoryMapping& MemoryMapping::operator=(MemoryMapping&& other) {
  swap(other);
  return *this;
}

void MemoryMapping::swap(MemoryMapping& other) noexcept {
  using std::swap;
  swap(this->file_, other.file_);
  swap(this->mapStart_, other.mapStart_);
  swap(this->mapLength_, other.mapLength_);
  swap(this->options_, other.options_);
  swap(this->locked_, other.locked_);
  swap(this->data_, other.data_);
}

void swap(MemoryMapping& a, MemoryMapping& b) noexcept {
  a.swap(b);
}

void alignedForwardMemcpy(void* dst, const void* src, size_t size) {
  assert(reinterpret_cast<uintptr_t>(src) % alignof(unsigned long) == 0);
  assert(reinterpret_cast<uintptr_t>(dst) % alignof(unsigned long) == 0);

  auto srcl = static_cast<const unsigned long*>(src);
  auto dstl = static_cast<unsigned long*>(dst);

  while (size >= sizeof(unsigned long)) {
    *dstl++ = *srcl++;
    size -= sizeof(unsigned long);
  }

  auto srcc = reinterpret_cast<const unsigned char*>(srcl);
  auto dstc = reinterpret_cast<unsigned char*>(dstl);

  while (size != 0) {
    *dstc++ = *srcc++;
    --size;
  }
}

void mmapFileCopy(const char* src, const char* dest, mode_t mode) {
  MemoryMapping srcMap(src);
  srcMap.hintLinearScan();

  MemoryMapping destMap(
      File(dest, O_RDWR | O_CREAT | O_TRUNC, mode),
      0,
      off_t(srcMap.range().size()),
      MemoryMapping::writable());

  alignedForwardMemcpy(
      destMap.writableRange().data(),
      srcMap.range().data(),
      srcMap.range().size());
}

bool MemoryMapping::LockFlags::operator==(const LockFlags& other) const {
  return lockOnFault == other.lockOnFault;
}

} // namespace folly
<commit_msg>Change an ifdef to a constexpr ternary<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <folly/system/MemoryMapping.h>

#include <algorithm>
#include <cerrno>
#include <functional>
#include <utility>

#include <glog/logging.h>

#include <folly/Format.h>
#include <folly/Portability.h>
#include <folly/portability/GFlags.h>
#include <folly/portability/SysMman.h>
#include <folly/portability/SysSyscall.h>

#ifdef __linux__
#include <folly/experimental/io/HugePages.h> // @manual
#endif

#include <fcntl.h>
#include <sys/types.h>
#include <system_error>

static constexpr ssize_t kDefaultMlockChunkSize = !folly::kMscVer
    // Linux implementations of unmap/mlock/munlock take a kernel
    // semaphore and block other threads from doing other memory
    // operations. Split the operations in chunks.
    ? (1 << 20) // 1MB
    // MSVC doesn't have this problem, and calling munmap many times
    // with the same address is a bad idea with the windows implementation.
    : (-1);

DEFINE_int64(
    mlock_chunk_size,
    kDefaultMlockChunkSize,
    "Maximum bytes to mlock/munlock/munmap at once "
    "(will be rounded up to PAGESIZE). Ignored if negative.");

namespace folly {

namespace {

enum mmap_flags : int {
#ifdef MAP_POPULATE
  populate = MAP_POPULATE,
#else
  populate = 0,
#endif
};

} // namespace

MemoryMapping::MemoryMapping(MemoryMapping&& other) noexcept {
  swap(other);
}

MemoryMapping::MemoryMapping(
    File file,
    off_t offset,
    off_t length,
    Options options)
    : file_(std::move(file)), options_(std::move(options)) {
  CHECK(file_);
  init(offset, length);
}

MemoryMapping::MemoryMapping(
    const char* name,
    off_t offset,
    off_t length,
    Options options)
    : MemoryMapping(
          File(name, options.writable ? O_RDWR : O_RDONLY),
          offset,
          length,
          options) {}

MemoryMapping::MemoryMapping(
    int fd,
    off_t offset,
    off_t length,
    Options options)
    : MemoryMapping(File(fd), offset, length, options) {}

MemoryMapping::MemoryMapping(AnonymousType, off_t length, Options options)
    : options_(std::move(options)) {
  init(0, length);
}

namespace {

#ifdef __linux__
void getDeviceOptions(dev_t device, off_t& pageSize, bool& autoExtend) {
  auto ps = getHugePageSizeForDevice(device);
  if (ps) {
    pageSize = ps->size;
    autoExtend = true;
  }
}
#else
inline void getDeviceOptions(dev_t, off_t&, bool&) {}
#endif

} // namespace

void MemoryMapping::init(off_t offset, off_t length) {
  const bool grow = options_.grow;
  const bool anon = !file_;
  CHECK(!(grow && anon));

  off_t& pageSize = options_.pageSize;

  struct stat st;

  // On Linux, hugetlbfs file systems don't require ftruncate() to grow the
  // file, and (on kernels before 2.6.24) don't even allow it. Also, the file
  // size is always a multiple of the page size.
  bool autoExtend = false;

  if (!anon) {
    // Stat the file
    CHECK_ERR(fstat(file_.fd(), &st));

    if (pageSize == 0) {
      getDeviceOptions(st.st_dev, pageSize, autoExtend);
    }
  } else {
    DCHECK(!file_);
    DCHECK_EQ(offset, 0);
    CHECK_EQ(pageSize, 0);
    CHECK_GE(length, 0);
  }

  if (pageSize == 0) {
    pageSize = off_t(sysconf(_SC_PAGESIZE));
  }

  CHECK_GT(pageSize, 0);
  CHECK_EQ(pageSize & (pageSize - 1), 0); // power of two
  CHECK_GE(offset, 0);

  // Round down the start of the mapped region
  off_t skipStart = offset % pageSize;
  offset -= skipStart;

  mapLength_ = length;
  if (mapLength_ != -1) {
    mapLength_ += skipStart;

    // Round up the end of the mapped region
    mapLength_ = (mapLength_ + pageSize - 1) / pageSize * pageSize;
  }

  off_t remaining = anon ? length : st.st_size - offset;

  if (mapLength_ == -1) {
    length = mapLength_ = remaining;
  } else {
    if (length > remaining) {
      if (grow) {
        if (!autoExtend) {
          PCHECK(0 == ftruncate(file_.fd(), offset + length))
              << "ftruncate() failed, couldn't grow file to "
              << offset + length;
          remaining = length;
        } else {
          // Extend mapping to multiple of page size, don't use ftruncate
          remaining = mapLength_;
        }
      } else {
        length = remaining;
      }
    }
    if (mapLength_ > remaining) {
      mapLength_ = remaining;
    }
  }

  if (length == 0) {
    mapLength_ = 0;
    mapStart_ = nullptr;
  } else {
    int flags = options_.shared ? MAP_SHARED : MAP_PRIVATE;
    if (anon) {
      flags |= MAP_ANONYMOUS;
    }
    if (options_.prefault) {
      flags |= mmap_flags::populate;
    }

    // The standard doesn't actually require PROT_NONE to be zero...
    int prot = PROT_NONE;
    if (options_.readable || options_.writable) {
      prot =
          ((options_.readable ? PROT_READ : 0) |
           (options_.writable ? PROT_WRITE : 0));
    }

    unsigned char* start = static_cast<unsigned char*>(mmap(
        options_.address, size_t(mapLength_), prot, flags, file_.fd(), offset));
    PCHECK(start != MAP_FAILED)
        << " offset=" << offset << " length=" << mapLength_;
    mapStart_ = start;
    data_.reset(start + skipStart, size_t(length));
  }
}

namespace {

off_t memOpChunkSize(off_t length, off_t pageSize) {
  off_t chunkSize = length;
  if (FLAGS_mlock_chunk_size <= 0) {
    return chunkSize;
  }

  chunkSize = off_t(FLAGS_mlock_chunk_size);
  off_t r = chunkSize % pageSize;
  if (r) {
    chunkSize += (pageSize - r);
  }
  return chunkSize;
}

/**
 * Run @op in chunks over the buffer @mem of @bufSize length.
 *
 * Return:
 * - success: true + amountSucceeded == bufSize (op success on whole buffer)
 * - failure: false + amountSucceeded == nr bytes on which op succeeded.
 */
bool memOpInChunks(
    std::function<int(void*, size_t)> op,
    void* mem,
    size_t bufSize,
    off_t pageSize,
    size_t& amountSucceeded) {
  // Linux' unmap/mlock/munlock take a kernel semaphore and block other threads
  // from doing other memory operations. If the size of the buffer is big the
  // semaphore can be down for seconds (for benchmarks see
  // http://kostja-osipov.livejournal.com/42963.html).  Doing the operations in
  // chunks breaks the locking into intervals and lets other threads do memory
  // operations of their own.

  size_t chunkSize = size_t(memOpChunkSize(off_t(bufSize), pageSize));

  char* addr = static_cast<char*>(mem);
  amountSucceeded = 0;

  while (amountSucceeded < bufSize) {
    size_t size = std::min(chunkSize, bufSize - amountSucceeded);
    if (op(addr + amountSucceeded, size) != 0) {
      return false;
    }
    amountSucceeded += size;
  }

  return true;
}

/**
 * mlock2 is Linux-only and exists since Linux 4.4
 * On Linux pre-4.4 and other platforms fail with ENOSYS.
 * glibc added the mlock2 wrapper in 2.27
 * https://lists.gnu.org/archive/html/info-gnu/2018-02/msg00000.html
 */
int mlock2wrapper(
    const void* addr,
    size_t len,
    MemoryMapping::LockFlags flags) {
  int intFlags = 0;
  if (flags.lockOnFault) {
    // MLOCK_ONFAULT, only available in non-portable headers.
    intFlags |= 0x01;
  }

#if defined(__GLIBC__) && !defined(__APPLE__)
#if __GLIBC_PREREQ(2, 27)
  return mlock2(addr, len, intFlags);
#elif defined(SYS_mlock2)
  // SYS_mlock2 is defined in Linux headers since 4.4
  return syscall(SYS_mlock2, addr, len, intFlags);
#else // !__GLIBC_PREREQ(2, 27) && !defined(SYS_mlock2)
  errno = ENOSYS;
  return -1;
#endif
#else // !defined(__GLIBC__) || defined(__APPLE__)
  errno = ENOSYS;
  return -1;
#endif
}

} // namespace

bool MemoryMapping::mlock(LockMode mode, LockFlags flags) {
  size_t amountSucceeded = 0;
  locked_ = memOpInChunks(
      [flags](void* addr, size_t len) -> int {
        // If no flags are set, mlock2() behaves exactly the same as
        // mlock(). Prefer the portable variant.
        return flags == LockFlags{} ? ::mlock(addr, len)
                                    : mlock2wrapper(addr, len, flags);
      },
      mapStart_,
      size_t(mapLength_),
      options_.pageSize,
      amountSucceeded);
  if (locked_) {
    return true;
  }

  auto msg =
      folly::format("mlock({}) failed at {}", mapLength_, amountSucceeded);
  if (mode == LockMode::TRY_LOCK && errno == EPERM) {
    PLOG(WARNING) << msg;
  } else if (mode == LockMode::TRY_LOCK && errno == ENOMEM) {
    VLOG(1) << msg;
  } else {
    PLOG(FATAL) << msg;
  }

  // only part of the buffer was mlocked, unlock it back
  if (!memOpInChunks(
          ::munlock,
          mapStart_,
          amountSucceeded,
          options_.pageSize,
          amountSucceeded)) {
    PLOG(WARNING) << "munlock()";
  }

  return false;
}

void MemoryMapping::munlock(bool dontneed) {
  if (!locked_) {
    return;
  }

  size_t amountSucceeded = 0;
  if (!memOpInChunks(
          ::munlock,
          mapStart_,
          size_t(mapLength_),
          options_.pageSize,
          amountSucceeded)) {
    PLOG(WARNING) << "munlock()";
  }
  if (mapLength_ && dontneed &&
      ::madvise(mapStart_, size_t(mapLength_), MADV_DONTNEED)) {
    PLOG(WARNING) << "madvise()";
  }
  locked_ = false;
}

void MemoryMapping::hintLinearScan() {
  advise(MADV_SEQUENTIAL);
}

MemoryMapping::~MemoryMapping() {
  if (mapLength_) {
    size_t amountSucceeded = 0;
    if (!memOpInChunks(
            ::munmap,
            mapStart_,
            size_t(mapLength_),
            options_.pageSize,
            amountSucceeded)) {
      PLOG(FATAL) << folly::format(
          "munmap({}) failed at {}", mapLength_, amountSucceeded);
    }
  }
}

void MemoryMapping::advise(int advice) const {
  advise(advice, 0, size_t(mapLength_));
}

void MemoryMapping::advise(int advice, size_t offset, size_t length) const {
  CHECK_LE(offset + length, size_t(mapLength_))
      << " offset: " << offset << " length: " << length
      << " mapLength_: " << mapLength_;

  // Include the entire start page: round down to page boundary.
  const auto offMisalign = offset % options_.pageSize;
  offset -= offMisalign;
  length += offMisalign;

  // Round the last page down to page boundary.
  if (offset + length != size_t(mapLength_)) {
    length -= length % options_.pageSize;
  }

  if (length == 0) {
    return;
  }

  char* mapStart = static_cast<char*>(mapStart_) + offset;
  PLOG_IF(WARNING, ::madvise(mapStart, length, advice)) << "madvise";
}

MemoryMapping& MemoryMapping::operator=(MemoryMapping&& other) {
  swap(other);
  return *this;
}

void MemoryMapping::swap(MemoryMapping& other) noexcept {
  using std::swap;
  swap(this->file_, other.file_);
  swap(this->mapStart_, other.mapStart_);
  swap(this->mapLength_, other.mapLength_);
  swap(this->options_, other.options_);
  swap(this->locked_, other.locked_);
  swap(this->data_, other.data_);
}

void swap(MemoryMapping& a, MemoryMapping& b) noexcept {
  a.swap(b);
}

void alignedForwardMemcpy(void* dst, const void* src, size_t size) {
  assert(reinterpret_cast<uintptr_t>(src) % alignof(unsigned long) == 0);
  assert(reinterpret_cast<uintptr_t>(dst) % alignof(unsigned long) == 0);

  auto srcl = static_cast<const unsigned long*>(src);
  auto dstl = static_cast<unsigned long*>(dst);

  while (size >= sizeof(unsigned long)) {
    *dstl++ = *srcl++;
    size -= sizeof(unsigned long);
  }

  auto srcc = reinterpret_cast<const unsigned char*>(srcl);
  auto dstc = reinterpret_cast<unsigned char*>(dstl);

  while (size != 0) {
    *dstc++ = *srcc++;
    --size;
  }
}

void mmapFileCopy(const char* src, const char* dest, mode_t mode) {
  MemoryMapping srcMap(src);
  srcMap.hintLinearScan();

  MemoryMapping destMap(
      File(dest, O_RDWR | O_CREAT | O_TRUNC, mode),
      0,
      off_t(srcMap.range().size()),
      MemoryMapping::writable());

  alignedForwardMemcpy(
      destMap.writableRange().data(),
      srcMap.range().data(),
      srcMap.range().size());
}

bool MemoryMapping::LockFlags::operator==(const LockFlags& other) const {
  return lockOnFault == other.lockOnFault;
}

} // namespace folly
<|endoftext|>


<commit_before>// Copyright (c) 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.

// This file was forked off the Mac port.

#include "webkit/tools/test_shell/test_webview_delegate.h"

#include <gtk/gtk.h>

#include "base/gfx/point.h"
#include "base/string_util.h"
#include "net/base/net_errors.h"
#include "chrome/common/page_transition_types.h"
#include "webkit/glue/webcursor.h"
#include "webkit/glue/webdatasource.h"
#include "webkit/glue/webdropdata.h"
#include "webkit/glue/weberror.h"
#include "webkit/glue/webframe.h"
#include "webkit/glue/webpreferences.h"
#include "webkit/glue/weburlrequest.h"
#include "webkit/glue/webkit_glue.h"
#include "webkit/glue/webview.h"
#include "webkit/glue/window_open_disposition.h"
#include "webkit/tools/test_shell/test_navigation_controller.h"
#include "webkit/tools/test_shell/test_shell.h"

// WebViewDelegate -----------------------------------------------------------

TestWebViewDelegate::~TestWebViewDelegate() {
}

WebPluginDelegate* TestWebViewDelegate::CreatePluginDelegate(
    WebView* webview,
    const GURL& url,
    const std::string& mime_type,
    const std::string& clsid,
    std::string* actual_mime_type) {
  NOTIMPLEMENTED();
  return NULL;
}

void TestWebViewDelegate::ShowJavaScriptAlert(const std::wstring& message) {
  // TODO(port): remove GTK_WINDOW bit after gfx::WindowHandle is fixed.
  GtkWidget* dialog = gtk_message_dialog_new(
      GTK_WINDOW(shell_->mainWnd()), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO,
      GTK_BUTTONS_OK, "%s", WideToUTF8(message).c_str());
  gtk_window_set_title(GTK_DIALOG(dialog), "JavaScript Alert");
  gtk_dialog_run(GTK_DIALOG(dialog));  // Runs a nested message loop.
  gtk_widget_destroy(dialog);
}

void TestWebViewDelegate::Show(WebWidget* webview,
                               WindowOpenDisposition disposition) {
  NOTIMPLEMENTED();
}

void TestWebViewDelegate::CloseWidgetSoon(WebWidget* webwidget) {
  NOTIMPLEMENTED();
}

void TestWebViewDelegate::SetCursor(WebWidget* webwidget,
                                    const WebCursor& cursor) {
  GdkCursorType cursor_type = cursor.GetCursorType();
  if (cursor_type_ == cursor_type)
    return;

  cursor_type_ = cursor_type;
  if (cursor_type_ == GDK_CURSOR_IS_PIXMAP) {
    NOTIMPLEMENTED();
    cursor_type = GDK_ARROW;  // Just a hack for now.
  }
  GdkCursor* gdk_cursor = gdk_cursor_new(cursor_type);
  gdk_window_set_cursor(shell_->webViewWnd()->window, gdk_cursor);
  // The window now owns the cursor.
  gdk_cursor_unref(gdk_cursor);
}

void TestWebViewDelegate::GetWindowRect(WebWidget* webwidget,
                                        gfx::Rect* out_rect) {
  DCHECK(out_rect);
  //if (WebWidgetHost* host = GetHostForWidget(webwidget)) {
    NOTIMPLEMENTED();
  //}
}

void TestWebViewDelegate::SetWindowRect(WebWidget* webwidget,
                                        const gfx::Rect& rect) {
  // TODO(port): window movement
  if (webwidget == shell_->webView()) {
    // ignored
  } else if (webwidget == shell_->popup()) {
    NOTIMPLEMENTED();
  }
}

void TestWebViewDelegate::GetRootWindowRect(WebWidget* webwidget,
                                            gfx::Rect* out_rect) {
  //if (WebWidgetHost* host = GetHostForWidget(webwidget)) {
    NOTIMPLEMENTED();
  //}
}

void TestWebViewDelegate::RunModal(WebWidget* webwidget) {
  NOTIMPLEMENTED();
}

// Private methods -----------------------------------------------------------

void TestWebViewDelegate::SetPageTitle(const std::wstring& title) {
  gtk_window_set_title(GTK_WINDOW(shell_->mainWnd()),
                       ("Test Shell - " + WideToUTF8(title)).c_str());
}

void TestWebViewDelegate::SetAddressBarURL(const GURL& url) {
  gtk_entry_set_text(GTK_ENTRY(shell_->editWnd()), url.spec().c_str());
}
<commit_msg>Fix Linux build.  I suck.<commit_after>// Copyright (c) 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.

// This file was forked off the Mac port.

#include "webkit/tools/test_shell/test_webview_delegate.h"

#include <gtk/gtk.h>

#include "base/gfx/point.h"
#include "base/string_util.h"
#include "net/base/net_errors.h"
#include "chrome/common/page_transition_types.h"
#include "webkit/glue/webcursor.h"
#include "webkit/glue/webdatasource.h"
#include "webkit/glue/webdropdata.h"
#include "webkit/glue/weberror.h"
#include "webkit/glue/webframe.h"
#include "webkit/glue/webpreferences.h"
#include "webkit/glue/weburlrequest.h"
#include "webkit/glue/webkit_glue.h"
#include "webkit/glue/webview.h"
#include "webkit/glue/window_open_disposition.h"
#include "webkit/tools/test_shell/test_navigation_controller.h"
#include "webkit/tools/test_shell/test_shell.h"

// WebViewDelegate -----------------------------------------------------------

TestWebViewDelegate::~TestWebViewDelegate() {
}

WebPluginDelegate* TestWebViewDelegate::CreatePluginDelegate(
    WebView* webview,
    const GURL& url,
    const std::string& mime_type,
    const std::string& clsid,
    std::string* actual_mime_type) {
  NOTIMPLEMENTED();
  return NULL;
}

void TestWebViewDelegate::ShowJavaScriptAlert(const std::wstring& message) {
  // TODO(port): remove GTK_WINDOW bit after gfx::WindowHandle is fixed.
  GtkWidget* dialog = gtk_message_dialog_new(
      GTK_WINDOW(shell_->mainWnd()), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO,
      GTK_BUTTONS_OK, "%s", WideToUTF8(message).c_str());
  gtk_window_set_title(GTK_WINDOW(dialog), "JavaScript Alert");
  gtk_dialog_run(GTK_DIALOG(dialog));  // Runs a nested message loop.
  gtk_widget_destroy(dialog);
}

void TestWebViewDelegate::Show(WebWidget* webview,
                               WindowOpenDisposition disposition) {
  NOTIMPLEMENTED();
}

void TestWebViewDelegate::CloseWidgetSoon(WebWidget* webwidget) {
  NOTIMPLEMENTED();
}

void TestWebViewDelegate::SetCursor(WebWidget* webwidget,
                                    const WebCursor& cursor) {
  GdkCursorType cursor_type = cursor.GetCursorType();
  if (cursor_type_ == cursor_type)
    return;

  cursor_type_ = cursor_type;
  if (cursor_type_ == GDK_CURSOR_IS_PIXMAP) {
    NOTIMPLEMENTED();
    cursor_type = GDK_ARROW;  // Just a hack for now.
  }
  GdkCursor* gdk_cursor = gdk_cursor_new(cursor_type);
  gdk_window_set_cursor(shell_->webViewWnd()->window, gdk_cursor);
  // The window now owns the cursor.
  gdk_cursor_unref(gdk_cursor);
}

void TestWebViewDelegate::GetWindowRect(WebWidget* webwidget,
                                        gfx::Rect* out_rect) {
  DCHECK(out_rect);
  //if (WebWidgetHost* host = GetHostForWidget(webwidget)) {
    NOTIMPLEMENTED();
  //}
}

void TestWebViewDelegate::SetWindowRect(WebWidget* webwidget,
                                        const gfx::Rect& rect) {
  // TODO(port): window movement
  if (webwidget == shell_->webView()) {
    // ignored
  } else if (webwidget == shell_->popup()) {
    NOTIMPLEMENTED();
  }
}

void TestWebViewDelegate::GetRootWindowRect(WebWidget* webwidget,
                                            gfx::Rect* out_rect) {
  //if (WebWidgetHost* host = GetHostForWidget(webwidget)) {
    NOTIMPLEMENTED();
  //}
}

void TestWebViewDelegate::RunModal(WebWidget* webwidget) {
  NOTIMPLEMENTED();
}

// Private methods -----------------------------------------------------------

void TestWebViewDelegate::SetPageTitle(const std::wstring& title) {
  gtk_window_set_title(GTK_WINDOW(shell_->mainWnd()),
                       ("Test Shell - " + WideToUTF8(title)).c_str());
}

void TestWebViewDelegate::SetAddressBarURL(const GURL& url) {
  gtk_entry_set_text(GTK_ENTRY(shell_->editWnd()), url.spec().c_str());
}
<|endoftext|>


<commit_before>// $Id: parameterSection.C,v 1.15 2001/03/11 21:02:11 anker Exp $

#include <BALL/FORMAT/parameterSection.h>
#include <BALL/FORMAT/parameters.h>

using namespace std;

namespace BALL
{

	const String ParameterSection::UNDEFINED = "(UNDEFINED)";

	ParameterSection::ParameterSection() throw()
		:	section_name_(""),
			format_line_(""),
			section_entries_(),
			variable_names_(),
			entries_(0),
			keys_(0),
			number_of_variables_(0),
			version_(0),
			valid_(false)
	{
	}

	ParameterSection::ParameterSection(const ParameterSection& parameter_section)
		throw()
		:	section_name_(parameter_section.section_name_),
			format_line_(parameter_section.format_line_),
			section_entries_(parameter_section.section_entries_),
			variable_names_(parameter_section.variable_names_),
			entries_(parameter_section.entries_),
			keys_(parameter_section.keys_),
			number_of_variables_(parameter_section.number_of_variables_),
			version_(parameter_section.version_),
			valid_(parameter_section.valid_)
	{
	}

	ParameterSection::~ParameterSection() throw()
	{
		clear();
	}

	void ParameterSection::clear() throw()
	{
		// clear the section name
		section_name_ = "";
		format_line_ = "";

		// destroy all hash maps
		section_entries_.clear();
		variable_names_.clear();

		// clear all allocated entries
		entries_.clear();

		// clear all keys
		keys_.clear();

		// delete the version array
		version_.clear();

		// clear the number of entries/variables
		number_of_variables_ = 0;

		// tag this instance as invalid
		valid_ = false;
	}

	const String& ParameterSection::getSectionName() const
		throw()
	{
		return section_name_;
	}

	bool ParameterSection::extractSection(Parameters& parameters,
			const String& section_name) throw()
 	{
		if (!parameters.isValid())
		{
			return false;
		}

		// this instance is only valid if extractSection works
		valid_ = false;

		// store the section name
		section_name_ = section_name;

		INIFile&  ini_file = parameters.getParameterFile();
		// check for the existence of the required section
		if (!ini_file.hasSection(section_name) ||
				 ini_file.getSectionLength(section_name) == 0)
		{
			return false;
		}

		// if section has the length 0, we are finished
		if (ini_file.getSectionLength(section_name) == 0)
   	{
			 Log.info() << "ParameterSectionFile " << ini_file.getFilename()
									<< " Section " << section_name << "isEmpty." << endl;
   		 return true;
   	}

		// ================================================================
		// loop over all lines and store the format line
		// skip all comment and options lines
		// count the number of non-comment lines

		// count non-comment lines only
		int	number_of_lines = 0;
		String line;
		Size first_line = ini_file.getSectionFirstLine(section_name);
		Size  last_line = ini_file.getSectionLastLine(section_name);

		for (Position i = first_line; i <= last_line; i++)
		{
			// get the line and remove leading white spaces
			if (ini_file.getLine(i) == 0)
			{
				Log.error() << "Error in call to INIFile::getLine(), i = " << i
										<< " , File: << " << ini_file.getFilename() << endl;
				return false;
			}
			line = *ini_file.getLine(i);
			line.trimLeft();

			// skip all empty lines, comments and option lines
			if (line.isEmpty()   ||
					(line[0] == ';') || (line[0] == '!') || (line[0] == '#') || (line[0] == '@'))
			{
				// comment lines start with "!" or ";" or "#"
				// option lines start with "@"
				continue;
			}

			// extract format line: the first non-comment/non-option line
			if (number_of_lines == 0)
			{
				format_line_ = line;
			}

			// count non-comment lines
			number_of_lines++;
		}

		// ===========================================================================
		// interpret the format line

		// f contains the fields resulting from a splitQuoted of the format line
		vector<String> f;
		Size number_of_fields = format_line_.split(f, String::CHARACTER_CLASS__WHITESPACE);

		if (number_of_fields == 0 || number_of_fields > 20)
		{
			Log.error() << "ParameterSection::extractSection: error reading section " << section_name
				<< " of file " << ini_file.getFilename() << ": wrong number of fields in the format line: "
				<< number_of_fields << endl;
			Log.error() << "FORMAT: " << format_line_ << endl;

			return false;
		}

		// Initialisations:

		// keys is an array containing the fields that will be assembled to the line key
		Index	keys[ParameterSection::MAX_FIELDS];
		Size	number_of_keys = 0;
		// variables is an array containing the fields that represent variables
		Index	variables[ParameterSection::MAX_FIELDS];
		Size number_of_variables = 0;
		// clear the old contents of variable_names_
		variable_names_.clear();

		// check every field definition
		for (Position i = 0; i < (Position)number_of_fields; i++)
		{
			if (f[i].hasPrefix("key:"))
			{
				keys[number_of_keys++] = (Index)i;
				continue;
			}

			if (f[i].hasPrefix("value:"))
			{
				// check whether a variable name was given
				String variable_name(f[i].after(":", 0));
				if (variable_name.isEmpty())
				{
					Log.error() << "ParameterSection::extractSection: error while reading section "
											<< section_name << ": empty variable name: " << f[i] << endl;
					continue;
				}

				if (variable_names_.has(variable_name))
				{
					Log.error() << "ParameterSection::extractSection: error while reading section "
											<< section_name << ": duplicate variable name: " << f[i] << endl;
					continue;
				}

				// correct definition: store it.
				variable_names_[variable_name] = (Index)number_of_variables;
				variables[number_of_variables++] = (Index)i;
			}
		}

		if (number_of_keys == 0)
		{
			return false;
		}
		// format line looks ok
		// ======================================================================
		// now extract all non-comment lines

		// true, if each line contains version information
		// indicated by a variable definition named "ver"
		bool check_version(variable_names_.has("ver"));

		// store for faster access
		number_of_variables_ = variable_names_.size();

		// allocate space for all entries
		entries_.clear();
		entries_.resize(number_of_lines * number_of_variables);
		// clear all former contest of the keys_ array
		keys_.clear();
		section_entries_.clear();

		number_of_lines = -1; // skip format line

		for (Position i = first_line; i <= last_line; i++)
		{
			line = *ini_file.getLine(i);
			line.trimLeft();

			// if line is empty or is a comment line, nothing to be done
			if ((line.isEmpty()) ||
					(line[0] == ';') || (line[0] == '!') || (line[0] == '#'))
			{
				continue;
			}

			// options are of the form "@option=value"
			if (line[0] == '@')
			{
				// remove the leading '@'
				line.erase(0, 1);

				// insert the option
				String option_key		= line.before("=");
				String option_value = line.after("=");
				options.set(option_key, option_value);
				continue;
			}

			number_of_lines++;

			// skip format line
			if (number_of_lines == 0)
			{
				continue;
			}

			// now split the line...
			char* c = "\"'";
			number_of_fields = line.splitQuoted(f,String::CHARACTER_CLASS__WHITESPACE, c);

			// assemble the keys
			String key;
			for (Size j = 0; j < number_of_keys; j++)
			{
				key.append(f[keys[j]]);
				if (j != number_of_keys - 1)
				{
					key.append(" ");
				}
			}

			// check whether we have already read this key
			if (check_version && section_entries_.has(key))
			{
				// yes, we do - compare version numbers
				float old_version = entries_[section_entries_[key] * number_of_variables_
															        + variable_names_["ver"]].toFloat();
				float new_version = f[variables[variable_names_["ver"]]].toFloat();
				if (old_version > new_version)
				{
					// key is ignored because a newer version already exists
					continue;
				}

				if (old_version == new_version)
				{
					Log.warn() << "ParameterSection: repeated entry with same version number in line "
										 << number_of_lines << " of section [" << section_name << "] " << endl
										 << "  in file " << ini_file.getFilename() << ": " << line << endl;
					continue;
				}
			}

			// no version checking
			// if this key is new, remember it!
			if (!section_entries_.has(key))
			{
				// add the key to the array of keys
				keys_.push_back(key);

				// insert the key into the hash map
				section_entries_[key] = number_of_lines;
			}

			// copy all variable fields to the corresponding array
			for (Position j = 0; j < (Position)number_of_variables; j++)
			{
				if ((Position)variables[j] < f.size())
				{
					entries_[number_of_lines * number_of_variables_ + j] = f[variables[j]];
				}
			}
		}

		valid_ = true;
		return true;
	}

	bool ParameterSection::has(const String& key, const String& variable) const
		throw()
	{
		return section_entries_.has(key) && variable_names_.has(variable);
	}

	bool ParameterSection::has(const String& key) const throw()
	{
		return section_entries_.has(key);
	}

	const String& ParameterSection::getValue(const String& key,
			const String& variable) const throw()
	{
		// check whether the entry exists
		if (!section_entries_.has(key) || !variable_names_.has(variable))
		{
			return UNDEFINED;
		}

		// return the value
		return entries_[section_entries_[key] * number_of_variables_ + variable_names_[variable]];
	}

	const String& ParameterSection::getValue(Size key_index,
			Size variable_index) const throw()
	{
		// check whether the entry exists
		if ((key_index < keys_.size())
				&& (variable_index < number_of_variables_))
		{
			// return the section entry corresponding to the key
			return entries_[(section_entries_[keys_[key_index]]) * number_of_variables_ + variable_index];
		}

		return UNDEFINED;
	}

	const String& ParameterSection::getKey(Position key_index) const throw()
	{
		// check whether the entry exists
		if ((key_index >= section_entries_.size()))
		{
			return UNDEFINED;
		}

		// return the value
		return keys_[key_index];
	}

	Size ParameterSection::getNumberOfKeys() const throw()
	{
		return keys_.size();
	}

	Size ParameterSection::getNumberOfVariables() const throw()
	{
		return number_of_variables_;
	}

	bool ParameterSection::hasVariable(const String& variable) const throw()
	{
		return variable_names_.has(variable);
	}

	Position ParameterSection::getColumnIndex(const String& variable) const
		throw()
	{
		if (variable_names_.has(variable))
		{
			return variable_names_[variable];
		}

		return INVALID_POSITION;
	}

	const ParameterSection& ParameterSection::operator =
		(const ParameterSection& section) throw()
	{
		options = section.options;
		section_name_ = section.section_name_;
		format_line_ = section.format_line_;
		section_entries_ = section.section_entries_;
		variable_names_ = section.variable_names_;
		entries_ = section.entries_;
		keys_ = section.keys_;
		number_of_variables_ = section.number_of_variables_;
		version_ = section.version_;
		valid_ = section.valid_;

		return *this;
	}

	bool ParameterSection::isValid() const throw()
	{
		return valid_;
	}

	bool ParameterSection::operator == (const ParameterSection& parameter_section)
		const throw()
	{
		return ( (options == parameter_section.options)
				&& (section_name_ == parameter_section.section_name_)
				&& (format_line_ == parameter_section.format_line_)
				&& (section_entries_ == parameter_section.section_entries_)
				&& (variable_names_ == parameter_section.variable_names_)
				&& (entries_ == parameter_section.entries_)
				&& (keys_ == parameter_section.keys_)
				&& (number_of_variables_ == parameter_section.number_of_variables_)
				&& (version_ == parameter_section.version_)
				&& (valid_ == parameter_section.valid_) );
	}

} // namespace BALL
<commit_msg>cosmetic change<commit_after>// $Id: parameterSection.C,v 1.16 2001/03/12 00:50:35 amoll Exp $

#include <BALL/FORMAT/parameterSection.h>
#include <BALL/FORMAT/parameters.h>

using namespace std;

namespace BALL
{

	const String ParameterSection::UNDEFINED = "(UNDEFINED)";

	ParameterSection::ParameterSection() throw()
		:	section_name_(""),
			format_line_(""),
			section_entries_(),
			variable_names_(),
			entries_(0),
			keys_(0),
			number_of_variables_(0),
			version_(0),
			valid_(false)
	{
	}

	ParameterSection::ParameterSection(const ParameterSection& parameter_section)
		throw()
		:	section_name_(parameter_section.section_name_),
			format_line_(parameter_section.format_line_),
			section_entries_(parameter_section.section_entries_),
			variable_names_(parameter_section.variable_names_),
			entries_(parameter_section.entries_),
			keys_(parameter_section.keys_),
			number_of_variables_(parameter_section.number_of_variables_),
			version_(parameter_section.version_),
			valid_(parameter_section.valid_)
	{
	}

	ParameterSection::~ParameterSection() throw()
	{
		clear();
	}

	void ParameterSection::clear() throw()
	{
		// clear the section name
		section_name_ = "";
		format_line_ = "";

		// destroy all hash maps
		section_entries_.clear();
		variable_names_.clear();

		// clear all allocated entries
		entries_.clear();

		// clear all keys
		keys_.clear();

		// delete the version array
		version_.clear();

		// clear the number of entries/variables
		number_of_variables_ = 0;

		// tag this instance as invalid
		valid_ = false;
	}

	const String& ParameterSection::getSectionName() const
		throw()
	{
		return section_name_;
	}

	bool ParameterSection::extractSection(Parameters& parameters,
			const String& section_name) throw()
 	{
		if (!parameters.isValid())
		{
			return false;
		}

		// this instance is only valid if extractSection works
		valid_ = false;

		// store the section name
		section_name_ = section_name;

		INIFile&  ini_file = parameters.getParameterFile();
		// check for the existence of the required section
		if (!ini_file.hasSection(section_name) ||
				 ini_file.getSectionLength(section_name) == 0)
		{
			return false;
		}

		// if section has the length 0, we are finished
		if (ini_file.getSectionLength(section_name) == 0)
   	{
			 Log.info() << "ParameterSectionFile " << ini_file.getFilename()
									<< " Section " << section_name << "isEmpty." << endl;
   		 return true;
   	}

		// ================================================================
		// loop over all lines and store the format line
		// skip all comment and options lines
		// count the number of non-comment lines

		// count non-comment lines only
		int	number_of_lines = 0;
		String line;
		Size first_line = ini_file.getSectionFirstLine(section_name);
		Size  last_line = ini_file.getSectionLastLine(section_name);

		for (Position i = first_line; i <= last_line; i++)
		{
			// get the line and remove leading white spaces
			if (ini_file.getLine(i) == 0)
			{
				Log.error() << "Error in call to INIFile::getLine(), i = " << i
										<< " , File: << " << ini_file.getFilename() << endl;
				return false;
			}
			line = *ini_file.getLine(i);
			line.trimLeft();

			// skip all empty lines, comments and option lines
			if (line.isEmpty()   ||
					(line[0] == ';') || (line[0] == '!') || (line[0] == '#') || (line[0] == '@'))
			{
				// comment lines start with "!" or ";" or "#"
				// option lines start with "@"
				continue;
			}

			// extract format line: the first non-comment/non-option line
			if (number_of_lines == 0)
			{
				format_line_ = line;
			}

			// count non-comment lines
			number_of_lines++;
		}

		// ===========================================================================
		// interpret the format line

		// f contains the fields resulting from a splitQuoted of the format line
		vector<String> f;
		Size number_of_fields = format_line_.split(f, String::CHARACTER_CLASS__WHITESPACE);

		if (number_of_fields == 0 || number_of_fields > 20)
		{
			Log.error() << "ParameterSection::extractSection: error reading section " << section_name
				<< " of file " << ini_file.getFilename() << ": wrong number of fields in the format line: "
				<< number_of_fields << endl;
			Log.error() << "FORMAT: " << format_line_ << endl;

			return false;
		}

		// Initialisations:

		// keys is an array containing the fields that will be assembled to the line key
		Index	keys[ParameterSection::MAX_FIELDS];
		Size	number_of_keys = 0;
		// variables is an array containing the fields that represent variables
		Index	variables[ParameterSection::MAX_FIELDS];
		Size number_of_variables = 0;
		// clear the old contents of variable_names_
		variable_names_.clear();

		// check every field definition
		for (Position i = 0; i < (Position)number_of_fields; i++)
		{
			if (f[i].hasPrefix("key:"))
			{
				keys[number_of_keys++] = (Index)i;
				continue;
			}

			if (f[i].hasPrefix("value:"))
			{
				// check whether a variable name was given
				String variable_name(f[i].after(":", 0));
				if (variable_name.isEmpty())
				{
					Log.error() << "ParameterSection::extractSection: error while reading section "
											<< section_name << ": empty variable name: " << f[i] << endl;
					continue;
				}

				if (variable_names_.has(variable_name))
				{
					Log.error() << "ParameterSection::extractSection: error while reading section "
											<< section_name << ": duplicate variable name: " << f[i] << endl;
					continue;
				}

				// correct definition: store it.
				variable_names_[variable_name] = (Index)number_of_variables;
				variables[number_of_variables++] = (Index)i;
			}
		}

		if (number_of_keys == 0)
		{
			return false;
		}
		// format line looks ok
		// ======================================================================
		// now extract all non-comment lines

		// true, if each line contains version information
		// indicated by a variable definition named "ver"
		bool check_version(variable_names_.has("ver"));

		// store for faster access
		number_of_variables_ = variable_names_.size();

		// allocate space for all entries
		entries_.clear();
		entries_.resize(number_of_lines * number_of_variables);
		// clear all former contest of the keys_ array
		keys_.clear();
		section_entries_.clear();

		number_of_lines = -1; // skip format line

		for (Position i = first_line; i <= last_line; i++)
		{
			line = *ini_file.getLine(i);
			line.trimLeft();

			// if line is empty or is a comment line, nothing to be done
			if ((line.isEmpty()) ||
					(line[0] == ';') || (line[0] == '!') || (line[0] == '#'))
			{
				continue;
			}

			// options are of the form "@option=value"
			if (line[0] == '@')
			{
				// remove the leading '@'
				line.erase(0, 1);

				// insert the option
				String option_key		= line.before("=");
				String option_value = line.after("=");
				options.set(option_key, option_value);
				continue;
			}

			number_of_lines++;

			// skip format line
			if (number_of_lines == 0)
			{
				continue;
			}

			// now split the line...
			number_of_fields = line.splitQuoted(f,String::CHARACTER_CLASS__WHITESPACE, "\"'");

			// assemble the keys
			String key;
			for (Size j = 0; j < number_of_keys; j++)
			{
				key.append(f[keys[j]]);
				if (j != number_of_keys - 1)
				{
					key.append(" ");
				}
			}

			// check whether we have already read this key
			if (check_version && section_entries_.has(key))
			{
				// yes, we do - compare version numbers
				float old_version = entries_[section_entries_[key] * number_of_variables_
															        + variable_names_["ver"]].toFloat();
				float new_version = f[variables[variable_names_["ver"]]].toFloat();
				if (old_version > new_version)
				{
					// key is ignored because a newer version already exists
					continue;
				}

				if (old_version == new_version)
				{
					Log.warn() << "ParameterSection: repeated entry with same version number in line "
										 << number_of_lines << " of section [" << section_name << "] " << endl
										 << "  in file " << ini_file.getFilename() << ": " << line << endl;
					continue;
				}
			}

			// no version checking
			// if this key is new, remember it!
			if (!section_entries_.has(key))
			{
				// add the key to the array of keys
				keys_.push_back(key);

				// insert the key into the hash map
				section_entries_[key] = number_of_lines;
			}

			// copy all variable fields to the corresponding array
			for (Position j = 0; j < (Position)number_of_variables; j++)
			{
				if ((Position)variables[j] < f.size())
				{
					entries_[number_of_lines * number_of_variables_ + j] = f[variables[j]];
				}
			}
		}

		valid_ = true;
		return true;
	}

	bool ParameterSection::has(const String& key, const String& variable) const
		throw()
	{
		return section_entries_.has(key) && variable_names_.has(variable);
	}

	bool ParameterSection::has(const String& key) const throw()
	{
		return section_entries_.has(key);
	}

	const String& ParameterSection::getValue(const String& key,
			const String& variable) const throw()
	{
		// check whether the entry exists
		if (!section_entries_.has(key) || !variable_names_.has(variable))
		{
			return UNDEFINED;
		}

		// return the value
		return entries_[section_entries_[key] * number_of_variables_ + variable_names_[variable]];
	}

	const String& ParameterSection::getValue(Size key_index,
			Size variable_index) const throw()
	{
		// check whether the entry exists
		if ((key_index < keys_.size())
				&& (variable_index < number_of_variables_))
		{
			// return the section entry corresponding to the key
			return entries_[(section_entries_[keys_[key_index]]) * number_of_variables_ + variable_index];
		}

		return UNDEFINED;
	}

	const String& ParameterSection::getKey(Position key_index) const throw()
	{
		// check whether the entry exists
		if ((key_index >= section_entries_.size()))
		{
			return UNDEFINED;
		}

		// return the value
		return keys_[key_index];
	}

	Size ParameterSection::getNumberOfKeys() const throw()
	{
		return keys_.size();
	}

	Size ParameterSection::getNumberOfVariables() const throw()
	{
		return number_of_variables_;
	}

	bool ParameterSection::hasVariable(const String& variable) const throw()
	{
		return variable_names_.has(variable);
	}

	Position ParameterSection::getColumnIndex(const String& variable) const
		throw()
	{
		if (variable_names_.has(variable))
		{
			return variable_names_[variable];
		}

		return INVALID_POSITION;
	}

	const ParameterSection& ParameterSection::operator =
		(const ParameterSection& section) throw()
	{
		options = section.options;
		section_name_ = section.section_name_;
		format_line_ = section.format_line_;
		section_entries_ = section.section_entries_;
		variable_names_ = section.variable_names_;
		entries_ = section.entries_;
		keys_ = section.keys_;
		number_of_variables_ = section.number_of_variables_;
		version_ = section.version_;
		valid_ = section.valid_;

		return *this;
	}

	bool ParameterSection::isValid() const throw()
	{
		return valid_;
	}

	bool ParameterSection::operator == (const ParameterSection& parameter_section)
		const throw()
	{
		return ( (options == parameter_section.options)
				&& (section_name_ == parameter_section.section_name_)
				&& (format_line_ == parameter_section.format_line_)
				&& (section_entries_ == parameter_section.section_entries_)
				&& (variable_names_ == parameter_section.variable_names_)
				&& (entries_ == parameter_section.entries_)
				&& (keys_ == parameter_section.keys_)
				&& (number_of_variables_ == parameter_section.number_of_variables_)
				&& (version_ == parameter_section.version_)
				&& (valid_ == parameter_section.valid_) );
	}

} // namespace BALL
<|endoftext|>


<commit_before>/**
 * @file pot.cpp
 *
 *
 * @date May 25, 2015
 * @author Tack
 */

#include <boost/lexical_cast.hpp>
#include <math.h>

#include "pot.h"
#include "plugin_factory.h"
#include "logger_factory.h"
#include "level.h"
#include "forecast_time.h"
#include "regular_grid.h"
#include "util.h"

using namespace std;
using namespace himan::plugin;

pot::pot()
{
    itsClearTextFormula = "complex formula";

    itsLogger = logger_factory::Instance()->GetLog("pot");
}

void pot::Process(std::shared_ptr<const plugin_configuration> conf)
{
    Init(conf);

    /*
     * Set target parameter properties
     * - name PARM_NAME, this name is found from neons. For example: T-K
     * - univ_id UNIV_ID, newbase-id, ie code table 204
     * - grib1 id must be in database
     * - grib2 descriptor X'Y'Z, http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_table4-2.shtml
     *
     */

    // param theRequestedParam(PARM_NAME, UNIV_ID, GRIB2DISCIPLINE, GRIB2CATEGORY, GRIB2NUMBER);
    param POT("POT-PRCNT", 12100, 0, 19, 2);
    // If this param is also used as a source param for other calculations
    // (like for example dewpoint, relative humidity), unit should also be
    // specified

    POT.Unit(kPrcnt);

    SetParams({POT});

    Start();
}

/*
 * Calculate()
 *
 * This function does the actual calculation.
 */

void pot::Calculate(info_t myTargetInfo, unsigned short threadIndex)
{

    /*
     * Required source parameters
     */

    const param CapeParam("CAPE-JKG");
    const param RainParam("RRR-KGM2");
    // ----

    // Current time and level as given to this thread

    forecast_time forecastTime = myTargetInfo->Time();
    level forecastLevel = myTargetInfo->Level();
    forecast_type forecastType = myTargetInfo->ForecastType();

    auto myThreadedLogger = logger_factory::Instance()->GetLog("pot_pluginThread #" + boost::lexical_cast<string> (threadIndex));

    myThreadedLogger->Debug("Calculating time " + static_cast<string> (forecastTime.ValidDateTime()) + " level " + static_cast<string> (forecastLevel));

    info_t CAPEInfo, RRInfo;

    CAPEInfo = Fetch(forecastTime, forecastLevel, CapeParam, forecastType, false);
    RRInfo = Fetch(forecastTime, forecastLevel, RainParam, forecastType, false);

    if (!(CAPEInfo && RRInfo))
    {
        myThreadedLogger->Info("Skipping step " + boost::lexical_cast<string> (forecastTime.Step()) + ", level " + static_cast<string> (forecastLevel));
        return;
    }

    string deviceType = "CPU";

    LOCKSTEP(myTargetInfo, CAPEInfo, RRInfo)
    {
	double POT;
        double CAPE = CAPEInfo->Value();
        double RR = RRInfo->Value();
        double LAT = myTargetInfo->LatLon().Y();

	double PoLift = 0;
	double PoThermoDyn = 0;

        if (CAPE == kFloatMissing || RR == kFloatMissing)
        {
            continue;
        }

	if (CAPE >= 100 && CAPE <= 1000)
	{
		PoThermoDyn = 0.434294482 * log(CAPE) - 2;    //salamoinnin todennäköisyyden on oikeastikin havaittu kasvavan logaritmisesti CAPE-arvojen kasvaessa.
	}

	if (CAPE > 1000)
	{
		PoThermoDyn = 1;
	}

	// Tropiikki käsitellään vähän eri tavalla, koska siellä CAPE <---> salamointi -relaatio on erilainen

	if (LAT <20 && LAT > -20)
	{

		if (CAPE >= 500 && CAPE <= 2000)
		{
			PoThermoDyn = 0.72134752 * log(CAPE) - 4.482892142;
		}

		if (CAPE > 2000)
		{
			PoThermoDyn = 1;
		}
	}

	// Laukaisevan tekijän (Lift) todennäköisyys

	if (RR >= 0.05 && RR <= 5)
   	{
		PoLift  = 0.217147241 * log(RR) + 0.650514998;	// Funktio kasvaa nopeasti logaritmisesti nollasta ykköseen, kun sateen intensiteetti saa arvoja 0.05 ---> 5 mm/h
	}

	if (RR > 5)
   	{
		PoLift = 1;
	}

	//POT on ainesosiensa todennäköisyyksien tulo

	POT = PoLift * PoThermoDyn * 100;

        //return result
        myTargetInfo->Value(POT);
    }

    myThreadedLogger->Info("[" + deviceType + "] Missing values: " + boost::lexical_cast<string> (myTargetInfo->Data().MissingCount()) + "/" + boost::lexical_cast<string> (myTargetInfo->Data().Size()));

}
<commit_msg>change everything<commit_after>/**
 * @file pot.cpp
 *
 *
 * @date May 25, 2015
 * @author Tack
 */

#include <boost/lexical_cast.hpp>
#include <math.h>

#include "pot.h"
#include "plugin_factory.h"
#include "logger_factory.h"
#include "level.h"
#include "forecast_time.h"
#include "regular_grid.h"
#include "util.h"
#include "matrix.h"

using namespace std;
using namespace himan::plugin;

pot::pot()
{
    itsClearTextFormula = "complex formula";

    itsLogger = logger_factory::Instance()->GetLog("pot");
}

void pot::Process(std::shared_ptr<const plugin_configuration> conf)
{
    Init(conf);

    /*
     * Set target parameter properties
     * - name PARM_NAME, this name is found from neons. For example: T-K
     * - univ_id UNIV_ID, newbase-id, ie code table 204
     * - grib1 id must be in database
     * - grib2 descriptor X'Y'Z, http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_table4-2.shtml
     *
     */

    // param theRequestedParam(PARM_NAME, UNIV_ID, GRIB2DISCIPLINE, GRIB2CATEGORY, GRIB2NUMBER);
    param POT("POT-PRCNT", 12100, 0, 19, 2);
    // If this param is also used as a source param for other calculations
    // (like for example dewpoint, relative humidity), unit should also be
    // specified

    POT.Unit(kPrcnt);

    SetParams({POT});

    Start();
}

/*
 * Calculate()
 *
 * This function does the actual calculation.
 */

void pot::Calculate(info_t myTargetInfo, unsigned short threadIndex)
{

    /*
     * Required source parameters
     */

    const param CapeParam("CAPE-JKG");
    const param RainParam("RRR-KGM2");
    // ----

    // Current time and level as given to this thread

    forecast_time forecastTime = myTargetInfo->Time();
    level forecastLevel = myTargetInfo->Level();
    forecast_type forecastType = myTargetInfo->ForecastType();

    auto myThreadedLogger = logger_factory::Instance()->GetLog("pot_pluginThread #" + boost::lexical_cast<string> (threadIndex));

    myThreadedLogger->Debug("Calculating time " + static_cast<string> (forecastTime.ValidDateTime()) + " level " + static_cast<string> (forecastLevel));

    info_t CAPEInfo, RRInfo;

    CAPEInfo = Fetch(forecastTime, forecastLevel, CapeParam, forecastType, false);
    RRInfo = Fetch(forecastTime, forecastLevel, RainParam, forecastType, false);

    if (!(CAPEInfo && RRInfo))
    {
        myThreadedLogger->Info("Skipping step " + boost::lexical_cast<string> (forecastTime.Step()) + ", level " + static_cast<string> (forecastLevel));
        return;
    }

    // käytetään sadeparametrina mallin sateen alueellista keskiarvoa, jotta diskreettejä sadeolioita saadaan vähän levitettyä ympäristöön, tässä toimisi paremmin esim. 30 km säde.
    // Filter RR
    himan::matrix<double> filter_kernel(3,3,1,kFloatMissing);
    filter_kernel_U.Fill(1/9);
    himan::matrix<double> filtered_RR = util::Filter2D(RRInfo->Data(), filter_kernel_U);
    RRInfo->Grid()->Data(filtered_RR);

    string deviceType = "CPU";

    LOCKSTEP(myTargetInfo, CAPEInfo, RRInfo)
    {
	double POT;
        double CAPE_ec = CAPEInfo->Value();
        double RR = RRInfo->Value();
        double LAT = myTargetInfo->LatLon().Y();

	double PoLift_ec = 0;
	double PoThermoDyn_ec = 0;

	// Määritetään salamointi vs. CAPE riippuvuutta varten tarvitaan CAPEn ala- ja ylärajoille yhtälöt. Ala- ja ylärajat muuttuvat leveyspiirin funktiona.
	double lat_abs = abs(LAT);
	double cape_low = -25*lat_abs + 1225;
	double cape_high = -40*lat_abs + 2600;

	// Kiinnitetään cape_low ja high levespiirien 25...45  ulkopuolella vakioarvoihin.
	if (lat_abs <25)
	{
		cape_low = 600;
		cape_high = 1600;
	}

	if (lat_abs > 45)
	{
		cape_low = 100;
		cape_high = 800;
	}

	// CAPE-arvot skaalataan arvoihin 1....10. Ala- ja ylärajat muuttuvat leveyspiirin funktiona.
	double k =  9/(cape_high - cape_low);
	double scaled_cape = k*CAPE_ec + (1- k*cape_low);

	// Leikataan skaalatun CAPEN arvot, jotka menevät yli 10
	if (scaled_cape >10) scaled_cape = 10;

	//Ukkosta suosivan termodynamiikan todennäköisyys
	PoThermoDyn_ec = 0.4343 * log(scaled_cape);      //salamoinnin todennäköisyys kasvaa logaritmisesti CAPE-arvojen kasvaessa.

	// Laukaisevan tekijän (Lift) todennäköisyys kasvaa ennustetun sateen intensiteetin funktiona.
	// Perustelu: Konvektioparametrisointi (eli malli saa nollasta poikkeavaa sademäärää) malleissa käynnistyy useimmiten alueilla, missä mallissa on konvergenssia tai liftiä tarjolla

	if (RR >= 0.05 && RR <= 5)
	{
		PoLift_ec  = 0.217147241 * log(sade) + 0.650514998;  // Funktio kasvaa nopeasti logaritmisesti nollasta ykköseen
	}

	if (RR > 5)
	{
		PoLift_ec  = 1;
	}

	//POT on ainesosiensa todennäköisyyksien tulo
	POT = PoLift_ec * PoThermoDyn_ec * 100;

        //return result
        myTargetInfo->Value(POT);
    }

    myThreadedLogger->Info("[" + deviceType + "] Missing values: " + boost::lexical_cast<string> (myTargetInfo->Data().MissingCount()) + "/" + boost::lexical_cast<string> (myTargetInfo->Data().Size()));

}
<|endoftext|>


<commit_before>#include <boost/python.hpp>
#include <string>

/* VK HEADERS */
#include "version.h"
#include "node.h"

using namespace boost::python;
using valkyrie::Version;
using valkyrie::Node;

BOOST_PYTHON_MODULE (pyvalkyrie)
{
    // version
    class_<Version>("Version", no_init)
            .def("major", &Version::getMajor)
            .staticmethod("major")
            .def("minor", &Version::getMinor)
            .staticmethod("minor")
            .def("patch", &Version::getPatch)
            .staticmethod("patch")
            .def("is_at_least", &Version::isAtLeast)
            .staticmethod("is_at_least")
            .def("name", &Version::getVersion)
            .staticmethod("name")
    ;

    // node
    class_<Node>("Node", init<int, double, double, double>())
            .add_property("id", &Node::get_id)
            .add_property("x" , &Node::get_x)
            .add_property("y" , &Node::get_y)
            .add_property("z" , &Node::get_z)
    ;
}

<commit_msg>preliminary bindings for valkyrie::Model<commit_after>#include <boost/python.hpp>
#include <string>

/* VK HEADERS */
#include "version.h"
#include "node.h"
#include "model.h"

using namespace boost::python;
using namespace valkyrie;

BOOST_PYTHON_MODULE (pyvalkyrie)
{
    // version
    class_<Version>("Version", no_init)
            .def("major", &Version::getMajor)
            .staticmethod("major")
            .def("minor", &Version::getMinor)
            .staticmethod("minor")
            .def("patch", &Version::getPatch)
            .staticmethod("patch")
            .def("is_at_least", &Version::isAtLeast)
            .staticmethod("is_at_least")
            .def("name", &Version::getVersion)
            .staticmethod("name")
    ;

    // node
    class_<Node>("Node", init<int, double, double, double>())
            .add_property("id", &Node::get_id)
            .add_property("x" , &Node::get_x)
            .add_property("y" , &Node::get_y)
            .add_property("z" , &Node::get_z)
    ;

     // model
    class_<Model>("Model", init<const std::string&>())
            .add_property("name", &Model::get_name)
            .def("__str__", &Model::get_name)
            .def("add_node", &Model::addNode)
    ;
}

<|endoftext|>


<commit_before>// Steer TRD QA train for Reconstruction (Clusterizer, Tracking and PID).
//
// Usage:
//   AddTrainPerformanceTRD.C(MC, friends, tasks)
//   tasks : "ALL" or one/more of the following:
//     "EFF"  : TRD Tracking Efficiency
//     "EFFC" : TRD Tracking Efficiency Combined (barrel + stand alone) - only in case of simulations
//     "MULT"  : TRD single track selection
//     "RES"  : TRD tracking Resolution
//     "CLRES": clusters Resolution
//     "CAL"  : TRD calibration
//     "ALGN" : TRD alignment
//     "PID"  : TRD PID - pion efficiency
//     "PIDR" : TRD PID - reference data
//     "DET"  : Basic TRD Detector checks
//     "NOFR" : Data set does not have AliESDfriends.root
//     "NOMC" : Data set does not have Monte Carlo Informations (real data), so all tasks which rely
//              on MC information are switched off
//
// In compiled mode :
// Don't forget to load first the libraries
// gSystem->Load("libMemStat.so")
// gSystem->Load("libMemStatGui.so")
// gSystem->Load("libANALYSIS.so")
// gSystem->Load("libANALYSISalice.so")
// gSystem->Load("libPWG1.so");
//
// Authors:
//   Alex Bercuci (A.Bercuci@gsi.de)
//   Markus Fasel (m.Fasel@gsi.de)

#if ! defined (__CINT__) || defined (__MAKECINT__)
//#ifndef __CINT__
#include <Riostream.h>

#include "TStopwatch.h"
#include "TMemStat.h"
#include "TMemStatViewerGUI.h"

#include "TROOT.h"
#include "TClass.h"
#include "TSystem.h"
#include "TString.h"
#include "TError.h"
#include "TChain.h"
#include "TGrid.h"
#include "TAlienCollection.h"
#include "TGridCollection.h"
#include "TGridResult.h"
#include "TGeoGlobalMagField.h"

#include "AliMagF.h"
#include "AliTracker.h"
#include "AliLog.h"
#include "AliCDBManager.h"
#include "AliGRPManager.h"
#include "AliGeomManager.h"
#include "AliAnalysisManager.h"
#include "AliAnalysisDataContainer.h"
#include "AliMCEventHandler.h"
#include "AliESDInputHandler.h"

#include "TRD/AliTRDtrackerV1.h"
#include "TRD/AliTRDcalibDB.h"

#include "PWG1/TRD/macros/AliTRDperformanceTrain.h"
#include "PWG1/TRD/macros/AddTRDcheckESD.C"
#include "PWG1/TRD/macros/AddTRDinfoGen.C"
#include "PWG1/TRD/macros/AddTRDcheckDET.C"
#include "PWG1/TRD/macros/AddTRDefficiency.C"
#include "PWG1/TRD/macros/AddTRDresolution.C"
#include "PWG1/TRD/macros/AddTRDcheckPID.C"
#include "PWG1/TRD/macros/AddTRDv0Monitor.C"
#endif

#include "../TRD/macros/AliTRDperformanceTrain.h"
const Char_t* Translate(Bool_t doCheckESD=kTRUE, Bool_t doCheckDET=kTRUE, Bool_t doEffic=kTRUE, Bool_t doResolution=kTRUE, Bool_t doCheckPID=kTRUE, Bool_t doV0Monitor=kTRUE);
Bool_t AddTrainPerformanceTRD(Char_t *trd="ALL", const Char_t *addMacroPath = "$ALICE_ROOT/PWG1/TRD/macros")
{
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if(!mgr) {
    Error("AddTrainPerformanceTRD", "AliAnalysisManager not set!");
    return kFALSE;
  }

  // TRD data containers
  AliAnalysisDataContainer *ci[kNOutSlots];
  AliAnalysisDataContainer *ce[5];

  // initialize TRD settings
  AliTRDcalibDB *cal = AliTRDcalibDB::Instance();
  AliTRDtrackerV1::SetNTimeBins(cal->GetNumberOfTimeBinsDCS());
  Info("AddTrainPerformanceTRD", Form("Add Macros taken from %s", addMacroPath));
  Info("AddTrainPerformanceTRD", Form("TRD wagons \"%s\"", trd));
  for(Int_t it=0; it<NTRDQATASKS; it++){
    if(gROOT->LoadMacro(Form("%s/Add%s.C+", addMacroPath, TString(fgkTRDtaskClassName[it])(3,20).Data()))) {
      Error("AddTrainPerformanceTRD()", Form("Error loading %s task.", fgkTRDtaskClassName[it]));
      return kFALSE;
    }

    switch(it){
    case kCheckESD:
      AddTRDcheckESD(mgr); break;
    case kInfoGen:
      AddTRDinfoGen(mgr, trd, NULL, ci); break;
    case kCheckDET:
      // map slots
      ce[0]=ci[kEventInfo];
      ce[1]=ci[kTracksBarrel];
      ce[2]=ci[kTracksSA];
      ce[3]=ci[kTracksKink];
      AddTRDcheckDET(mgr, trd, ce);
       break;
    case kEfficiency:
      // map slots
      ce[0]=ci[kTracksBarrel];
      ce[1]=ci[kTracksSA];
      ce[2]=ci[kTracksKink];
      AddTRDefficiency(mgr, trd, ce);
      break;
    case kResolution:
      // map slots
      ce[0]=ci[kTracksBarrel];
      ce[1]=ci[kTracksSA];
      ce[2]=ci[kTracksKink];
      AddTRDresolution(mgr, trd, ce);
      break;
    case kCheckPID:
      // map slots
      ce[0]=ci[kTracksBarrel];
      ce[1]=ci[kV0List];
      AddTRDcheckPID(mgr, trd, ce, &ce[2]);
      break;
    case kV0Monitor:
      // slots already mapped by checkPID
      AddTRDv0Monitor(mgr, trd, ce);
      break;
    default:
      Warning("AddTrainPerformanceTRD()", Form("No performance task registered at slot %d.", it));
    }
  }
  return kTRUE;
}

const Char_t* Translate(Bool_t doCheckESD, Bool_t doCheckDET, Bool_t doEffic, Bool_t doResolution, Bool_t doCheckPID, Bool_t doCheckV0)
{
  TString opt("");
  if( doCheckESD==kTRUE &&
      doCheckDET==kTRUE &&
      doEffic==kTRUE &&
      doResolution==kTRUE &&
      doCheckPID==kTRUE
  ) opt="ALL";
  else{
    Bool_t kINDENT(kFALSE);
    if(doCheckESD){
      opt.Append("ESD");
      kINDENT=kTRUE;
    }
    if(doCheckDET){
      if(kINDENT) opt.Append(" ");
      opt.Append("DET");
      kINDENT = kTRUE;
    }
    if(doEffic){
      if(kINDENT) opt.Append(" ");
      opt.Append("EFF");
      kINDENT=kTRUE;
    }
    if(doResolution){
      if(kINDENT) opt.Append(" ");
      opt.Append("RES");
      kINDENT=kTRUE;
    }
    if(doCheckPID){
      if(kINDENT) opt.Append(" ");
      opt.Append("PID");
      kINDENT=kTRUE;
    }
    if(doCheckV0){
      if(kINDENT) opt.Append(" ");
      opt.Append("V0");
      kINDENT=kTRUE;
    }
  }

  return (const Char_t*)opt.Data();
}

<commit_msg>addition to commit 42743<commit_after>// Steer TRD QA train for Reconstruction (Clusterizer, Tracking and PID).
//
// Usage:
//   AddTrainPerformanceTRD.C(MC, friends, tasks)
//   tasks : "ALL" or one/more of the following:
//     "EFF"  : TRD Tracking Efficiency
//     "EFFC" : TRD Tracking Efficiency Combined (barrel + stand alone) - only in case of simulations
//     "MULT"  : TRD single track selection
//     "RES"  : TRD tracking Resolution
//     "CLRES": clusters Resolution
//     "CAL"  : TRD calibration
//     "ALGN" : TRD alignment
//     "PID"  : TRD PID - pion efficiency
//     "PIDR" : TRD PID - reference data
//     "DET"  : Basic TRD Detector checks
//     "NOFR" : Data set does not have AliESDfriends.root
//     "NOMC" : Data set does not have Monte Carlo Informations (real data), so all tasks which rely
//              on MC information are switched off
//
// In compiled mode :
// Don't forget to load first the libraries
// gSystem->Load("libMemStat.so")
// gSystem->Load("libMemStatGui.so")
// gSystem->Load("libANALYSIS.so")
// gSystem->Load("libANALYSISalice.so")
// gSystem->Load("libPWG1.so");
//
// Authors:
//   Alex Bercuci (A.Bercuci@gsi.de)
//   Markus Fasel (m.Fasel@gsi.de)

#if ! defined (__CINT__) || defined (__MAKECINT__)
//#ifndef __CINT__
#include <Riostream.h>

#include "TStopwatch.h"
#include "TMemStat.h"
#include "TMemStatViewerGUI.h"

#include "TROOT.h"
#include "TClass.h"
#include "TSystem.h"
#include "TString.h"
#include "TError.h"
#include "TChain.h"
#include "TGrid.h"
#include "TAlienCollection.h"
#include "TGridCollection.h"
#include "TGridResult.h"
#include "TGeoGlobalMagField.h"

#include "AliMagF.h"
#include "AliTracker.h"
#include "AliLog.h"
#include "AliCDBManager.h"
#include "AliGRPManager.h"
#include "AliGeomManager.h"
#include "AliAnalysisManager.h"
#include "AliAnalysisDataContainer.h"
#include "AliMCEventHandler.h"
#include "AliESDInputHandler.h"

#include "TRD/AliTRDtrackerV1.h"
#include "TRD/AliTRDcalibDB.h"

#include "PWG1/TRD/macros/AliTRDperformanceTrain.h"
#include "PWG1/TRD/macros/AddTRDcheckESD.C"
#include "PWG1/TRD/macros/AddTRDinfoGen.C"
#include "PWG1/TRD/macros/AddTRDcheckDET.C"
#include "PWG1/TRD/macros/AddTRDefficiency.C"
#include "PWG1/TRD/macros/AddTRDresolution.C"
#include "PWG1/TRD/macros/AddTRDcheckPID.C"
#include "PWG1/TRD/macros/AddTRDv0Monitor.C"
#endif

#include "../TRD/macros/AliTRDperformanceTrain.h"
const Char_t* Translate(Bool_t doCheckESD=kTRUE, Bool_t doCheckDET=kTRUE, Bool_t doEffic=kTRUE, Bool_t doResolution=kTRUE, Bool_t doCheckPID=kTRUE, Bool_t doV0Monitor=kTRUE);
Bool_t AddTrainPerformanceTRD(Char_t *trd="ALL", const Char_t *addMacroPath = "$ALICE_ROOT/PWG1/TRD/macros")
{
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if(!mgr) {
    Error("AddTrainPerformanceTRD", "AliAnalysisManager not set!");
    return kFALSE;
  }

  // TRD data containers
  AliAnalysisDataContainer *ci[kNOutSlots];
  AliAnalysisDataContainer *ce[5];

  Info("AddTrainPerformanceTRD", Form("Add Macros taken from %s", addMacroPath));
  Info("AddTrainPerformanceTRD", Form("TRD wagons \"%s\"", trd));
  for(Int_t it=0; it<NTRDQATASKS; it++){
    if(gROOT->LoadMacro(Form("%s/Add%s.C+", addMacroPath, TString(fgkTRDtaskClassName[it])(3,20).Data()))) {
      Error("AddTrainPerformanceTRD()", Form("Error loading %s task.", fgkTRDtaskClassName[it]));
      return kFALSE;
    }

    switch(it){
    case kCheckESD:
      AddTRDcheckESD(mgr); break;
    case kInfoGen:
      AddTRDinfoGen(mgr, trd, NULL, ci); break;
    case kCheckDET:
      // map slots
      ce[0]=ci[kEventInfo];
      ce[1]=ci[kTracksBarrel];
      ce[2]=ci[kTracksSA];
      ce[3]=ci[kTracksKink];
      AddTRDcheckDET(mgr, trd, ce);
       break;
    case kEfficiency:
      // map slots
      ce[0]=ci[kTracksBarrel];
      ce[1]=ci[kTracksSA];
      ce[2]=ci[kTracksKink];
      AddTRDefficiency(mgr, trd, ce);
      break;
    case kResolution:
      // map slots
      ce[0]=ci[kTracksBarrel];
      ce[1]=ci[kTracksSA];
      ce[2]=ci[kTracksKink];
      AddTRDresolution(mgr, trd, ce);
      break;
    case kCheckPID:
      // map slots
      ce[0]=ci[kTracksBarrel];
      ce[1]=ci[kV0List];
      AddTRDcheckPID(mgr, trd, ce, &ce[2]);
      break;
    case kV0Monitor:
      // slots already mapped by checkPID
      AddTRDv0Monitor(mgr, trd, ce);
      break;
    default:
      Warning("AddTrainPerformanceTRD()", Form("No performance task registered at slot %d.", it));
    }
  }
  return kTRUE;
}

const Char_t* Translate(Bool_t doCheckESD, Bool_t doCheckDET, Bool_t doEffic, Bool_t doResolution, Bool_t doCheckPID, Bool_t doCheckV0)
{
  TString opt("");
  if( doCheckESD==kTRUE &&
      doCheckDET==kTRUE &&
      doEffic==kTRUE &&
      doResolution==kTRUE &&
      doCheckPID==kTRUE
  ) opt="ALL";
  else{
    Bool_t kINDENT(kFALSE);
    if(doCheckESD){
      opt.Append("ESD");
      kINDENT=kTRUE;
    }
    if(doCheckDET){
      if(kINDENT) opt.Append(" ");
      opt.Append("DET");
      kINDENT = kTRUE;
    }
    if(doEffic){
      if(kINDENT) opt.Append(" ");
      opt.Append("EFF");
      kINDENT=kTRUE;
    }
    if(doResolution){
      if(kINDENT) opt.Append(" ");
      opt.Append("RES");
      kINDENT=kTRUE;
    }
    if(doCheckPID){
      if(kINDENT) opt.Append(" ");
      opt.Append("PID");
      kINDENT=kTRUE;
    }
    if(doCheckV0){
      if(kINDENT) opt.Append(" ");
      opt.Append("V0");
      kINDENT=kTRUE;
    }
  }

  return (const Char_t*)opt.Data();
}

<|endoftext|>