<commit_before>/**************************************************************************
** This file is part of LiteIDE
**
** Copyright (c) 2011-2013 LiteIDE Team. All rights reserved.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
** Lesser General Public License for more details.
**
** In addition, as a special exception,  that plugins developed for LiteIDE,
** are allowed to remain closed sourced and can be distributed under any license .
** These rights are included in the file LGPL_EXCEPTION.txt in this package.
**
**************************************************************************/
// Module: envmanager.cpp
// Creator: visualfc <visualfc@gmail.com>

#include "envmanager.h"
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QRegExp>
#include <QToolBar>
#include <QMenu>
#include <QComboBox>
#include <QLabel>
#include <QAction>
#include <QDebug>
//lite_memory_check_begin
#if defined(WIN32) && defined(_MSC_VER) &&  defined(_DEBUG)
     #define _CRTDBG_MAP_ALLOC
     #include <stdlib.h>
     #include <crtdbg.h>
     #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ )
     #define new DEBUG_NEW
#endif
//lite_memory_check_end

Env::Env(QObject *parent) :
    LiteApi::IEnv(parent)
{
    m_env = QProcessEnvironment::systemEnvironment();
}

QString Env::id() const
{
    return m_id;
}

QString Env::filePath() const
{
    return m_filePath;
}

QProcessEnvironment& Env::environment()
{
    return m_env;
}

QStringList Env::orgEnvLines() const
{
    return m_orgEnvLines;
}

void Env::reload()
{
    if (m_filePath.isEmpty()) {
        return;
    }
    QFile f(m_filePath);
    if (!f.open(QIODevice::ReadOnly)) {
        return;
    }
    loadEnvFile(&f);
    f.close();
}

void Env::loadEnvFile(QIODevice *dev)
{
    QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
    m_orgEnvLines.clear();
#ifdef Q_OS_WIN
    QRegExp rx("\\%([\\w]+)\\%");
#else
    QRegExp rx("\\$([\\w]+)");
#endif
    while (!dev->atEnd()) {
        QString line = dev->readLine().trimmed();
        if (line.indexOf("#") == 0) {
            continue;
        }
        int pos = line.indexOf("=");
        if (pos == -1) {
            continue;
        }
        m_orgEnvLines.append(line);
        QString key = line.left(pos).trimmed();
        QString value = line.right(line.length()-pos-1).trimmed();
        QStringList cap0;
        QStringList cap1;
        pos = 0;
        while ((pos = rx.indexIn(value, pos)) != -1) {
             cap0 << rx.cap(0);
             cap1 << rx.cap(1);
             pos += rx.matchedLength();
        }
        for (int i = 0; i < cap0.size(); i++) {
            if (env.contains(cap1.at(i))) {
                value.replace(cap0.at(i),env.value(cap1.at(i)));
            }
        }
        env.insert(key,value);
    }
    m_env = env;
}

void Env::loadEnv(EnvManager *manager, const QString &filePath)
{
    QFile f(filePath);
    if (!f.open(QIODevice::ReadOnly)) {
        return;
    }

    Env *env = new Env(manager);
    env->m_filePath = filePath;
    env->m_id = QFileInfo(filePath).baseName();
    env->loadEnvFile(&f);
    f.close();
    manager->addEnv(env);
}

EnvManager::EnvManager(QObject *parent)
    : LiteApi::IEnvManager(parent),
      m_curEnv(0),m_toolBar(0)
{
}

EnvManager::~EnvManager()
{
    if (m_toolBar) {
        m_liteApp->actionManager()->removeToolBar(m_toolBar);
    }
    if (m_curEnv) {
        m_liteApp->settings()->setValue("LiteEnv/current",m_curEnv->id());
    }
}

void EnvManager::addEnv(LiteApi::IEnv *env)
{
    m_envList.append(env);
}

void EnvManager::removeEnv(LiteApi::IEnv *env)
{
    m_envList.removeAll(env);
}

LiteApi::IEnv *EnvManager::findEnv(const QString &id) const
{
    foreach (LiteApi::IEnv *env, m_envList) {
        if (env->id() == id) {
            return env;
        }
    }
    if (!m_envList.empty()) {
        return m_envList.first();
    }
    return NULL;
}

QList<LiteApi::IEnv*> EnvManager::envList() const
{
    return m_envList;
}

void EnvManager::setCurrentEnv(LiteApi::IEnv *env)
{
    if (m_curEnv == env) {
        return;
    }
    m_curEnv = env;
    if (m_curEnv) {
        m_curEnv->reload();
        m_liteApp->settings()->setValue("LiteEnv/current",m_curEnv->id());
    }
    emit currentEnvChanged(m_curEnv);
}

LiteApi::IEnv *EnvManager::currentEnv() const
{
    return m_curEnv;
}

QProcessEnvironment EnvManager::currentEnvironment() const
{
    if (m_curEnv) {
        return m_curEnv->environment();
    }
    return QProcessEnvironment::systemEnvironment();
}

void EnvManager::loadEnvFiles(const QString &path)
{
    QDir dir = path;
    m_liteApp->appendLog("LiteEnv","Loaded environment files from "+path);
    dir.setFilter(QDir::Files | QDir::NoSymLinks);
    dir.setNameFilters(QStringList("*.env"));
    foreach (QString fileName, dir.entryList()) {
        Env::loadEnv(this,QFileInfo(dir,fileName).absoluteFilePath());
    }
}

bool EnvManager::initWithApp(LiteApi::IApplication *app)
{
    if (!LiteApi::IEnvManager::initWithApp(app)) {
        return false;
    }
    loadEnvFiles(m_liteApp->resourcePath()+"/liteenv");

    m_toolBar = m_liteApp->actionManager()->insertToolBar("toolbar/env",tr("Environment Toolbar"),"toolbar/tabs");
    m_liteApp->actionManager()->insertViewMenu(LiteApi::ViewMenuToolBarPos,m_toolBar->toggleViewAction());

    m_envCmb = new QComboBox;
    m_envCmb->setSizeAdjustPolicy(QComboBox::AdjustToContents);
    m_envCmb->setMinimumContentsLength(6);
    m_envCmb->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Preferred);
    m_envCmb->setToolTip(tr("Environment"));

    m_toolBar->addWidget(m_envCmb);
    QAction *editAct = new QAction(QIcon("icon:liteenv/images/setenv.png"),tr("Edit Environment"),this);
    m_toolBar->addAction(editAct);

    foreach (LiteApi::IEnv *env, m_envList) {
        m_envCmb->addItem(env->id());
    }

    m_liteApp->extension()->addObject("LiteApi.IEnvManager",this);

    QString id = m_liteApp->settings()->value("LiteEnv/current","system").toString();
    if (!id.isEmpty()) {
        this->setCurrentEnvId(id);
    }

    connect(m_envCmb,SIGNAL(activated(QString)),this,SLOT(envActivated(QString)));
    connect(editAct,SIGNAL(triggered()),this,SLOT(editCurrentEnv()));
    connect(m_liteApp->editorManager(),SIGNAL(editorSaved(LiteApi::IEditor*)),this,SLOT(editorSaved(LiteApi::IEditor*)));
    return true;
}

void EnvManager::setCurrentEnvId(const QString &id)
{
    LiteApi::IEnv *env = findEnv(id);
    if (!env) {
        return;
    }
    for (int i = 0; i < m_envCmb->count(); i++) {
        if (m_envCmb->itemText(i) == id) {
            m_envCmb->setCurrentIndex(i);
            break;
        }
    }
    setCurrentEnv(env);
}

void EnvManager::envActivated(QString id)
{
    LiteApi::IEnv *env = findEnv(id);
    setCurrentEnv(env);
}

void EnvManager::editCurrentEnv()
{
    if (!m_curEnv) {
        return;
    }
    m_liteApp->fileManager()->openEditor(m_curEnv->filePath(),true);
}

void EnvManager::editorSaved(LiteApi::IEditor *editor)
{
    LiteApi::ITextEditor *ed = LiteApi::getTextEditor(editor);
    if (!ed) {
        return;
    }

    if (m_curEnv && m_curEnv->filePath() == ed->filePath()) {
        m_curEnv->reload();
        currentEnvChanged(m_curEnv);
    }
}
<commit_msg>fix env files use utf8<commit_after>/**************************************************************************
** This file is part of LiteIDE
**
** Copyright (c) 2011-2013 LiteIDE Team. All rights reserved.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
** Lesser General Public License for more details.
**
** In addition, as a special exception,  that plugins developed for LiteIDE,
** are allowed to remain closed sourced and can be distributed under any license .
** These rights are included in the file LGPL_EXCEPTION.txt in this package.
**
**************************************************************************/
// Module: envmanager.cpp
// Creator: visualfc <visualfc@gmail.com>

#include "envmanager.h"
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QRegExp>
#include <QToolBar>
#include <QMenu>
#include <QComboBox>
#include <QLabel>
#include <QAction>
#include <QDebug>
//lite_memory_check_begin
#if defined(WIN32) && defined(_MSC_VER) &&  defined(_DEBUG)
     #define _CRTDBG_MAP_ALLOC
     #include <stdlib.h>
     #include <crtdbg.h>
     #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ )
     #define new DEBUG_NEW
#endif
//lite_memory_check_end

Env::Env(QObject *parent) :
    LiteApi::IEnv(parent)
{
    m_env = QProcessEnvironment::systemEnvironment();
}

QString Env::id() const
{
    return m_id;
}

QString Env::filePath() const
{
    return m_filePath;
}

QProcessEnvironment& Env::environment()
{
    return m_env;
}

QStringList Env::orgEnvLines() const
{
    return m_orgEnvLines;
}

void Env::reload()
{
    if (m_filePath.isEmpty()) {
        return;
    }
    QFile f(m_filePath);
    if (!f.open(QIODevice::ReadOnly)) {
        return;
    }
    loadEnvFile(&f);
    f.close();
}

void Env::loadEnvFile(QIODevice *dev)
{
    QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
    m_orgEnvLines.clear();
#ifdef Q_OS_WIN
    QRegExp rx("\\%([\\w]+)\\%");
#else
    QRegExp rx("\\$([\\w]+)");
#endif
    while (!dev->atEnd()) {
        QString line = QString::fromUtf8(dev->readLine().trimmed());
        if (line.indexOf("#") == 0) {
            continue;
        }
        int pos = line.indexOf("=");
        if (pos == -1) {
            continue;
        }
        m_orgEnvLines.append(line);
        QString key = line.left(pos).trimmed();
        QString value = line.right(line.length()-pos-1).trimmed();
        QStringList cap0;
        QStringList cap1;
        pos = 0;
        while ((pos = rx.indexIn(value, pos)) != -1) {
             cap0 << rx.cap(0);
             cap1 << rx.cap(1);
             pos += rx.matchedLength();
        }
        for (int i = 0; i < cap0.size(); i++) {
            if (env.contains(cap1.at(i))) {
                value.replace(cap0.at(i),env.value(cap1.at(i)));
            }
        }
        env.insert(key,value);
    }
    m_env = env;
}

void Env::loadEnv(EnvManager *manager, const QString &filePath)
{
    QFile f(filePath);
    if (!f.open(QIODevice::ReadOnly)) {
        return;
    }

    Env *env = new Env(manager);
    env->m_filePath = filePath;
    env->m_id = QFileInfo(filePath).baseName();
    env->loadEnvFile(&f);
    f.close();
    manager->addEnv(env);
}

EnvManager::EnvManager(QObject *parent)
    : LiteApi::IEnvManager(parent),
      m_curEnv(0),m_toolBar(0)
{
}

EnvManager::~EnvManager()
{
    if (m_toolBar) {
        m_liteApp->actionManager()->removeToolBar(m_toolBar);
    }
    if (m_curEnv) {
        m_liteApp->settings()->setValue("LiteEnv/current",m_curEnv->id());
    }
}

void EnvManager::addEnv(LiteApi::IEnv *env)
{
    m_envList.append(env);
}

void EnvManager::removeEnv(LiteApi::IEnv *env)
{
    m_envList.removeAll(env);
}

LiteApi::IEnv *EnvManager::findEnv(const QString &id) const
{
    foreach (LiteApi::IEnv *env, m_envList) {
        if (env->id() == id) {
            return env;
        }
    }
    if (!m_envList.empty()) {
        return m_envList.first();
    }
    return NULL;
}

QList<LiteApi::IEnv*> EnvManager::envList() const
{
    return m_envList;
}

void EnvManager::setCurrentEnv(LiteApi::IEnv *env)
{
    if (m_curEnv == env) {
        return;
    }
    m_curEnv = env;
    if (m_curEnv) {
        m_curEnv->reload();
        m_liteApp->settings()->setValue("LiteEnv/current",m_curEnv->id());
    }
    emit currentEnvChanged(m_curEnv);
}

LiteApi::IEnv *EnvManager::currentEnv() const
{
    return m_curEnv;
}

QProcessEnvironment EnvManager::currentEnvironment() const
{
    if (m_curEnv) {
        return m_curEnv->environment();
    }
    return QProcessEnvironment::systemEnvironment();
}

void EnvManager::loadEnvFiles(const QString &path)
{
    QDir dir = path;
    m_liteApp->appendLog("LiteEnv","Loaded environment files from "+path);
    dir.setFilter(QDir::Files | QDir::NoSymLinks);
    dir.setNameFilters(QStringList("*.env"));
    foreach (QString fileName, dir.entryList()) {
        Env::loadEnv(this,QFileInfo(dir,fileName).absoluteFilePath());
    }
}

bool EnvManager::initWithApp(LiteApi::IApplication *app)
{
    if (!LiteApi::IEnvManager::initWithApp(app)) {
        return false;
    }
    loadEnvFiles(m_liteApp->resourcePath()+"/liteenv");

    m_toolBar = m_liteApp->actionManager()->insertToolBar("toolbar/env",tr("Environment Toolbar"),"toolbar/tabs");
    m_liteApp->actionManager()->insertViewMenu(LiteApi::ViewMenuToolBarPos,m_toolBar->toggleViewAction());

    m_envCmb = new QComboBox;
    m_envCmb->setSizeAdjustPolicy(QComboBox::AdjustToContents);
    m_envCmb->setMinimumContentsLength(6);
    m_envCmb->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Preferred);
    m_envCmb->setToolTip(tr("Environment"));

    m_toolBar->addWidget(m_envCmb);
    QAction *editAct = new QAction(QIcon("icon:liteenv/images/setenv.png"),tr("Edit Environment"),this);
    m_toolBar->addAction(editAct);

    foreach (LiteApi::IEnv *env, m_envList) {
        m_envCmb->addItem(env->id());
    }

    m_liteApp->extension()->addObject("LiteApi.IEnvManager",this);

    QString id = m_liteApp->settings()->value("LiteEnv/current","system").toString();
    if (!id.isEmpty()) {
        this->setCurrentEnvId(id);
    }

    connect(m_envCmb,SIGNAL(activated(QString)),this,SLOT(envActivated(QString)));
    connect(editAct,SIGNAL(triggered()),this,SLOT(editCurrentEnv()));
    connect(m_liteApp->editorManager(),SIGNAL(editorSaved(LiteApi::IEditor*)),this,SLOT(editorSaved(LiteApi::IEditor*)));
    return true;
}

void EnvManager::setCurrentEnvId(const QString &id)
{
    LiteApi::IEnv *env = findEnv(id);
    if (!env) {
        return;
    }
    for (int i = 0; i < m_envCmb->count(); i++) {
        if (m_envCmb->itemText(i) == id) {
            m_envCmb->setCurrentIndex(i);
            break;
        }
    }
    setCurrentEnv(env);
}

void EnvManager::envActivated(QString id)
{
    LiteApi::IEnv *env = findEnv(id);
    setCurrentEnv(env);
}

void EnvManager::editCurrentEnv()
{
    if (!m_curEnv) {
        return;
    }
    m_liteApp->fileManager()->openEditor(m_curEnv->filePath(),true);
}

void EnvManager::editorSaved(LiteApi::IEditor *editor)
{
    LiteApi::ITextEditor *ed = LiteApi::getTextEditor(editor);
    if (!ed) {
        return;
    }

    if (m_curEnv && m_curEnv->filePath() == ed->filePath()) {
        m_curEnv->reload();
        currentEnvChanged(m_curEnv);
    }
}
<|endoftext|>


<commit_before>#include <assert.h>
#include <sstream>

#include "interpreter.h"
#include "lexer.h"
#include "parser.h"

int main()
{
    {
        std::stringstream out;
        interpret(parse(tokenize("a := 1\nprint(a)")), out);
        assert(out.str() == "1\n");
    }

    {
        std::stringstream out;
        interpret(parse(tokenize("a := 0\nIF a THEN print(1) END")), out);
        assert(out.str() == "");
    }

    {
        std::stringstream out;
        interpret(parse(tokenize("a := 1\nIF a THEN print(1) END")), out);
        assert(out.str() == "1\n");
    }
}
<commit_msg>Delete test_interpreter.cpp<commit_after><|endoftext|>


<commit_before>#include "Cache.h"
#include <unordered_map>
#include <cassert>
#include <iostream>
#include <llvm/IR/Module.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/Support/Path.h>
#include <llvm/Support/FileSystem.h>
#include <llvm/Support/raw_os_ostream.h>
#include "ExecutionEngine.h"

namespace dev
{
namespace eth
{
namespace jit
{

//#define CACHE_LOG std::cerr << "CACHE "
#define CACHE_LOG std::ostream(nullptr)

namespace
{
	llvm::MemoryBuffer* g_lastObject;
	ExecutionEngineListener* g_listener;
}

ObjectCache* Cache::getObjectCache(ExecutionEngineListener* _listener)
{
	static ObjectCache objectCache;
	g_listener = _listener;
	return &objectCache;
}

std::unique_ptr<llvm::Module> Cache::getObject(std::string const& id)
{
	if (g_listener)
		g_listener->stateChanged(ExecState::CacheLoad);

	CACHE_LOG << id << ": search\n";
	assert(!g_lastObject);
	llvm::SmallString<256> cachePath;
	llvm::sys::path::system_temp_directory(false, cachePath);
	llvm::sys::path::append(cachePath, "evm_objs", id);

#if defined(__GNUC__) && !defined(NDEBUG)
	llvm::sys::fs::file_status st;
	auto err = llvm::sys::fs::status(cachePath.str(), st);
	if (err)
		return nullptr;
	auto mtime = st.getLastModificationTime().toEpochTime();

	std::tm tm;
	strptime(__DATE__ __TIME__, " %b %d %Y %H:%M:%S", &tm);
	auto btime = (uint64_t)std::mktime(&tm);
	if (btime > mtime)
		return nullptr;
#endif

	if (auto r = llvm::MemoryBuffer::getFile(cachePath.str(), -1, false))
		g_lastObject = llvm::MemoryBuffer::getMemBufferCopy(r.get()->getBuffer());
	else if (r.getError() != std::make_error_code(std::errc::no_such_file_or_directory))
		std::cerr << r.getError().message(); // TODO: Add log

	if (g_lastObject)  // if object found create fake module
	{
		CACHE_LOG << id << ": found\n";
		auto&& context = llvm::getGlobalContext();
		auto module = std::unique_ptr<llvm::Module>(new llvm::Module(id, context));
		auto mainFuncType = llvm::FunctionType::get(llvm::Type::getVoidTy(context), {}, false);
		auto mainFunc = llvm::Function::Create(mainFuncType, llvm::Function::ExternalLinkage, id, module.get());
		llvm::BasicBlock::Create(context, {}, mainFunc); // FIXME: Check if empty basic block is valid
		return module;
	}
	CACHE_LOG << id << ": not found\n";
	return nullptr;
}

void ObjectCache::notifyObjectCompiled(llvm::Module const* _module, llvm::MemoryBuffer const* _object)
{
	if (g_listener)
		g_listener->stateChanged(ExecState::CacheWrite);

	auto&& id = _module->getModuleIdentifier();
	llvm::SmallString<256> cachePath;
	llvm::sys::path::system_temp_directory(false, cachePath);
	llvm::sys::path::append(cachePath, "evm_objs");

	if (llvm::sys::fs::create_directory(cachePath.str()))
		return; // TODO: Add log

	llvm::sys::path::append(cachePath, id);

	CACHE_LOG << id << ": write\n";
	std::string error;
	llvm::raw_fd_ostream cacheFile(cachePath.c_str(), error, llvm::sys::fs::F_None);
	cacheFile << _object->getBuffer();
}

llvm::MemoryBuffer* ObjectCache::getObject(llvm::Module const* _module)
{
	CACHE_LOG << _module->getModuleIdentifier() << ": use\n";
	auto o = g_lastObject;
	g_lastObject = nullptr;
	return o;
}

}
}
}
<commit_msg>Add `unreachable` instruction to fake module generated by Cache<commit_after>#include "Cache.h"
#include <unordered_map>
#include <cassert>
#include <iostream>
#include <llvm/IR/Module.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Instructions.h>
#include <llvm/Support/Path.h>
#include <llvm/Support/FileSystem.h>
#include <llvm/Support/raw_os_ostream.h>
#include "ExecutionEngine.h"

namespace dev
{
namespace eth
{
namespace jit
{

//#define CACHE_LOG std::cerr << "CACHE "
#define CACHE_LOG std::ostream(nullptr)

namespace
{
	llvm::MemoryBuffer* g_lastObject;
	ExecutionEngineListener* g_listener;
}

ObjectCache* Cache::getObjectCache(ExecutionEngineListener* _listener)
{
	static ObjectCache objectCache;
	g_listener = _listener;
	return &objectCache;
}

std::unique_ptr<llvm::Module> Cache::getObject(std::string const& id)
{
	if (g_listener)
		g_listener->stateChanged(ExecState::CacheLoad);

	CACHE_LOG << id << ": search\n";
	assert(!g_lastObject);
	llvm::SmallString<256> cachePath;
	llvm::sys::path::system_temp_directory(false, cachePath);
	llvm::sys::path::append(cachePath, "evm_objs", id);

#if defined(__GNUC__) && !defined(NDEBUG)
	llvm::sys::fs::file_status st;
	auto err = llvm::sys::fs::status(cachePath.str(), st);
	if (err)
		return nullptr;
	auto mtime = st.getLastModificationTime().toEpochTime();

	std::tm tm;
	strptime(__DATE__ __TIME__, " %b %d %Y %H:%M:%S", &tm);
	auto btime = (uint64_t)std::mktime(&tm);
	if (btime > mtime)
		return nullptr;
#endif

	if (auto r = llvm::MemoryBuffer::getFile(cachePath.str(), -1, false))
		g_lastObject = llvm::MemoryBuffer::getMemBufferCopy(r.get()->getBuffer());
	else if (r.getError() != std::make_error_code(std::errc::no_such_file_or_directory))
		std::cerr << r.getError().message(); // TODO: Add log

	if (g_lastObject)  // if object found create fake module
	{
		CACHE_LOG << id << ": found\n";
		auto&& context = llvm::getGlobalContext();
		auto module = std::unique_ptr<llvm::Module>(new llvm::Module(id, context));
		auto mainFuncType = llvm::FunctionType::get(llvm::Type::getVoidTy(context), {}, false);
		auto mainFunc = llvm::Function::Create(mainFuncType, llvm::Function::ExternalLinkage, id, module.get());
		auto bb = llvm::BasicBlock::Create(context, {}, mainFunc);
		bb->getInstList().push_back(new llvm::UnreachableInst{context});
		return module;
	}
	CACHE_LOG << id << ": not found\n";
	return nullptr;
}

void ObjectCache::notifyObjectCompiled(llvm::Module const* _module, llvm::MemoryBuffer const* _object)
{
	if (g_listener)
		g_listener->stateChanged(ExecState::CacheWrite);

	auto&& id = _module->getModuleIdentifier();
	llvm::SmallString<256> cachePath;
	llvm::sys::path::system_temp_directory(false, cachePath);
	llvm::sys::path::append(cachePath, "evm_objs");

	if (llvm::sys::fs::create_directory(cachePath.str()))
		return; // TODO: Add log

	llvm::sys::path::append(cachePath, id);

	CACHE_LOG << id << ": write\n";
	std::string error;
	llvm::raw_fd_ostream cacheFile(cachePath.c_str(), error, llvm::sys::fs::F_None);
	cacheFile << _object->getBuffer();
}

llvm::MemoryBuffer* ObjectCache::getObject(llvm::Module const* _module)
{
	CACHE_LOG << _module->getModuleIdentifier() << ": use\n";
	auto o = g_lastObject;
	g_lastObject = nullptr;
	return o;
}

}
}
}
<|endoftext|>


<commit_before>#include "Cache.h"

#include <mutex>

#include "preprocessor/llvm_includes_start.h"
#include <llvm/IR/Module.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Instructions.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/Support/Path.h>
#include <llvm/Support/FileSystem.h>
#include <llvm/Support/raw_os_ostream.h>
#include "preprocessor/llvm_includes_end.h"

#include "support/Path.h"
#include "ExecStats.h"
#include "Utils.h"
#include "BuildInfo.gen.h"

namespace dev
{
namespace evmjit
{

namespace
{
	using Guard = std::lock_guard<std::mutex>;
	std::mutex x_cacheMutex;
	CacheMode g_mode;
	std::unique_ptr<llvm::MemoryBuffer> g_lastObject;
	JITListener* g_listener;

	std::string getVersionedCacheDir()
	{
		llvm::SmallString<256> path{path::user_cache_directory()};
		static const auto c_ethereumAppName = (UTILS_OS_WINDOWS || UTILS_OS_MAC) ? "Ethereum" : "ethereum";
		llvm::sys::path::append(path, c_ethereumAppName, "evmjit", EVMJIT_VERSION);
		return path.str();
	}

}

ObjectCache* Cache::init(CacheMode _mode, JITListener* _listener)
{
	DLOG(cache) << "Cache dir: " << getVersionedCacheDir() << "\n";

	Guard g{x_cacheMutex};

	g_mode = _mode;
	g_listener = _listener;

	if (g_mode == CacheMode::clear)
	{
		Cache::clear();
		g_mode = CacheMode::off;
	}

	if (g_mode != CacheMode::off)
	{
		static ObjectCache objectCache;
		return &objectCache;
	}
	return nullptr;
}

void Cache::clear()
{
	Guard g{x_cacheMutex};

	auto cachePath = getVersionedCacheDir();
	std::error_code err;
	for (auto it = llvm::sys::fs::directory_iterator{cachePath, err}; it != decltype(it){}; it.increment(err))
		llvm::sys::fs::remove(it->path());
}

void Cache::preload(llvm::ExecutionEngine& _ee, std::unordered_map<std::string, uint64_t>& _funcCache)
{
	Guard g{x_cacheMutex};

	// Disable listener
	auto listener = g_listener;
	g_listener = nullptr;

	auto cachePath = getVersionedCacheDir();
	std::error_code err;
	for (auto it = llvm::sys::fs::directory_iterator{cachePath, err}; it != decltype(it){}; it.increment(err))
	{
		auto name = it->path().substr(cachePath.size() + 1);
		if (auto module = getObject(name))
		{
			DLOG(cache) << "Preload: " << name << "\n";
			_ee.addModule(std::move(module));
			auto addr = _ee.getFunctionAddress(name);
			assert(addr);
			_funcCache[std::move(name)] = addr;
		}
	}

	g_listener = listener;
}

std::unique_ptr<llvm::Module> Cache::getObject(std::string const& id)
{
	Guard g{x_cacheMutex};

	if (g_mode != CacheMode::on && g_mode != CacheMode::read)
		return nullptr;

	// TODO: Disabled because is not thread-safe.
	//if (g_listener)
	//	g_listener->stateChanged(ExecState::CacheLoad);

	DLOG(cache) << id << ": search\n";
	if (!CHECK(!g_lastObject))
		g_lastObject = nullptr;

	llvm::SmallString<256> cachePath{getVersionedCacheDir()};
	llvm::sys::path::append(cachePath, id);

	if (auto r = llvm::MemoryBuffer::getFile(cachePath, -1, false))
		g_lastObject = llvm::MemoryBuffer::getMemBufferCopy(r.get()->getBuffer());
	else if (r.getError() != std::make_error_code(std::errc::no_such_file_or_directory))
		DLOG(cache) << r.getError().message(); // TODO: Add warning log

	if (g_lastObject)  // if object found create fake module
	{
		DLOG(cache) << id << ": found\n";
		auto&& context = llvm::getGlobalContext();
		auto module = llvm::make_unique<llvm::Module>(id, context);
		auto mainFuncType = llvm::FunctionType::get(llvm::Type::getVoidTy(context), {}, false);
		auto mainFunc = llvm::Function::Create(mainFuncType, llvm::Function::ExternalLinkage, id, module.get());
		auto bb = llvm::BasicBlock::Create(context, {}, mainFunc);
		bb->getInstList().push_back(new llvm::UnreachableInst{context});
		return module;
	}
	DLOG(cache) << id << ": not found\n";
	return nullptr;
}

void ObjectCache::notifyObjectCompiled(llvm::Module const* _module, llvm::MemoryBufferRef _object)
{
	Guard g{x_cacheMutex};

	// Only in "on" and "write" mode
	if (g_mode != CacheMode::on && g_mode != CacheMode::write)
		return;

	// TODO: Disabled because is not thread-safe.
	// if (g_listener)
		// g_listener->stateChanged(ExecState::CacheWrite);

	auto&& id = _module->getModuleIdentifier();
	llvm::SmallString<256> cachePath{getVersionedCacheDir()};
	if (auto err = llvm::sys::fs::create_directories(cachePath))
	{
		DLOG(cache) << "Cannot create cache dir " << cachePath.str().str() << " (error: " << err.message() << "\n";
		return;
	}

	llvm::sys::path::append(cachePath, id);

	DLOG(cache) << id << ": write\n";
	std::error_code error;
	llvm::raw_fd_ostream cacheFile(cachePath, error, llvm::sys::fs::F_None);
	cacheFile << _object.getBuffer();
}

std::unique_ptr<llvm::MemoryBuffer> ObjectCache::getObject(llvm::Module const* _module)
{
	Guard g{x_cacheMutex};

	DLOG(cache) << _module->getModuleIdentifier() << ": use\n";
	return std::move(g_lastObject);
}

}
}
<commit_msg>New cache versioning (#60)<commit_after>#include "Cache.h"

#include <mutex>

#include "preprocessor/llvm_includes_start.h"
#include <llvm/IR/Module.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Instructions.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/Support/Path.h>
#include <llvm/Support/FileSystem.h>
#include <llvm/Support/raw_os_ostream.h>
#include "preprocessor/llvm_includes_end.h"

#include "support/Path.h"
#include "ExecStats.h"
#include "Utils.h"

namespace dev
{
namespace evmjit
{

namespace
{
	/// The ABI version of jitted codes. It reflects how a generated code
	/// communicates with outside world. When this communication changes old
	/// cached code must be invalidated.
	const auto c_internalABIVersion = 1;

	using Guard = std::lock_guard<std::mutex>;
	std::mutex x_cacheMutex;
	CacheMode g_mode;
	std::unique_ptr<llvm::MemoryBuffer> g_lastObject;
	JITListener* g_listener;

	std::string getVersionedCacheDir()
	{
		llvm::SmallString<256> path{path::user_cache_directory()};
		llvm::sys::path::append(path, "ethereum", "evmjit",
								std::to_string(c_internalABIVersion));
		return path.str();
	}

}

ObjectCache* Cache::init(CacheMode _mode, JITListener* _listener)
{
	DLOG(cache) << "Cache dir: " << getVersionedCacheDir() << "\n";

	Guard g{x_cacheMutex};

	g_mode = _mode;
	g_listener = _listener;

	if (g_mode == CacheMode::clear)
	{
		Cache::clear();
		g_mode = CacheMode::off;
	}

	if (g_mode != CacheMode::off)
	{
		static ObjectCache objectCache;
		return &objectCache;
	}
	return nullptr;
}

void Cache::clear()
{
	Guard g{x_cacheMutex};

	auto cachePath = getVersionedCacheDir();
	std::error_code err;
	for (auto it = llvm::sys::fs::directory_iterator{cachePath, err}; it != decltype(it){}; it.increment(err))
		llvm::sys::fs::remove(it->path());
}

void Cache::preload(llvm::ExecutionEngine& _ee, std::unordered_map<std::string, uint64_t>& _funcCache)
{
	Guard g{x_cacheMutex};

	// Disable listener
	auto listener = g_listener;
	g_listener = nullptr;

	auto cachePath = getVersionedCacheDir();
	std::error_code err;
	for (auto it = llvm::sys::fs::directory_iterator{cachePath, err}; it != decltype(it){}; it.increment(err))
	{
		auto name = it->path().substr(cachePath.size() + 1);
		if (auto module = getObject(name))
		{
			DLOG(cache) << "Preload: " << name << "\n";
			_ee.addModule(std::move(module));
			auto addr = _ee.getFunctionAddress(name);
			assert(addr);
			_funcCache[std::move(name)] = addr;
		}
	}

	g_listener = listener;
}

std::unique_ptr<llvm::Module> Cache::getObject(std::string const& id)
{
	Guard g{x_cacheMutex};

	if (g_mode != CacheMode::on && g_mode != CacheMode::read)
		return nullptr;

	// TODO: Disabled because is not thread-safe.
	//if (g_listener)
	//	g_listener->stateChanged(ExecState::CacheLoad);

	DLOG(cache) << id << ": search\n";
	if (!CHECK(!g_lastObject))
		g_lastObject = nullptr;

	llvm::SmallString<256> cachePath{getVersionedCacheDir()};
	llvm::sys::path::append(cachePath, id);

	if (auto r = llvm::MemoryBuffer::getFile(cachePath, -1, false))
		g_lastObject = llvm::MemoryBuffer::getMemBufferCopy(r.get()->getBuffer());
	else if (r.getError() != std::make_error_code(std::errc::no_such_file_or_directory))
		DLOG(cache) << r.getError().message(); // TODO: Add warning log

	if (g_lastObject)  // if object found create fake module
	{
		DLOG(cache) << id << ": found\n";
		auto&& context = llvm::getGlobalContext();
		auto module = llvm::make_unique<llvm::Module>(id, context);
		auto mainFuncType = llvm::FunctionType::get(llvm::Type::getVoidTy(context), {}, false);
		auto mainFunc = llvm::Function::Create(mainFuncType, llvm::Function::ExternalLinkage, id, module.get());
		auto bb = llvm::BasicBlock::Create(context, {}, mainFunc);
		bb->getInstList().push_back(new llvm::UnreachableInst{context});
		return module;
	}
	DLOG(cache) << id << ": not found\n";
	return nullptr;
}

void ObjectCache::notifyObjectCompiled(llvm::Module const* _module, llvm::MemoryBufferRef _object)
{
	Guard g{x_cacheMutex};

	// Only in "on" and "write" mode
	if (g_mode != CacheMode::on && g_mode != CacheMode::write)
		return;

	// TODO: Disabled because is not thread-safe.
	// if (g_listener)
		// g_listener->stateChanged(ExecState::CacheWrite);

	auto&& id = _module->getModuleIdentifier();
	llvm::SmallString<256> cachePath{getVersionedCacheDir()};
	if (auto err = llvm::sys::fs::create_directories(cachePath))
	{
		DLOG(cache) << "Cannot create cache dir " << cachePath.str().str() << " (error: " << err.message() << "\n";
		return;
	}

	llvm::sys::path::append(cachePath, id);

	DLOG(cache) << id << ": write\n";
	std::error_code error;
	llvm::raw_fd_ostream cacheFile(cachePath, error, llvm::sys::fs::F_None);
	cacheFile << _object.getBuffer();
}

std::unique_ptr<llvm::MemoryBuffer> ObjectCache::getObject(llvm::Module const* _module)
{
	Guard g{x_cacheMutex};

	DLOG(cache) << _module->getModuleIdentifier() << ": use\n";
	return std::move(g_lastObject);
}

}
}
<|endoftext|>


<commit_before>/***************************************************************************//**
 * \file addInitialPerturbation.inl
 * \author Olivier Mesnard (mesnardo@gwu.edu)
 * \brief Implementation of the method `addInitialPerturbation`
 *        of the class `NavierStokesSolver`.
 */

/**
 * \brief Adds a perturbation to the initial flux field.
 *
 * This perturbation takes the form of a Taylor-Green vortex, whose amplitude
 * and frequency are stored in the object `flow`.
 *
 * The amplitude and the frequency of the vortices can be set in the input file
 * `flowDescription.yaml` as following:
 * `initialPertubation: [amplitude, frequency]`
 * where `amplitude` and `frequency` are real values.
 *
 * In 2-D, this perturbation takes the form
 * \f[ u' = - amplitude \cos(X) \sin(Y) \f]
 * \f[ v' = amplitude \sin(X) \cos(Y) \f]
 *
 * and in 3-D
 * \f[ u' = - amplitude \cos(X) \sin(Y) \sin(Z) \f]
 * \f[ v' = amplitude \sin(X) \cos(Y) \sin(Z) \f]
 * \f[ w' = 0 \f]
 *
 * where
 * \f[ X = 2\pi frequency (x-x_{start})/(x_{end}-x_{start}) \f]
 * \f[ X = 2\pi frequency (y-y_{start})/(y_{end}-y_{start}) \f]
 * \f[ X = 2\pi frequency (z-z_{start})/(z_{end}-z_{start}) \f]
 */
template <PetscInt dim>
PetscErrorCode NavierStokesSolver<dim>::addInitialPerturbation()
{
  return 0;
} // addInitialPerturbation

// two-dimensional specialization
template <>
PetscErrorCode NavierStokesSolver<2>::addInitialPerturbation()
{
  PetscErrorCode ierr;

  PetscInt i, j,           // loop indices
           m, n,           // local number of nodes along each direction
           mstart, nstart; // starting indices

  // Taylor-Green vortex perturbation
  PetscReal amplitude = flow->perturbationAmplitude,
            frequency = flow->perturbationFrequency;
  PetscReal X, Y; // scaled location

  // get access to individual packed vectors in their global representation
  Vec qxGlobal, qyGlobal;
  ierr = DMCompositeGetAccess(qPack, q, &qxGlobal, &qyGlobal); CHKERRQ(ierr);

  // fluxes in x-direction
  PetscReal **qx;
  ierr = DMDAVecGetArray(uda, qxGlobal, &qx); CHKERRQ(ierr);
  ierr = DMDAGetCorners(uda, &mstart, &nstart, NULL, &m, &n, NULL); CHKERRQ(ierr);
  for (j=nstart; j<nstart+n; j++)
  {
    Y = 2.0*PETSC_PI*frequency * (0.5*(mesh->y[j]+mesh->y[j+1])-mesh->y[0]) / (mesh->y[mesh->ny]-mesh->y[0]);
    for (i=mstart; i<mstart+m; i++)
    {
      X = 2.0*PETSC_PI*frequency * (mesh->x[i+1]-mesh->x[0]) / (mesh->x[mesh->nx]-mesh->x[0]);
      qx[j][i] += -amplitude*cos(X)*sin(Y) * mesh->dy[j];
    }
  }
  ierr = DMDAVecRestoreArray(uda, qxGlobal, &qx); CHKERRQ(ierr);
  // fluxes in y-direction
  PetscReal **qy;
  ierr = DMDAVecGetArray(vda, qyGlobal, &qy); CHKERRQ(ierr);
  ierr = DMDAGetCorners(vda, &mstart, &nstart, NULL, &m, &n, NULL); CHKERRQ(ierr);
  for (j=nstart; j<nstart+n; j++)
  {
    Y = 2.0*PETSC_PI*frequency * (mesh->y[j]-mesh->y[0]) / (mesh->y[mesh->ny]-mesh->y[0]);
    for (i=mstart; i<mstart+m; i++)
    {
      X = 2.0*PETSC_PI*frequency * (0.5*(mesh->x[i]+mesh->x[i+1])-mesh->x[0]) / (mesh->x[mesh->nx]-mesh->x[0]);
      qy[j][i] += amplitude*sin(X)*cos(Y) * mesh->dx[i];
    }
  }
  ierr = DMDAVecRestoreArray(vda, qyGlobal, &qy); CHKERRQ(ierr);

  ierr = DMCompositeRestoreAccess(qPack, q, &qxGlobal, &qyGlobal); CHKERRQ(ierr);

  return 0;
} // addInitialPerturbation

// three-dimensional specialization
template <>
PetscErrorCode NavierStokesSolver<3>::addInitialPerturbation()
{
  PetscErrorCode ierr;

  PetscInt i, j, k,                // loop indices
           m, n, p,                // local number of nodes along each direction
           mstart, nstart, pstart; // starting indices

  // Taylor-Green vortex perturbation
  PetscReal amplitude = flow->perturbationAmplitude,
            frequency = flow->perturbationFrequency;
  PetscReal X, Y, Z; // scaled location

  // get access to individual packed vectors in their global representation
  Vec qxGlobal, qyGlobal, qzGlobal;
  ierr = DMCompositeGetAccess(qPack, q, &qxGlobal, &qyGlobal, &qzGlobal); CHKERRQ(ierr);

  // fluxes in x-direction
  PetscReal ***qx;
  ierr = DMDAVecGetArray(uda, qxGlobal, &qx); CHKERRQ(ierr);
  ierr = DMDAGetCorners(uda, &mstart, &nstart, &pstart, &m, &n, &p); CHKERRQ(ierr);
  for (k=pstart; k<pstart+p; k++)
  {
    Z = 2.0*PETSC_PI*frequency * (0.5*(mesh->z[k]+mesh->z[k+1])-mesh->z[0]) / (mesh->z[mesh->nz]-mesh->z[0]);
    for (j=nstart; j<nstart+n; j++)
    {
      Y = 2.0*PETSC_PI*frequency * (0.5*(mesh->y[j]+mesh->y[j+1])-mesh->y[0]) / (mesh->y[mesh->ny]-mesh->y[0]);
      for (i=mstart; i<mstart+m; i++)
      {
        X = 2.0*PETSC_PI*frequency * (mesh->x[i+1]-mesh->x[0]) / (mesh->x[mesh->nx]-mesh->x[0]);
        qx[k][j][i] += -amplitude*cos(X)*sin(Y)*sin(Z) * (mesh->dy[j]*mesh->dz[k]);
      }
    }
  }
  ierr = DMDAVecRestoreArray(uda, qxGlobal, &qx); CHKERRQ(ierr);
  // fluxes in y-direction
  PetscReal ***qy;
  ierr = DMDAVecGetArray(vda, qyGlobal, &qy); CHKERRQ(ierr);
  ierr = DMDAGetCorners(vda, &mstart, &nstart, &pstart, &m, &n, &p); CHKERRQ(ierr);
  for (k=pstart; k<pstart+p; k++)
  {
    Z = 2.0*PETSC_PI*frequency * (0.5*(mesh->z[k]+mesh->z[k+1])-mesh->z[0]) / (mesh->z[mesh->nz]-mesh->z[0]);
    for (j=nstart; j<nstart+n; j++)
    {
      Y = 2.0*PETSC_PI*frequency * (mesh->y[j]-mesh->y[0]) / (mesh->y[mesh->ny]-mesh->y[0]);
      for (i=mstart; i<mstart+m; i++)
      {
        X = 2.0*PETSC_PI*frequency * (0.5*(mesh->x[i]+mesh->x[i+1])-mesh->x[0]) / (mesh->x[mesh->nx]-mesh->x[0]);
        qy[k][j][i] += amplitude*sin(X)*cos(Y)*sin(Z) * (mesh->dx[i]*mesh->dz[k]);
      }
    }
  }
  ierr = DMDAVecRestoreArray(vda, qyGlobal, &qy); CHKERRQ(ierr);

  ierr = DMCompositeRestoreAccess(qPack, q, &qxGlobal, &qyGlobal, &qzGlobal); CHKERRQ(ierr);

  return 0;
} // addInitialPerturbation<commit_msg>[bug-fix] Correct initial perturbation of y-fluxes<commit_after>/***************************************************************************//**
 * \file addInitialPerturbation.inl
 * \author Olivier Mesnard (mesnardo@gwu.edu)
 * \brief Implementation of the method `addInitialPerturbation`
 *        of the class `NavierStokesSolver`.
 */

/**
 * \brief Adds a perturbation to the initial flux field.
 *
 * This perturbation takes the form of a Taylor-Green vortex, whose amplitude
 * and frequency are stored in the object `flow`.
 *
 * The amplitude and the frequency of the vortices can be set in the input file
 * `flowDescription.yaml` as following:
 * `initialPertubation: [amplitude, frequency]`
 * where `amplitude` and `frequency` are real values.
 *
 * In 2-D, this perturbation takes the form
 * \f[ u' = - amplitude \cos(X) \sin(Y) \f]
 * \f[ v' = amplitude \sin(X) \cos(Y) \f]
 *
 * and in 3-D
 * \f[ u' = - amplitude \cos(X) \sin(Y) \sin(Z) \f]
 * \f[ v' = amplitude \sin(X) \cos(Y) \sin(Z) \f]
 * \f[ w' = 0 \f]
 *
 * where
 * \f[ X = 2\pi frequency (x-x_{start})/(x_{end}-x_{start}) \f]
 * \f[ X = 2\pi frequency (y-y_{start})/(y_{end}-y_{start}) \f]
 * \f[ X = 2\pi frequency (z-z_{start})/(z_{end}-z_{start}) \f]
 */
template <PetscInt dim>
PetscErrorCode NavierStokesSolver<dim>::addInitialPerturbation()
{
  return 0;
} // addInitialPerturbation

// two-dimensional specialization
template <>
PetscErrorCode NavierStokesSolver<2>::addInitialPerturbation()
{
  PetscErrorCode ierr;

  PetscInt i, j,           // loop indices
           m, n,           // local number of nodes along each direction
           mstart, nstart; // starting indices

  // Taylor-Green vortex perturbation
  PetscReal amplitude = flow->perturbationAmplitude,
            frequency = flow->perturbationFrequency;
  PetscReal X, Y; // scaled location

  // get access to individual packed vectors in their global representation
  Vec qxGlobal, qyGlobal;
  ierr = DMCompositeGetAccess(qPack, q, &qxGlobal, &qyGlobal); CHKERRQ(ierr);

  // fluxes in x-direction
  PetscReal **qx;
  ierr = DMDAVecGetArray(uda, qxGlobal, &qx); CHKERRQ(ierr);
  ierr = DMDAGetCorners(uda, &mstart, &nstart, NULL, &m, &n, NULL); CHKERRQ(ierr);
  for (j=nstart; j<nstart+n; j++)
  {
    Y = 2.0*PETSC_PI*frequency * (0.5*(mesh->y[j]+mesh->y[j+1])-mesh->y[0]) / (mesh->y[mesh->ny]-mesh->y[0]);
    for (i=mstart; i<mstart+m; i++)
    {
      X = 2.0*PETSC_PI*frequency * (mesh->x[i+1]-mesh->x[0]) / (mesh->x[mesh->nx]-mesh->x[0]);
      qx[j][i] += -amplitude*cos(X)*sin(Y) * mesh->dy[j];
    }
  }
  ierr = DMDAVecRestoreArray(uda, qxGlobal, &qx); CHKERRQ(ierr);
  // fluxes in y-direction
  PetscReal **qy;
  ierr = DMDAVecGetArray(vda, qyGlobal, &qy); CHKERRQ(ierr);
  ierr = DMDAGetCorners(vda, &mstart, &nstart, NULL, &m, &n, NULL); CHKERRQ(ierr);
  for (j=nstart; j<nstart+n; j++)
  {
    Y = 2.0*PETSC_PI*frequency * (mesh->y[j+1]-mesh->y[0]) / (mesh->y[mesh->ny]-mesh->y[0]);
    for (i=mstart; i<mstart+m; i++)
    {
      X = 2.0*PETSC_PI*frequency * (0.5*(mesh->x[i]+mesh->x[i+1])-mesh->x[0]) / (mesh->x[mesh->nx]-mesh->x[0]);
      qy[j][i] += amplitude*sin(X)*cos(Y) * mesh->dx[i];
    }
  }
  ierr = DMDAVecRestoreArray(vda, qyGlobal, &qy); CHKERRQ(ierr);

  ierr = DMCompositeRestoreAccess(qPack, q, &qxGlobal, &qyGlobal); CHKERRQ(ierr);

  return 0;
} // addInitialPerturbation

// three-dimensional specialization
template <>
PetscErrorCode NavierStokesSolver<3>::addInitialPerturbation()
{
  PetscErrorCode ierr;

  PetscInt i, j, k,                // loop indices
           m, n, p,                // local number of nodes along each direction
           mstart, nstart, pstart; // starting indices

  // Taylor-Green vortex perturbation
  PetscReal amplitude = flow->perturbationAmplitude,
            frequency = flow->perturbationFrequency;
  PetscReal X, Y, Z; // scaled location

  // get access to individual packed vectors in their global representation
  Vec qxGlobal, qyGlobal, qzGlobal;
  ierr = DMCompositeGetAccess(qPack, q, &qxGlobal, &qyGlobal, &qzGlobal); CHKERRQ(ierr);

  // fluxes in x-direction
  PetscReal ***qx;
  ierr = DMDAVecGetArray(uda, qxGlobal, &qx); CHKERRQ(ierr);
  ierr = DMDAGetCorners(uda, &mstart, &nstart, &pstart, &m, &n, &p); CHKERRQ(ierr);
  for (k=pstart; k<pstart+p; k++)
  {
    Z = 2.0*PETSC_PI*frequency * (0.5*(mesh->z[k]+mesh->z[k+1])-mesh->z[0]) / (mesh->z[mesh->nz]-mesh->z[0]);
    for (j=nstart; j<nstart+n; j++)
    {
      Y = 2.0*PETSC_PI*frequency * (0.5*(mesh->y[j]+mesh->y[j+1])-mesh->y[0]) / (mesh->y[mesh->ny]-mesh->y[0]);
      for (i=mstart; i<mstart+m; i++)
      {
        X = 2.0*PETSC_PI*frequency * (mesh->x[i+1]-mesh->x[0]) / (mesh->x[mesh->nx]-mesh->x[0]);
        qx[k][j][i] += -amplitude*cos(X)*sin(Y)*sin(Z) * (mesh->dy[j]*mesh->dz[k]);
      }
    }
  }
  ierr = DMDAVecRestoreArray(uda, qxGlobal, &qx); CHKERRQ(ierr);
  // fluxes in y-direction
  PetscReal ***qy;
  ierr = DMDAVecGetArray(vda, qyGlobal, &qy); CHKERRQ(ierr);
  ierr = DMDAGetCorners(vda, &mstart, &nstart, &pstart, &m, &n, &p); CHKERRQ(ierr);
  for (k=pstart; k<pstart+p; k++)
  {
    Z = 2.0*PETSC_PI*frequency * (0.5*(mesh->z[k]+mesh->z[k+1])-mesh->z[0]) / (mesh->z[mesh->nz]-mesh->z[0]);
    for (j=nstart; j<nstart+n; j++)
    {
      Y = 2.0*PETSC_PI*frequency * (mesh->y[j+1]-mesh->y[0]) / (mesh->y[mesh->ny]-mesh->y[0]);
      for (i=mstart; i<mstart+m; i++)
      {
        X = 2.0*PETSC_PI*frequency * (0.5*(mesh->x[i]+mesh->x[i+1])-mesh->x[0]) / (mesh->x[mesh->nx]-mesh->x[0]);
        qy[k][j][i] += amplitude*sin(X)*cos(Y)*sin(Z) * (mesh->dx[i]*mesh->dz[k]);
      }
    }
  }
  ierr = DMDAVecRestoreArray(vda, qyGlobal, &qy); CHKERRQ(ierr);

  ierr = DMCompositeRestoreAccess(qPack, q, &qxGlobal, &qyGlobal, &qzGlobal); CHKERRQ(ierr);

  return 0;
} // addInitialPerturbation<|endoftext|>


<commit_before>#include <cnctrq/cnctrqTrqStatisticWorker.h>
#include <prtcl/core/pcSessionExport.H>
#include <cncSession.h>
#include <peer/cSession.H>
#include <sys/stat.h>
#include <prtcl/iCncTrq.H>

#include <iostream>

using v8::Array;
using v8::Context;
using v8::Function;
using v8::FunctionTemplate;
using v8::Handle;
using v8::Local;
using v8::Object;
using v8::Persistent;
using v8::String;
using v8::Value;

using cnc::cncSession;
using pepsis::peer::cSession;
using frqu::prtcl::core::pcSessionExport;
using frqu::prtcl::cnctrq::cnctrqClient;

typedef pepsis::peer::cName::name_ptr name_ptr;
typedef pepsis::peer::cHost::host_ptr host_ptr;

namespace cnc {
  namespace cnctrq {

	typedef pString string_type;

    cnctrqTrqStatisticWorker::cnctrqTrqStatisticWorker(int trq_id
                                             , path_type path
                                             , Nan::Callback* callback)
      : AsyncWorker(callback)
      , _path(path)
      , _errcode(0)
      , _client(0)
    {
      //
      //  Obtain the TRQ's hostname from its TRQ ID.
      //
      name_ptr trq_hostname
        = pcSessionExport::self().HostnameByTrqID(trq_id);
      if (!trq_hostname) {
        _errcode = -EHOSTDOWN;
        return;
      }
      //
      //  Create the RPC client
      //
      _client = new frqu::prtcl::cnctrq::cnctrqClient(trq_hostname);
    }
    //
    //  Destructor.
    //
    cnctrqTrqStatisticWorker::~cnctrqTrqStatisticWorker() { delete _client; }
    //
    //  Execute
    //
    void cnctrqTrqStatisticWorker::Execute() {
      if (_errcode)
        return;  // An error has occurred before we were called.
      _errcode = _client->TrqStatistic(_path, _sum_st_size, _sum_extents);
    }
    //
    //  HandleOKCallback
    //
    void cnctrqTrqStatisticWorker::HandleOKCallback() {
      //
      //  Elaborate the error code.
      //
      int http_status;
      string_type error_sym;
      string_type error_description_brief;
      cncSession::self().RpcToHttpStatus(_errcode
                                        , http_status
                                        , error_sym
                                        , error_description_brief);
      //
      //  Allocate the return object
      //
      Local<Object> rtn = Nan::New<Object>();
      Nan::Set(rtn
               , Nan::New("errcode").ToLocalChecked()
               , Nan::New(_errcode));
      Nan::Set(rtn
               , Nan::New("http_status").ToLocalChecked()
               , Nan::New(http_status));
      Nan::Set(rtn
               , Nan::New("error_sym").ToLocalChecked()
               , Nan::New(error_sym.c_str()).ToLocalChecked());
      Nan::Set(rtn
               , Nan::New("error_description_brief").ToLocalChecked()
               , Nan::New(error_description_brief.c_str()).ToLocalChecked());

      pString member;
      member = pcSessionExport::self().UInt64AsString(_sum_st_size);
      Nan::Set(rtn
               , Nan::New("sum_st_size").ToLocalChecked()
               , Nan::New(member.c_str()).ToLocalChecked());

      member = pcSessionExport::self().UInt64AsString(_sum_extents);
      Nan::Set(rtn
               , Nan::New("sum_extents").ToLocalChecked()
               , Nan::New(member.c_str()).ToLocalChecked());

      //
      //  Prepare for callback
      //
      const unsigned argc = 1;
      Local<Value> argv[argc] = { rtn };
      callback->Call(argc, argv);
    }
    //
  } // namespace 'cnctrq'
} // namespace 'cnc'
<commit_msg>vcnc: represent the vtrq storage stats as numbers rather than strings<commit_after>#include <cnctrq/cnctrqTrqStatisticWorker.h>
#include <prtcl/core/pcSessionExport.H>
#include <cncSession.h>
#include <peer/cSession.H>
#include <sys/stat.h>
#include <prtcl/iCncTrq.H>

#include <iostream>

using v8::Array;
using v8::Context;
using v8::Function;
using v8::FunctionTemplate;
using v8::Handle;
using v8::Local;
using v8::Object;
using v8::Persistent;
using v8::String;
using v8::Value;

using cnc::cncSession;
using pepsis::peer::cSession;
using frqu::prtcl::core::pcSessionExport;
using frqu::prtcl::cnctrq::cnctrqClient;

typedef pepsis::peer::cName::name_ptr name_ptr;
typedef pepsis::peer::cHost::host_ptr host_ptr;

namespace cnc {
  namespace cnctrq {

	typedef pString string_type;

    cnctrqTrqStatisticWorker::cnctrqTrqStatisticWorker(int trq_id
                                             , path_type path
                                             , Nan::Callback* callback)
      : AsyncWorker(callback)
      , _path(path)
      , _errcode(0)
      , _client(0)
    {
      //
      //  Obtain the TRQ's hostname from its TRQ ID.
      //
      name_ptr trq_hostname
        = pcSessionExport::self().HostnameByTrqID(trq_id);
      if (!trq_hostname) {
        _errcode = -EHOSTDOWN;
        return;
      }
      //
      //  Create the RPC client
      //
      _client = new frqu::prtcl::cnctrq::cnctrqClient(trq_hostname);
    }
    //
    //  Destructor.
    //
    cnctrqTrqStatisticWorker::~cnctrqTrqStatisticWorker() { delete _client; }
    //
    //  Execute
    //
    void cnctrqTrqStatisticWorker::Execute() {
      if (_errcode)
        return;  // An error has occurred before we were called.
      _errcode = _client->TrqStatistic(_path, _sum_st_size, _sum_extents);
    }
    //
    //  HandleOKCallback
    //
    void cnctrqTrqStatisticWorker::HandleOKCallback() {
      //
      //  Elaborate the error code.
      //
      int http_status;
      string_type error_sym;
      string_type error_description_brief;
      cncSession::self().RpcToHttpStatus(_errcode
                                        , http_status
                                        , error_sym
                                        , error_description_brief);
      //
      //  Allocate the return object
      //
      Local<Object> rtn = Nan::New<Object>();
      Nan::Set(rtn
               , Nan::New("errcode").ToLocalChecked()
               , Nan::New(_errcode));
      Nan::Set(rtn
               , Nan::New("http_status").ToLocalChecked()
               , Nan::New(http_status));
      Nan::Set(rtn
               , Nan::New("error_sym").ToLocalChecked()
               , Nan::New(error_sym.c_str()).ToLocalChecked());
      Nan::Set(rtn
               , Nan::New("error_description_brief").ToLocalChecked()
               , Nan::New(error_description_brief.c_str()).ToLocalChecked());
      Nan::Set(rtn
               , Nan::New("sum_st_size").ToLocalChecked()
               , Nan::New(static_cast<double>(_sum_st_size)));

      Nan::Set(rtn
               , Nan::New("sum_extents").ToLocalChecked()
               , Nan::New(static_cast<double>(_sum_extents)));

      //
      //  Prepare for callback
      //
      const unsigned argc = 1;
      Local<Value> argv[argc] = { rtn };
      callback->Call(argc, argv);
    }
    //
  } // namespace 'cnctrq'
} // namespace 'cnc'
<|endoftext|>


<commit_before>// This file is part of MicroRestD <http://github.com/ufal/microrestd/>.
//
// Copyright 2015 Institute of Formal and Applied Linguistics, Faculty of
// Mathematics and Physics, Charles University in Prague, Czech Republic.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include <chrono>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>
#include <thread>

#include "microrestd.h"

using namespace std;
using namespace ufal::microrestd;

class file_service : public rest_service {
  class file_generator : public response_generator {
   public:
    file_generator(ifstream* f) : f(f) {}

    virtual bool generate() override {
      size_t data_size = data.size();
      data.resize(data_size + 1024);
      f->read(data.data() + data_size, 1024);
      data.resize(data_size + f->gcount());

      // Now sleep for 2 seconds to simulate hard work :-)
      this_thread::sleep_for(chrono::seconds(2));

      return f->gcount();
    }
    virtual string_piece current() const override {
      return string_piece(data.data(), data.size());
    }
    virtual void consume(size_t length) override {
      if (length >= data.size()) data.clear();
      else if (length) data.erase(data.begin(), data.begin() + length);
    }

   private:
    unique_ptr<ifstream> f;
    vector<char> data;
  };

 public:
  virtual bool handle(rest_request& req) override {
    if (req.method != "HEAD" && req.method != "GET" && req.method != "POST") return req.respond_method_not_allowed("HEAD, GET, POST");

    if (!req.url.empty()) {
      unique_ptr<ifstream> file(new ifstream(req.url.c_str() + 1, ifstream::in | ifstream::binary));
      if (file && file->is_open())
        return req.respond("application/octet-stream", new file_generator(file.release()));
    }

    return req.respond_not_found();
  }
};

int main(int argc, char* argv[]) {
  if (argc < 2)
    return cerr << "Usage: " << argv[0] << " port [threads] [connection_limit]" << endl, 1;
  int port = stoi(argv[1]);
  int threads = argc >= 3 ? stoi(argv[2]) : 0;
  int connection_limit = argc >= 4 ? stoi(argv[3]) : 2;

  rest_server server;
  server.set_log_file(&cerr);
  server.set_max_connections(connection_limit);
  server.set_threads(threads);

  file_service service;
  if (!server.start(&service, port))
    return cerr << "Cannot start REST server!" << endl, 1;
  server.wait_until_signalled();
  server.stop();

  return 0;
}
<commit_msg>Remove unnecessary ifstream::in.<commit_after>// This file is part of MicroRestD <http://github.com/ufal/microrestd/>.
//
// Copyright 2015 Institute of Formal and Applied Linguistics, Faculty of
// Mathematics and Physics, Charles University in Prague, Czech Republic.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include <chrono>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>
#include <thread>

#include "microrestd.h"

using namespace std;
using namespace ufal::microrestd;

class file_service : public rest_service {
  class file_generator : public response_generator {
   public:
    file_generator(ifstream* f) : f(f) {}

    virtual bool generate() override {
      size_t data_size = data.size();
      data.resize(data_size + 1024);
      f->read(data.data() + data_size, 1024);
      data.resize(data_size + f->gcount());

      // Now sleep for 2 seconds to simulate hard work :-)
      this_thread::sleep_for(chrono::seconds(2));

      return f->gcount();
    }
    virtual string_piece current() const override {
      return string_piece(data.data(), data.size());
    }
    virtual void consume(size_t length) override {
      if (length >= data.size()) data.clear();
      else if (length) data.erase(data.begin(), data.begin() + length);
    }

   private:
    unique_ptr<ifstream> f;
    vector<char> data;
  };

 public:
  virtual bool handle(rest_request& req) override {
    if (req.method != "HEAD" && req.method != "GET" && req.method != "POST") return req.respond_method_not_allowed("HEAD, GET, POST");

    if (!req.url.empty()) {
      unique_ptr<ifstream> file(new ifstream(req.url.c_str() + 1, ifstream::binary));
      if (file && file->is_open())
        return req.respond("application/octet-stream", new file_generator(file.release()));
    }

    return req.respond_not_found();
  }
};

int main(int argc, char* argv[]) {
  if (argc < 2)
    return cerr << "Usage: " << argv[0] << " port [threads] [connection_limit]" << endl, 1;
  int port = stoi(argv[1]);
  int threads = argc >= 3 ? stoi(argv[2]) : 0;
  int connection_limit = argc >= 4 ? stoi(argv[3]) : 2;

  rest_server server;
  server.set_log_file(&cerr);
  server.set_max_connections(connection_limit);
  server.set_threads(threads);

  file_service service;
  if (!server.start(&service, port))
    return cerr << "Cannot start REST server!" << endl, 1;
  server.wait_until_signalled();
  server.stop();

  return 0;
}
<|endoftext|>


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

#include "media/filters/ffmpeg_video_decode_engine.h"

#include "base/command_line.h"
#include "base/string_number_conversions.h"
#include "base/task.h"
#include "media/base/buffers.h"
#include "media/base/callback.h"
#include "media/base/limits.h"
#include "media/base/media_switches.h"
#include "media/ffmpeg/ffmpeg_common.h"
#include "media/ffmpeg/ffmpeg_util.h"
#include "media/filters/ffmpeg_demuxer.h"

namespace media {

FFmpegVideoDecodeEngine::FFmpegVideoDecodeEngine()
    : codec_context_(NULL),
      av_stream_(NULL),
      event_handler_(NULL) {
}

FFmpegVideoDecodeEngine::~FFmpegVideoDecodeEngine() {
}

void FFmpegVideoDecodeEngine::Initialize(
    MessageLoop* message_loop,
    VideoDecodeEngine::EventHandler* event_handler,
    const VideoCodecConfig& config) {
  // Always try to use three threads for video decoding.  There is little reason
  // not to since current day CPUs tend to be multi-core and we measured
  // performance benefits on older machines such as P4s with hyperthreading.
  //
  // Handling decoding on separate threads also frees up the pipeline thread to
  // continue processing. Although it'd be nice to have the option of a single
  // decoding thread, FFmpeg treats having one thread the same as having zero
  // threads (i.e., avcodec_decode_video() will execute on the calling thread).
  // Yet another reason for having three threads :)
  static const int kDecodeThreads = 3;
  static const int kMaxDecodeThreads = 16;

  av_stream_ = static_cast<AVStream*>(config.opaque_context_);
  codec_context_ = av_stream_->codec;
  codec_context_->flags2 |= CODEC_FLAG2_FAST;  // Enable faster H264 decode.
  // Enable motion vector search (potentially slow), strong deblocking filter
  // for damaged macroblocks, and set our error detection sensitivity.
  codec_context_->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK;
  codec_context_->error_recognition = FF_ER_CAREFUL;

  AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);

  // TODO(fbarchard): Improve thread logic based on size / codec.
  int decode_threads = kDecodeThreads;

  const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
  std::string threads(cmd_line->GetSwitchValueASCII(switches::kVideoThreads));
  if ((!threads.empty() &&
      !base::StringToInt(threads, &decode_threads)) ||
      decode_threads < 0 || decode_threads > kMaxDecodeThreads) {
    decode_threads = kDecodeThreads;
  }

  // We don't allocate AVFrame on the stack since different versions of FFmpeg
  // may change the size of AVFrame, causing stack corruption.  The solution is
  // to let FFmpeg allocate the structure via avcodec_alloc_frame().
  av_frame_.reset(avcodec_alloc_frame());
  VideoCodecInfo info;
  info.success_ = false;
  info.provides_buffers_ = false;
  info.stream_info_.surface_type_ = VideoFrame::TYPE_SYSTEM_MEMORY;
  info.stream_info_.surface_format_ = GetSurfaceFormat();
  info.stream_info_.surface_width_ = config.width_;
  info.stream_info_.surface_height_ = config.height_;
  if (codec &&
      avcodec_thread_init(codec_context_, decode_threads) >= 0 &&
      avcodec_open(codec_context_, codec) >= 0 &&
      av_frame_.get()) {
    info.success_ = true;
  }
#if !defined(FF_THREAD_FRAME)
#pragma message ("Warning: Not building with FFmpeg MT.")
#else
#pragma message ("Building with FFmpeg MT.")
#endif
  event_handler_ = event_handler;
  event_handler_->OnInitializeComplete(info);
}

// TODO(fbarchard): Find way to remove this memcpy of the entire image.
static void CopyPlane(size_t plane,
                      scoped_refptr<VideoFrame> video_frame,
                      const AVFrame* frame) {
  DCHECK_EQ(video_frame->width() % 2, 0u);
  const uint8* source = frame->data[plane];
  const size_t source_stride = frame->linesize[plane];
  uint8* dest = video_frame->data(plane);
  const size_t dest_stride = video_frame->stride(plane);
  size_t bytes_per_line = video_frame->width();
  size_t copy_lines = video_frame->height();
  if (plane != VideoFrame::kYPlane) {
    bytes_per_line /= 2;
    if (video_frame->format() == VideoFrame::YV12) {
      copy_lines = (copy_lines + 1) / 2;
    }
  }
  DCHECK(bytes_per_line <= source_stride && bytes_per_line <= dest_stride);
  for (size_t i = 0; i < copy_lines; ++i) {
    memcpy(dest, source, bytes_per_line);
    source += source_stride;
    dest += dest_stride;
  }
}

void FFmpegVideoDecodeEngine::EmptyThisBuffer(
    scoped_refptr<Buffer> buffer) {
  DecodeFrame(buffer);
}

void FFmpegVideoDecodeEngine::FillThisBuffer(scoped_refptr<VideoFrame> frame) {
  scoped_refptr<Buffer> buffer;
  event_handler_->OnEmptyBufferCallback(buffer);
}

// Try to decode frame when both input and output are ready.
void FFmpegVideoDecodeEngine::DecodeFrame(scoped_refptr<Buffer> buffer) {
  scoped_refptr<VideoFrame> video_frame;

  // Create a packet for input data.
  // Due to FFmpeg API changes we no longer have const read-only pointers.
  AVPacket packet;
  av_init_packet(&packet);
  packet.data = const_cast<uint8*>(buffer->GetData());
  packet.size = buffer->GetDataSize();

  // Let FFmpeg handle presentation timestamp reordering.
  codec_context_->reordered_opaque = buffer->GetTimestamp().InMicroseconds();

  // This is for codecs not using get_buffer to initialize
  // |av_frame_->reordered_opaque|
  av_frame_->reordered_opaque = codec_context_->reordered_opaque;

  int frame_decoded = 0;
  int result = avcodec_decode_video2(codec_context_,
                                     av_frame_.get(),
                                     &frame_decoded,
                                     &packet);

  // Log the problem if we can't decode a video frame and exit early.
  if (result < 0) {
    LOG(INFO) << "Error decoding a video frame with timestamp: "
              << buffer->GetTimestamp().InMicroseconds() << " us"
              << " , duration: "
              << buffer->GetDuration().InMicroseconds() << " us"
              << " , packet size: "
              << buffer->GetDataSize() << " bytes";
    // TODO(jiesun): call event_handler_->OnError() instead.
    event_handler_->OnFillBufferCallback(video_frame);
    return;
  }

  // If frame_decoded == 0, then no frame was produced.
  if (frame_decoded == 0) {
    if (buffer->IsEndOfStream())  // We had started flushing.
      event_handler_->OnFillBufferCallback(video_frame);
    else
      event_handler_->OnEmptyBufferCallback(buffer);
    return;
  }

  // TODO(fbarchard): Work around for FFmpeg http://crbug.com/27675
  // The decoder is in a bad state and not decoding correctly.
  // Checking for NULL avoids a crash in CopyPlane().
  if (!av_frame_->data[VideoFrame::kYPlane] ||
      !av_frame_->data[VideoFrame::kUPlane] ||
      !av_frame_->data[VideoFrame::kVPlane]) {
    // TODO(jiesun): call event_handler_->OnError() instead.
    event_handler_->OnFillBufferCallback(video_frame);
    return;
  }

  // Determine timestamp and calculate the duration based on the repeat picture
  // count.  According to FFmpeg docs, the total duration can be calculated as
  // follows:
  //   duration = (1 / fps) + (repeat_pict) / (2 * fps)
  //            = (2 + repeat_pict) / (2 * fps)
  DCHECK_LE(av_frame_->repeat_pict, 2);  // Sanity check.
  // Even frame rate is fixed, for some streams and codecs, the value of
  // |codec_context_->time_base| and |av_stream_->time_base| are not the
  // inverse of the |av_stream_->r_frame_rate|. They use 1 milli-second as
  // time-base units and use increment of av_packet->pts which is not one.
  // Use the inverse of |av_stream_->r_frame_rate| instead of time_base.
  AVRational doubled_time_base;
  doubled_time_base.den = av_stream_->r_frame_rate.num;
  doubled_time_base.num = av_stream_->r_frame_rate.den;
  doubled_time_base.den *= 2;

  base::TimeDelta timestamp =
      base::TimeDelta::FromMicroseconds(av_frame_->reordered_opaque);
  base::TimeDelta duration =
      ConvertTimestamp(doubled_time_base, 2 + av_frame_->repeat_pict);

  VideoFrame::CreateFrame(GetSurfaceFormat(),
                          codec_context_->width,
                          codec_context_->height,
                          timestamp,
                          duration,
                          &video_frame);
  if (!video_frame.get()) {
    // TODO(jiesun): call event_handler_->OnError() instead.
    event_handler_->OnFillBufferCallback(video_frame);
    return;
  }

  // Copy the frame data since FFmpeg reuses internal buffers for AVFrame
  // output, meaning the data is only valid until the next
  // avcodec_decode_video() call.
  // TODO(scherkus): figure out pre-allocation/buffer cycling scheme.
  // TODO(scherkus): is there a cleaner way to figure out the # of planes?
  CopyPlane(VideoFrame::kYPlane, video_frame.get(), av_frame_.get());
  CopyPlane(VideoFrame::kUPlane, video_frame.get(), av_frame_.get());
  CopyPlane(VideoFrame::kVPlane, video_frame.get(), av_frame_.get());

  event_handler_->OnFillBufferCallback(video_frame);
}

void FFmpegVideoDecodeEngine::Uninitialize() {
  // TODO(jiesun): Release buffers when we support buffer recycling.
  event_handler_->OnUninitializeComplete();
}

void FFmpegVideoDecodeEngine::Flush() {
  avcodec_flush_buffers(codec_context_);
  event_handler_->OnFlushComplete();
}

void FFmpegVideoDecodeEngine::Seek() {
  event_handler_->OnSeekComplete();
}

VideoFrame::Format FFmpegVideoDecodeEngine::GetSurfaceFormat() const {
  // J (Motion JPEG) versions of YUV are full range 0..255.
  // Regular (MPEG) YUV is 16..240.
  // For now we will ignore the distinction and treat them the same.
  switch (codec_context_->pix_fmt) {
    case PIX_FMT_YUV420P:
    case PIX_FMT_YUVJ420P:
      return VideoFrame::YV12;
      break;
    case PIX_FMT_YUV422P:
    case PIX_FMT_YUVJ422P:
      return VideoFrame::YV16;
      break;
    default:
      // TODO(scherkus): More formats here?
      return VideoFrame::INVALID;
  }
}

}  // namespace media
<commit_msg>remove pragma message to fix build issue BUG=none TEST=none<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/filters/ffmpeg_video_decode_engine.h"

#include "base/command_line.h"
#include "base/string_number_conversions.h"
#include "base/task.h"
#include "media/base/buffers.h"
#include "media/base/callback.h"
#include "media/base/limits.h"
#include "media/base/media_switches.h"
#include "media/ffmpeg/ffmpeg_common.h"
#include "media/ffmpeg/ffmpeg_util.h"
#include "media/filters/ffmpeg_demuxer.h"

namespace media {

FFmpegVideoDecodeEngine::FFmpegVideoDecodeEngine()
    : codec_context_(NULL),
      av_stream_(NULL),
      event_handler_(NULL) {
}

FFmpegVideoDecodeEngine::~FFmpegVideoDecodeEngine() {
}

void FFmpegVideoDecodeEngine::Initialize(
    MessageLoop* message_loop,
    VideoDecodeEngine::EventHandler* event_handler,
    const VideoCodecConfig& config) {
  // Always try to use three threads for video decoding.  There is little reason
  // not to since current day CPUs tend to be multi-core and we measured
  // performance benefits on older machines such as P4s with hyperthreading.
  //
  // Handling decoding on separate threads also frees up the pipeline thread to
  // continue processing. Although it'd be nice to have the option of a single
  // decoding thread, FFmpeg treats having one thread the same as having zero
  // threads (i.e., avcodec_decode_video() will execute on the calling thread).
  // Yet another reason for having three threads :)
  static const int kDecodeThreads = 3;
  static const int kMaxDecodeThreads = 16;

  av_stream_ = static_cast<AVStream*>(config.opaque_context_);
  codec_context_ = av_stream_->codec;
  codec_context_->flags2 |= CODEC_FLAG2_FAST;  // Enable faster H264 decode.
  // Enable motion vector search (potentially slow), strong deblocking filter
  // for damaged macroblocks, and set our error detection sensitivity.
  codec_context_->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK;
  codec_context_->error_recognition = FF_ER_CAREFUL;

  AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);

  // TODO(fbarchard): Improve thread logic based on size / codec.
  int decode_threads = kDecodeThreads;

  const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
  std::string threads(cmd_line->GetSwitchValueASCII(switches::kVideoThreads));
  if ((!threads.empty() &&
      !base::StringToInt(threads, &decode_threads)) ||
      decode_threads < 0 || decode_threads > kMaxDecodeThreads) {
    decode_threads = kDecodeThreads;
  }

  // We don't allocate AVFrame on the stack since different versions of FFmpeg
  // may change the size of AVFrame, causing stack corruption.  The solution is
  // to let FFmpeg allocate the structure via avcodec_alloc_frame().
  av_frame_.reset(avcodec_alloc_frame());
  VideoCodecInfo info;
  info.success_ = false;
  info.provides_buffers_ = false;
  info.stream_info_.surface_type_ = VideoFrame::TYPE_SYSTEM_MEMORY;
  info.stream_info_.surface_format_ = GetSurfaceFormat();
  info.stream_info_.surface_width_ = config.width_;
  info.stream_info_.surface_height_ = config.height_;
  if (codec &&
      avcodec_thread_init(codec_context_, decode_threads) >= 0 &&
      avcodec_open(codec_context_, codec) >= 0 &&
      av_frame_.get()) {
    info.success_ = true;
  }
  event_handler_ = event_handler;
  event_handler_->OnInitializeComplete(info);
}

// TODO(fbarchard): Find way to remove this memcpy of the entire image.
static void CopyPlane(size_t plane,
                      scoped_refptr<VideoFrame> video_frame,
                      const AVFrame* frame) {
  DCHECK_EQ(video_frame->width() % 2, 0u);
  const uint8* source = frame->data[plane];
  const size_t source_stride = frame->linesize[plane];
  uint8* dest = video_frame->data(plane);
  const size_t dest_stride = video_frame->stride(plane);
  size_t bytes_per_line = video_frame->width();
  size_t copy_lines = video_frame->height();
  if (plane != VideoFrame::kYPlane) {
    bytes_per_line /= 2;
    if (video_frame->format() == VideoFrame::YV12) {
      copy_lines = (copy_lines + 1) / 2;
    }
  }
  DCHECK(bytes_per_line <= source_stride && bytes_per_line <= dest_stride);
  for (size_t i = 0; i < copy_lines; ++i) {
    memcpy(dest, source, bytes_per_line);
    source += source_stride;
    dest += dest_stride;
  }
}

void FFmpegVideoDecodeEngine::EmptyThisBuffer(
    scoped_refptr<Buffer> buffer) {
  DecodeFrame(buffer);
}

void FFmpegVideoDecodeEngine::FillThisBuffer(scoped_refptr<VideoFrame> frame) {
  scoped_refptr<Buffer> buffer;
  event_handler_->OnEmptyBufferCallback(buffer);
}

// Try to decode frame when both input and output are ready.
void FFmpegVideoDecodeEngine::DecodeFrame(scoped_refptr<Buffer> buffer) {
  scoped_refptr<VideoFrame> video_frame;

  // Create a packet for input data.
  // Due to FFmpeg API changes we no longer have const read-only pointers.
  AVPacket packet;
  av_init_packet(&packet);
  packet.data = const_cast<uint8*>(buffer->GetData());
  packet.size = buffer->GetDataSize();

  // Let FFmpeg handle presentation timestamp reordering.
  codec_context_->reordered_opaque = buffer->GetTimestamp().InMicroseconds();

  // This is for codecs not using get_buffer to initialize
  // |av_frame_->reordered_opaque|
  av_frame_->reordered_opaque = codec_context_->reordered_opaque;

  int frame_decoded = 0;
  int result = avcodec_decode_video2(codec_context_,
                                     av_frame_.get(),
                                     &frame_decoded,
                                     &packet);

  // Log the problem if we can't decode a video frame and exit early.
  if (result < 0) {
    LOG(INFO) << "Error decoding a video frame with timestamp: "
              << buffer->GetTimestamp().InMicroseconds() << " us"
              << " , duration: "
              << buffer->GetDuration().InMicroseconds() << " us"
              << " , packet size: "
              << buffer->GetDataSize() << " bytes";
    // TODO(jiesun): call event_handler_->OnError() instead.
    event_handler_->OnFillBufferCallback(video_frame);
    return;
  }

  // If frame_decoded == 0, then no frame was produced.
  if (frame_decoded == 0) {
    if (buffer->IsEndOfStream())  // We had started flushing.
      event_handler_->OnFillBufferCallback(video_frame);
    else
      event_handler_->OnEmptyBufferCallback(buffer);
    return;
  }

  // TODO(fbarchard): Work around for FFmpeg http://crbug.com/27675
  // The decoder is in a bad state and not decoding correctly.
  // Checking for NULL avoids a crash in CopyPlane().
  if (!av_frame_->data[VideoFrame::kYPlane] ||
      !av_frame_->data[VideoFrame::kUPlane] ||
      !av_frame_->data[VideoFrame::kVPlane]) {
    // TODO(jiesun): call event_handler_->OnError() instead.
    event_handler_->OnFillBufferCallback(video_frame);
    return;
  }

  // Determine timestamp and calculate the duration based on the repeat picture
  // count.  According to FFmpeg docs, the total duration can be calculated as
  // follows:
  //   duration = (1 / fps) + (repeat_pict) / (2 * fps)
  //            = (2 + repeat_pict) / (2 * fps)
  DCHECK_LE(av_frame_->repeat_pict, 2);  // Sanity check.
  // Even frame rate is fixed, for some streams and codecs, the value of
  // |codec_context_->time_base| and |av_stream_->time_base| are not the
  // inverse of the |av_stream_->r_frame_rate|. They use 1 milli-second as
  // time-base units and use increment of av_packet->pts which is not one.
  // Use the inverse of |av_stream_->r_frame_rate| instead of time_base.
  AVRational doubled_time_base;
  doubled_time_base.den = av_stream_->r_frame_rate.num;
  doubled_time_base.num = av_stream_->r_frame_rate.den;
  doubled_time_base.den *= 2;

  base::TimeDelta timestamp =
      base::TimeDelta::FromMicroseconds(av_frame_->reordered_opaque);
  base::TimeDelta duration =
      ConvertTimestamp(doubled_time_base, 2 + av_frame_->repeat_pict);

  VideoFrame::CreateFrame(GetSurfaceFormat(),
                          codec_context_->width,
                          codec_context_->height,
                          timestamp,
                          duration,
                          &video_frame);
  if (!video_frame.get()) {
    // TODO(jiesun): call event_handler_->OnError() instead.
    event_handler_->OnFillBufferCallback(video_frame);
    return;
  }

  // Copy the frame data since FFmpeg reuses internal buffers for AVFrame
  // output, meaning the data is only valid until the next
  // avcodec_decode_video() call.
  // TODO(scherkus): figure out pre-allocation/buffer cycling scheme.
  // TODO(scherkus): is there a cleaner way to figure out the # of planes?
  CopyPlane(VideoFrame::kYPlane, video_frame.get(), av_frame_.get());
  CopyPlane(VideoFrame::kUPlane, video_frame.get(), av_frame_.get());
  CopyPlane(VideoFrame::kVPlane, video_frame.get(), av_frame_.get());

  event_handler_->OnFillBufferCallback(video_frame);
}

void FFmpegVideoDecodeEngine::Uninitialize() {
  // TODO(jiesun): Release buffers when we support buffer recycling.
  event_handler_->OnUninitializeComplete();
}

void FFmpegVideoDecodeEngine::Flush() {
  avcodec_flush_buffers(codec_context_);
  event_handler_->OnFlushComplete();
}

void FFmpegVideoDecodeEngine::Seek() {
  event_handler_->OnSeekComplete();
}

VideoFrame::Format FFmpegVideoDecodeEngine::GetSurfaceFormat() const {
  // J (Motion JPEG) versions of YUV are full range 0..255.
  // Regular (MPEG) YUV is 16..240.
  // For now we will ignore the distinction and treat them the same.
  switch (codec_context_->pix_fmt) {
    case PIX_FMT_YUV420P:
    case PIX_FMT_YUVJ420P:
      return VideoFrame::YV12;
      break;
    case PIX_FMT_YUV422P:
    case PIX_FMT_YUVJ422P:
      return VideoFrame::YV16;
      break;
    default:
      // TODO(scherkus): More formats here?
      return VideoFrame::INVALID;
  }
}

}  // namespace media
<|endoftext|>


<commit_before>#include <gtest/gtest.h>

#include <string>

#include <cpr.h>
#include <curl/curl.h>

#include "server.h"

using namespace cpr;

static Server* server = new Server();
auto base = server->GetBaseUrl();
auto baseSSL = server->GetBaseUrlSSL();

TEST(ErrorTests, BasicSSLFailure) {
    auto url = Url{baseSSL + "/hello.html"};
    auto response = cpr::Get(url);
    EXPECT_EQ(url, response.url);
    EXPECT_EQ(0, response.status_code);
    auto curl_version = curl_version_info(CURLVERSION_NOW);
    auto expected = ErrorCode::UNSUPPORTED_PROTOCOL;
    if(curl_version->features & CURL_VERSION_SSL) {
        expected = ErrorCode::SSL_CONNECT_ERROR;
    }
    EXPECT_EQ(expected, response.error.code);

}

TEST(ErrorTests, UnsupportedProtocolFailure) {
    auto url = Url{"urk://wat.is.this"};
    auto response = cpr::Get(url);
    EXPECT_EQ(0, response.status_code);
    EXPECT_EQ(ErrorCode::UNSUPPORTED_PROTOCOL, response.error.code);
}

TEST(ErrorTests, InvalidURLFailure) {
    auto url = Url{"???"};
    auto response = cpr::Get(url);
    EXPECT_EQ(0, response.status_code);
    EXPECT_EQ(ErrorCode::INVALID_URL_FORMAT, response.error.code);
}

TEST(ErrorTests, TimeoutFailure) {
    auto url = Url{"http://railstars.com"};
    auto response = cpr::Get(url, cpr::Timeout{1});
    EXPECT_EQ(0, response.status_code);
    EXPECT_EQ(ErrorCode::OPERATION_TIMEDOUT, response.error.code);
}

TEST(ErrorTests, ProxyFailure) {
    auto url = Url{base + "/hello.html"};
    auto response = cpr::Get(url, cpr::Proxies{{"http", "http://bad_host/"}});
    EXPECT_EQ(url, response.url);
    EXPECT_EQ(0, response.status_code);
    EXPECT_EQ(ErrorCode::PROXY_RESOLUTION_FAILURE, response.error.code);
}

int main(int argc, char** argv) {
    ::testing::InitGoogleTest(&argc, argv);
    ::testing::AddGlobalTestEnvironment(server);
    return RUN_ALL_TESTS();
}
<commit_msg>Remove spacing in headers<commit_after>#include <gtest/gtest.h>

#include <string>

#include <cpr.h>
#include <curl/curl.h>

#include "server.h"

using namespace cpr;

static Server* server = new Server();
auto base = server->GetBaseUrl();
auto baseSSL = server->GetBaseUrlSSL();

TEST(ErrorTests, BasicSSLFailure) {
    auto url = Url{baseSSL + "/hello.html"};
    auto response = cpr::Get(url);
    EXPECT_EQ(url, response.url);
    EXPECT_EQ(0, response.status_code);
    auto curl_version = curl_version_info(CURLVERSION_NOW);
    auto expected = ErrorCode::UNSUPPORTED_PROTOCOL;
    if(curl_version->features & CURL_VERSION_SSL) {
        expected = ErrorCode::SSL_CONNECT_ERROR;
    }
    EXPECT_EQ(expected, response.error.code);

}

TEST(ErrorTests, UnsupportedProtocolFailure) {
    auto url = Url{"urk://wat.is.this"};
    auto response = cpr::Get(url);
    EXPECT_EQ(0, response.status_code);
    EXPECT_EQ(ErrorCode::UNSUPPORTED_PROTOCOL, response.error.code);
}

TEST(ErrorTests, InvalidURLFailure) {
    auto url = Url{"???"};
    auto response = cpr::Get(url);
    EXPECT_EQ(0, response.status_code);
    EXPECT_EQ(ErrorCode::INVALID_URL_FORMAT, response.error.code);
}

TEST(ErrorTests, TimeoutFailure) {
    auto url = Url{"http://railstars.com"};
    auto response = cpr::Get(url, cpr::Timeout{1});
    EXPECT_EQ(0, response.status_code);
    EXPECT_EQ(ErrorCode::OPERATION_TIMEDOUT, response.error.code);
}

TEST(ErrorTests, ProxyFailure) {
    auto url = Url{base + "/hello.html"};
    auto response = cpr::Get(url, cpr::Proxies{{"http", "http://bad_host/"}});
    EXPECT_EQ(url, response.url);
    EXPECT_EQ(0, response.status_code);
    EXPECT_EQ(ErrorCode::PROXY_RESOLUTION_FAILURE, response.error.code);
}

int main(int argc, char** argv) {
    ::testing::InitGoogleTest(&argc, argv);
    ::testing::AddGlobalTestEnvironment(server);
    return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>#include "../../include/d2tmh.h"

// Constructor
cRefinery::cRefinery()
{

 // other variables (class specific)

}

int cRefinery::getType() {
	return REFINERY;
}

cRefinery::~cRefinery()
{

}

/*  OVERLOADED FUNCTIONS  */

// Specific Construction Yard thinking
void cRefinery::think()
{

     // When a refinery, and expecting a unit
     if (iUnitID > -1)
        {
			int iMyID=-1;
			for (int i=0; i < MAX_STRUCTURES; i++)
				if (structure[i] == this)
				{
					iMyID=i;
					break;
				}

            // when the unit somehow does not go to us anymore, stop animating
            if (unit[iUnitID].isValid() == false)
            {
                iUnitID=-1;
				setAnimating(false);
                return;
            }

			if (unit[iUnitID].iStructureID != iMyID)
			{
				iUnitID=-1;
				setAnimating(false);
				return;
			}

            // the unit id is filled in, that means the unit is IN this structure
            // the TIMER_harvest of the unit will be used to dump the harvest in the
            // refinery

            unit[iUnitID].TIMER_harvest++;

            cPlayerDifficultySettings * difficultySettings = player[getOwner()].getDifficultySettings();

            if (unit[iUnitID].TIMER_harvest > difficultySettings->getDumpSpeed(10))
            {
                unit[iUnitID].TIMER_harvest = 0;

                // dump credits
                if (unit[iUnitID].iCredits > 0)
                {
                    int iAmount = 5;

                    // cap at max
                    if (unit[iUnitID].iCredits > units[unit[iUnitID].iType].credit_capacity)
                        unit[iUnitID].iCredits = units[unit[iUnitID].iType].credit_capacity;

                    if ((unit[iUnitID].iCredits - iAmount) < 0)
                    {
                        iAmount = unit[iUnitID].iCredits;
                    }

					if (player[unit[iUnitID].iPlayer].credits < player[unit[iUnitID].iPlayer].max_credits)
                    {
						player[unit[iUnitID].iPlayer].credits += iAmount;

                        // TODO: update harvested amopunt
                    }

                    unit[iUnitID].iCredits -= iAmount;
                }
                else
                {
					int iNewCell = iFreeAround();

					if (iNewCell > -1)
					{
						unit[iUnitID].iCell = iNewCell;

                        // let player know...
						if (unit[iUnitID].iPlayer==0)
							play_voice(SOUND_VOICE_02_ATR);

						// place back on map now
						//map.cell[iCell].id[MAPID_UNITS] = iUnitID;
					}
					else
					{
						logbook("Could not find space for this unit");

						// TODO: make carryall pick this up
						return;
					}

                    // done & restore unit
                    unit[iUnitID].iCredits = 0;
                    unit[iUnitID].iStructureID = -1;
                    unit[iUnitID].iHitPoints = unit[iUnitID].iTempHitPoints;
                    unit[iUnitID].iTempHitPoints = -1;
                    unit[iUnitID].iGoalCell = unit[iUnitID].iCell;
					unit[iUnitID].iPathIndex = -1;

					unit[iUnitID].TIMER_movewait = 0;
					unit[iUnitID].TIMER_thinkwait = 0;

                    if (DEBUGGING)
                        assert(iUnitID > -1);

                    map.cell[unit[iUnitID].iCell].id[MAPID_UNITS] = iUnitID;

					// perhaps we can find a carryall to help us out
					int iHarvestCell = UNIT_find_harvest_spot(iUnitID);

					if (iHarvestCell)
					{
						int iCarry = CARRYALL_TRANSFER(iUnitID, iHarvestCell);

						if (iCarry < 0)
						{
							unit[iUnitID].iGoalCell = iHarvestCell;
						}
						else
						{
							unit[iUnitID].TIMER_movewait = 100;
							unit[iUnitID].TIMER_thinkwait = 100;
						}
					}

					iUnitID=-1;
                }

            }

        }

	// think like base class
	cAbstractStructure::think();

}

void cRefinery::think_harvester_deploy() {
	if (!isAnimating()) return; // do nothing when not animating
    // harvester stuff
	if (iFrame < 0)  {
        iFrame = 1;
	}

    TIMER_flag++;

    if (TIMER_flag > 70) {
        TIMER_flag = 0;

        iFrame++;
		if (iFrame > 4) {
			iFrame = 1;
		}
	}
}

void cRefinery::think_animation() {
	cAbstractStructure::think_animation();
	cAbstractStructure::think_flag();
	think_harvester_deploy();
}

void cRefinery::think_guard()
{

}

/*  STRUCTURE SPECIFIC FUNCTIONS  */
int cRefinery::getSpiceSiloCapacity() {
	cHitpointCalculator hitpointCalculator;
	float percentage = ((float)getHitPoints() / (float)structures[getType()].hp);
	return hitpointCalculator.getByPercent(1000, percentage);
}
<commit_msg>Thanks to Peter Gaal, fix for harvester leaving refinery bug. Harvester is now not getting stuck.<commit_after>#include "../../include/d2tmh.h"

// Constructor
cRefinery::cRefinery()
{

 // other variables (class specific)

}

int cRefinery::getType() {
	return REFINERY;
}

cRefinery::~cRefinery()
{

}

/*  OVERLOADED FUNCTIONS  */

// Specific Construction Yard thinking
void cRefinery::think()
{

     // When a refinery, and expecting a unit
     if (iUnitID > -1)
        {
			int iMyID=-1;
			for (int i=0; i < MAX_STRUCTURES; i++)
				if (structure[i] == this)
				{
					iMyID=i;
					break;
				}

            // when the unit somehow does not go to us anymore, stop animating
            if (unit[iUnitID].isValid() == false)
            {
                iUnitID=-1;
				setAnimating(false);
                return;
            }

			if (unit[iUnitID].iStructureID != iMyID)
			{
				iUnitID=-1;
				setAnimating(false);
				return;
			}

            // the unit id is filled in, that means the unit is IN this structure
            // the TIMER_harvest of the unit will be used to dump the harvest in the
            // refinery

            unit[iUnitID].TIMER_harvest++;

            cPlayerDifficultySettings * difficultySettings = player[getOwner()].getDifficultySettings();

            if (unit[iUnitID].TIMER_harvest > difficultySettings->getDumpSpeed(10))
            {
                unit[iUnitID].TIMER_harvest = 0;

                // dump credits
                if (unit[iUnitID].iCredits > 0)
                {
                    int iAmount = 5;

                    // cap at max
                    if (unit[iUnitID].iCredits > units[unit[iUnitID].iType].credit_capacity)
                        unit[iUnitID].iCredits = units[unit[iUnitID].iType].credit_capacity;

                    if ((unit[iUnitID].iCredits - iAmount) < 0)
                    {
                        iAmount = unit[iUnitID].iCredits;
                    }

					if (player[unit[iUnitID].iPlayer].credits < player[unit[iUnitID].iPlayer].max_credits)
                    {
						player[unit[iUnitID].iPlayer].credits += iAmount;

                        // TODO: update harvested amopunt
                    }

                    unit[iUnitID].iCredits -= iAmount;
                    unit[iUnitID].iOffsetX = 0;
                    unit[iUnitID].iOffsetY = 0;
                }
                else
                {
					int iNewCell = iFreeAround();

					if (iNewCell > -1)
					{
						unit[iUnitID].iCell = iNewCell;

                        // let player know...
						if (unit[iUnitID].iPlayer==0)
							play_voice(SOUND_VOICE_02_ATR);

						// place back on map now
						//map.cell[iCell].id[MAPID_UNITS] = iUnitID;
					}
					else
					{
						logbook("Could not find space for this unit");

						// TODO: make carryall pick this up
						return;
					}

                    // done & restore unit
                    unit[iUnitID].iCredits = 0;
                    unit[iUnitID].iStructureID = -1;
                    unit[iUnitID].iHitPoints = unit[iUnitID].iTempHitPoints;
                    unit[iUnitID].iTempHitPoints = -1;
                    unit[iUnitID].iGoalCell = unit[iUnitID].iCell;
					unit[iUnitID].iPathIndex = -1;

					unit[iUnitID].TIMER_movewait = 0;
					unit[iUnitID].TIMER_thinkwait = 0;

                    if (DEBUGGING)
                        assert(iUnitID > -1);

                    map.cell[unit[iUnitID].iCell].id[MAPID_UNITS] = iUnitID;

					// perhaps we can find a carryall to help us out
					int iHarvestCell = UNIT_find_harvest_spot(iUnitID);

					if (iHarvestCell)
					{
						int iCarry = CARRYALL_TRANSFER(iUnitID, iHarvestCell);

						if (iCarry < 0)
						{
							unit[iUnitID].iGoalCell = iHarvestCell;
						}
						else
						{
							unit[iUnitID].TIMER_movewait = 100;
							unit[iUnitID].TIMER_thinkwait = 100;
						}
					}

					iUnitID=-1;
                }

            }

        }

	// think like base class
	cAbstractStructure::think();

}

void cRefinery::think_harvester_deploy() {
	if (!isAnimating()) return; // do nothing when not animating
    // harvester stuff
	if (iFrame < 0)  {
        iFrame = 1;
	}

    TIMER_flag++;

    if (TIMER_flag > 70) {
        TIMER_flag = 0;

        iFrame++;
		if (iFrame > 4) {
			iFrame = 1;
		}
	}
}

void cRefinery::think_animation() {
	cAbstractStructure::think_animation();
	cAbstractStructure::think_flag();
	think_harvester_deploy();
}

void cRefinery::think_guard()
{

}

/*  STRUCTURE SPECIFIC FUNCTIONS  */
int cRefinery::getSpiceSiloCapacity() {
	cHitpointCalculator hitpointCalculator;
	float percentage = ((float)getHitPoints() / (float)structures[getType()].hp);
	return hitpointCalculator.getByPercent(1000, percentage);
}
<|endoftext|>


<commit_before>#ifndef MJOLNIR_UNDERDAMPED_LANGEVIN_INTEGRATOR
#define MJOLNIR_UNDERDAMPED_LANGEVIN_INTEGRATOR
#include "constants.hpp"
#include "RandomNumberGenerator.hpp"

namespace mjolnir
{

template<typename traitsT>
class UnderdampedLangevinStepper
{
  public:
    typedef traitsT traits_type;
    typedef System<traits_type>     system_type;
    typedef ForceField<traits_type> forcefield_type;
    typedef RandomNumberGenerator<traits_type>    rng_type;
    typedef typename traits_type::boundary_type   boundary_type;
    typedef typename traits_type::real_type       real_type;
    typedef typename traits_type::coordinate_type coordinate_type;

    struct parameter_set
    {
        real_type       gamma;
        real_type       r_mass;
        real_type       sqrt_gamma_over_mass;
        coordinate_type accel;
    };

  public:

    UnderdampedLangevinStepper(const real_type dt,
            std::vector<real_type>&& gamma, rng_type&& rng)
        : dt_(dt), halfdt_(dt * 0.5), halfdt2_(dt * dt * 0.5),
          rng_(std::move(rng)), parameters_(gamma.size())
    {
        for(std::size_t i=0; i<gamma.size(); ++i)
        {
            parameters_[i].gamma = gamma[i];
        }
    }
    ~UnderdampedLangevinStepper() = default;

    void initialize(system_type& sys, forcefield_type& ff);
    real_type step(const real_type time, system_type& sys, forcefield_type& ff);

    real_type delta_t() const noexcept {return dt_;}
    void  set_delta_t(const real_type dt) noexcept
    {
        dt_ = dt; halfdt_ = dt * 0.5; halfdt2_ = dt * dt * 0.5;
    }

    void update(const system_type& sys)
    {
        this->temperature_ = sys.attribute("temperature");
        this->noise_coef_  =
            std::sqrt(2 * physics<real_type>::kB * this->temperature_ / dt_);
    }

    rng_type&       random_number_generator()       noexcept {return rng_;}
    rng_type const& random_number_generator() const noexcept {return rng_;}

  private:

    coordinate_type gen_random_accel(const real_type sqrt_g_over_m)
    {
        const real_type coef = this->noise_coef_ * sqrt_g_over_m;
        return coordinate_type(this->rng_.gaussian(0., coef),
                               this->rng_.gaussian(0., coef),
                               this->rng_.gaussian(0., coef));
    }

  private:
    real_type dt_;
    real_type halfdt_;
    real_type halfdt2_;
    real_type temperature_;
    real_type noise_coef_;
    rng_type  rng_;

    std::vector<parameter_set> parameters_;
};

template<typename traitsT>
void UnderdampedLangevinStepper<traitsT>::initialize(
        system_type& system, forcefield_type& ff)
{
    this->update(system);

    for(std::size_t i=0; i<system.size(); ++i)
    {
        system[i].force = coordinate_type(0.0, 0.0, 0.0);
    }
    system.largest_displacement() = 0;
    ff.calc_force(system);

    for(std::size_t i=0; i<system.size(); ++i)
    {
        auto& p = parameters_[i];
        p.r_mass = 1.0 / system[i].mass;
        p.sqrt_gamma_over_mass = std::sqrt(p.gamma * p.r_mass);
        p.accel = system[i].force * p.r_mass +
                  this->gen_random_accel(p.sqrt_gamma_over_mass);
    }
    return;
}

template<typename traitsT>
typename UnderdampedLangevinStepper<traitsT>::real_type
UnderdampedLangevinStepper<traitsT>::step(
        const real_type time, system_type& sys, forcefield_type& ff)
{
    real_type largest_disp2(0);
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        const auto& param = this->parameters_[i];

        const real_type gamma_dt_over_2           = param.gamma * halfdt_;
        const real_type one_minus_gamma_dt_over_2 = 1. - gamma_dt_over_2;

        const auto disp = (dt_ * one_minus_gamma_dt_over_2) * (sys[i].velocity) +
                halfdt2_ * param.accel;

        sys[i].position = sys.adjust_position(sys[i].position + disp);

        sys[i].velocity *= one_minus_gamma_dt_over_2 *
            (one_minus_gamma_dt_over_2 * one_minus_gamma_dt_over_2 +
             gamma_dt_over_2);
        sys[i].velocity += (halfdt_ * one_minus_gamma_dt_over_2) * param.accel;

        sys[i].force = coordinate_type(0., 0., 0.);

        largest_disp2 = std::max(largest_disp2, length_sq(disp));
    }
    sys.largest_displacement() = std::sqrt(largest_disp2);

    // calc f(t+dt)
    ff.calc_force(sys);

    // calc a(t+dt) and v(t+dt), generate noise
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        auto& param = this->parameters_[i];
        param.accel = sys[i].force * param.r_mass +
                      this->gen_random_accel(param.sqrt_gamma_over_mass);

        sys[i].velocity += halfdt_ * (1. - param.gamma * halfdt_) * param.accel;
    }

    return time + dt_;
}

} // mjolnir
#endif /* MJOLNIR_UNDERDAMPED_LANGEVIN_INTEGRATOR */
<commit_msg>remove needless functions<commit_after>#ifndef MJOLNIR_UNDERDAMPED_LANGEVIN_INTEGRATOR
#define MJOLNIR_UNDERDAMPED_LANGEVIN_INTEGRATOR
#include "constants.hpp"
#include "RandomNumberGenerator.hpp"

namespace mjolnir
{

template<typename traitsT>
class UnderdampedLangevinStepper
{
  public:
    typedef traitsT traits_type;
    typedef System<traits_type>     system_type;
    typedef ForceField<traits_type> forcefield_type;
    typedef RandomNumberGenerator<traits_type>    rng_type;
    typedef typename traits_type::boundary_type   boundary_type;
    typedef typename traits_type::real_type       real_type;
    typedef typename traits_type::coordinate_type coordinate_type;

    struct parameter_set
    {
        real_type       gamma;
        real_type       r_mass;
        real_type       sqrt_gamma_over_mass;
        coordinate_type accel;
    };

  public:

    UnderdampedLangevinStepper(const real_type dt,
            std::vector<real_type>&& gamma, rng_type&& rng)
        : dt_(dt), halfdt_(dt * 0.5), halfdt2_(dt * dt * 0.5),
          rng_(std::move(rng)), parameters_(gamma.size())
    {
        for(std::size_t i=0; i<gamma.size(); ++i)
        {
            parameters_[i].gamma = gamma[i];
        }
    }
    ~UnderdampedLangevinStepper() = default;

    void initialize(system_type& sys, forcefield_type& ff);
    real_type step(const real_type time, system_type& sys, forcefield_type& ff);

    real_type delta_t() const noexcept {return dt_;}
    void  set_delta_t(const real_type dt) noexcept
    {
        dt_ = dt; halfdt_ = dt * 0.5; halfdt2_ = dt * dt * 0.5;
    }

    void update(const system_type& sys)
    {
        this->temperature_ = sys.attribute("temperature");
        this->noise_coef_  =
            std::sqrt(2 * physics<real_type>::kB * this->temperature_ / dt_);
    }

  private:

    coordinate_type gen_random_accel(const real_type sqrt_g_over_m)
    {
        const real_type coef = this->noise_coef_ * sqrt_g_over_m;
        return coordinate_type(this->rng_.gaussian(0., coef),
                               this->rng_.gaussian(0., coef),
                               this->rng_.gaussian(0., coef));
    }

  private:
    real_type dt_;
    real_type halfdt_;
    real_type halfdt2_;
    real_type temperature_;
    real_type noise_coef_;
    rng_type  rng_;

    std::vector<parameter_set> parameters_;
};

template<typename traitsT>
void UnderdampedLangevinStepper<traitsT>::initialize(
        system_type& system, forcefield_type& ff)
{
    this->update(system);

    for(std::size_t i=0; i<system.size(); ++i)
    {
        system[i].force = coordinate_type(0.0, 0.0, 0.0);
    }
    system.largest_displacement() = 0;
    ff.calc_force(system);

    for(std::size_t i=0; i<system.size(); ++i)
    {
        auto& p = parameters_[i];
        p.r_mass = 1.0 / system[i].mass;
        p.sqrt_gamma_over_mass = std::sqrt(p.gamma * p.r_mass);
        p.accel = system[i].force * p.r_mass +
                  this->gen_random_accel(p.sqrt_gamma_over_mass);
    }
    return;
}

template<typename traitsT>
typename UnderdampedLangevinStepper<traitsT>::real_type
UnderdampedLangevinStepper<traitsT>::step(
        const real_type time, system_type& sys, forcefield_type& ff)
{
    real_type largest_disp2(0);
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        const auto& param = this->parameters_[i];

        const real_type gamma_dt_over_2           = param.gamma * halfdt_;
        const real_type one_minus_gamma_dt_over_2 = 1. - gamma_dt_over_2;

        const auto disp = (dt_ * one_minus_gamma_dt_over_2) * (sys[i].velocity) +
                halfdt2_ * param.accel;

        sys[i].position = sys.adjust_position(sys[i].position + disp);

        sys[i].velocity *= one_minus_gamma_dt_over_2 *
            (one_minus_gamma_dt_over_2 * one_minus_gamma_dt_over_2 +
             gamma_dt_over_2);
        sys[i].velocity += (halfdt_ * one_minus_gamma_dt_over_2) * param.accel;

        sys[i].force = coordinate_type(0., 0., 0.);

        largest_disp2 = std::max(largest_disp2, length_sq(disp));
    }
    sys.largest_displacement() = std::sqrt(largest_disp2);

    // calc f(t+dt)
    ff.calc_force(sys);

    // calc a(t+dt) and v(t+dt), generate noise
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        auto& param = this->parameters_[i];
        param.accel = sys[i].force * param.r_mass +
                      this->gen_random_accel(param.sqrt_gamma_over_mass);

        sys[i].velocity += halfdt_ * (1. - param.gamma * halfdt_) * param.accel;
    }

    return time + dt_;
}

} // mjolnir
#endif /* MJOLNIR_UNDERDAMPED_LANGEVIN_INTEGRATOR */
<|endoftext|>