<commit_before>#include <ContentForgeTool.h>
#include <ShaderCompiler.h>
#include <Utils.h>
#include <CLI11.hpp>
#include <iostream>
#include <thread>
#include <filesystem>

namespace fs = std::filesystem;

// Set working directory to $(TargetDir)
// Example args:
// -s src/shaders/hlsl_usm/CEGUI.hlsl.meta
// -s src/shaders/hlsl_usm/CEGUI.hlsl
// -s src/shaders

class CLog : public DEMShaderCompiler::ILogDelegate
{
private:

	std::string Prefix;

public:

	CLog(const std::string& TaskID)
	{
		Prefix = "[DLL " + TaskID + "] ";
	}

	virtual void Log(const char* pMessage) override
	{
		// FIXME: not thread safe, just for testing
		std::cout << Prefix << pMessage << std::endl;
	}
};

class CHLSLTool : public CContentForgeTool
{
public:

	std::string _DBPath;
	std::string _InputSignaturesDir;

	CHLSLTool(const std::string& Name, const std::string& Desc, CVersion Version) :
		CContentForgeTool(Name, Desc, Version)
	{
		// Set default before parsing command line
		_RootDir = "../../../content";
	}

	virtual void ProcessCommandLine(CLI::App& CLIApp) override
	{
		CContentForgeTool::ProcessCommandLine(CLIApp);
		CLIApp.add_option("--db", _DBPath, "Shader DB file path");
		CLIApp.add_option("--is,--inputsig", _InputSignaturesDir, "Folder where input signature binaries will be saved");
	}

	virtual int Init() override
	{
		if (_DBPath.empty())
			_DBPath = (fs::path(_RootDir) / fs::path("src/shaders/shaders.db3")).string();

		if (_InputSignaturesDir.empty())
			_InputSignaturesDir = (fs::path(_RootDir) / fs::path("shaders/sig")).string();

		if (!DEMShaderCompiler::Init(_DBPath.c_str())) return 1;

		return 0;
	}

	virtual bool ProcessTask(CContentForgeTask& Task) override
	{
		if (_LogVerbosity >= EVerbosity::Debug)
		{
			std::cout << "Source: " << Task.SrcFilePath.generic_string() << std::endl;
			std::cout << "Task: " << Task.TaskID.CStr() << std::endl;
			std::cout << "Thread: " << std::this_thread::get_id() << std::endl;
		}

		const std::string EntryPoint = GetParam<std::string>(Task.Params, "Entry", std::string{});
		if (EntryPoint.empty()) return false;

		const std::string Output = GetParam<std::string>(Task.Params, "Output", std::string{});
		const int Target = GetParam<int>(Task.Params, "Target", 0);
		const std::string Defines = GetParam<std::string>(Task.Params, "Defines", std::string{});
		const bool Debug = GetParam<bool>(Task.Params, "Debug", false);

		EShaderType ShaderType;
		const CStrID Type = GetParam<CStrID>(Task.Params, "Type", CStrID::Empty);
		if (Type == "Vertex") ShaderType = ShaderType_Vertex;
		else if (Type == "Pixel") ShaderType = ShaderType_Pixel;
		else if (Type == "Geometry") ShaderType = ShaderType_Geometry;
		else if (Type == "Hull") ShaderType = ShaderType_Hull;
		else if (Type == "Domain") ShaderType = ShaderType_Domain;
		else return false;

		const std::string TaskID(Task.TaskID.CStr());
		const auto DestPath = fs::path(_RootDir) / fs::path(Output) / (TaskID + ".bin");

		CLog Log(TaskID);

		const auto Code = DEMShaderCompiler::CompileShader(
			Task.SrcFilePath.string().c_str(), DestPath.string().c_str(), _InputSignaturesDir.c_str(),
			ShaderType, Target, EntryPoint.c_str(), Defines.c_str(), Debug, Task.SrcFileData->data(), Task.SrcFileData->size(), &Log);

		return Code == DEM_SHADER_COMPILER_SUCCESS;
	}
};

int main(int argc, const char** argv)
{
	CHLSLTool Tool("cf-hlsl", "HLSL to DeusExMachina resource converter", { 0, 1, 0 });
	return Tool.Execute(argc, argv);
}

/*
"Command line args:\n"
"------------------\n"
"-db [filepath]              path to persistent shader DB,\n"
"                            default: 'Shaders:ShaderDB.db3'\n"
"-d                          build shaders with debug info\n"
"-sm3                        build only old sm3.0 techs, else only\n"
"                            Unified Shader Model techs will be built\n"
"-r                          rebuild shaders even if not changed\n"

int ExitApp(int Code, bool WaitKey);
int CompileEffect(const char* pInFilePath, const char* pOutFilePath, bool Debug, EShaderModel ShaderModel);
int CompileRenderPath(const char* pInFilePath, const char* pOutFilePath, EShaderModel ShaderModel);

int main(int argc, const char** argv)
{
	std::string DB(Args.GetStringArg("-db"));
	bool Debug = Args.GetBoolArg("-d");
	bool Rebuild = Args.GetBoolArg("-r"); //!!!or if tool / DLL version changed (store in DB)!
	EShaderModel ShaderModel = Args.GetBoolArg("-sm3") ? ShaderModel_30 : ShaderModel_USM;

	if (DB.IsEmpty()) DB = "Shaders:ShaderDB.db3";
	if (Rebuild) IOSrv->DeleteFile(DB); //???!!!pass the Rebuild flag inside instead!

#ifdef _DEBUG
	std::string DLLPath = IOSrv->ResolveAssigns("Home:../DEMShaderCompiler/DEMShaderCompiler_d.dll");
#else
	std::string DLLPath = IOSrv->ResolveAssigns("Home:../DEMShaderCompiler/DEMShaderCompiler.dll");
#endif
	std::string OutputDir = PathUtils::GetAbsolutePath(IOSrv->ResolveAssigns("Home:"), IOSrv->ResolveAssigns("Shaders:Bin/"));
	if (!InitDEMShaderCompilerDLL(DLLPath.CStr(), DB.CStr(), OutputDir.CStr())) return ExitApp(ERR_MAIN_FAILED, WaitKey);

	for (size_t i = 0; i < InList.GetCount(); ++i)
	{
		const std::string& InRec = InList[i];
		const std::string& OutRec = OutList[i];

		n_msg(VL_INFO, "Compiling pair %d: '%s' -> '%s'\n", i, InRec.CStr(), OutRec.CStr());

		bool Dir = IOSrv->DirectoryExists(InRec);
		if (!Dir && IOSrv->DirectoryExists(OutRec)) return ExitApp(ERR_IN_OUT_TYPES_DONT_MATCH, WaitKey);

		if (Dir)
		{
			n_msg(VL_ERROR, "Whole directory compilation is not supported yet\n");
			return ExitApp(ERR_NOT_IMPLEMENTED_YET, WaitKey);
		}
		else
		{
			if (!IOSrv->FileExists(InRec)) return ExitApp(ERR_IN_NOT_FOUND, WaitKey);
			int Code = RenderPathes ? CompileRenderPath(InRec, OutRec, ShaderModel) : CompileEffect(InRec, OutRec, Debug, ShaderModel);
			if (Code != 0) return ExitApp(Code, WaitKey);
		}
	}

	return ExitApp(SUCCESS, WaitKey);
}
//---------------------------------------------------------------------

int ExitApp(int Code, bool WaitKey)
{
	if (!TermDEMShaderCompilerDLL())
	{
		n_msg(VL_ERROR, "DEM shader compiler was not unloaded cleanly\n");
		Code = ERR_MAIN_FAILED;
	}

	if (Code != SUCCESS) n_msg(VL_ERROR, TOOL_NAME" v"VERSION": Error occurred with code %d\n", Code);

	if (WaitKey)
	{
		Sys::Log("\nPress any key to exit...\n");
		_getch();
	}

	return Code;
}
//---------------------------------------------------------------------
*/<commit_msg>Dead code removed<commit_after>#include <ContentForgeTool.h>
#include <ShaderCompiler.h>
#include <Utils.h>
#include <CLI11.hpp>
#include <thread>
#include <filesystem>

namespace fs = std::filesystem;

// Set working directory to $(TargetDir)
// Example args:
// -s src/shaders/hlsl_usm/CEGUI.hlsl.meta
// -s src/shaders/hlsl_usm/CEGUI.hlsl
// -s src/shaders

class CLog : public DEMShaderCompiler::ILogDelegate
{
private:

	std::string Prefix;

public:

	CLog(const std::string& TaskID)
	{
		Prefix = "[DLL " + TaskID + "] ";
	}

	virtual void Log(const char* pMessage) override
	{
		// FIXME: not thread safe, just for testing
		std::cout << Prefix << pMessage << std::endl;
	}
};

class CHLSLTool : public CContentForgeTool
{
public:

	std::string _DBPath;
	std::string _InputSignaturesDir;

	CHLSLTool(const std::string& Name, const std::string& Desc, CVersion Version) :
		CContentForgeTool(Name, Desc, Version)
	{
		// Set default before parsing command line
		_RootDir = "../../../content";
	}

	virtual void ProcessCommandLine(CLI::App& CLIApp) override
	{
		CContentForgeTool::ProcessCommandLine(CLIApp);
		CLIApp.add_option("--db", _DBPath, "Shader DB file path");
		CLIApp.add_option("--is,--inputsig", _InputSignaturesDir, "Folder where input signature binaries will be saved");
	}

	virtual int Init() override
	{
		if (_DBPath.empty())
			_DBPath = (fs::path(_RootDir) / fs::path("src/shaders/shaders.db3")).string();

		if (_InputSignaturesDir.empty())
			_InputSignaturesDir = (fs::path(_RootDir) / fs::path("shaders/sig")).string();

		if (!DEMShaderCompiler::Init(_DBPath.c_str())) return 1;

		return 0;
	}

	virtual bool ProcessTask(CContentForgeTask& Task) override
	{
		if (_LogVerbosity >= EVerbosity::Debug)
		{
			std::cout << "Source: " << Task.SrcFilePath.generic_string() << std::endl;
			std::cout << "Task: " << Task.TaskID.CStr() << std::endl;
			std::cout << "Thread: " << std::this_thread::get_id() << std::endl;
		}

		const std::string EntryPoint = GetParam<std::string>(Task.Params, "Entry", std::string{});
		if (EntryPoint.empty()) return false;

		const std::string Output = GetParam<std::string>(Task.Params, "Output", std::string{});
		const int Target = GetParam<int>(Task.Params, "Target", 0);
		const std::string Defines = GetParam<std::string>(Task.Params, "Defines", std::string{});
		const bool Debug = GetParam<bool>(Task.Params, "Debug", false);

		EShaderType ShaderType;
		const CStrID Type = GetParam<CStrID>(Task.Params, "Type", CStrID::Empty);
		if (Type == "Vertex") ShaderType = ShaderType_Vertex;
		else if (Type == "Pixel") ShaderType = ShaderType_Pixel;
		else if (Type == "Geometry") ShaderType = ShaderType_Geometry;
		else if (Type == "Hull") ShaderType = ShaderType_Hull;
		else if (Type == "Domain") ShaderType = ShaderType_Domain;
		else return false;

		const std::string TaskID(Task.TaskID.CStr());
		const auto DestPath = fs::path(_RootDir) / fs::path(Output) / (TaskID + ".bin");

		CLog Log(TaskID);

		const auto Code = DEMShaderCompiler::CompileShader(
			Task.SrcFilePath.string().c_str(), DestPath.string().c_str(), _InputSignaturesDir.c_str(),
			ShaderType, Target, EntryPoint.c_str(), Defines.c_str(), Debug, Task.SrcFileData->data(), Task.SrcFileData->size(), &Log);

		return Code == DEM_SHADER_COMPILER_SUCCESS;
	}
};

int main(int argc, const char** argv)
{
	CHLSLTool Tool("cf-hlsl", "HLSL to DeusExMachina resource converter", { 0, 1, 0 });
	return Tool.Execute(argc, argv);
}
<|endoftext|>


<commit_before><commit_msg>10161 - Ant on a Chessboard<commit_after><|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
////////////////////////////////////////////////////////////////////////////////

#include "SchedulerFeature.h"

#ifdef _WIN32
#include <stdio.h>
#include <windows.h>
#endif

#include "ApplicationFeatures/ApplicationServer.h"
#include "Basics/ArangoGlobalContext.h"
#include "Basics/WorkMonitor.h"
#include "Logger/LogAppender.h"
#include "ProgramOptions/ProgramOptions.h"
#include "ProgramOptions/Section.h"
#include "RestServer/ServerFeature.h"
#include "Scheduler/Scheduler.h"
#include "V8Server/V8DealerFeature.h"
#include "V8Server/v8-dispatcher.h"

using namespace arangodb;
using namespace arangodb::application_features;
using namespace arangodb::basics;
using namespace arangodb::options;
using namespace arangodb::rest;

Scheduler* SchedulerFeature::SCHEDULER = nullptr;

SchedulerFeature::SchedulerFeature(
    application_features::ApplicationServer* server)
    : ApplicationFeature(server, "Scheduler"), _scheduler(nullptr) {
  setOptional(true);
  requiresElevatedPrivileges(false);
  //startsAfter("Database");
  startsAfter("FileDescriptors");
  startsAfter("Logger");
  startsAfter("WorkMonitor");
}

SchedulerFeature::~SchedulerFeature() {}

void SchedulerFeature::collectOptions(
    std::shared_ptr<options::ProgramOptions> options) {
  options->addSection("scheduler", "Configure the I/O scheduler");

  options->addOption("--server.threads", "number of threads",
                     new UInt64Parameter(&_nrServerThreads));

  options->addHiddenOption("--server.minimal-threads",
                           "minimal number of threads",
                           new UInt64Parameter(&_nrMinimalThreads));

  options->addHiddenOption("--server.maximal-threads",
                           "maximal number of threads",
                           new UInt64Parameter(&_nrMaximalThreads));

  options->addOption("--server.maximal-queue-size",
                     "maximum queue length for asynchronous operations",
                     new UInt64Parameter(&_queueSize));

  options->addOldOption("scheduler.threads", "server.threads");
}

void SchedulerFeature::validateOptions(
    std::shared_ptr<options::ProgramOptions>) {
  if (_nrServerThreads == 0) {
    _nrServerThreads = TRI_numberProcessors();
    LOG_TOPIC(DEBUG, arangodb::Logger::FIXME) << "Detected number of processors: " << _nrServerThreads;
  }

  if (_queueSize < 128) {
    LOG_TOPIC(FATAL, arangodb::Logger::FIXME)
        << "invalid value for `--server.maximal-queue-size', need at least 128";
    FATAL_ERROR_EXIT();
  }

  if (_nrMinimalThreads < 2) {
    _nrMinimalThreads = 2;
  }

  if (_nrServerThreads <= _nrMinimalThreads) {
    _nrServerThreads = _nrMinimalThreads;
  }

  if (_nrMaximalThreads == 0) {
    _nrMaximalThreads = 4 * _nrServerThreads;
  }

  if (_nrMaximalThreads < 64) {
    _nrMaximalThreads = 64;
  }

  if (_nrMinimalThreads > _nrMaximalThreads) {
    _nrMaximalThreads = _nrMinimalThreads;
  }

  TRI_ASSERT(0 < _nrMinimalThreads);
  TRI_ASSERT(_nrMinimalThreads <= _nrServerThreads);
  TRI_ASSERT(_nrServerThreads <= _nrMaximalThreads);
}

void SchedulerFeature::start() {
  ArangoGlobalContext::CONTEXT->maskAllSignals();
  buildScheduler();

  bool ok = _scheduler->start(nullptr);

  if (!ok) {
    LOG_TOPIC(FATAL, arangodb::Logger::FIXME) << "the scheduler cannot be started";
    FATAL_ERROR_EXIT();
  }

  buildHangupHandler();

  LOG_TOPIC(DEBUG, Logger::STARTUP) << "scheduler has started";

  V8DealerFeature* dealer =
      ApplicationServer::getFeature<V8DealerFeature>("V8Dealer");

  dealer->defineContextUpdate(
      [](v8::Isolate* isolate, v8::Handle<v8::Context> context, size_t) {
        TRI_InitV8Dispatcher(isolate, context);
      },
      nullptr);
}

void SchedulerFeature::beginShutdown() {
  // shut-down scheduler
  if (_scheduler != nullptr) {
    _scheduler->stopRebalancer();
  }
}

void SchedulerFeature::stop() {
  static size_t const MAX_TRIES = 100;

  // shutdown user jobs (needs the scheduler)
  TRI_ShutdownV8Dispatcher();

  // cancel signals
  if (_exitSignals != nullptr) {
    _exitSignals->cancel();
    _exitSignals.reset();
  }

#ifndef WIN32
  if (_hangupSignals != nullptr) {
    _hangupSignals->cancel();
    _hangupSignals.reset();
  }
#endif

  // clear the handlers stuck in the WorkMonitor
  WorkMonitor::clearHandlers();

  // shut-down scheduler
  _scheduler->beginShutdown();

  for (size_t count = 0; count < MAX_TRIES && _scheduler->isRunning();
       ++count) {
    LOG_TOPIC(TRACE, Logger::STARTUP) << "waiting for scheduler to stop";
    usleep(100000);
  }
}

void SchedulerFeature::unprepare() {
  if (_scheduler != nullptr) {
    _scheduler->shutdown();
  }
  SCHEDULER = nullptr;
}

#ifdef _WIN32
bool CtrlHandler(DWORD eventType) {
  bool shutdown = false;
  std::string shutdownMessage;

  switch (eventType) {
    case CTRL_BREAK_EVENT: {
      shutdown = true;
      shutdownMessage = "control-break received";
      break;
    }

    case CTRL_C_EVENT: {
      shutdown = true;
      shutdownMessage = "control-c received";
      break;
    }

    case CTRL_CLOSE_EVENT: {
      shutdown = true;
      shutdownMessage = "window-close received";
      break;
    }

    case CTRL_LOGOFF_EVENT: {
      shutdown = true;
      shutdownMessage = "user-logoff received";
      break;
    }

    case CTRL_SHUTDOWN_EVENT: {
      shutdown = true;
      shutdownMessage = "system-shutdown received";
      break;
    }

    default: {
      shutdown = false;
      break;
    }
  }

  if (shutdown == false) {
    LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "Invalid CTRL HANDLER event received - ignoring event";
    return true;
  }

  static bool seen = false;

  if (!seen) {
    LOG_TOPIC(INFO, arangodb::Logger::FIXME) << "" << shutdownMessage << ", beginning shut down sequence";

    if (application_features::ApplicationServer::server != nullptr) {
      application_features::ApplicationServer::server->beginShutdown();
    }

    seen = true;
    return true;
  }

  // ........................................................................
  // user is desperate to kill the server!
  // ........................................................................

  LOG_TOPIC(INFO, arangodb::Logger::FIXME) << "" << shutdownMessage << ", terminating";
  _exit(EXIT_FAILURE);  // quick exit for windows
  return true;
}

#endif

void SchedulerFeature::buildScheduler() {
  _scheduler =
      std::make_unique<Scheduler>(static_cast<uint64_t>(_nrMinimalThreads),
                                  static_cast<uint64_t>(_nrServerThreads),
                                  static_cast<uint64_t>(_nrMaximalThreads),
                                  static_cast<uint64_t>(_queueSize));

  SCHEDULER = _scheduler.get();
}

void SchedulerFeature::buildControlCHandler() {
#ifdef WIN32
  {
    int result = SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, true);

    if (result == 0) {
      LOG_TOPIC(WARN, arangodb::Logger::FIXME) << "unable to install control-c handler";
    }
  }
#else

  auto ioService = _scheduler->managerService();
  _exitSignals = std::make_shared<boost::asio::signal_set>(*ioService, SIGINT,
                                                           SIGTERM, SIGQUIT);

  _signalHandler = [this](const boost::system::error_code& error, int number) {
    if (error) {
      return;
    }

    LOG_TOPIC(INFO, arangodb::Logger::FIXME) << "control-c received, beginning shut down sequence";
    server()->beginShutdown();
    _exitSignals->async_wait(_exitHandler);
  };

  _exitHandler = [](const boost::system::error_code& error, int number) {
    if (error) {
      return;
    }

    LOG_TOPIC(FATAL, arangodb::Logger::FIXME) << "control-c received (again!), terminating";
    FATAL_ERROR_EXIT();
  };

  _exitSignals->async_wait(_signalHandler);
#endif
}

void SchedulerFeature::buildHangupHandler() {
#ifndef WIN32
  auto ioService = _scheduler->managerService();

  _hangupSignals =
      std::make_shared<boost::asio::signal_set>(*ioService, SIGHUP);

  _hangupHandler = [this](const boost::system::error_code& error, int number) {
    if (error) {
      return;
    }

    LOG_TOPIC(INFO, arangodb::Logger::FIXME) << "hangup received, about to reopen logfile";
    LogAppender::reopen();
    LOG_TOPIC(INFO, arangodb::Logger::FIXME) << "hangup received, reopened logfile";

    _hangupSignals->async_wait(_hangupHandler);
  };

  _hangupSignals->async_wait(_hangupHandler);
#endif
}
<commit_msg>fix a shutdown error<commit_after>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
////////////////////////////////////////////////////////////////////////////////

#include "SchedulerFeature.h"

#ifdef _WIN32
#include <stdio.h>
#include <windows.h>
#endif

#include "ApplicationFeatures/ApplicationServer.h"
#include "Basics/ArangoGlobalContext.h"
#include "Basics/WorkMonitor.h"
#include "Logger/LogAppender.h"
#include "ProgramOptions/ProgramOptions.h"
#include "ProgramOptions/Section.h"
#include "RestServer/ServerFeature.h"
#include "Scheduler/Scheduler.h"
#include "V8Server/V8DealerFeature.h"
#include "V8Server/v8-dispatcher.h"

using namespace arangodb;
using namespace arangodb::application_features;
using namespace arangodb::basics;
using namespace arangodb::options;
using namespace arangodb::rest;

Scheduler* SchedulerFeature::SCHEDULER = nullptr;

SchedulerFeature::SchedulerFeature(
    application_features::ApplicationServer* server)
    : ApplicationFeature(server, "Scheduler"), _scheduler(nullptr) {
  setOptional(true);
  requiresElevatedPrivileges(false);
  startsAfter("Database");
  startsAfter("FileDescriptors");
  startsAfter("Logger");
  startsAfter("WorkMonitor");
}

SchedulerFeature::~SchedulerFeature() {}

void SchedulerFeature::collectOptions(
    std::shared_ptr<options::ProgramOptions> options) {
  options->addSection("scheduler", "Configure the I/O scheduler");

  options->addOption("--server.threads", "number of threads",
                     new UInt64Parameter(&_nrServerThreads));

  options->addHiddenOption("--server.minimal-threads",
                           "minimal number of threads",
                           new UInt64Parameter(&_nrMinimalThreads));

  options->addHiddenOption("--server.maximal-threads",
                           "maximal number of threads",
                           new UInt64Parameter(&_nrMaximalThreads));

  options->addOption("--server.maximal-queue-size",
                     "maximum queue length for asynchronous operations",
                     new UInt64Parameter(&_queueSize));

  options->addOldOption("scheduler.threads", "server.threads");
}

void SchedulerFeature::validateOptions(
    std::shared_ptr<options::ProgramOptions>) {
  if (_nrServerThreads == 0) {
    _nrServerThreads = TRI_numberProcessors();
    LOG_TOPIC(DEBUG, arangodb::Logger::FIXME) << "Detected number of processors: " << _nrServerThreads;
  }

  if (_queueSize < 128) {
    LOG_TOPIC(FATAL, arangodb::Logger::FIXME)
        << "invalid value for `--server.maximal-queue-size', need at least 128";
    FATAL_ERROR_EXIT();
  }

  if (_nrMinimalThreads < 2) {
    _nrMinimalThreads = 2;
  }

  if (_nrServerThreads <= _nrMinimalThreads) {
    _nrServerThreads = _nrMinimalThreads;
  }

  if (_nrMaximalThreads == 0) {
    _nrMaximalThreads = 4 * _nrServerThreads;
  }

  if (_nrMaximalThreads < 64) {
    _nrMaximalThreads = 64;
  }

  if (_nrMinimalThreads > _nrMaximalThreads) {
    _nrMaximalThreads = _nrMinimalThreads;
  }

  TRI_ASSERT(0 < _nrMinimalThreads);
  TRI_ASSERT(_nrMinimalThreads <= _nrServerThreads);
  TRI_ASSERT(_nrServerThreads <= _nrMaximalThreads);
}

void SchedulerFeature::start() {
  ArangoGlobalContext::CONTEXT->maskAllSignals();
  buildScheduler();

  bool ok = _scheduler->start(nullptr);

  if (!ok) {
    LOG_TOPIC(FATAL, arangodb::Logger::FIXME) << "the scheduler cannot be started";
    FATAL_ERROR_EXIT();
  }

  buildHangupHandler();

  LOG_TOPIC(DEBUG, Logger::STARTUP) << "scheduler has started";

  V8DealerFeature* dealer =
      ApplicationServer::getFeature<V8DealerFeature>("V8Dealer");

  dealer->defineContextUpdate(
      [](v8::Isolate* isolate, v8::Handle<v8::Context> context, size_t) {
        TRI_InitV8Dispatcher(isolate, context);
      },
      nullptr);
}

void SchedulerFeature::beginShutdown() {
  // shut-down scheduler
  if (_scheduler != nullptr) {
    _scheduler->stopRebalancer();
  }
}

void SchedulerFeature::stop() {
  static size_t const MAX_TRIES = 100;

  // shutdown user jobs (needs the scheduler)
  TRI_ShutdownV8Dispatcher();

  // cancel signals
  if (_exitSignals != nullptr) {
    _exitSignals->cancel();
    _exitSignals.reset();
  }

#ifndef WIN32
  if (_hangupSignals != nullptr) {
    _hangupSignals->cancel();
    _hangupSignals.reset();
  }
#endif

  // clear the handlers stuck in the WorkMonitor
  WorkMonitor::clearHandlers();

  // shut-down scheduler
  _scheduler->beginShutdown();

  for (size_t count = 0; count < MAX_TRIES && _scheduler->isRunning();
       ++count) {
    LOG_TOPIC(TRACE, Logger::STARTUP) << "waiting for scheduler to stop";
    usleep(100000);
  }
}

void SchedulerFeature::unprepare() {
  if (_scheduler != nullptr) {
    _scheduler->shutdown();
  }
  SCHEDULER = nullptr;
}

#ifdef _WIN32
bool CtrlHandler(DWORD eventType) {
  bool shutdown = false;
  std::string shutdownMessage;

  switch (eventType) {
    case CTRL_BREAK_EVENT: {
      shutdown = true;
      shutdownMessage = "control-break received";
      break;
    }

    case CTRL_C_EVENT: {
      shutdown = true;
      shutdownMessage = "control-c received";
      break;
    }

    case CTRL_CLOSE_EVENT: {
      shutdown = true;
      shutdownMessage = "window-close received";
      break;
    }

    case CTRL_LOGOFF_EVENT: {
      shutdown = true;
      shutdownMessage = "user-logoff received";
      break;
    }

    case CTRL_SHUTDOWN_EVENT: {
      shutdown = true;
      shutdownMessage = "system-shutdown received";
      break;
    }

    default: {
      shutdown = false;
      break;
    }
  }

  if (shutdown == false) {
    LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "Invalid CTRL HANDLER event received - ignoring event";
    return true;
  }

  static bool seen = false;

  if (!seen) {
    LOG_TOPIC(INFO, arangodb::Logger::FIXME) << "" << shutdownMessage << ", beginning shut down sequence";

    if (application_features::ApplicationServer::server != nullptr) {
      application_features::ApplicationServer::server->beginShutdown();
    }

    seen = true;
    return true;
  }

  // ........................................................................
  // user is desperate to kill the server!
  // ........................................................................

  LOG_TOPIC(INFO, arangodb::Logger::FIXME) << "" << shutdownMessage << ", terminating";
  _exit(EXIT_FAILURE);  // quick exit for windows
  return true;
}

#endif

void SchedulerFeature::buildScheduler() {
  _scheduler =
      std::make_unique<Scheduler>(static_cast<uint64_t>(_nrMinimalThreads),
                                  static_cast<uint64_t>(_nrServerThreads),
                                  static_cast<uint64_t>(_nrMaximalThreads),
                                  static_cast<uint64_t>(_queueSize));

  SCHEDULER = _scheduler.get();
}

void SchedulerFeature::buildControlCHandler() {
#ifdef WIN32
  {
    int result = SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, true);

    if (result == 0) {
      LOG_TOPIC(WARN, arangodb::Logger::FIXME) << "unable to install control-c handler";
    }
  }
#else

  auto ioService = _scheduler->managerService();
  _exitSignals = std::make_shared<boost::asio::signal_set>(*ioService, SIGINT,
                                                           SIGTERM, SIGQUIT);

  _signalHandler = [this](const boost::system::error_code& error, int number) {
    if (error) {
      return;
    }

    LOG_TOPIC(INFO, arangodb::Logger::FIXME) << "control-c received, beginning shut down sequence";
    server()->beginShutdown();
    _exitSignals->async_wait(_exitHandler);
  };

  _exitHandler = [](const boost::system::error_code& error, int number) {
    if (error) {
      return;
    }

    LOG_TOPIC(FATAL, arangodb::Logger::FIXME) << "control-c received (again!), terminating";
    FATAL_ERROR_EXIT();
  };

  _exitSignals->async_wait(_signalHandler);
#endif
}

void SchedulerFeature::buildHangupHandler() {
#ifndef WIN32
  auto ioService = _scheduler->managerService();

  _hangupSignals =
      std::make_shared<boost::asio::signal_set>(*ioService, SIGHUP);

  _hangupHandler = [this](const boost::system::error_code& error, int number) {
    if (error) {
      return;
    }

    LOG_TOPIC(INFO, arangodb::Logger::FIXME) << "hangup received, about to reopen logfile";
    LogAppender::reopen();
    LOG_TOPIC(INFO, arangodb::Logger::FIXME) << "hangup received, reopened logfile";

    _hangupSignals->async_wait(_hangupHandler);
  };

  _hangupSignals->async_wait(_hangupHandler);
#endif
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2016 CNRS
// Author: NMansard
//
//
// This file is part of hpp-pinocchio
// hpp-pinocchio is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either version
// 3 of the License, or (at your option) any later version.
//
// hpp-pinocchio is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Lesser Public License for more details.  You should have
// received a copy of the GNU Lesser General Public License along with
// hpp-pinocchio  If not, see
// <http://www.gnu.org/licenses/>.

#define BOOST_TEST_MODULE tdevice

#include <boost/test/unit_test.hpp>

#include <hpp/model/device.hh>
#include <hpp/model/urdf/util.hh>

#include <hpp/pinocchio/device.hh>
#include <hpp/pinocchio/joint.hh>
#include "../tests/utils.hh"

static bool verbose = false;

//      virtual ~Device() ;
//NOTCHECKED      DevicePtr_t clone()
//NOTCHECKED      DevicePtr_t cloneConst() const
//NOTCHECKED      const std::string& name () const
//      static DevicePtr_t create (const std::string & name);
//NOTCHECKED      static DevicePtr_t createCopy (const DevicePtr_t& device);
//NOTCHECKED      static DevicePtr_t createCopyConst (const DeviceConstPtr_t& device);
//      void model( ModelPtr_t modelPtr )
//      ModelConstPtr_t model() const
//      ModelPtr_t model()
//      void data( DataPtr_t dataPtr )
//      DataConstPtr_t data() const
//      DataPtr_t data()
//      void createData();
//      const JointVector_t& getJointVector () const;
//      JointPtr_t rootJoint () const;
//      JointPtr_t getJointAtConfigRank (const size_type& r) const;
//      JointPtr_t getJointAtVelocityRank (const size_type& r) const;
//      JointPtr_t getJointByName (const std::string& name) const;
//NOTCHECKED      JointPtr_t getJointByBodyName (const std::string& name) const;
//      size_type configSize () const;
//      size_type numberDof () const;
//NOTCHECKED      ExtraConfigSpace& extraConfigSpace ()
//NOTCHECKED      const ExtraConfigSpace& extraConfigSpace () const
//NOTCHECKED      virtual void setDimensionExtraConfigSpace (const size_type& dimension)
//      const Configuration_t& currentConfiguration () const
//      virtual bool currentConfiguration (ConfigurationIn_t configuration);
//NOTCHECKED      Configuration_t neutralConfiguration () const;
//      const vector_t& currentVelocity () const
//      void currentVelocity (vectorIn_t velocity)
//      const vector_t& currentAcceleration () const
//      void currentAcceleration (vectorIn_t acceleration)
//      const value_type& mass () const;
//      vector3_t positionCenterOfMass () const;
//      const ComJacobian_t& jacobianCenterOfMass () const;
//NOTCHECKED      void addGripper (const GripperPtr_t& gripper)
//NOTCHECKED      Grippers_t& grippers ()
//NOTCHECKED      const Grippers_t& grippers () const
//NOTCHECKED      const ObjectVector_t& obstacles (Request_t type) const;
//NOTCHECKED      virtual void addCollisionPairs ;
//NOTCHECKED      virtual void removeCollisionPairs;
//NOTCHECKED      const CollisionPairs_t& collisionPairs (Request_t type) const;
//NOTCHECKED      ObjectIterator objectIterator (Request_t type);
//NOTCHECKED      bool collisionTest () const;
//NOTCHECKED      void computeDistances ();
//NOTCHECKED      const DistanceResults_t& distanceResults () const ;
//NOTCHECKED      void controlComputation (const Computation_t& flag)
//NOTCHECKED      Computation_t computationFlag () const
//NOTCHECKED      virtual void computeForwardKinematics ();
//NOTCHECKED      virtual std::ostream& print (std::ostream& os) const;
// protected:
//      Device(const std::string& name);
//NOTCHECKED      void updateDistances ();
//NOTCHECKED      Device(const Device& device);
//      void resizeState ();
//NOTCHECKED      void resizeJacobians ();
// protected:
//NOTCHECKED      ModelPtr_t model_;
//NOTCHECKED      DataPtr_t data_;
//NOTCHECKED      std::string name_;
//NOTCHECKED      DistanceResults_t distances_;
//NOTCHECKED      Configuration_t currentConfiguration_;
//NOTCHECKED      vector_t currentVelocity_;
//NOTCHECKED      vector_t currentAcceleration_;
//NOTCHECKED      bool upToDate_;
//NOTCHECKED      Computation_t computationFlag_;
//NOTCHECKED      CollisionPairs_t collisionPairs_;
//NOTCHECKED      CollisionPairs_t distancePairs_;
//NOTCHECKED      Grippers_t grippers_;
//NOTCHECKED      ExtraConfigSpace extraConfigSpace_;
//NOTCHECKED      DeviceWkPtr_t weakPtr_;

/* --- UNIT TESTS ----------------------------------------------------------- */
/* --- UNIT TESTS ----------------------------------------------------------- */
/* --- UNIT TESTS ----------------------------------------------------------- */

/* -------------------------------------------------------------------------- */
BOOST_AUTO_TEST_CASE (create)
{
  hpp::model::DevicePtr_t model = hppModel();
  hpp::pinocchio::DevicePtr_t pinocchio = hppPinocchio();

  std::ofstream log ("./tdevice.log");
  log << *(model.get ()) << std::endl;
}

/* -------------------------------------------------------------------------- */
BOOST_AUTO_TEST_CASE (easyGetter)
{
  hpp::model::DevicePtr_t model = hppModel();
  hpp::pinocchio::DevicePtr_t pinocchio = hppPinocchio();

  model->setDimensionExtraConfigSpace(2);
  pinocchio->setDimensionExtraConfigSpace(2);

  /* --- Check NQ NV */
  if(verbose)
    {
      std::cout << "nq = " << model->configSize() << " vs " << pinocchio->configSize() << std::endl;
      std::cout << "nq = " << model->numberDof()  << " vs " << pinocchio->numberDof()  << std::endl;
    }

  BOOST_CHECK ( model->configSize()==pinocchio->configSize() );
  BOOST_CHECK ( model->numberDof() ==pinocchio->numberDof() );

  /* --- Check configuration */
  {
    BOOST_CHECK ( model    ->currentConfiguration().size()==model    ->configSize() );
    BOOST_CHECK ( pinocchio->currentConfiguration().size()==pinocchio->configSize() );
    Eigen::VectorXd q = Eigen::VectorXd::Random( model->configSize() );
    const Eigen::VectorXd qcopy = q;
    model->currentConfiguration(q);
    BOOST_CHECK( model->currentConfiguration() == qcopy );
    q = qcopy;
    pinocchio->currentConfiguration(q);
    BOOST_CHECK( pinocchio->currentConfiguration() == qcopy );
  }

  /* --- Check vel acc */
  {
    BOOST_CHECK ( model    ->currentVelocity().size()==model    ->numberDof() );
    BOOST_CHECK ( pinocchio->currentVelocity().size()==pinocchio->numberDof() );
    BOOST_CHECK ( model    ->currentAcceleration().size()==model    ->numberDof() );
    BOOST_CHECK ( pinocchio->currentAcceleration().size()==pinocchio->numberDof() );

    Eigen::VectorXd q = Eigen::VectorXd::Random( model->numberDof() );
    const Eigen::VectorXd qcopy = q;
    model->currentVelocity(q);
    BOOST_CHECK( model->currentVelocity() == qcopy );
    q = qcopy;
    pinocchio->currentVelocity(q);
    BOOST_CHECK( pinocchio->currentVelocity() == qcopy );
    q = qcopy;
     model->currentAcceleration(q);
    BOOST_CHECK( model->currentAcceleration() == qcopy );
    q = qcopy;
    pinocchio->currentAcceleration(q);
    BOOST_CHECK( pinocchio->currentAcceleration() == qcopy );
  }
}

/* -------------------------------------------------------------------------- */
BOOST_AUTO_TEST_CASE (compute)
{
  hpp::model::DevicePtr_t model = hppModel();
  hpp::pinocchio::DevicePtr_t pinocchio = hppPinocchio();

  Eigen::VectorXd q = Eigen::VectorXd::Random( model->configSize() );
  q[3] += 1.0;
  q.segment<4>(3) /= q.segment<4>(3).norm();

  model->currentConfiguration(q);
  model->controlComputation (hpp::model::Device::ALL);
  model->computeForwardKinematics();

  pinocchio->currentConfiguration(m2p::q(q));
  pinocchio->controlComputation (hpp::pinocchio::Device::ALL);
  pinocchio->computeForwardKinematics();

  if( verbose )
    {
      std::cout << "com_model     = " << model    ->positionCenterOfMass() << std::endl;
      std::cout << "com_pinocchio = " << pinocchio->positionCenterOfMass() << std::endl;

      std::cout << model    ->jacobianCenterOfMass().leftCols<9>() << std::endl;
      std::cout << pinocchio->jacobianCenterOfMass().leftCols<9>() << std::endl;
    }

  BOOST_CHECK( model->mass() == pinocchio->mass() );

  BOOST_CHECK( model->positionCenterOfMass().isApprox
               (pinocchio->positionCenterOfMass()) );

  Eigen::MatrixXd Jmodel     = model    ->jacobianCenterOfMass();
  Eigen::MatrixXd Jpinocchio = pinocchio->jacobianCenterOfMass();
  Eigen::MatrixXd oRb = Jpinocchio.leftCols<3>();

  BOOST_CHECK( (Jmodel    *p2m::Xq(oRb)).isApprox(Jpinocchio) );
  BOOST_CHECK( (Jpinocchio*m2p::Xq(oRb)).isApprox(Jmodel) );
}

void checkJointBound(const hpp::model::JointPtr_t& jm, const hpp::pinocchio::JointPtr_t& jp)
{
  BOOST_CHECK(jp->configSize() == jm->configSize());
  for (int rk = 0; rk < jm->configSize(); ++rk) {
    BOOST_CHECK(jp->isBounded(rk) == jm->isBounded(rk));
    if (jm->isBounded(rk)) {
      BOOST_CHECK(jp->lowerBound(rk) == jm->lowerBound(rk));
      BOOST_CHECK(jp->upperBound(rk) == jm->upperBound(rk));
    }
  }
}

BOOST_AUTO_TEST_CASE(jointAccess)
{
  static bool verbose = true;
  hpp::model::DevicePtr_t model = hppModel();
  hpp::pinocchio::DevicePtr_t pinocchio = hppPinocchio();

  BOOST_CHECK (pinocchio->rootJoint()->rankInConfiguration() == 0);

  if(verbose)
    std::cout << pinocchio->getJointAtConfigRank(0)->name() << " -- "
              <<  pinocchio->rootJoint()->name() <<std::endl;
  BOOST_CHECK (pinocchio->getJointAtConfigRank(0)->name() == pinocchio->rootJoint()->name());

  BOOST_CHECK (pinocchio->getJointAtVelocityRank(0)->name() == pinocchio->rootJoint()->name());

  for (int i=1;i<pinocchio->model()->njoint;++i)
    {
      BOOST_CHECK( pinocchio->getJointAtConfigRank(pinocchio->model()->joints[i].idx_q())->name()
                   == pinocchio->model()->names[i] );
      BOOST_CHECK( pinocchio->getJointAtVelocityRank(pinocchio->model()->joints[i].idx_v())->name()
                   == pinocchio->model()->names[i] );
    }

  hpp::model::JointPtr_t jm = model->getJointVector()[5];
  BOOST_CHECK( pinocchio->getJointByName (jm->name())->name() == jm->name() );

  // Compare the joint vector
  if (verbose)
    std::cout << "\n\nComparing joint vectors\n\n";

  hpp::model::size_type idM = 0;
  hpp::model    ::JointVector_t jvm = model    ->getJointVector();
  hpp::pinocchio::JointVector_t jvp = pinocchio->getJointVector();
  for (int idP=0;idP<jvp.size();++idP)
  {
    // Skip anchor joints for hpp-model
    while(idM < jvm.size() &&
        dynamic_cast<hpp::model::JointAnchor*>(jvm[idM]) != NULL) {
      idM++;
    }
    if(verbose)
      std::cout
        << jvp[idP]->name() << " -- "
        << jvm[idM]->name() << std::endl;
    se3::JointIndex jidP = jvp[idP]->index();
    BOOST_CHECK(jidP == idP + 1);
    if (verbose)
      std::cout << pinocchio->model()->joints[jidP].shortname() << std::endl;

    if (pinocchio->model()->joints[jidP].shortname() == "JointModelFreeFlyer") {
      // The root joint have different names in model and pinocchio
      if (idP == 0) { idM += 2; continue; }
      // Joint is a freeflyer
      std::string nameP = jvp[idP]->name();
      BOOST_CHECK( jvm[idM]->name().compare(0, nameP.length(), nameP) == 0);
      idM++;
      BOOST_CHECK( jvm[idM]->name().compare(0, nameP.length(), nameP) == 0);
      idM++;
    } else {
      // Joint is a neither an anchor nor a freeflyer
      BOOST_CHECK(jvp[idP]->name() == jvm[idM]->name());
      // Check joint bound
      checkJointBound (jvm[idM], jvp[idP]);
      idM++;
    }
  }
  // Check that all the remainings joint of hpp-model are anchor joints.
  while(idM != jvm.size()) {
    BOOST_CHECK(dynamic_cast<hpp::model::JointAnchor*>(jvm[idM]) != NULL);
    idM++;
  }
}
<commit_msg>Add uncomplete check of Joint::currentTransformation<commit_after>//
// Copyright (c) 2016 CNRS
// Author: NMansard
//
//
// This file is part of hpp-pinocchio
// hpp-pinocchio is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either version
// 3 of the License, or (at your option) any later version.
//
// hpp-pinocchio is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Lesser Public License for more details.  You should have
// received a copy of the GNU Lesser General Public License along with
// hpp-pinocchio  If not, see
// <http://www.gnu.org/licenses/>.

#define BOOST_TEST_MODULE tdevice

#include <boost/test/unit_test.hpp>

#include <hpp/model/device.hh>
#include <hpp/model/urdf/util.hh>

#include <hpp/pinocchio/device.hh>
#include <hpp/pinocchio/joint.hh>
#include "../tests/utils.hh"

static bool verbose = false;

//      virtual ~Device() ;
//NOTCHECKED      DevicePtr_t clone()
//NOTCHECKED      DevicePtr_t cloneConst() const
//NOTCHECKED      const std::string& name () const
//      static DevicePtr_t create (const std::string & name);
//NOTCHECKED      static DevicePtr_t createCopy (const DevicePtr_t& device);
//NOTCHECKED      static DevicePtr_t createCopyConst (const DeviceConstPtr_t& device);
//      void model( ModelPtr_t modelPtr )
//      ModelConstPtr_t model() const
//      ModelPtr_t model()
//      void data( DataPtr_t dataPtr )
//      DataConstPtr_t data() const
//      DataPtr_t data()
//      void createData();
//      const JointVector_t& getJointVector () const;
//      JointPtr_t rootJoint () const;
//      JointPtr_t getJointAtConfigRank (const size_type& r) const;
//      JointPtr_t getJointAtVelocityRank (const size_type& r) const;
//      JointPtr_t getJointByName (const std::string& name) const;
//NOTCHECKED      JointPtr_t getJointByBodyName (const std::string& name) const;
//      size_type configSize () const;
//      size_type numberDof () const;
//NOTCHECKED      ExtraConfigSpace& extraConfigSpace ()
//NOTCHECKED      const ExtraConfigSpace& extraConfigSpace () const
//NOTCHECKED      virtual void setDimensionExtraConfigSpace (const size_type& dimension)
//      const Configuration_t& currentConfiguration () const
//      virtual bool currentConfiguration (ConfigurationIn_t configuration);
//NOTCHECKED      Configuration_t neutralConfiguration () const;
//      const vector_t& currentVelocity () const
//      void currentVelocity (vectorIn_t velocity)
//      const vector_t& currentAcceleration () const
//      void currentAcceleration (vectorIn_t acceleration)
//      const value_type& mass () const;
//      vector3_t positionCenterOfMass () const;
//      const ComJacobian_t& jacobianCenterOfMass () const;
//NOTCHECKED      void addGripper (const GripperPtr_t& gripper)
//NOTCHECKED      Grippers_t& grippers ()
//NOTCHECKED      const Grippers_t& grippers () const
//NOTCHECKED      const ObjectVector_t& obstacles (Request_t type) const;
//NOTCHECKED      virtual void addCollisionPairs ;
//NOTCHECKED      virtual void removeCollisionPairs;
//NOTCHECKED      const CollisionPairs_t& collisionPairs (Request_t type) const;
//NOTCHECKED      ObjectIterator objectIterator (Request_t type);
//NOTCHECKED      bool collisionTest () const;
//NOTCHECKED      void computeDistances ();
//NOTCHECKED      const DistanceResults_t& distanceResults () const ;
//NOTCHECKED      void controlComputation (const Computation_t& flag)
//NOTCHECKED      Computation_t computationFlag () const
//NOTCHECKED      virtual void computeForwardKinematics ();
//NOTCHECKED      virtual std::ostream& print (std::ostream& os) const;
// protected:
//      Device(const std::string& name);
//NOTCHECKED      void updateDistances ();
//NOTCHECKED      Device(const Device& device);
//      void resizeState ();
//NOTCHECKED      void resizeJacobians ();
// protected:
//NOTCHECKED      ModelPtr_t model_;
//NOTCHECKED      DataPtr_t data_;
//NOTCHECKED      std::string name_;
//NOTCHECKED      DistanceResults_t distances_;
//NOTCHECKED      Configuration_t currentConfiguration_;
//NOTCHECKED      vector_t currentVelocity_;
//NOTCHECKED      vector_t currentAcceleration_;
//NOTCHECKED      bool upToDate_;
//NOTCHECKED      Computation_t computationFlag_;
//NOTCHECKED      CollisionPairs_t collisionPairs_;
//NOTCHECKED      CollisionPairs_t distancePairs_;
//NOTCHECKED      Grippers_t grippers_;
//NOTCHECKED      ExtraConfigSpace extraConfigSpace_;
//NOTCHECKED      DeviceWkPtr_t weakPtr_;

/* --- UNIT TESTS ----------------------------------------------------------- */
/* --- UNIT TESTS ----------------------------------------------------------- */
/* --- UNIT TESTS ----------------------------------------------------------- */

/* -------------------------------------------------------------------------- */
BOOST_AUTO_TEST_CASE (create)
{
  hpp::model::DevicePtr_t model = hppModel();
  hpp::pinocchio::DevicePtr_t pinocchio = hppPinocchio();

  std::ofstream log ("./tdevice.log");
  log << *(model.get ()) << std::endl;
}

/* -------------------------------------------------------------------------- */
BOOST_AUTO_TEST_CASE (easyGetter)
{
  hpp::model::DevicePtr_t model = hppModel();
  hpp::pinocchio::DevicePtr_t pinocchio = hppPinocchio();

  model->setDimensionExtraConfigSpace(2);
  pinocchio->setDimensionExtraConfigSpace(2);

  /* --- Check NQ NV */
  if(verbose)
    {
      std::cout << "nq = " << model->configSize() << " vs " << pinocchio->configSize() << std::endl;
      std::cout << "nq = " << model->numberDof()  << " vs " << pinocchio->numberDof()  << std::endl;
    }

  BOOST_CHECK ( model->configSize()==pinocchio->configSize() );
  BOOST_CHECK ( model->numberDof() ==pinocchio->numberDof() );

  /* --- Check configuration */
  {
    BOOST_CHECK ( model    ->currentConfiguration().size()==model    ->configSize() );
    BOOST_CHECK ( pinocchio->currentConfiguration().size()==pinocchio->configSize() );
    Eigen::VectorXd q = Eigen::VectorXd::Random( model->configSize() );
    const Eigen::VectorXd qcopy = q;
    model->currentConfiguration(q);
    BOOST_CHECK( model->currentConfiguration() == qcopy );
    q = qcopy;
    pinocchio->currentConfiguration(q);
    BOOST_CHECK( pinocchio->currentConfiguration() == qcopy );
  }

  /* --- Check vel acc */
  {
    BOOST_CHECK ( model    ->currentVelocity().size()==model    ->numberDof() );
    BOOST_CHECK ( pinocchio->currentVelocity().size()==pinocchio->numberDof() );
    BOOST_CHECK ( model    ->currentAcceleration().size()==model    ->numberDof() );
    BOOST_CHECK ( pinocchio->currentAcceleration().size()==pinocchio->numberDof() );

    Eigen::VectorXd q = Eigen::VectorXd::Random( model->numberDof() );
    const Eigen::VectorXd qcopy = q;
    model->currentVelocity(q);
    BOOST_CHECK( model->currentVelocity() == qcopy );
    q = qcopy;
    pinocchio->currentVelocity(q);
    BOOST_CHECK( pinocchio->currentVelocity() == qcopy );
    q = qcopy;
     model->currentAcceleration(q);
    BOOST_CHECK( model->currentAcceleration() == qcopy );
    q = qcopy;
    pinocchio->currentAcceleration(q);
    BOOST_CHECK( pinocchio->currentAcceleration() == qcopy );
  }
}

/* -------------------------------------------------------------------------- */
BOOST_AUTO_TEST_CASE (compute)
{
  hpp::model::DevicePtr_t model = hppModel();
  hpp::pinocchio::DevicePtr_t pinocchio = hppPinocchio();

  Eigen::VectorXd q = Eigen::VectorXd::Random( model->configSize() );
  q[3] += 1.0;
  q.segment<4>(3) /= q.segment<4>(3).norm();

  model->currentConfiguration(q);
  model->controlComputation (hpp::model::Device::ALL);
  model->computeForwardKinematics();

  pinocchio->currentConfiguration(m2p::q(q));
  pinocchio->controlComputation (hpp::pinocchio::Device::ALL);
  pinocchio->computeForwardKinematics();

  // Skip root joint because the name is not the same.
  for (int i=2;i<pinocchio->model()->njoint;++i)
    {
      const std::string& name = pinocchio->model()->names[i];
      hpp::model    ::JointPtr_t jm = model    ->getJointByName (name);
      hpp::pinocchio::JointPtr_t jp = pinocchio->getJointByName (name);

      hpp::model    ::Transform3f tfm = jm->currentTransformation();
      hpp::pinocchio::Transform3f tfp = jp->currentTransformation();

      // The center of the joint frames should be the same.
      BOOST_CHECK( tfm.getTranslation().isApprox(tfp.translation()) );
      // The rotations may be permuted because HPP only has a rotation around X.
      // To be checked using urdf link position (see hpp-constraints/pmdiff/tvalue.cc
    }

  if( verbose )
    {
      std::cout << "com_model     = " << model    ->positionCenterOfMass() << std::endl;
      std::cout << "com_pinocchio = " << pinocchio->positionCenterOfMass() << std::endl;

      std::cout << model    ->jacobianCenterOfMass().leftCols<9>() << std::endl;
      std::cout << pinocchio->jacobianCenterOfMass().leftCols<9>() << std::endl;
    }

  BOOST_CHECK( model->mass() == pinocchio->mass() );

  BOOST_CHECK( model->positionCenterOfMass().isApprox
               (pinocchio->positionCenterOfMass()) );

  Eigen::MatrixXd Jmodel     = model    ->jacobianCenterOfMass();
  Eigen::MatrixXd Jpinocchio = pinocchio->jacobianCenterOfMass();
  Eigen::MatrixXd oRb = Jpinocchio.leftCols<3>();

  BOOST_CHECK( (Jmodel    *p2m::Xq(oRb)).isApprox(Jpinocchio) );
  BOOST_CHECK( (Jpinocchio*m2p::Xq(oRb)).isApprox(Jmodel) );
}

void checkJointBound(const hpp::model::JointPtr_t& jm, const hpp::pinocchio::JointPtr_t& jp)
{
  BOOST_CHECK(jp->configSize() == jm->configSize());
  for (int rk = 0; rk < jm->configSize(); ++rk) {
    BOOST_CHECK(jp->isBounded(rk) == jm->isBounded(rk));
    if (jm->isBounded(rk)) {
      BOOST_CHECK(jp->lowerBound(rk) == jm->lowerBound(rk));
      BOOST_CHECK(jp->upperBound(rk) == jm->upperBound(rk));
    }
  }
}

BOOST_AUTO_TEST_CASE(jointAccess)
{
  static bool verbose = true;
  hpp::model::DevicePtr_t model = hppModel();
  hpp::pinocchio::DevicePtr_t pinocchio = hppPinocchio();

  BOOST_CHECK (pinocchio->rootJoint()->rankInConfiguration() == 0);

  if(verbose)
    std::cout << pinocchio->getJointAtConfigRank(0)->name() << " -- "
              <<  pinocchio->rootJoint()->name() <<std::endl;
  BOOST_CHECK (pinocchio->getJointAtConfigRank(0)->name() == pinocchio->rootJoint()->name());

  BOOST_CHECK (pinocchio->getJointAtVelocityRank(0)->name() == pinocchio->rootJoint()->name());

  for (int i=1;i<pinocchio->model()->njoint;++i)
    {
      BOOST_CHECK( pinocchio->getJointAtConfigRank(pinocchio->model()->joints[i].idx_q())->name()
                   == pinocchio->model()->names[i] );
      BOOST_CHECK( pinocchio->getJointAtVelocityRank(pinocchio->model()->joints[i].idx_v())->name()
                   == pinocchio->model()->names[i] );
    }

  hpp::model::JointPtr_t jm = model->getJointVector()[5];
  BOOST_CHECK( pinocchio->getJointByName (jm->name())->name() == jm->name() );

  // Compare the joint vector
  if (verbose)
    std::cout << "\n\nComparing joint vectors\n\n";

  hpp::model::size_type idM = 0;
  hpp::model    ::JointVector_t jvm = model    ->getJointVector();
  hpp::pinocchio::JointVector_t jvp = pinocchio->getJointVector();
  for (int idP=0;idP<jvp.size();++idP)
  {
    // Skip anchor joints for hpp-model
    while(idM < jvm.size() &&
        dynamic_cast<hpp::model::JointAnchor*>(jvm[idM]) != NULL) {
      idM++;
    }
    if(verbose)
      std::cout
        << jvp[idP]->name() << " -- "
        << jvm[idM]->name() << std::endl;
    se3::JointIndex jidP = jvp[idP]->index();
    BOOST_CHECK(jidP == idP + 1);
    if (verbose)
      std::cout << pinocchio->model()->joints[jidP].shortname() << std::endl;

    if (pinocchio->model()->joints[jidP].shortname() == "JointModelFreeFlyer") {
      // The root joint have different names in model and pinocchio
      if (idP == 0) { idM += 2; continue; }
      // Joint is a freeflyer
      std::string nameP = jvp[idP]->name();
      BOOST_CHECK( jvm[idM]->name().compare(0, nameP.length(), nameP) == 0);
      idM++;
      BOOST_CHECK( jvm[idM]->name().compare(0, nameP.length(), nameP) == 0);
      idM++;
    } else {
      // Joint is a neither an anchor nor a freeflyer
      BOOST_CHECK(jvp[idP]->name() == jvm[idM]->name());
      // Check joint bound
      checkJointBound (jvm[idM], jvp[idP]);
      idM++;
    }
  }
  // Check that all the remainings joint of hpp-model are anchor joints.
  while(idM != jvm.size()) {
    BOOST_CHECK(dynamic_cast<hpp::model::JointAnchor*>(jvm[idM]) != NULL);
    idM++;
  }
}
<|endoftext|>


<commit_before><commit_msg>do not add deprecated limits<commit_after><|endoftext|>


<commit_before>// template impl (included from header)
// #include "hheap.h"

template<typename V>
Node<V>::Node(int32_t _id, V _value) :
    id(_id), value(_value), rank(0), is_hollow(false), is_root(true), next_sibling(
        nullptr), head_childs(nullptr) {
}

template<typename V, typename C>
inline std::vector<Node<V>*>& HollowHeap<V, C>::RootsAtRank(uint32_t rank) {
  if (roots_of_rank_.size() <= rank) {
    uint32_t old_size = roots_of_rank_.size();
    roots_of_rank_.resize(rank + 1, nullptr);
    for (uint32_t i = old_size; i <= rank; ++i) {
      roots_of_rank_[i] = new std::vector<Node<V>*>();
    }
  }

  return *roots_of_rank_[rank];
}

template<typename V, typename C>
HollowHeap<V, C>::HollowHeap() :
    size_(0), comparator_(), min_node_(nullptr), roots_of_rank_(), node_map_(), n_ids_(
        0), node_map_arr_(nullptr) {
}

template<typename V, typename C>
HollowHeap<V, C>::HollowHeap(uint32_t n_ids) :
    size_(0), comparator_(), min_node_(nullptr), roots_of_rank_(), node_map_(), n_ids_(
        n_ids), node_map_arr_(new Node<V>*[n_ids_]) {
  Node<V> **arr = node_map_arr_.get();
  std::fill(arr, arr + n_ids_, nullptr);
}

// return false if id is already inserted
template<typename V, typename C>
bool HollowHeap<V, C>::Push(uint32_t id, V value) {
  if (n_ids_) {
    if (node_map_arr_[id] != nullptr) {
      return false;
    }
  } else {
    if (node_map_.find(id) != node_map_.end()) {
      return false;
    }
  }

  Node<V> *new_node = new Node<V>(id, value);

  if (n_ids_) {
    node_map_arr_[id] = new_node;
  } else {
    node_map_[id] = new_node;
  }

  RootsAtRank(0).emplace_back(new_node);

  ++size_;
  if (min_node_ == nullptr || comparator_(value, min_node_->value)) {
    min_node_ = new_node;
  }
  return true;
}

template<typename V, typename C>
void HollowHeap<V, C>::Push(V value) {
  Node<V> *new_node = new Node<V>(-1, value);

  RootsAtRank(0).emplace_back(new_node);

  ++size_;
  if (min_node_ == nullptr || comparator_(value, min_node_->value)) {
    min_node_ = new_node;
  }
}

template<typename V, typename C>
std::pair<int32_t, V> HollowHeap<V, C>::Top() const {
  return std::make_pair(min_node_->id, min_node_->value);
}

template<typename V, typename C>
inline Node<V>* HollowHeap<V, C>::link(Node<V> *r1, Node<V> *r2) {
  Node<V> *temp;
  if (comparator_(r1->value, r2->value)) {
    temp = r1->head_childs;
    r1->head_childs = r2;
    r2->next_sibling = temp;
    r2->is_root = false;
    ++r1->rank;
    return r1;
  } else {
    temp = r2->head_childs;
    r2->head_childs = r1;
    r1->next_sibling = temp;
    r1->is_root = false;
    ++r2->rank;
    return r2;
  }
}

template<typename V, typename C>
void HollowHeap<V, C>::Pop() {
  Node<V> *temp, *temp_2;
  // remove id & make top hollow
  if (min_node_->id >= 0) {
    if (n_ids_) {
      node_map_arr_[min_node_->id] = nullptr;
    } else {
      node_map_.erase(min_node_->id);
    }
  }
  min_node_->is_hollow = true;

  // recursively remove hollow roots
  for (auto it = roots_of_rank_.rbegin(); it != roots_of_rank_.rend(); ++it) {
    std::vector<Node<V>*> &l = **it;
    uint32_t non_hollow = 0;
    for (uint32_t i = 0; i < l.size(); ++i) {
      if (l[i]->is_hollow) { // hollow node
        Node<V> *current = l[i]->head_childs;
        while (current) {
          roots_of_rank_[current->rank]->emplace_back(current);
          current->is_root = true;
          temp = current;
          current = current->next_sibling;
          temp->next_sibling = nullptr;
        }
        delete l[i];
      } else {
        l[non_hollow++] = l[i];
      }
    }
    l.resize(non_hollow);
  }

  // re-link roots and shrink roots vector
  int32_t max_rank = -1;
  for (uint32_t i = 0; i < roots_of_rank_.size(); ++i) {
    std::vector<Node<V>*> &l = *roots_of_rank_[i];
    if (l.size()) {
      max_rank = l.front()->rank;
    }
    uint32_t num_links = l.size() >> 1;
    while (num_links--) {
      temp = l.back();
      l.pop_back();
      temp_2 = l.back();
      l.pop_back();
      temp = link(temp, temp_2);
      RootsAtRank(temp->rank).emplace_back(temp);
    }
  }
  // shrink roots vector
  for (uint32_t i = max_rank + 1; i < roots_of_rank_.size(); ++i) {
    delete roots_of_rank_[i];
  }
  roots_of_rank_.resize(max_rank + 1);

  // update min-id
  min_node_ = nullptr;
  for (auto it = roots_of_rank_.begin(); it != roots_of_rank_.end(); ++it) {
    std::vector<Node<V>*> &l = **it;
    if (l.size()) {
      if (min_node_ == nullptr || comparator_(l[0]->value, min_node_->value)) {
        min_node_ = l[0];
      }
    }
  }

  // reduce size;
  --size_;
}

// return false if id is not inserted yet, or updating value is invalid
template<typename V, typename C>
bool HollowHeap<V, C>::Update(uint32_t id, V value) {
  Node<V> *current_node;
  if (n_ids_) {
    current_node = node_map_arr_[id];
    if (current_node == nullptr || !comparator_(value, current_node->value)) {
      return false;
    }
  } else {
    auto i = node_map_.find(id);
    if (i == node_map_.end() || !comparator_(value, i->second->value)) {
      return false;
    }
    current_node = i->second;
  }

  // if id is root
  if (current_node->is_root) {
    current_node->value = value;
    if (comparator_(current_node->value, min_node_->value)) {
      min_node_ = current_node;
    }
    return true;
  }

  // make current node hollow
  current_node->is_hollow = true;

  // build new node
  Node<V> *new_node = new Node<V>(id, value);

  if (current_node->rank > 2) {
    new_node->rank = current_node->rank - 2;
    Node<V> *second_child = current_node->head_childs->next_sibling;
    new_node->head_childs = second_child->next_sibling;
    second_child->next_sibling = nullptr;
  }

  if (n_ids_) {
    node_map_arr_[id] = new_node;
  } else {
    node_map_[id] = new_node;
  }
  RootsAtRank(new_node->rank).emplace_back(new_node);

  // update min-id
  if (comparator_(new_node->value, min_node_->value)) {
    min_node_ = new_node;
  }

  return true;
}

template<typename V, typename C>
uint32_t HollowHeap<V, C>::size() const {
  return size_;
}

template<typename V, typename C>
bool HollowHeap<V, C>::empty() const {
  return size_ == 0;
}

template<typename V, typename C>
bool HollowHeap<V, C>::ContainsId(uint32_t id) const {
  if (n_ids_) {
    return node_map_arr_[id] != nullptr;
  } else {
    return node_map_.find(id) != node_map_.end();
  }
}

template<typename V, typename C>
V HollowHeap<V, C>::Get(uint32_t id) const {
  if (n_ids_) {
    return node_map_arr_[id]->value;
  } else {
    return node_map_[id]->value;
  }
}

template<typename V, typename C>
void HollowHeap<V, C>::PopId(uint32_t id) {
  Node<V> *node;
  // find node corresponding to id
  if (n_ids_) {
    node = node_map_arr_[id];
  } else {
    node = node_map_[id];
  }

  // pop
  if (node == min_node_) {
    Pop();
  } else {
    node->is_hollow = true;
    if (n_ids_) {
      node_map_arr_[id] = nullptr;
    } else {
      node_map_.erase(id);
    }
    // reduce size;
    --size_;
  }
}

template<typename V, typename C>
void HollowHeap<V, C>::DeleteNodeRecursively(Node<V> *node) {
  Node<V> *temp;
  while (node->head_childs != nullptr) {
    temp = node->head_childs->next_sibling;
    DeleteNodeRecursively(node->head_childs);
    node->head_childs = temp;
  }
  delete node;
}

template<typename V, typename C>
HollowHeap<V, C>::~HollowHeap() {
  for (auto it = roots_of_rank_.begin(); it != roots_of_rank_.end(); ++it) {
    std::vector<Node<V>*> &l = **it;
    for (const auto &n : l) {
      DeleteNodeRecursively(n);
    }
    delete *it;
  }
}
<commit_msg>minor fix<commit_after>// template impl (included from header)
// #include "hheap.h"

template<typename V>
Node<V>::Node(int32_t _id, V _value) :
    id(_id), value(_value), rank(0), is_hollow(false), is_root(true), next_sibling(
        nullptr), head_childs(nullptr) {
}

template<typename V, typename C>
inline std::vector<Node<V>*>& HollowHeap<V, C>::RootsAtRank(uint32_t rank) {
  if (roots_of_rank_.size() <= rank) {
    uint32_t old_size = roots_of_rank_.size();
    roots_of_rank_.resize(rank + 1, nullptr);
    for (uint32_t i = old_size; i <= rank; ++i) {
      roots_of_rank_[i] = new std::vector<Node<V>*>();
    }
  }

  return *roots_of_rank_[rank];
}

template<typename V, typename C>
HollowHeap<V, C>::HollowHeap() :
    size_(0), comparator_(), min_node_(nullptr), roots_of_rank_(), node_map_(), n_ids_(
        0), node_map_arr_(nullptr) {
}

template<typename V, typename C>
HollowHeap<V, C>::HollowHeap(uint32_t n_ids) :
    size_(0), comparator_(), min_node_(nullptr), roots_of_rank_(), node_map_(), n_ids_(
        n_ids), node_map_arr_(new Node<V>*[n_ids_]) {
  Node<V> **arr = node_map_arr_.get();
  std::fill(arr, arr + n_ids_, nullptr);
}

// return false if id is already inserted
template<typename V, typename C>
bool HollowHeap<V, C>::Push(uint32_t id, V value) {
  if (n_ids_) {
    if (node_map_arr_[id] != nullptr) {
      return false;
    }
  } else {
    if (node_map_.find(id) != node_map_.end()) {
      return false;
    }
  }

  Node<V> *new_node = new Node<V>(id, value);

  if (n_ids_) {
    node_map_arr_[id] = new_node;
  } else {
    node_map_[id] = new_node;
  }

  RootsAtRank(0).emplace_back(new_node);

  ++size_;
  if (min_node_ == nullptr || comparator_(value, min_node_->value)) {
    min_node_ = new_node;
  }
  return true;
}

template<typename V, typename C>
void HollowHeap<V, C>::Push(V value) {
  Node<V> *new_node = new Node<V>(-1, value);

  RootsAtRank(0).emplace_back(new_node);

  ++size_;
  if (min_node_ == nullptr || comparator_(value, min_node_->value)) {
    min_node_ = new_node;
  }
}

template<typename V, typename C>
std::pair<int32_t, V> HollowHeap<V, C>::Top() const {
  return std::make_pair(min_node_->id, min_node_->value);
}

template<typename V, typename C>
inline Node<V>* HollowHeap<V, C>::link(Node<V> *r1, Node<V> *r2) {
  Node<V> *temp;
  if (comparator_(r1->value, r2->value)) {
    temp = r1->head_childs;
    r1->head_childs = r2;
    r2->next_sibling = temp;
    r2->is_root = false;
    ++r1->rank;
    return r1;
  } else {
    temp = r2->head_childs;
    r2->head_childs = r1;
    r1->next_sibling = temp;
    r1->is_root = false;
    ++r2->rank;
    return r2;
  }
}

template<typename V, typename C>
void HollowHeap<V, C>::Pop() {
  Node<V> *temp, *temp_2;
  // remove id & make top hollow
  if (min_node_->id >= 0) {
    if (n_ids_) {
      node_map_arr_[min_node_->id] = nullptr;
    } else {
      node_map_.erase(min_node_->id);
    }
  }
  min_node_->is_hollow = true;

  // recursively remove hollow roots
  for (auto it = roots_of_rank_.rbegin(); it != roots_of_rank_.rend(); ++it) {
    std::vector<Node<V>*> &l = **it;
    uint32_t non_hollow = 0;
    for (uint32_t i = 0; i < l.size(); ++i) {
      if (l[i]->is_hollow) { // hollow node
        Node<V> *current = l[i]->head_childs;
        while (current) {
          roots_of_rank_[current->rank]->emplace_back(current);
          current->is_root = true;
          temp = current;
          current = current->next_sibling;
          temp->next_sibling = nullptr;
        }
        delete l[i];
      } else {
        l[non_hollow++] = l[i];
      }
    }
    l.resize(non_hollow);
  }

  // re-link roots and shrink roots vector
  int32_t max_rank = -1;
  for (uint32_t i = 0; i < roots_of_rank_.size(); ++i) {
    std::vector<Node<V>*> &l = *roots_of_rank_[i];
    if (l.size()) {
      max_rank = l.front()->rank;
    }
    uint32_t num_links = l.size() >> 1;
    while (num_links--) {
      temp = l.back();
      l.pop_back();
      temp_2 = l.back();
      l.pop_back();
      temp = link(temp, temp_2);
      RootsAtRank(temp->rank).emplace_back(temp);
    }
  }
  // shrink roots vector
  for (uint32_t i = max_rank + 1; i < roots_of_rank_.size(); ++i) {
    delete roots_of_rank_[i];
  }
  roots_of_rank_.resize(max_rank + 1);

  // update min-id
  min_node_ = nullptr;
  for (auto it = roots_of_rank_.begin(); it != roots_of_rank_.end(); ++it) {
    std::vector<Node<V>*> &l = **it;
    if (l.size()) {
      if (min_node_ == nullptr || comparator_(l[0]->value, min_node_->value)) {
        min_node_ = l[0];
      }
    }
  }

  // reduce size;
  --size_;
}

// return false if id is not inserted yet, or updating value is invalid
template<typename V, typename C>
bool HollowHeap<V, C>::Update(uint32_t id, V value) {
  Node<V> *current_node;
  if (n_ids_) {
    current_node = node_map_arr_[id];
    if (current_node == nullptr || !comparator_(value, current_node->value)) {
      return false;
    }
  } else {
    auto i = node_map_.find(id);
    if (i == node_map_.end() || !comparator_(value, i->second->value)) {
      return false;
    }
    current_node = i->second;
  }

  // if id is root
  if (current_node->is_root) {
    current_node->value = value;
    if (comparator_(current_node->value, min_node_->value)) {
      min_node_ = current_node;
    }
    return true;
  }

  // make current node hollow
  current_node->is_hollow = true;

  // build new node
  Node<V> *new_node = new Node<V>(id, value);

  if (current_node->rank > 2) {
    new_node->rank = current_node->rank - 2;
    Node<V> *second_child = current_node->head_childs->next_sibling;
    new_node->head_childs = second_child->next_sibling;
    second_child->next_sibling = nullptr;
  }

  if (n_ids_) {
    node_map_arr_[id] = new_node;
  } else {
    node_map_[id] = new_node;
  }
  RootsAtRank(new_node->rank).emplace_back(new_node);

  // update min-id
  if (comparator_(new_node->value, min_node_->value)) {
    min_node_ = new_node;
  }

  return true;
}

template<typename V, typename C>
uint32_t HollowHeap<V, C>::size() const {
  return size_;
}

template<typename V, typename C>
bool HollowHeap<V, C>::empty() const {
  return size_ == 0;
}

template<typename V, typename C>
bool HollowHeap<V, C>::ContainsId(uint32_t id) const {
  if (n_ids_) {
    return node_map_arr_[id] != nullptr;
  } else {
    return node_map_.find(id) != node_map_.end();
  }
}

template<typename V, typename C>
V HollowHeap<V, C>::Get(uint32_t id) const {
  if (n_ids_) {
    return node_map_arr_[id]->value;
  } else {
    return node_map_.find(id)->second->value;
  }
}

template<typename V, typename C>
void HollowHeap<V, C>::PopId(uint32_t id) {
  Node<V> *node;
  // find node corresponding to id
  if (n_ids_) {
    node = node_map_arr_[id];
  } else {
    node = node_map_[id];
  }

  // pop
  if (node == min_node_) {
    Pop();
  } else {
    node->is_hollow = true;
    if (n_ids_) {
      node_map_arr_[id] = nullptr;
    } else {
      node_map_.erase(id);
    }
    // reduce size;
    --size_;
  }
}

template<typename V, typename C>
void HollowHeap<V, C>::DeleteNodeRecursively(Node<V> *node) {
  Node<V> *temp;
  while (node->head_childs != nullptr) {
    temp = node->head_childs->next_sibling;
    DeleteNodeRecursively(node->head_childs);
    node->head_childs = temp;
  }
  delete node;
}

template<typename V, typename C>
HollowHeap<V, C>::~HollowHeap() {
  for (auto it = roots_of_rank_.begin(); it != roots_of_rank_.end(); ++it) {
    std::vector<Node<V>*> &l = **it;
    for (const auto &n : l) {
      DeleteNodeRecursively(n);
    }
    delete *it;
  }
}
<|endoftext|>


<commit_before>#include "opencv2/core/utility.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <string>
#include <iostream>
#include <map>

using namespace std;
using namespace cv;

//================================================================================

template<typename M>
inline typename M::mapped_type getValue(const M &dict, const typename M::key_type &key, const string & errorMessage)
{
    typename M::const_iterator it = dict.find(key);
    if (it == dict.end())
    {
        CV_Error(Error::StsBadArg, errorMessage);
    }
    return it->second;
}

inline map<string, Size> sizeByResolution()
{
    map<string, Size> res;
    res["720p"] = Size(1280, 720);
    res["1080p"] = Size(1920, 1080);
    res["4k"] = Size(3840, 2160);
    return res;
}

inline map<string, int> fourccByCodec()
{
    map<string, int> res;
    res["h264"] = VideoWriter::fourcc('H','2','6','4');
    res["h265"] = VideoWriter::fourcc('H','E','V','C');
    res["mpeg2"] = VideoWriter::fourcc('M','P','E','G');
    res["mpeg4"] = VideoWriter::fourcc('M','P','4','2');
    res["mjpeg"] = VideoWriter::fourcc('M','J','P','G');
    res["vp8"] = VideoWriter::fourcc('V','P','8','0');
    return res;
}

inline map<string, string> defaultEncodeElementByCodec()
{
    map<string, string> res;
    res["h264"] = "x264enc";
    res["h265"] = "x265enc";
    res["mpeg2"] = "mpeg2enc";
    res["mjpeg"] = "jpegenc";
    res["vp8"] = "vp8enc";
    return res;
}

inline map<string, string> VAAPIEncodeElementByCodec()
{
    map<string, string> res;
    res["h264"] = "parsebin ! vaapih264enc";
    res["h265"] = "parsebin ! vaapih265enc";
    res["mpeg2"] = "parsebin ! vaapimpeg2enc";
    res["mjpeg"] = "parsebin ! vaapijpegenc";
    res["vp8"] = "parsebin ! vaapivp8enc";
    return res;
}

inline map<string, string> mfxDecodeElementByCodec()
{
    map<string, string> res;
    res["h264"] = "parsebin ! mfxh264dec";
    res["h265"] = "parsebin ! mfxhevcdec";
    res["mpeg2"] = "parsebin ! mfxmpeg2dec";
    res["mjpeg"] = "parsebin ! mfxjpegdec";
    return res;
}

inline map<string, string> mfxEncodeElementByCodec()
{
    map<string, string> res;
    res["h264"] = "mfxh264enc";
    res["h265"] = "mfxhevcenc";
    res["mpeg2"] = "mfxmpeg2enc";
    res["mjpeg"] = "mfxjpegenc";
    return res;
}

inline map<string, string> libavDecodeElementByCodec()
{
    map<string, string> res;
    res["h264"] = "parsebin ! avdec_h264";
    res["h265"] = "parsebin ! avdec_h265";
    res["mpeg2"] = "parsebin ! avdec_mpeg2video";
    res["mpeg4"] = "parsebin ! avdec_mpeg4";
    res["mjpeg"] = "parsebin ! avdec_mjpeg";
    res["vp8"] = "parsebin ! avdec_vp8";
    return res;
}

inline map<string, string> libavEncodeElementByCodec()
{
    map<string, string> res;
    res["h264"] = "avenc_h264";
    res["h265"] = "avenc_h265";
    res["mpeg2"] = "avenc_mpeg2video";
    res["mpeg4"] = "avenc_mpeg4";
    res["mjpeg"] = "avenc_mjpeg";
    res["vp8"] = "avenc_vp8";
    return res;
}

inline map<string, string> demuxPluginByContainer()
{
    map<string, string> res;
    res["avi"] = "avidemux";
    res["mp4"] = "qtdemux";
    res["mov"] = "qtdemux";
    res["mkv"] = "matroskademux";
    return res;
}

inline map<string, string> muxPluginByContainer()
{
    map<string, string> res;
    res["avi"] = "avimux";
    res["mp4"] = "qtmux";
    res["mov"] = "qtmux";
    res["mkv"] = "matroskamux";
    return res;
}

//================================================================================

inline string containerByName(const string &name)
{
    size_t found = name.rfind(".");
    if (found != string::npos)
    {
        return name.substr(found + 1);  // container type
    }
    return string();
}

//================================================================================

inline Ptr<VideoCapture> createCapture(const string &backend, const string &file_name, const string &codec)
{
    if (backend == "gst-default")
    {
        cout << "Created GStreamer capture ( " << file_name << " )" << endl;
        return makePtr<VideoCapture>(file_name, CAP_GSTREAMER);
    }
    else if (backend.find("gst") == 0)
    {
        ostringstream line;
        line << "filesrc location=\"" << file_name << "\"";
        line << " ! ";
        line << getValue(demuxPluginByContainer(), containerByName(file_name), "Invalid container");
        line << " ! ";
        if (backend.find("basic") == 4)
            line << "decodebin";
        else if (backend.find("vaapi") == 4)
            line << "vaapidecodebin";
        else if (backend.find("libav") == 4)
            line << getValue(libavDecodeElementByCodec(), codec, "Invalid codec");
        else if (backend.find("mfx") == 4)
            line << getValue(mfxDecodeElementByCodec(), codec, "Invalid or unsupported codec");
        else
            return Ptr<VideoCapture>();
        line << " ! videoconvert n-threads=" << getNumThreads();
        line << " ! appsink sync=false";
        cout << "Created GStreamer capture  ( " << line.str() << " )" << endl;
        return makePtr<VideoCapture>(line.str(), CAP_GSTREAMER);
    }
    else if (backend == "ffmpeg")
    {
        cout << "Created FFmpeg capture ( " << file_name << " )" << endl;
        return makePtr<VideoCapture>(file_name, CAP_FFMPEG);
    }
    return Ptr<VideoCapture>();
}

inline Ptr<VideoCapture> createSynthSource(Size sz, unsigned fps)
{
    ostringstream line;
    line << "videotestsrc pattern=smpte";
    line << " ! video/x-raw";
    line << ",width=" << sz.width << ",height=" << sz.height;
    if (fps > 0)
        line << ",framerate=" << fps << "/1";
    line << " ! appsink sync=false";
    cout << "Created synthetic video source ( " << line.str() << " )" << endl;
    return makePtr<VideoCapture>(line.str(), CAP_GSTREAMER);
}

inline Ptr<VideoWriter> createWriter(const string &backend, const string &file_name, const string &codec, Size sz, unsigned fps)
{
    if (backend == "gst-default")
    {
        cout << "Created GStreamer writer ( " << file_name << ", FPS=" << fps << ", Size=" << sz << ")" << endl;
        return makePtr<VideoWriter>(file_name, CAP_GSTREAMER, getValue(fourccByCodec(), codec, "Invalid codec"), fps, sz, true);
    }
    else if (backend.find("gst") == 0)
    {
        ostringstream line;
        line << "appsrc ! videoconvert n-threads=" << getNumThreads() << " ! ";
        if (backend.find("basic") == 4)
            line << getValue(defaultEncodeElementByCodec(), codec, "Invalid codec");
        else if (backend.find("vaapi") == 4)
            line << getValue(VAAPIEncodeElementByCodec(), codec, "Invalid codec");
        else if (backend.find("libav") == 4)
            line << getValue(libavEncodeElementByCodec(), codec, "Invalid codec");
        else if (backend.find("mfx") == 4)
            line << getValue(mfxEncodeElementByCodec(), codec, "Invalid codec");
        else
            return Ptr<VideoWriter>();
        line << " ! ";
        line << getValue(muxPluginByContainer(), containerByName(file_name), "Invalid container");
        line << " ! ";
        line << "filesink location=\"" << file_name << "\"";
        cout << "Created GStreamer writer ( " << line.str() << " )" << endl;
        return makePtr<VideoWriter>(line.str(), CAP_GSTREAMER, 0, fps, sz, true);
    }
    else if (backend == "ffmpeg")
    {
        cout << "Created FFMpeg writer ( " << file_name << ", FPS=" << fps << ", Size=" << sz << " )" << endl;
        return makePtr<VideoWriter>(file_name, CAP_FFMPEG, getValue(fourccByCodec(), codec, "Invalid codec"), fps, sz, true);
    }
    return Ptr<VideoWriter>();
}

//================================================================================

int main(int argc, char *argv[])
{
    const string keys =
        "{h help usage ? |           | print help messages   }"
        "{m mode         |decode     | coding mode (supported: encode, decode) }"
        "{b backend      |default    | video backend (supported: 'gst-default', 'gst-basic', 'gst-vaapi', 'gst-libav', 'gst-mfx', 'ffmpeg') }"
        "{c codec        |h264       | codec name     (supported: 'h264', 'h265', 'mpeg2', 'mpeg4', 'mjpeg', 'vp8') }"
        "{f file path    |           | path to file }"
        "{r resolution   |720p       | video resolution for encoding (supported: '720p', '1080p', '4k') }"
        "{fps            |30         | fix frame per second for encoding (supported: fps > 0) }"
        "{fast           |           | fast measure fps }";
    CommandLineParser cmd_parser(argc, argv, keys);
    cmd_parser.about("This program measures performance of video encoding and decoding using different backends OpenCV.");
    if (cmd_parser.has("help"))
    {
        cmd_parser.printMessage();
        return 0;
    }
    bool fast_measure = cmd_parser.has("fast");               // fast measure fps
    unsigned fix_fps      = cmd_parser.get<unsigned>("fps");      // fixed frame per second
    string backend     = cmd_parser.get<string>("backend");   // video backend
    string mode         = cmd_parser.get<string>("mode");       // coding mode
    string codec        = cmd_parser.get<string>("codec");      // codec type
    string file_name    = cmd_parser.get<string>("file");       // path to videofile
    string resolution   = cmd_parser.get<string>("resolution"); // video resolution
    if (!cmd_parser.check())
    {
        cmd_parser.printErrors();
        return -1;
    }
    if (mode != "encode" && mode != "decode")
    {
        cout << "Unsupported mode: " << mode << endl;
        return -1;
    }
    file_name = samples::findFile(file_name);
    cout << "Mode: " << mode << ", Backend: " << backend << ", File: " << file_name << ", Codec: " << codec << endl;

    TickMeter total;
    Ptr<VideoCapture> cap;
    Ptr<VideoWriter> wrt;
    try
    {
        if (mode == "decode")
        {
            cap = createCapture(backend, file_name, codec);
            if (!cap)
            {
                cout << "Failed to create video capture" << endl;
                return -3;
            }
            if (!cap->isOpened())
            {
                cout << "Capture is not opened" << endl;
                return -4;
            }
        }
        else if (mode == "encode")
        {
            Size sz = getValue(sizeByResolution(), resolution, "Invalid resolution");
            cout << "FPS: " << fix_fps << ", Frame size: " << sz << endl;
            cap = createSynthSource(sz, fix_fps);
            wrt = createWriter(backend, file_name, codec, sz, fix_fps);
            if (!cap || !wrt)
            {
                cout << "Failed to create synthetic video source or video writer" << endl;
                return -3;
            }
            if (!cap->isOpened() || !wrt->isOpened())
            {
                cout << "Synthetic video source or video writer is not opened" << endl;
                return -4;
            }
        }
    }
    catch (...)
    {
        cout << "Unsupported parameters" << endl;
        return -2;
    }

    TickMeter tick;
    Mat frame;
    Mat element;
    total.start();
    while(true)
    {
        if (mode == "decode")
        {
            tick.start();
            if (!cap->grab())
            {
                cout << "No more frames - break" << endl;
                break;
            }
            if (!cap->retrieve(frame))
            {
                cout << "Failed to retrieve frame - break" << endl;
                break;
            }
            if (frame.empty())
            {
                cout << "Empty frame received - break" << endl;
                break;
            }
            tick.stop();
        }
        else if (mode == "encode")
        {
            int limit = 100;
            while (!cap->grab() && --limit != 0)
            {
                cout << "Skipping empty input frame - " << limit << endl;
            }
            cap->retrieve(element);
            tick.start();
            *wrt << element;
            tick.stop();
        }

        if (fast_measure && tick.getCounter() >= 1000)
        {
            cout << "Fast mode frame limit reached - break" << endl;
            break;
        }
        if (mode == "encode" && tick.getCounter() >= 1000)
        {
            cout << "Encode frame limit reached - break" << endl;
            break;
        }
    }
    total.stop();
    if (tick.getCounter() == 0)
    {
        cout << "No frames have been processed" << endl;
        return -10;
    }
    else
    {
        double res_fps = tick.getCounter() / tick.getTimeSec();
        cout << tick.getCounter() << " frames in " << tick.getTimeSec() << " sec ~ " << res_fps << " FPS" << " (total time: " << total.getTimeSec() << " sec)" << endl;
    }
    return 0;
}
<commit_msg>samples: skip findFile() in encoding mode<commit_after>#include "opencv2/core/utility.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <string>
#include <iostream>
#include <map>

using namespace std;
using namespace cv;

//================================================================================

template<typename M>
inline typename M::mapped_type getValue(const M &dict, const typename M::key_type &key, const string & errorMessage)
{
    typename M::const_iterator it = dict.find(key);
    if (it == dict.end())
    {
        CV_Error(Error::StsBadArg, errorMessage);
    }
    return it->second;
}

inline map<string, Size> sizeByResolution()
{
    map<string, Size> res;
    res["720p"] = Size(1280, 720);
    res["1080p"] = Size(1920, 1080);
    res["4k"] = Size(3840, 2160);
    return res;
}

inline map<string, int> fourccByCodec()
{
    map<string, int> res;
    res["h264"] = VideoWriter::fourcc('H','2','6','4');
    res["h265"] = VideoWriter::fourcc('H','E','V','C');
    res["mpeg2"] = VideoWriter::fourcc('M','P','E','G');
    res["mpeg4"] = VideoWriter::fourcc('M','P','4','2');
    res["mjpeg"] = VideoWriter::fourcc('M','J','P','G');
    res["vp8"] = VideoWriter::fourcc('V','P','8','0');
    return res;
}

inline map<string, string> defaultEncodeElementByCodec()
{
    map<string, string> res;
    res["h264"] = "x264enc";
    res["h265"] = "x265enc";
    res["mpeg2"] = "mpeg2enc";
    res["mjpeg"] = "jpegenc";
    res["vp8"] = "vp8enc";
    return res;
}

inline map<string, string> VAAPIEncodeElementByCodec()
{
    map<string, string> res;
    res["h264"] = "parsebin ! vaapih264enc";
    res["h265"] = "parsebin ! vaapih265enc";
    res["mpeg2"] = "parsebin ! vaapimpeg2enc";
    res["mjpeg"] = "parsebin ! vaapijpegenc";
    res["vp8"] = "parsebin ! vaapivp8enc";
    return res;
}

inline map<string, string> mfxDecodeElementByCodec()
{
    map<string, string> res;
    res["h264"] = "parsebin ! mfxh264dec";
    res["h265"] = "parsebin ! mfxhevcdec";
    res["mpeg2"] = "parsebin ! mfxmpeg2dec";
    res["mjpeg"] = "parsebin ! mfxjpegdec";
    return res;
}

inline map<string, string> mfxEncodeElementByCodec()
{
    map<string, string> res;
    res["h264"] = "mfxh264enc";
    res["h265"] = "mfxhevcenc";
    res["mpeg2"] = "mfxmpeg2enc";
    res["mjpeg"] = "mfxjpegenc";
    return res;
}

inline map<string, string> libavDecodeElementByCodec()
{
    map<string, string> res;
    res["h264"] = "parsebin ! avdec_h264";
    res["h265"] = "parsebin ! avdec_h265";
    res["mpeg2"] = "parsebin ! avdec_mpeg2video";
    res["mpeg4"] = "parsebin ! avdec_mpeg4";
    res["mjpeg"] = "parsebin ! avdec_mjpeg";
    res["vp8"] = "parsebin ! avdec_vp8";
    return res;
}

inline map<string, string> libavEncodeElementByCodec()
{
    map<string, string> res;
    res["h264"] = "avenc_h264";
    res["h265"] = "avenc_h265";
    res["mpeg2"] = "avenc_mpeg2video";
    res["mpeg4"] = "avenc_mpeg4";
    res["mjpeg"] = "avenc_mjpeg";
    res["vp8"] = "avenc_vp8";
    return res;
}

inline map<string, string> demuxPluginByContainer()
{
    map<string, string> res;
    res["avi"] = "avidemux";
    res["mp4"] = "qtdemux";
    res["mov"] = "qtdemux";
    res["mkv"] = "matroskademux";
    return res;
}

inline map<string, string> muxPluginByContainer()
{
    map<string, string> res;
    res["avi"] = "avimux";
    res["mp4"] = "qtmux";
    res["mov"] = "qtmux";
    res["mkv"] = "matroskamux";
    return res;
}

//================================================================================

inline string containerByName(const string &name)
{
    size_t found = name.rfind(".");
    if (found != string::npos)
    {
        return name.substr(found + 1);  // container type
    }
    return string();
}

//================================================================================

inline Ptr<VideoCapture> createCapture(const string &backend, const string &file_name, const string &codec)
{
    if (backend == "gst-default")
    {
        cout << "Created GStreamer capture ( " << file_name << " )" << endl;
        return makePtr<VideoCapture>(file_name, CAP_GSTREAMER);
    }
    else if (backend.find("gst") == 0)
    {
        ostringstream line;
        line << "filesrc location=\"" << file_name << "\"";
        line << " ! ";
        line << getValue(demuxPluginByContainer(), containerByName(file_name), "Invalid container");
        line << " ! ";
        if (backend.find("basic") == 4)
            line << "decodebin";
        else if (backend.find("vaapi") == 4)
            line << "vaapidecodebin";
        else if (backend.find("libav") == 4)
            line << getValue(libavDecodeElementByCodec(), codec, "Invalid codec");
        else if (backend.find("mfx") == 4)
            line << getValue(mfxDecodeElementByCodec(), codec, "Invalid or unsupported codec");
        else
            return Ptr<VideoCapture>();
        line << " ! videoconvert n-threads=" << getNumThreads();
        line << " ! appsink sync=false";
        cout << "Created GStreamer capture  ( " << line.str() << " )" << endl;
        return makePtr<VideoCapture>(line.str(), CAP_GSTREAMER);
    }
    else if (backend == "ffmpeg")
    {
        cout << "Created FFmpeg capture ( " << file_name << " )" << endl;
        return makePtr<VideoCapture>(file_name, CAP_FFMPEG);
    }
    return Ptr<VideoCapture>();
}

inline Ptr<VideoCapture> createSynthSource(Size sz, unsigned fps)
{
    ostringstream line;
    line << "videotestsrc pattern=smpte";
    line << " ! video/x-raw";
    line << ",width=" << sz.width << ",height=" << sz.height;
    if (fps > 0)
        line << ",framerate=" << fps << "/1";
    line << " ! appsink sync=false";
    cout << "Created synthetic video source ( " << line.str() << " )" << endl;
    return makePtr<VideoCapture>(line.str(), CAP_GSTREAMER);
}

inline Ptr<VideoWriter> createWriter(const string &backend, const string &file_name, const string &codec, Size sz, unsigned fps)
{
    if (backend == "gst-default")
    {
        cout << "Created GStreamer writer ( " << file_name << ", FPS=" << fps << ", Size=" << sz << ")" << endl;
        return makePtr<VideoWriter>(file_name, CAP_GSTREAMER, getValue(fourccByCodec(), codec, "Invalid codec"), fps, sz, true);
    }
    else if (backend.find("gst") == 0)
    {
        ostringstream line;
        line << "appsrc ! videoconvert n-threads=" << getNumThreads() << " ! ";
        if (backend.find("basic") == 4)
            line << getValue(defaultEncodeElementByCodec(), codec, "Invalid codec");
        else if (backend.find("vaapi") == 4)
            line << getValue(VAAPIEncodeElementByCodec(), codec, "Invalid codec");
        else if (backend.find("libav") == 4)
            line << getValue(libavEncodeElementByCodec(), codec, "Invalid codec");
        else if (backend.find("mfx") == 4)
            line << getValue(mfxEncodeElementByCodec(), codec, "Invalid codec");
        else
            return Ptr<VideoWriter>();
        line << " ! ";
        line << getValue(muxPluginByContainer(), containerByName(file_name), "Invalid container");
        line << " ! ";
        line << "filesink location=\"" << file_name << "\"";
        cout << "Created GStreamer writer ( " << line.str() << " )" << endl;
        return makePtr<VideoWriter>(line.str(), CAP_GSTREAMER, 0, fps, sz, true);
    }
    else if (backend == "ffmpeg")
    {
        cout << "Created FFMpeg writer ( " << file_name << ", FPS=" << fps << ", Size=" << sz << " )" << endl;
        return makePtr<VideoWriter>(file_name, CAP_FFMPEG, getValue(fourccByCodec(), codec, "Invalid codec"), fps, sz, true);
    }
    return Ptr<VideoWriter>();
}

//================================================================================

int main(int argc, char *argv[])
{
    const string keys =
        "{h help usage ? |           | print help messages   }"
        "{m mode         |decode     | coding mode (supported: encode, decode) }"
        "{b backend      |default    | video backend (supported: 'gst-default', 'gst-basic', 'gst-vaapi', 'gst-libav', 'gst-mfx', 'ffmpeg') }"
        "{c codec        |h264       | codec name     (supported: 'h264', 'h265', 'mpeg2', 'mpeg4', 'mjpeg', 'vp8') }"
        "{f file path    |           | path to file }"
        "{r resolution   |720p       | video resolution for encoding (supported: '720p', '1080p', '4k') }"
        "{fps            |30         | fix frame per second for encoding (supported: fps > 0) }"
        "{fast           |           | fast measure fps }";
    CommandLineParser cmd_parser(argc, argv, keys);
    cmd_parser.about("This program measures performance of video encoding and decoding using different backends OpenCV.");
    if (cmd_parser.has("help"))
    {
        cmd_parser.printMessage();
        return 0;
    }
    bool fast_measure = cmd_parser.has("fast");               // fast measure fps
    unsigned fix_fps      = cmd_parser.get<unsigned>("fps");      // fixed frame per second
    string backend     = cmd_parser.get<string>("backend");   // video backend
    string mode         = cmd_parser.get<string>("mode");       // coding mode
    string codec        = cmd_parser.get<string>("codec");      // codec type
    string file_name    = cmd_parser.get<string>("file");       // path to videofile
    string resolution   = cmd_parser.get<string>("resolution"); // video resolution
    if (!cmd_parser.check())
    {
        cmd_parser.printErrors();
        return -1;
    }
    if (mode != "encode" && mode != "decode")
    {
        cout << "Unsupported mode: " << mode << endl;
        return -1;
    }
    if (mode == "decode")
    {
        file_name = samples::findFile(file_name);
    }
    cout << "Mode: " << mode << ", Backend: " << backend << ", File: " << file_name << ", Codec: " << codec << endl;

    TickMeter total;
    Ptr<VideoCapture> cap;
    Ptr<VideoWriter> wrt;
    try
    {
        if (mode == "decode")
        {
            cap = createCapture(backend, file_name, codec);
            if (!cap)
            {
                cout << "Failed to create video capture" << endl;
                return -3;
            }
            if (!cap->isOpened())
            {
                cout << "Capture is not opened" << endl;
                return -4;
            }
        }
        else if (mode == "encode")
        {
            Size sz = getValue(sizeByResolution(), resolution, "Invalid resolution");
            cout << "FPS: " << fix_fps << ", Frame size: " << sz << endl;
            cap = createSynthSource(sz, fix_fps);
            wrt = createWriter(backend, file_name, codec, sz, fix_fps);
            if (!cap || !wrt)
            {
                cout << "Failed to create synthetic video source or video writer" << endl;
                return -3;
            }
            if (!cap->isOpened() || !wrt->isOpened())
            {
                cout << "Synthetic video source or video writer is not opened" << endl;
                return -4;
            }
        }
    }
    catch (...)
    {
        cout << "Unsupported parameters" << endl;
        return -2;
    }

    TickMeter tick;
    Mat frame;
    Mat element;
    total.start();
    while(true)
    {
        if (mode == "decode")
        {
            tick.start();
            if (!cap->grab())
            {
                cout << "No more frames - break" << endl;
                break;
            }
            if (!cap->retrieve(frame))
            {
                cout << "Failed to retrieve frame - break" << endl;
                break;
            }
            if (frame.empty())
            {
                cout << "Empty frame received - break" << endl;
                break;
            }
            tick.stop();
        }
        else if (mode == "encode")
        {
            int limit = 100;
            while (!cap->grab() && --limit != 0)
            {
                cout << "Skipping empty input frame - " << limit << endl;
            }
            cap->retrieve(element);
            tick.start();
            *wrt << element;
            tick.stop();
        }

        if (fast_measure && tick.getCounter() >= 1000)
        {
            cout << "Fast mode frame limit reached - break" << endl;
            break;
        }
        if (mode == "encode" && tick.getCounter() >= 1000)
        {
            cout << "Encode frame limit reached - break" << endl;
            break;
        }
    }
    total.stop();
    if (tick.getCounter() == 0)
    {
        cout << "No frames have been processed" << endl;
        return -10;
    }
    else
    {
        double res_fps = tick.getCounter() / tick.getTimeSec();
        cout << tick.getCounter() << " frames in " << tick.getTimeSec() << " sec ~ " << res_fps << " FPS" << " (total time: " << total.getTimeSec() << " sec)" << endl;
    }
    return 0;
}
<|endoftext|>


<commit_before>/*
 * BloomFilter.cpp
 *
 *  Created on: 08.08.2015
 *      Author: Henning
 */

#include "BloomFilter.h"
#include "Random.h"

namespace Aux {

BloomFilter::BloomFilter(count numHashes, count size): numHashes(numHashes), size(size) {
	membership.resize(numHashes);
	salts.resize(numHashes);

	for (index i = 0; i < numHashes; ++i) {
		membership[i].resize(size, false);
		salts[i] = Aux::Random::integer();
	}
}

void BloomFilter::insert(index key) {
	for (index func = 0; func < numHashes; ++func) {
		membership[func][hash(key, func)] = true;
	}
}

bool BloomFilter::isMember(index key) const {
	bool result = true;
	for (index func = 0; func < numHashes; ++func) {
		result = result && membership[func][hash(key, func)];
	}
	return result;
}

index BloomFilter::hash(index key, index hfunc) const {
	index result = 0;
	std::hash<index> myhash;

	result = myhash(key ^ salts[hfunc]);
	return (result % size);
}

}
<commit_msg>Bloom filter doc, max clique computes clique as well (not only size)<commit_after>/*
 * BloomFilter.cpp
 *
 *  Created on: 08.08.2015
 *      Author: Henning
 */

#include "BloomFilter.h"
#include "Random.h"

namespace Aux {

BloomFilter::BloomFilter(count numHashes, count size): numHashes(numHashes), size(size),
	membership(numHashes), salts(numHashes)
{
	for (index i = 0; i < numHashes; ++i) {
		membership[i].resize(size, false);
		salts[i] = Aux::Random::integer();
	}
}

void BloomFilter::insert(index key) {
	// set hashed positions of key in each array to true
	for (index func = 0; func < numHashes; ++func) {
		membership[func][hash(key, func)] = true;
	}
}

bool BloomFilter::isMember(index key) const {
	bool result = true;

	// find out if all hashed positions of key are true
	for (index func = 0; (func < numHashes) && result; ++func) {
		result = result && membership[func][hash(key, func)];
	}
	return result;
}

index BloomFilter::hash(index key, index hfunc) const {
	index result = 0;
	std::hash<index> myhash;

	// instead of using different hash functions: salt key with different (but fixed) random salt
	result = myhash(key ^ salts[hfunc]);
	return (result % size);
}

}
<|endoftext|>