<commit_before>/*
 * Copyright 2011-2012 Gregory Banks
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "np.h"
#include "np/testmanager.hxx"
#include "np/testnode.hxx"
#include "np/classifier.hxx"
#include "np/spiegel/spiegel.hxx"
#include "np/spiegel/dwarf/state.hxx"

namespace np {
using namespace std;

testmanager_t *testmanager_t::instance_ = 0;

testmanager_t::testmanager_t()
{
    assert(instance_ == 0);
    instance_ = this;
}

testmanager_t::~testmanager_t()
{
    while (classifiers_.size())
    {
	delete classifiers_.back();
	classifiers_.pop_back();
    }

    delete root_;
    root_ = 0;
    delete common_;
    common_ = 0;

    if (spiegel_)
	delete spiegel_;

    assert(instance_ == this);
    instance_ = 0;
}

testmanager_t *
testmanager_t::instance()
{
    if (!instance_)
    {
	new testmanager_t();
	instance_->print_banner();
	instance_->setup_classifiers();
	instance_->discover_functions();
	instance_->setup_builtin_intercepts();
	/* TODO: check tree for a) leaves without FT_TEST
	 * and b) non-leaves with FT_TEST */
// 	instance_->root_->dump(0);
    }
    return instance_;
}

void
testmanager_t::print_banner()
{
    printf("np: NovaProva Copyright (c) Gregory Banks\n");
    printf("np: Built for O/S "_NP_OS" architecture "_NP_ARCH"\n");
}

functype_t
testmanager_t::classify_function(const char *func,
				 char *match_return,
				 size_t maxmatch)
{
    if (match_return)
	match_return[0] = '\0';

    vector<classifier_t*>::iterator i;
    for (i = classifiers_.begin() ; i != classifiers_.end() ; ++i)
    {
	functype_t ft = (functype_t) (*i)->classify(func, match_return, maxmatch);
	if (ft != FT_UNKNOWN)
	    return ft;
	/* else, no match: just keep looking */
    }
    return FT_UNKNOWN;
}

void
testmanager_t::add_classifier(const char *re,
			      bool case_sensitive,
			      functype_t type)
{
    classifier_t *cl = new classifier_t;
    if (!cl->set_regexp(re, case_sensitive))
    {
	delete cl;
	return;
    }
    cl->set_results(FT_UNKNOWN, type);
    classifiers_.push_back(cl);
}

void
testmanager_t::setup_classifiers()
{
    add_classifier("^test_([a-z0-9].*)", false, FT_TEST);
    add_classifier("^[tT]est([A-Z].*)", false, FT_TEST);
    add_classifier("^[sS]etup$", false, FT_BEFORE);
    add_classifier("^set_up$", false, FT_BEFORE);
    add_classifier("^[iI]nit$", false, FT_BEFORE);
    add_classifier("^[tT]ear[dD]own$", false, FT_AFTER);
    add_classifier("^tear_down$", false, FT_AFTER);
    add_classifier("^[cC]leanup$", false, FT_AFTER);
    add_classifier("^mock_(.*)", false, FT_MOCK);
    add_classifier("^[mM]ock([A-Z].*)", false, FT_MOCK);
    add_classifier("^__np_parameter_(.*)", false, FT_PARAM);
}

static string
test_name(np::spiegel::function_t *fn, char *submatch)
{
    string name = fn->get_compile_unit()->get_absolute_path();

    /* strip the .c or .cxx extension */
    size_t p = name.find_last_of('.');
    if (p != string::npos)
	name.resize(p);

    if (submatch && submatch[0])
    {
	name += "/";
	name += submatch;
    }

    return name;
}

np::spiegel::function_t *
testmanager_t::find_mock_target(string name)
{
    vector<np::spiegel::compile_unit_t *> units = np::spiegel::get_compile_units();
    vector<np::spiegel::compile_unit_t *>::iterator i;
    for (i = units.begin() ; i != units.end() ; ++i)
    {
	vector<np::spiegel::function_t *> fns = (*i)->get_functions();
	vector<np::spiegel::function_t *>::iterator j;
	for (j = fns.begin() ; j != fns.end() ; ++j)
	{
	    if ((*j)->get_name() == name)
		return *j;
	}
    }
    return 0;
}

static const struct __np_param_dec *
get_param_dec(np::spiegel::function_t *fn)
{
    vector<np::spiegel::value_t> args;
    np::spiegel::value_t ret = fn->invoke(args);
    return (const struct __np_param_dec *)ret.val.vpointer;
}

void
testmanager_t::discover_functions()
{
    if (!spiegel_)
    {
	spiegel_ = new np::spiegel::dwarf::state_t();
	spiegel_->add_self();
	spiegel_->prepare_address_index();
	root_ = new testnode_t(0);
    }
    // else: splice common_ and root_ back together

    vector<np::spiegel::compile_unit_t *> units = np::spiegel::get_compile_units();
    vector<np::spiegel::compile_unit_t *>::iterator i;
    for (i = units.begin() ; i != units.end() ; ++i)
    {
// fprintf(stderr, "discover_functions: compile unit %s\n", (*i)->get_absolute_path().c_str());
	vector<np::spiegel::function_t *> fns = (*i)->get_functions();
	vector<np::spiegel::function_t *>::iterator j;
	for (j = fns.begin() ; j != fns.end() ; ++j)
	{
	    np::spiegel::function_t *fn = *j;
	    functype_t type;
	    char submatch[512];

	    // We want functions which are defined in this compile unit
	    if (!fn->get_address())
		continue;

	    type = classify_function(fn->get_name().c_str(),
				     submatch, sizeof(submatch));
	    switch (type)
	    {
	    case FT_UNKNOWN:
		continue;
	    case FT_TEST:
		// Test functions need a node name
		if (!submatch[0])
		    continue;
		// Test function return void
		if (fn->get_return_type()->get_classification() != np::spiegel::type_t::TC_VOID)
		    continue;
		// Test functions take no arguments
		if (fn->get_parameter_types().size() != 0)
		    continue;
		root_->make_path(test_name(fn, submatch))->set_function(type, fn);
		break;
	    case FT_BEFORE:
	    case FT_AFTER:
		// Before/after functions go into the parent node
		assert(!submatch[0]);
		// Before/after functions return int
		if (fn->get_return_type()->get_classification() != np::spiegel::type_t::TC_SIGNED_INT)
		    continue;
		// Before/after take no arguments
		if (fn->get_parameter_types().size() != 0)
		    continue;
		root_->make_path(test_name(fn, submatch))->set_function(type, fn);
		break;
	    case FT_MOCK:
		// Mock functions need a target name
		if (!submatch[0])
		    continue;
		{
		    np::spiegel::function_t *target = find_mock_target(submatch);
		    if (!target)
			continue;
		    root_->make_path(test_name(fn, 0))->add_mock(target, fn);
		}
		break;
	    case FT_PARAM:
		// Parameters need a name
		if (!submatch[0])
		    continue;
		const struct __np_param_dec *dec = get_param_dec(fn);
		root_->make_path(test_name(fn, 0))->add_parameter(
				submatch, dec->var, dec->values);
		break;
	    }
	}
    }

    // Calculate the effective root_ and common_
    common_ = root_;
    root_ = root_->detach_common();
}

extern void init_syslog_intercepts(testnode_t *);

void
testmanager_t::setup_builtin_intercepts()
{
    init_syslog_intercepts(root_);
}

// close the namespace
};
<commit_msg>Don't print the banner once per test child<commit_after>/*
 * Copyright 2011-2012 Gregory Banks
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "np.h"
#include "np/testmanager.hxx"
#include "np/testnode.hxx"
#include "np/classifier.hxx"
#include "np/spiegel/spiegel.hxx"
#include "np/spiegel/dwarf/state.hxx"

namespace np {
using namespace std;

testmanager_t *testmanager_t::instance_ = 0;

testmanager_t::testmanager_t()
{
    assert(instance_ == 0);
    instance_ = this;
}

testmanager_t::~testmanager_t()
{
    while (classifiers_.size())
    {
	delete classifiers_.back();
	classifiers_.pop_back();
    }

    delete root_;
    root_ = 0;
    delete common_;
    common_ = 0;

    if (spiegel_)
	delete spiegel_;

    assert(instance_ == this);
    instance_ = 0;
}

testmanager_t *
testmanager_t::instance()
{
    if (!instance_)
    {
	new testmanager_t();
	instance_->print_banner();
	instance_->setup_classifiers();
	instance_->discover_functions();
	instance_->setup_builtin_intercepts();
	/* TODO: check tree for a) leaves without FT_TEST
	 * and b) non-leaves with FT_TEST */
// 	instance_->root_->dump(0);
    }
    return instance_;
}

void
testmanager_t::print_banner()
{
    printf("np: NovaProva Copyright (c) Gregory Banks\n");
    printf("np: Built for O/S "_NP_OS" architecture "_NP_ARCH"\n");
    fflush(stdout);
}

functype_t
testmanager_t::classify_function(const char *func,
				 char *match_return,
				 size_t maxmatch)
{
    if (match_return)
	match_return[0] = '\0';

    vector<classifier_t*>::iterator i;
    for (i = classifiers_.begin() ; i != classifiers_.end() ; ++i)
    {
	functype_t ft = (functype_t) (*i)->classify(func, match_return, maxmatch);
	if (ft != FT_UNKNOWN)
	    return ft;
	/* else, no match: just keep looking */
    }
    return FT_UNKNOWN;
}

void
testmanager_t::add_classifier(const char *re,
			      bool case_sensitive,
			      functype_t type)
{
    classifier_t *cl = new classifier_t;
    if (!cl->set_regexp(re, case_sensitive))
    {
	delete cl;
	return;
    }
    cl->set_results(FT_UNKNOWN, type);
    classifiers_.push_back(cl);
}

void
testmanager_t::setup_classifiers()
{
    add_classifier("^test_([a-z0-9].*)", false, FT_TEST);
    add_classifier("^[tT]est([A-Z].*)", false, FT_TEST);
    add_classifier("^[sS]etup$", false, FT_BEFORE);
    add_classifier("^set_up$", false, FT_BEFORE);
    add_classifier("^[iI]nit$", false, FT_BEFORE);
    add_classifier("^[tT]ear[dD]own$", false, FT_AFTER);
    add_classifier("^tear_down$", false, FT_AFTER);
    add_classifier("^[cC]leanup$", false, FT_AFTER);
    add_classifier("^mock_(.*)", false, FT_MOCK);
    add_classifier("^[mM]ock([A-Z].*)", false, FT_MOCK);
    add_classifier("^__np_parameter_(.*)", false, FT_PARAM);
}

static string
test_name(np::spiegel::function_t *fn, char *submatch)
{
    string name = fn->get_compile_unit()->get_absolute_path();

    /* strip the .c or .cxx extension */
    size_t p = name.find_last_of('.');
    if (p != string::npos)
	name.resize(p);

    if (submatch && submatch[0])
    {
	name += "/";
	name += submatch;
    }

    return name;
}

np::spiegel::function_t *
testmanager_t::find_mock_target(string name)
{
    vector<np::spiegel::compile_unit_t *> units = np::spiegel::get_compile_units();
    vector<np::spiegel::compile_unit_t *>::iterator i;
    for (i = units.begin() ; i != units.end() ; ++i)
    {
	vector<np::spiegel::function_t *> fns = (*i)->get_functions();
	vector<np::spiegel::function_t *>::iterator j;
	for (j = fns.begin() ; j != fns.end() ; ++j)
	{
	    if ((*j)->get_name() == name)
		return *j;
	}
    }
    return 0;
}

static const struct __np_param_dec *
get_param_dec(np::spiegel::function_t *fn)
{
    vector<np::spiegel::value_t> args;
    np::spiegel::value_t ret = fn->invoke(args);
    return (const struct __np_param_dec *)ret.val.vpointer;
}

void
testmanager_t::discover_functions()
{
    if (!spiegel_)
    {
	spiegel_ = new np::spiegel::dwarf::state_t();
	spiegel_->add_self();
	spiegel_->prepare_address_index();
	root_ = new testnode_t(0);
    }
    // else: splice common_ and root_ back together

    vector<np::spiegel::compile_unit_t *> units = np::spiegel::get_compile_units();
    vector<np::spiegel::compile_unit_t *>::iterator i;
    for (i = units.begin() ; i != units.end() ; ++i)
    {
// fprintf(stderr, "discover_functions: compile unit %s\n", (*i)->get_absolute_path().c_str());
	vector<np::spiegel::function_t *> fns = (*i)->get_functions();
	vector<np::spiegel::function_t *>::iterator j;
	for (j = fns.begin() ; j != fns.end() ; ++j)
	{
	    np::spiegel::function_t *fn = *j;
	    functype_t type;
	    char submatch[512];

	    // We want functions which are defined in this compile unit
	    if (!fn->get_address())
		continue;

	    type = classify_function(fn->get_name().c_str(),
				     submatch, sizeof(submatch));
	    switch (type)
	    {
	    case FT_UNKNOWN:
		continue;
	    case FT_TEST:
		// Test functions need a node name
		if (!submatch[0])
		    continue;
		// Test function return void
		if (fn->get_return_type()->get_classification() != np::spiegel::type_t::TC_VOID)
		    continue;
		// Test functions take no arguments
		if (fn->get_parameter_types().size() != 0)
		    continue;
		root_->make_path(test_name(fn, submatch))->set_function(type, fn);
		break;
	    case FT_BEFORE:
	    case FT_AFTER:
		// Before/after functions go into the parent node
		assert(!submatch[0]);
		// Before/after functions return int
		if (fn->get_return_type()->get_classification() != np::spiegel::type_t::TC_SIGNED_INT)
		    continue;
		// Before/after take no arguments
		if (fn->get_parameter_types().size() != 0)
		    continue;
		root_->make_path(test_name(fn, submatch))->set_function(type, fn);
		break;
	    case FT_MOCK:
		// Mock functions need a target name
		if (!submatch[0])
		    continue;
		{
		    np::spiegel::function_t *target = find_mock_target(submatch);
		    if (!target)
			continue;
		    root_->make_path(test_name(fn, 0))->add_mock(target, fn);
		}
		break;
	    case FT_PARAM:
		// Parameters need a name
		if (!submatch[0])
		    continue;
		const struct __np_param_dec *dec = get_param_dec(fn);
		root_->make_path(test_name(fn, 0))->add_parameter(
				submatch, dec->var, dec->values);
		break;
	    }
	}
    }

    // Calculate the effective root_ and common_
    common_ = root_;
    root_ = root_->detach_common();
}

extern void init_syslog_intercepts(testnode_t *);

void
testmanager_t::setup_builtin_intercepts()
{
    init_syslog_intercepts(root_);
}

// close the namespace
};
<|endoftext|>


<commit_before>#include <map.hpp>
#include <iostream>
#include <Windows.h>

using namespace std;
using namespace fabric;

typedef int(*f_loadmap)();

///TODO: Linux and Mac compatibility

int Map::load(char* path) {
	// Load the map dll into memory
	HINSTANCE hGetProcIDLL = LoadLibrary(path);

	cout << path << endl;

	if (!hGetProcIDLL) {
		cout << "Could not load DLL at " << path << endl;
		return EXIT_FAILURE;
	}

	// Get adress to the loadmap function defied in the DLL
	f_loadmap loadmap = (f_loadmap)GetProcAddress(hGetProcIDLL, "loadmap");

	if (!loadmap) {
		cout << "Could not get loadmap function" << endl;
		return EXIT_FAILURE;
	}

	//Unload library
	FreeLibrary(hGetProcIDLL);

	loadmap();

	// Spawn all Behaviors for the gameobjs
	for (unsigned int i = 0; i < Engine::get()->vLoadedGameObjects->size(); i++) {
		Engine::get()->vLoadedGameObjects->at(i)->spawn();
	}

	std::cout << "Loaded ";
	std::cout << Engine::get()->vLoadedGameObjects->size();
	std::cout << " entitie(s)" << std::endl;

	// Call Setup on just loaded gameobjects
	for (unsigned int i = 0; i < Engine::get()->vLoadedGameObjects->size(); i++) {
		Engine::get()->vLoadedGameObjects->at(i)->setup();
	}

	return 0;

}

int Map::unload() {
	std::cout << "Unloading..." << std::endl;
	m_mMap->unload();
	std::cout << "Unloaded..." << std::endl;
	return 0;
}
<commit_msg>Added unload for maps<commit_after>#include <map.hpp>
#include <iostream>
#include <Windows.h>
#include <vector>

using namespace std;
using namespace fabric;

typedef vector<GameObject *>*(*f_loadmap)();

///TODO: Linux and Mac compatibility

int Map::load(char* path) {
	// Load the map dll into memory
	HINSTANCE hGetProcIDLL = LoadLibrary(path);

	cout << path << endl;

	if (!hGetProcIDLL) {
		cout << "Could not load DLL at " << path << endl;
		return EXIT_FAILURE;
	}

	// Get adress to the loadmap function defied in the DLL
	f_loadmap loadmap = (f_loadmap)GetProcAddress(hGetProcIDLL, "loadmap");

	if (!loadmap) {
		cout << "Could not get loadmap function" << endl;
		return EXIT_FAILURE;
	}

	// For safety delete the vLoadedGameObjects Pointer
	delete Engine::get()->vLoadedGameObjects;

	// Execute load and overwrite the vLoadedGameopjects pointer
	Engine::get()->vLoadedGameObjects = loadmap();

	// Spawn all Behaviors for the gameobjs
	for (unsigned int i = 0; i < Engine::get()->vLoadedGameObjects->size(); i++) {
		Engine::get()->vLoadedGameObjects->at(i)->spawn();
	}

	std::cout << "Loaded ";
	std::cout << Engine::get()->vLoadedGameObjects->size();
	std::cout << " entitie(s)" << std::endl;

	m_mMap = &hGetProcIDLL;

	// Call Setup on just loaded gameobjects
	for (unsigned int i = 0; i < Engine::get()->vLoadedGameObjects->size(); i++) {
		Engine::get()->vLoadedGameObjects->at(i)->setup();
	}

	return 0;

}

int Map::unload() {
	std::cout << "Unloading..." << std::endl;

	if (m_mMap) {
		FreeLibrary(*m_mMap);
		delete m_mMap;
		m_mMap = 0;
	}

	std::cout << "Unloaded..." << std::endl;
	return 0;
}
<|endoftext|>


<commit_before>#include "mainwindow.h"
#include <QApplication>
#include <qdir.h>
#include "core/log.h"
#include "core/profiler.h"
#include "core/resource_manager.h"
#include "core/resource_manager_base.h"
#include "editor/world_editor.h"
#include "editor/gizmo.h"
#include "engine/engine.h"
#include "engine/plugin_manager.h"
#include <graphics/gl_ext.h>
#include "graphics/irender_device.h"
#include "graphics/pipeline.h"
#include "graphics/renderer.h"
#include "physics/physics_scene.h"
#include "physics/physics_system.h"
#include "sceneview.h"
#include "gameview.h"
#include "wgl_render_device.h"
#include "materialmanager.h"

class App
{
	public:
		App()
		{
			m_game_render_device = NULL;
			m_edit_render_device = NULL;
			m_qt_app = NULL;
			m_main_window = NULL;
			m_world_editor = NULL;
		}

		~App()
		{
			delete m_main_window;
			delete m_qt_app;
			Lumix::WorldEditor::destroy(m_world_editor);
		}

		void onUniverseCreated()
		{
			m_edit_render_device->getPipeline().setScene(m_world_editor->getEngine().getRenderScene());
			m_game_render_device->getPipeline().setScene(m_world_editor->getEngine().getRenderScene());
		}

		void onUniverseDestroyed()
		{
			if(m_edit_render_device)
			{
				m_edit_render_device->getPipeline().setScene(NULL);
			}
			if(m_game_render_device)
			{
				m_game_render_device->getPipeline().setScene(NULL);
			}

		}

		HGLRC createGLContext(HWND hwnd[], int count)
		{
			ASSERT(count > 0);
			QWidget* widget = new QWidget();
			HWND gl_hwnd = (HWND)widget->winId();
			HDC hdc;
			hdc = GetDC(gl_hwnd);
			ASSERT(hdc != NULL);
			if (hdc == NULL)
			{
				Lumix::g_log_error.log("renderer") << "Could not get the device context";
				return NULL;
			}
			BOOL success;
			PIXELFORMATDESCRIPTOR pfd =
			{
				sizeof(PIXELFORMATDESCRIPTOR),  //  size of this pfd
				1,                     // version number
				PFD_DRAW_TO_WINDOW |   // support window
				PFD_SUPPORT_OPENGL |   // support OpenGL
				PFD_DOUBLEBUFFER,      // double buffered
				PFD_TYPE_RGBA,         // RGBA type
				24,                    // 24-bit color depth
				0, 0, 0, 0, 0, 0,      // color bits ignored
				0,                     // no alpha buffer
				0,                     // shift bit ignored
				0,                     // no accumulation buffer
				0, 0, 0, 0,            // accum bits ignored
				32,                    // 32-bit z-buffer
				0,                     // no stencil buffer
				0,                     // no auxiliary buffer
				PFD_MAIN_PLANE,        // main layer
				0,                     // reserved
				0, 0, 0                // layer masks ignored
			};
			int pixelformat = ChoosePixelFormat(hdc, &pfd);
			if (pixelformat == 0)
			{
				delete widget;
				ASSERT(false);
				Lumix::g_log_error.log("renderer") << "Could not choose a pixel format";
				return NULL;
			}
			success = SetPixelFormat(hdc, pixelformat, &pfd);
			if (success == FALSE)
			{
				delete widget;
				ASSERT(false);
				Lumix::g_log_error.log("renderer") << "Could not set a pixel format";
				return NULL;
			}
			HGLRC hglrc = wglCreateContext(hdc);
			if (hglrc == NULL)
			{
				delete widget;
				ASSERT(false);
				Lumix::g_log_error.log("renderer") << "Could not create an opengl context";
				return NULL;
			}
			success = wglMakeCurrent(hdc, hglrc);
			if (success == FALSE)
			{
				delete widget;
				ASSERT(false);
				Lumix::g_log_error.log("renderer") << "Could not make the opengl context current rendering context";
				return NULL;
			}

			{
				UINT numFormats;
				int atrribs[] =
				{
					WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
					WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
					WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
					WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
					WGL_COLOR_BITS_ARB, 32,
					WGL_DEPTH_BITS_ARB, 24,
					WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
					WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
					WGL_SAMPLES_ARB, 4,
					0
				};
				PFNWGLCHOOSEPIXELFORMATARBPROC foo;
				foo = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
				if (!foo)
				{
					delete widget;
					ASSERT(false);
					Lumix::g_log_error.log("renderer") << "Could not get function wglChoosePixelFormatARB";
					return NULL;
				}
				success = foo(hdc, atrribs, NULL, 1, &pixelformat, &numFormats);
			}
			wglDeleteContext(hglrc);
			hglrc = NULL;
			delete widget;

			for (int i = 0; i < count; ++i)
			{
				if (hwnd[i])
				{
					hdc = GetDC(hwnd[i]);
					ChoosePixelFormat(hdc, &pfd);
					if (hdc == NULL)
					{
						ASSERT(false);
						Lumix::g_log_error.log("renderer") << "Could not get the device context";
						return NULL;
					}
					SetPixelFormat(hdc, pixelformat, &pfd);

					if (!hglrc)
					{
						hglrc = wglCreateContext(hdc);
						if (hglrc == NULL)
						{
							ASSERT(false);
							Lumix::g_log_error.log("renderer") << "Could not create an opengl context";
							return NULL;
						}
						success = wglMakeCurrent(hdc, hglrc);
						if (success == FALSE)
						{
							ASSERT(false);
							Lumix::g_log_error.log("renderer") << "Could not make the opengl context current rendering context";
							return NULL;
						}
					}
				}
			}

			return hglrc;
		}

		void renderPhysics()
		{
			Lumix::PhysicsSystem* system = static_cast<Lumix::PhysicsSystem*>(m_world_editor->getEngine().getPluginManager().getPlugin("physics"));
			if(system && system->getScene())
			{
				system->getScene()->render();
			}
		}

		void init(int argc, char* argv[])
		{
			m_qt_app = new QApplication(argc, argv);
			QFile file("editor/stylesheet.qss");
			file.open(QFile::ReadOnly);
			m_qt_app->setStyleSheet(QLatin1String(file.readAll()));

			m_main_window = new MainWindow();
			m_main_window->show();

			HWND hwnd = (HWND)m_main_window->getSceneView()->getViewWidget()->winId();
			HWND game_hwnd = (HWND)m_main_window->getGameView()->getContentWidget()->winId();
			HWND hwnds[] = { hwnd, game_hwnd, (HWND)m_main_window->getMaterialManager()->getPreview()->winId() };
			HGLRC hglrc = createGLContext(hwnds, 3);

			m_world_editor = Lumix::WorldEditor::create(QDir::currentPath().toLocal8Bit().data());
			ASSERT(m_world_editor);
			m_world_editor->tick();

			m_main_window->setWorldEditor(*m_world_editor);
			m_main_window->getSceneView()->setWorldEditor(m_world_editor);

			m_edit_render_device = new WGLRenderDevice(m_world_editor->getEngine(), "pipelines/main.json");
			m_edit_render_device->m_hdc = GetDC(hwnd);
			m_edit_render_device->m_opengl_context = hglrc;
			m_edit_render_device->getPipeline().setScene(m_world_editor->getEngine().getRenderScene()); /// TODO manage scene properly
			m_world_editor->setEditViewRenderDevice(*m_edit_render_device);
			m_edit_render_device->getPipeline().addCustomCommandHandler("render_physics").bind<App, &App::renderPhysics>(this);

			m_game_render_device = new	WGLRenderDevice(m_world_editor->getEngine(), "pipelines/game_view.json");
			m_game_render_device->m_hdc = GetDC(game_hwnd);
			m_game_render_device->m_opengl_context = hglrc;
			m_game_render_device->getPipeline().setScene(m_world_editor->getEngine().getRenderScene()); /// TODO manage scene properly
			m_world_editor->getEngine().getRenderer().setRenderDevice(*m_game_render_device);

			m_world_editor->universeCreated().bind<App, &App::onUniverseCreated>(this);
			m_world_editor->universeDestroyed().bind<App, &App::onUniverseDestroyed>(this);

			m_main_window->getSceneView()->setPipeline(m_edit_render_device->getPipeline());
			m_main_window->getGameView()->setPipeline(m_game_render_device->getPipeline());
		}

		void shutdown()
		{
			delete m_game_render_device;
			m_game_render_device = NULL;
			delete m_edit_render_device;
			m_edit_render_device = NULL;
		}

		void renderEditView()
		{
			PROFILE_FUNCTION();
			m_edit_render_device->beginFrame();
			m_world_editor->render(*m_edit_render_device);
			m_world_editor->renderIcons(*m_edit_render_device);
			m_world_editor->getGizmo().updateScale(m_world_editor->getEditCamera());
			m_world_editor->getGizmo().render(m_world_editor->getEngine().getRenderer(), *m_edit_render_device);
			m_edit_render_device->endFrame();

			m_main_window->getMaterialManager()->updatePreview();
		}

		void handleEvents()
		{
			PROFILE_FUNCTION();
			{
				PROFILE_BLOCK("qt::processEvents");
				m_qt_app->processEvents();
			}
			BYTE keys[256];
			GetKeyboardState(keys);
			if (m_main_window->getSceneView()->getViewWidget()->hasFocus())
			{
				/// TODO refactor
				if(keys[VK_CONTROL] >> 7 == 0)
				{
					float speed = m_main_window->getSceneView()->getNavivationSpeed();
					if (keys[VK_LSHIFT] >> 7)
					{
						speed *= 10;
					}
					if (keys['W'] >> 7)
					{
						m_world_editor->navigate(1, 0, speed);
					}
					else if (keys['S'] >> 7)
					{
						m_world_editor->navigate(-1, 0, speed);
					}
					if (keys['A'] >> 7)
					{
						m_world_editor->navigate(0, -1, speed);
					}
					else if (keys['D'] >> 7)
					{
						m_world_editor->navigate(0, 1, speed);
					}
				}
			}
		}

		void run()
		{
			while (m_main_window->isVisible())
			{
				{
					PROFILE_BLOCK("tick");
					renderEditView();
					m_world_editor->getEngine().getRenderer().renderGame();
					m_world_editor->tick();
					handleEvents();
				}
				{
					PROFILE_BLOCK("tick2");
				}
				Lumix::g_profiler.frame();
			}
		}

	private:
		WGLRenderDevice* m_edit_render_device;
		WGLRenderDevice* m_game_render_device;
		MainWindow* m_main_window;
		Lumix::WorldEditor* m_world_editor;
		QApplication* m_qt_app;
};

int main(int argc, char* argv[])
{
	App app;
	app.init(argc, argv);
	app.run();
	app.shutdown();
	return 0;
}
<commit_msg>removed forgotten test code<commit_after>#include "mainwindow.h"
#include <QApplication>
#include <qdir.h>
#include "core/log.h"
#include "core/profiler.h"
#include "core/resource_manager.h"
#include "core/resource_manager_base.h"
#include "editor/world_editor.h"
#include "editor/gizmo.h"
#include "engine/engine.h"
#include "engine/plugin_manager.h"
#include <graphics/gl_ext.h>
#include "graphics/irender_device.h"
#include "graphics/pipeline.h"
#include "graphics/renderer.h"
#include "physics/physics_scene.h"
#include "physics/physics_system.h"
#include "sceneview.h"
#include "gameview.h"
#include "wgl_render_device.h"
#include "materialmanager.h"

class App
{
	public:
		App()
		{
			m_game_render_device = NULL;
			m_edit_render_device = NULL;
			m_qt_app = NULL;
			m_main_window = NULL;
			m_world_editor = NULL;
		}

		~App()
		{
			delete m_main_window;
			delete m_qt_app;
			Lumix::WorldEditor::destroy(m_world_editor);
		}

		void onUniverseCreated()
		{
			m_edit_render_device->getPipeline().setScene(m_world_editor->getEngine().getRenderScene());
			m_game_render_device->getPipeline().setScene(m_world_editor->getEngine().getRenderScene());
		}

		void onUniverseDestroyed()
		{
			if(m_edit_render_device)
			{
				m_edit_render_device->getPipeline().setScene(NULL);
			}
			if(m_game_render_device)
			{
				m_game_render_device->getPipeline().setScene(NULL);
			}

		}

		HGLRC createGLContext(HWND hwnd[], int count)
		{
			ASSERT(count > 0);
			QWidget* widget = new QWidget();
			HWND gl_hwnd = (HWND)widget->winId();
			HDC hdc;
			hdc = GetDC(gl_hwnd);
			ASSERT(hdc != NULL);
			if (hdc == NULL)
			{
				Lumix::g_log_error.log("renderer") << "Could not get the device context";
				return NULL;
			}
			BOOL success;
			PIXELFORMATDESCRIPTOR pfd =
			{
				sizeof(PIXELFORMATDESCRIPTOR),  //  size of this pfd
				1,                     // version number
				PFD_DRAW_TO_WINDOW |   // support window
				PFD_SUPPORT_OPENGL |   // support OpenGL
				PFD_DOUBLEBUFFER,      // double buffered
				PFD_TYPE_RGBA,         // RGBA type
				24,                    // 24-bit color depth
				0, 0, 0, 0, 0, 0,      // color bits ignored
				0,                     // no alpha buffer
				0,                     // shift bit ignored
				0,                     // no accumulation buffer
				0, 0, 0, 0,            // accum bits ignored
				32,                    // 32-bit z-buffer
				0,                     // no stencil buffer
				0,                     // no auxiliary buffer
				PFD_MAIN_PLANE,        // main layer
				0,                     // reserved
				0, 0, 0                // layer masks ignored
			};
			int pixelformat = ChoosePixelFormat(hdc, &pfd);
			if (pixelformat == 0)
			{
				delete widget;
				ASSERT(false);
				Lumix::g_log_error.log("renderer") << "Could not choose a pixel format";
				return NULL;
			}
			success = SetPixelFormat(hdc, pixelformat, &pfd);
			if (success == FALSE)
			{
				delete widget;
				ASSERT(false);
				Lumix::g_log_error.log("renderer") << "Could not set a pixel format";
				return NULL;
			}
			HGLRC hglrc = wglCreateContext(hdc);
			if (hglrc == NULL)
			{
				delete widget;
				ASSERT(false);
				Lumix::g_log_error.log("renderer") << "Could not create an opengl context";
				return NULL;
			}
			success = wglMakeCurrent(hdc, hglrc);
			if (success == FALSE)
			{
				delete widget;
				ASSERT(false);
				Lumix::g_log_error.log("renderer") << "Could not make the opengl context current rendering context";
				return NULL;
			}

			{
				UINT numFormats;
				int atrribs[] =
				{
					WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
					WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
					WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
					WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
					WGL_COLOR_BITS_ARB, 32,
					WGL_DEPTH_BITS_ARB, 24,
					WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
					WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
					WGL_SAMPLES_ARB, 4,
					0
				};
				PFNWGLCHOOSEPIXELFORMATARBPROC foo;
				foo = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
				if (!foo)
				{
					delete widget;
					ASSERT(false);
					Lumix::g_log_error.log("renderer") << "Could not get function wglChoosePixelFormatARB";
					return NULL;
				}
				success = foo(hdc, atrribs, NULL, 1, &pixelformat, &numFormats);
			}
			wglDeleteContext(hglrc);
			hglrc = NULL;
			delete widget;

			for (int i = 0; i < count; ++i)
			{
				if (hwnd[i])
				{
					hdc = GetDC(hwnd[i]);
					ChoosePixelFormat(hdc, &pfd);
					if (hdc == NULL)
					{
						ASSERT(false);
						Lumix::g_log_error.log("renderer") << "Could not get the device context";
						return NULL;
					}
					SetPixelFormat(hdc, pixelformat, &pfd);

					if (!hglrc)
					{
						hglrc = wglCreateContext(hdc);
						if (hglrc == NULL)
						{
							ASSERT(false);
							Lumix::g_log_error.log("renderer") << "Could not create an opengl context";
							return NULL;
						}
						success = wglMakeCurrent(hdc, hglrc);
						if (success == FALSE)
						{
							ASSERT(false);
							Lumix::g_log_error.log("renderer") << "Could not make the opengl context current rendering context";
							return NULL;
						}
					}
				}
			}

			return hglrc;
		}

		void renderPhysics()
		{
			Lumix::PhysicsSystem* system = static_cast<Lumix::PhysicsSystem*>(m_world_editor->getEngine().getPluginManager().getPlugin("physics"));
			if(system && system->getScene())
			{
				system->getScene()->render();
			}
		}

		void init(int argc, char* argv[])
		{
			m_qt_app = new QApplication(argc, argv);
			QFile file("editor/stylesheet.qss");
			file.open(QFile::ReadOnly);
			m_qt_app->setStyleSheet(QLatin1String(file.readAll()));

			m_main_window = new MainWindow();
			m_main_window->show();

			HWND hwnd = (HWND)m_main_window->getSceneView()->getViewWidget()->winId();
			HWND game_hwnd = (HWND)m_main_window->getGameView()->getContentWidget()->winId();
			HWND hwnds[] = { hwnd, game_hwnd, (HWND)m_main_window->getMaterialManager()->getPreview()->winId() };
			HGLRC hglrc = createGLContext(hwnds, 3);

			m_world_editor = Lumix::WorldEditor::create(QDir::currentPath().toLocal8Bit().data());
			ASSERT(m_world_editor);
			m_world_editor->tick();

			m_main_window->setWorldEditor(*m_world_editor);
			m_main_window->getSceneView()->setWorldEditor(m_world_editor);

			m_edit_render_device = new WGLRenderDevice(m_world_editor->getEngine(), "pipelines/main.json");
			m_edit_render_device->m_hdc = GetDC(hwnd);
			m_edit_render_device->m_opengl_context = hglrc;
			m_edit_render_device->getPipeline().setScene(m_world_editor->getEngine().getRenderScene()); /// TODO manage scene properly
			m_world_editor->setEditViewRenderDevice(*m_edit_render_device);
			m_edit_render_device->getPipeline().addCustomCommandHandler("render_physics").bind<App, &App::renderPhysics>(this);

			m_game_render_device = new	WGLRenderDevice(m_world_editor->getEngine(), "pipelines/game_view.json");
			m_game_render_device->m_hdc = GetDC(game_hwnd);
			m_game_render_device->m_opengl_context = hglrc;
			m_game_render_device->getPipeline().setScene(m_world_editor->getEngine().getRenderScene()); /// TODO manage scene properly
			m_world_editor->getEngine().getRenderer().setRenderDevice(*m_game_render_device);

			m_world_editor->universeCreated().bind<App, &App::onUniverseCreated>(this);
			m_world_editor->universeDestroyed().bind<App, &App::onUniverseDestroyed>(this);

			m_main_window->getSceneView()->setPipeline(m_edit_render_device->getPipeline());
			m_main_window->getGameView()->setPipeline(m_game_render_device->getPipeline());
		}

		void shutdown()
		{
			delete m_game_render_device;
			m_game_render_device = NULL;
			delete m_edit_render_device;
			m_edit_render_device = NULL;
		}

		void renderEditView()
		{
			PROFILE_FUNCTION();
			m_edit_render_device->beginFrame();
			m_world_editor->render(*m_edit_render_device);
			m_world_editor->renderIcons(*m_edit_render_device);
			m_world_editor->getGizmo().updateScale(m_world_editor->getEditCamera());
			m_world_editor->getGizmo().render(m_world_editor->getEngine().getRenderer(), *m_edit_render_device);
			m_edit_render_device->endFrame();

			m_main_window->getMaterialManager()->updatePreview();
		}

		void handleEvents()
		{
			PROFILE_FUNCTION();
			{
				PROFILE_BLOCK("qt::processEvents");
				m_qt_app->processEvents();
			}
			BYTE keys[256];
			GetKeyboardState(keys);
			if (m_main_window->getSceneView()->getViewWidget()->hasFocus())
			{
				/// TODO refactor
				if(keys[VK_CONTROL] >> 7 == 0)
				{
					float speed = m_main_window->getSceneView()->getNavivationSpeed();
					if (keys[VK_LSHIFT] >> 7)
					{
						speed *= 10;
					}
					if (keys['W'] >> 7)
					{
						m_world_editor->navigate(1, 0, speed);
					}
					else if (keys['S'] >> 7)
					{
						m_world_editor->navigate(-1, 0, speed);
					}
					if (keys['A'] >> 7)
					{
						m_world_editor->navigate(0, -1, speed);
					}
					else if (keys['D'] >> 7)
					{
						m_world_editor->navigate(0, 1, speed);
					}
				}
			}
		}

		void run()
		{
			while (m_main_window->isVisible())
			{
				{
					PROFILE_BLOCK("tick");
					renderEditView();
					m_world_editor->getEngine().getRenderer().renderGame();
					m_world_editor->tick();
					handleEvents();
				}
				Lumix::g_profiler.frame();
			}
		}

	private:
		WGLRenderDevice* m_edit_render_device;
		WGLRenderDevice* m_game_render_device;
		MainWindow* m_main_window;
		Lumix::WorldEditor* m_world_editor;
		QApplication* m_qt_app;
};

int main(int argc, char* argv[])
{
	App app;
	app.init(argc, argv);
	app.run();
	app.shutdown();
	return 0;
}
<|endoftext|>


<commit_before>#include "LIBCD.H"

#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#define DISC_IMAGE_FILENAME "TOMB5.BIN"

#define DECODE_BCD(x) (((x) >> 4) * 10 + ((x) & 0xF))
#define ENCODE_BCD(x) ((((x) / 10) << 4) | ((x) % 10))

FILE* openFile = NULL;

typedef struct commandQueue
{
	unsigned int mode;
	unsigned char* p;
	unsigned int processed;
	unsigned int count;
};

#define COMMAND_QUEUE_SIZE 256

commandQueue comQueue[COMMAND_QUEUE_SIZE];
commandQueue* comStart = &comQueue[0];
commandQueue* comEnd = &comQueue[COMMAND_QUEUE_SIZE-1];
int comQueueIndex = 0;
int comQueueCount = 0;
int currentSector = 0;
int sectorSize = 2352;//TODO obtain properly from cue sheet

#pragma pack(push, 1)
struct TOC
{
	unsigned char tocEntryLength;
	unsigned char extEntryLength;
	unsigned int sectorPosition[2];
	unsigned int fileSize[2];
	unsigned char date[7];
	unsigned char flags;
	unsigned char fileUnitSize;
	unsigned char interleaveGapSize;
	unsigned short volSeqNum[2];
	unsigned char nameLength;
};

struct Sector
{
	unsigned char	sync[12];	/// Sync pattern (usually 00 FF FF FF FF FF FF FF FF FF FF 00)
	unsigned char	addr[3];	/// Sector address (see below for encoding details)
	unsigned char	mode;		/// Mode (usually 2 for Mode 2 Form 1/2 sectors)
	unsigned char	subHead[8];	/// Sub-header (00 00 08 00 00 00 08 00 for Form 1 data sectors)
	unsigned char	data[2048];	/// Data (form 1)
	unsigned char	edc[4];		/// Error-detection code (CRC32 of data area)
	unsigned char	ecc[276];	/// Error-correction code (uses Reed-Solomon ECC algorithm)
};
#pragma pack(pop)

CdlFILE* CdSearchFile(CdlFILE* fp, char* name)
{
	memset(fp, 0, sizeof(CdlFILE));

	if (name[0] == '\\')
	{
		name++;
	}

	if (openFile != NULL)
	{
		fseek(openFile, 22 * sectorSize, SEEK_SET);

		int tocLocalOffset = 0;
		Sector sector;
		fread(&sector, sizeof(Sector), 1, openFile);
		TOC* toc = (TOC*)&sector.data[0];
		while (toc->tocEntryLength != 0)
		{
			if (strcmp((char*)&sector.data[tocLocalOffset + sizeof(TOC)], name) == 0)
			{
				memcpy(&fp->name[0], (char*)&sector.data[tocLocalOffset + sizeof(TOC)], strlen(name));
				fp->size = toc->fileSize[0];
				fseek(openFile, toc->sectorPosition[0] * sectorSize, SEEK_SET);
				fread(&sector, sizeof(Sector), 1, openFile);
				fp->pos.minute = sector.addr[0];
				fp->pos.second = sector.addr[1];
				fp->pos.sector = sector.addr[2];

#if _DEBUG
				printf("CDSearchFile() Found %s\n", name);
#endif
				return fp;
			}
			tocLocalOffset += toc->tocEntryLength;
			toc = (TOC*)&sector.data[tocLocalOffset];
		}
	}

	return NULL;
}

int mfhi(int a, int b)
{
	unsigned long long temp = (long long)((long long)(int)a * (long long)(int)b);

	int lo = temp & 0xffffffff;
	int hi = temp >> 32;
	return ((temp >> 32) & 0xFFFFFFFF);
}

CdlLOC* CdIntToPos(int i, CdlLOC* p)
{
	i += 150;
	p->sector = i % 75;
	int rem = i / 75;
	p->second = rem % 60;
	p->minute = rem / 60;
	return p;
}

int CdControl(u_char com, u_char * param, u_char * result)
{
	CdlFILE* cd = (CdlFILE*)param;

	switch (com)
	{
	case CdlSetloc:
		fseek(openFile, CdPosToInt(&cd->pos)*sectorSize, SEEK_SET);
		break;
	default:
		printf("Uhandled command!\n");
		break;
	}
	return 0;
}

int CdControlB(u_char com, u_char* param, u_char* result)
{
	CdlFILE* cd = (CdlFILE*)param;

	switch (com)
	{
	case CdlSetloc:
		fseek(openFile, CdPosToInt(&cd->pos)*sectorSize, SEEK_SET);
		break;
	default:
		printf("Uhandled command!\n");
		break;
	}

	return 0;
}

int CdControlF(u_char com, u_char * param)
{
	CdlFILE* cd = (CdlFILE*)param;

	switch (com)
	{
	case CdlSetloc:
		fseek(openFile, CdPosToInt(&cd->pos)*sectorSize, SEEK_SET);
		break;
	default:
		printf("Uhandled command!\n");
		break;
	}
	return 0;
}

int CdPosToInt(CdlLOC* p)
{
	return
		(75 * (60 * DECODE_BCD(p->minute) + DECODE_BCD(p->second))) + DECODE_BCD(p->sector) - 150;
}

int CdRead(int sectors, u_long* buf, int mode)
{
	if (comQueueIndex == COMMAND_QUEUE_SIZE)
		comQueueIndex = 0;

	comStart[comQueueIndex].mode = CdlReadS;
	comStart[comQueueIndex].p = (unsigned char*)buf;
	comStart[comQueueIndex].processed = 0;
	comStart[comQueueIndex].count = sectors;
	comQueueCount++;
	comQueueIndex++;
	return 0;
}

int CdReadSync(int mode, u_char* result)
{
	for (int i = 0; i < comQueueCount; i++)
	{
		if (comQueue[i].processed == 0)
		{
			Sector sector;
			fread(&sector, sizeof(Sector), 1, openFile);

			memcpy(comQueue[i].p, &sector.data[0], 2048);
			comQueue[i].p += 2048;

			if (--comQueue[i].count == 0)
			{
				comQueue[i].processed = 1;
				break;
			}

			return 1;
		}
	}
	return 0;
}

int CdSetDebug(int level)
{
	return 0;
}

int CdSync(int mode, u_char * result)
{
	return 0;
}

int CdInit(void)
{
	memset(&comQueue, 0, sizeof(comQueue));
	currentSector = 0;
	openFile = fopen(DISC_IMAGE_FILENAME, "rb");

	if (openFile == NULL)
	{
		printf("Error: CdInit() Failed to open disc image file! %s\n", DISC_IMAGE_FILENAME);
	}

	return 1;
}

int CdLastCom(void)
{
	return 0;
}
<commit_msg>fix bcd<commit_after>#include "LIBCD.H"

#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#define DISC_IMAGE_FILENAME "TOMB5.BIN"

#define DECODE_BCD(x) (((x) >> 4) * 10 + ((x) & 0xF))
#define ENCODE_BCD(x) ((((x) / 10) << 4) | ((x) % 10))

FILE* openFile = NULL;

typedef struct commandQueue
{
	unsigned int mode;
	unsigned char* p;
	unsigned int processed;
	unsigned int count;
};

#define COMMAND_QUEUE_SIZE 256

commandQueue comQueue[COMMAND_QUEUE_SIZE];
commandQueue* comStart = &comQueue[0];
commandQueue* comEnd = &comQueue[COMMAND_QUEUE_SIZE-1];
int comQueueIndex = 0;
int comQueueCount = 0;
int currentSector = 0;
int sectorSize = 2352;//TODO obtain properly from cue sheet

#pragma pack(push, 1)
struct TOC
{
	unsigned char tocEntryLength;
	unsigned char extEntryLength;
	unsigned int sectorPosition[2];
	unsigned int fileSize[2];
	unsigned char date[7];
	unsigned char flags;
	unsigned char fileUnitSize;
	unsigned char interleaveGapSize;
	unsigned short volSeqNum[2];
	unsigned char nameLength;
};

struct Sector
{
	unsigned char	sync[12];	/// Sync pattern (usually 00 FF FF FF FF FF FF FF FF FF FF 00)
	unsigned char	addr[3];	/// Sector address (see below for encoding details)
	unsigned char	mode;		/// Mode (usually 2 for Mode 2 Form 1/2 sectors)
	unsigned char	subHead[8];	/// Sub-header (00 00 08 00 00 00 08 00 for Form 1 data sectors)
	unsigned char	data[2048];	/// Data (form 1)
	unsigned char	edc[4];		/// Error-detection code (CRC32 of data area)
	unsigned char	ecc[276];	/// Error-correction code (uses Reed-Solomon ECC algorithm)
};
#pragma pack(pop)

CdlFILE* CdSearchFile(CdlFILE* fp, char* name)
{
	memset(fp, 0, sizeof(CdlFILE));

	if (name[0] == '\\')
	{
		name++;
	}

	if (openFile != NULL)
	{
		fseek(openFile, 22 * sectorSize, SEEK_SET);

		int tocLocalOffset = 0;
		Sector sector;
		fread(&sector, sizeof(Sector), 1, openFile);
		TOC* toc = (TOC*)&sector.data[0];
		while (toc->tocEntryLength != 0)
		{
			if (strcmp((char*)&sector.data[tocLocalOffset + sizeof(TOC)], name) == 0)
			{
				memcpy(&fp->name[0], (char*)&sector.data[tocLocalOffset + sizeof(TOC)], strlen(name));
				fp->size = toc->fileSize[0];
				fseek(openFile, toc->sectorPosition[0] * sectorSize, SEEK_SET);
				fread(&sector, sizeof(Sector), 1, openFile);
				fp->pos.minute = sector.addr[0];
				fp->pos.second = sector.addr[1];
				fp->pos.sector = sector.addr[2];

#if _DEBUG
				printf("CDSearchFile() Found %s\n", name);
#endif
				return fp;
			}
			tocLocalOffset += toc->tocEntryLength;
			toc = (TOC*)&sector.data[tocLocalOffset];
		}
	}

	return NULL;
}

int mfhi(int a, int b)
{
	unsigned long long temp = (long long)((long long)(int)a * (long long)(int)b);

	int lo = temp & 0xffffffff;
	int hi = temp >> 32;
	return ((temp >> 32) & 0xFFFFFFFF);
}

CdlLOC* CdIntToPos(int i, CdlLOC* p)
{
	i += 150;
	p->sector = ENCODE_BCD(i % 75);
	int rem = i / 75;
	p->second = ENCODE_BCD(rem % 60);
	p->minute = ENCODE_BCD(rem / 60);
	return p;
}

int CdControl(u_char com, u_char * param, u_char * result)
{
	CdlFILE* cd = (CdlFILE*)param;

	switch (com)
	{
	case CdlSetloc:
		fseek(openFile, CdPosToInt(&cd->pos)*sectorSize, SEEK_SET);
		break;
	default:
		printf("Uhandled command!\n");
		break;
	}
	return 0;
}

int CdControlB(u_char com, u_char* param, u_char* result)
{
	CdlFILE* cd = (CdlFILE*)param;

	switch (com)
	{
	case CdlSetloc:
		fseek(openFile, CdPosToInt(&cd->pos)*sectorSize, SEEK_SET);
		break;
	default:
		printf("Uhandled command!\n");
		break;
	}

	return 0;
}

int CdControlF(u_char com, u_char * param)
{
	CdlFILE* cd = (CdlFILE*)param;

	switch (com)
	{
	case CdlSetloc:
		fseek(openFile, CdPosToInt(&cd->pos)*sectorSize, SEEK_SET);
		break;
	default:
		printf("Uhandled command!\n");
		break;
	}
	return 0;
}

int CdPosToInt(CdlLOC* p)
{
	return
		(75 * (60 * DECODE_BCD(p->minute) + DECODE_BCD(p->second))) + DECODE_BCD(p->sector) - 150;
}

int CdRead(int sectors, u_long* buf, int mode)
{
	if (comQueueIndex == COMMAND_QUEUE_SIZE)
		comQueueIndex = 0;

	comStart[comQueueIndex].mode = CdlReadS;
	comStart[comQueueIndex].p = (unsigned char*)buf;
	comStart[comQueueIndex].processed = 0;
	comStart[comQueueIndex].count = sectors;
	comQueueCount++;
	comQueueIndex++;
	return 0;
}

int CdReadSync(int mode, u_char* result)
{
	for (int i = 0; i < comQueueCount; i++)
	{
		if (comQueue[i].processed == 0)
		{
			Sector sector;
			fread(&sector, sizeof(Sector), 1, openFile);

			memcpy(comQueue[i].p, &sector.data[0], 2048);
			comQueue[i].p += 2048;

			if (--comQueue[i].count == 0)
			{
				comQueue[i].processed = 1;
				break;
			}

			return 1;
		}
	}
	return 0;
}

int CdSetDebug(int level)
{
	return 0;
}

int CdSync(int mode, u_char * result)
{
	return 0;
}

int CdInit(void)
{
	memset(&comQueue, 0, sizeof(comQueue));
	currentSector = 0;
	openFile = fopen(DISC_IMAGE_FILENAME, "rb");

	if (openFile == NULL)
	{
		printf("Error: CdInit() Failed to open disc image file! %s\n", DISC_IMAGE_FILENAME);
	}

	return 1;
}

int CdLastCom(void)
{
	return 0;
}
<|endoftext|>


<commit_before>// Copyright 2015-2019 Elviss Strazdins. All rights reserved.

#ifndef OUZEL_STORAGE_PATH_HPP
#define OUZEL_STORAGE_PATH_HPP

#include <cstdint>
#include <stdexcept>
#include <string>

#if defined(_WIN32)
#  pragma push_macro("WIN32_LEAN_AND_MEAN")
#  pragma push_macro("NOMINMAX")
#  ifndef WIN32_LEAN_AND_MEAN
#    define WIN32_LEAN_AND_MEAN
#  endif
#  ifndef NOMINMAX
#    define NOMINMAX
#  endif
#  include <Windows.h>
#  pragma pop_macro("WIN32_LEAN_AND_MEAN")
#  pragma pop_macro("NOMINMAX")
#elif defined(__unix__) || defined(__APPLE__)
#  include <sys/stat.h>
#endif

namespace ouzel
{
    namespace storage
    {
        class Path final
        {
        public:
#if defined(_WIN32)
            static constexpr char directorySeparator = '\\';
            using String = std::wstring;
#elif defined(__unix__) || defined(__APPLE__)
            static constexpr char directorySeparator = '/';
            using String = std::string;
#endif

            Path() = default;
            Path(const std::string& p):
#if defined(_WIN32)
                path(convertToNative(toWchar(p)))
#elif defined(__unix__) || defined(__APPLE__)
                path(p)
#endif
            {
                // TODO: normalize
            }

            Path(const std::wstring& p):
#if defined(_WIN32)
                path(convertToNative(p))
#elif defined(__unix__) || defined(__APPLE__)
                path(toUtf8(p))
#endif
            {
                // TODO: normalize
            }

            operator std::string() const
            {
#if defined(_WIN32)
                return toUtf8(convertToUniversal(path));
#elif defined(__unix__) || defined(__APPLE__)
                return path;
#endif
            }

            Path getExtensionPart() const
            {
                const size_t pos = path.find_last_of('.');

                if (pos != std::string::npos)
                    return path.substr(pos + 1);

                return String();
            }

            Path getFilenamePart() const
            {
                const size_t pos = path.find_last_of(directorySeparator);

                if (pos != String::npos)
                    return path.substr(pos + 1);
                else
                    return path;
            }

            Path getDirectoryPart() const
            {
                const size_t pos = path.find_last_of(directorySeparator);

                if (pos != String::npos)
                    return path.substr(0, pos);

                return String();
            }

            bool isDirectory() const
            {
#if defined(_WIN32)
                const DWORD attributes = GetFileAttributesW(path.c_str());
                if (attributes == INVALID_FILE_ATTRIBUTES)
                    return false;

                return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
#elif defined(__unix__) || defined(__APPLE__)
                struct stat buf;
                if (stat(path.c_str(), &buf) == -1)
                    return false;

                return (buf.st_mode & S_IFMT) == S_IFDIR;
#endif
            }

            bool isFile() const
            {
#if defined(_WIN32)
                const DWORD attributes = GetFileAttributesW(path.c_str());
                if (attributes == INVALID_FILE_ATTRIBUTES)
                    return false;

                return (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
#elif defined(__unix__) || defined(__APPLE__)
                struct stat buf;
                if (stat(path.c_str(), &buf) == -1)
                    return false;

                return (buf.st_mode & S_IFMT) == S_IFREG;
#endif
            }

            bool isAbsolute() const noexcept
            {
#if defined(_WIN32)
                return path.size() >= 2 &&
                    ((path[0] >= L'a' && path[0] <= L'z') || (path[0] >= L'A' && path[0] <= L'Z')) &&
                    path[1] == L':';
#elif defined(__unix__) || defined(__APPLE__)
                return path.size() >= 1 && path[0] == '/';
#endif
            }

        private:
            static std::string toUtf8(const std::wstring& p)
            {
				std::string s;

				for (wchar_t w : p)
				{
					if (w <= 0x7F)
						s.push_back(static_cast<char>(w));
					else if (w <= 0x7FF)
					{
						s.push_back(static_cast<char>(0xC0 | ((w >> 6) & 0x1F)));
						s.push_back(static_cast<char>(0x80 | (w & 0x3F)));
					}
					else if (w <= 0xFFFF)
                    {
                        s.push_back(static_cast<char>(0xE0 | ((w >> 12) & 0x0F)));
                        s.push_back(static_cast<char>(0x80 | ((w >> 6) & 0x3F)));
                        s.push_back(static_cast<char>(0x80 | (w & 0x3F)));
                    }
#if WCHAR_MAX > 0xFFFF
                    else
                    {
                        s.push_back(static_cast<char>(0xF0 | ((w >> 18) & 0x07)));
                        s.push_back(static_cast<char>(0x80 | ((w >> 12) & 0x3F)));
                        s.push_back(static_cast<char>(0x80 | ((w >> 6) & 0x3F)));
                        s.push_back(static_cast<char>(0x80 | (w & 0x3F)));
                    }
#endif
				}

                return s;
            }

            static std::wstring toWchar(const std::string& p)
            {
                std::wstring s;

				for (auto i = p.begin(); i != p.end(); ++i)
				{
					char32_t cp = *i & 0xFF;

					if (cp <= 0x7F) // length = 1
					{
						// do nothing
					}
					else if ((cp >> 5) == 0x6) // length = 2
					{
						if (++i == p.end())
							throw std::runtime_error("Invalid UTF-8 string");
						cp = ((cp << 6) & 0x7FF) + (*i & 0x3F);
					}
					else if ((cp >> 4) == 0xE) // length = 3
					{
						if (++i == p.end())
							throw std::runtime_error("Invalid UTF-8 string");
						cp = ((cp << 12) & 0xFFFF) + (((*i & 0xFF) << 6) & 0x0FFF);
						if (++i == p.end())
							throw std::runtime_error("Invalid UTF-8 string");
						cp += *i & 0x3F;
					}
					else if ((cp >> 3) == 0x1E) // length = 4
					{
						if (++i == p.end())
							throw std::runtime_error("Invalid UTF-8 string");
						cp = ((cp << 18) & 0x1FFFFF) + (((*i & 0xFF) << 12) & 0x3FFFF);
						if (++i == p.end())
							throw std::runtime_error("Invalid UTF-8 string");
						cp += ((*i & 0xFF) << 6) & 0x0FFF;
						if (++i == p.end())
							throw std::runtime_error("Invalid UTF-8 string");
						cp += (*i) & 0x3F;
					}

					if (cp > WCHAR_MAX)
						throw std::runtime_error("Unsupported UTF-8 character");

					s.push_back(static_cast<wchar_t>(cp));
				}

                return s;
            }

#if defined(_WIN32)
            static std::wstring convertToNative(const std::wstring& p)
            {
                std::wstring result = p;

                for (auto& c : result)
                    if (c == L'/') c = L'\\';

                return result;
            }

            static std::wstring convertToUniversal(const std::wstring& p)
            {
                std::wstring result = p;

                for (auto& c : result)
                    if (c == L'\\') c = L'/';

                return result;
            }
#endif

            String path;
        };
    } // namespace storage
} // namespace ouzel

#endif
<commit_msg>Add native getter to Path<commit_after>// Copyright 2015-2019 Elviss Strazdins. All rights reserved.

#ifndef OUZEL_STORAGE_PATH_HPP
#define OUZEL_STORAGE_PATH_HPP

#include <cstdint>
#include <stdexcept>
#include <string>

#if defined(_WIN32)
#  pragma push_macro("WIN32_LEAN_AND_MEAN")
#  pragma push_macro("NOMINMAX")
#  ifndef WIN32_LEAN_AND_MEAN
#    define WIN32_LEAN_AND_MEAN
#  endif
#  ifndef NOMINMAX
#    define NOMINMAX
#  endif
#  include <Windows.h>
#  pragma pop_macro("WIN32_LEAN_AND_MEAN")
#  pragma pop_macro("NOMINMAX")
#elif defined(__unix__) || defined(__APPLE__)
#  include <sys/stat.h>
#endif

namespace ouzel
{
    namespace storage
    {
        class Path final
        {
        public:
#if defined(_WIN32)
            static constexpr char directorySeparator = '\\';
            using String = std::wstring;
#elif defined(__unix__) || defined(__APPLE__)
            static constexpr char directorySeparator = '/';
            using String = std::string;
#endif

            Path() = default;
            Path(const std::string& p):
#if defined(_WIN32)
                path(convertToNative(toWchar(p)))
#elif defined(__unix__) || defined(__APPLE__)
                path(p)
#endif
            {
                // TODO: normalize
            }

            Path(const std::wstring& p):
#if defined(_WIN32)
                path(convertToNative(p))
#elif defined(__unix__) || defined(__APPLE__)
                path(toUtf8(p))
#endif
            {
                // TODO: normalize
            }

            operator std::string() const
            {
#if defined(_WIN32)
                return toUtf8(convertToUniversal(path));
#elif defined(__unix__) || defined(__APPLE__)
                return path;
#endif
            }

            const String& getNative() const noexcept
            {
                return path;
            }

            Path getExtensionPart() const
            {
                const size_t pos = path.find_last_of('.');

                if (pos != std::string::npos)
                    return path.substr(pos + 1);

                return String();
            }

            Path getFilenamePart() const
            {
                const size_t pos = path.find_last_of(directorySeparator);

                if (pos != String::npos)
                    return path.substr(pos + 1);
                else
                    return path;
            }

            Path getDirectoryPart() const
            {
                const size_t pos = path.find_last_of(directorySeparator);

                if (pos != String::npos)
                    return path.substr(0, pos);

                return String();
            }

            bool isDirectory() const
            {
#if defined(_WIN32)
                const DWORD attributes = GetFileAttributesW(path.c_str());
                if (attributes == INVALID_FILE_ATTRIBUTES)
                    return false;

                return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
#elif defined(__unix__) || defined(__APPLE__)
                struct stat buf;
                if (stat(path.c_str(), &buf) == -1)
                    return false;

                return (buf.st_mode & S_IFMT) == S_IFDIR;
#endif
            }

            bool isFile() const
            {
#if defined(_WIN32)
                const DWORD attributes = GetFileAttributesW(path.c_str());
                if (attributes == INVALID_FILE_ATTRIBUTES)
                    return false;

                return (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
#elif defined(__unix__) || defined(__APPLE__)
                struct stat buf;
                if (stat(path.c_str(), &buf) == -1)
                    return false;

                return (buf.st_mode & S_IFMT) == S_IFREG;
#endif
            }

            bool isAbsolute() const noexcept
            {
#if defined(_WIN32)
                return path.size() >= 2 &&
                    ((path[0] >= L'a' && path[0] <= L'z') || (path[0] >= L'A' && path[0] <= L'Z')) &&
                    path[1] == L':';
#elif defined(__unix__) || defined(__APPLE__)
                return path.size() >= 1 && path[0] == '/';
#endif
            }

        private:
            static std::string toUtf8(const std::wstring& p)
            {
				std::string s;

				for (wchar_t w : p)
				{
					if (w <= 0x7F)
						s.push_back(static_cast<char>(w));
					else if (w <= 0x7FF)
					{
						s.push_back(static_cast<char>(0xC0 | ((w >> 6) & 0x1F)));
						s.push_back(static_cast<char>(0x80 | (w & 0x3F)));
					}
					else if (w <= 0xFFFF)
                    {
                        s.push_back(static_cast<char>(0xE0 | ((w >> 12) & 0x0F)));
                        s.push_back(static_cast<char>(0x80 | ((w >> 6) & 0x3F)));
                        s.push_back(static_cast<char>(0x80 | (w & 0x3F)));
                    }
#if WCHAR_MAX > 0xFFFF
                    else
                    {
                        s.push_back(static_cast<char>(0xF0 | ((w >> 18) & 0x07)));
                        s.push_back(static_cast<char>(0x80 | ((w >> 12) & 0x3F)));
                        s.push_back(static_cast<char>(0x80 | ((w >> 6) & 0x3F)));
                        s.push_back(static_cast<char>(0x80 | (w & 0x3F)));
                    }
#endif
				}

                return s;
            }

            static std::wstring toWchar(const std::string& p)
            {
                std::wstring s;

				for (auto i = p.begin(); i != p.end(); ++i)
				{
					char32_t cp = *i & 0xFF;

					if (cp <= 0x7F) // length = 1
					{
						// do nothing
					}
					else if ((cp >> 5) == 0x6) // length = 2
					{
						if (++i == p.end())
							throw std::runtime_error("Invalid UTF-8 string");
						cp = ((cp << 6) & 0x7FF) + (*i & 0x3F);
					}
					else if ((cp >> 4) == 0xE) // length = 3
					{
						if (++i == p.end())
							throw std::runtime_error("Invalid UTF-8 string");
						cp = ((cp << 12) & 0xFFFF) + (((*i & 0xFF) << 6) & 0x0FFF);
						if (++i == p.end())
							throw std::runtime_error("Invalid UTF-8 string");
						cp += *i & 0x3F;
					}
					else if ((cp >> 3) == 0x1E) // length = 4
					{
						if (++i == p.end())
							throw std::runtime_error("Invalid UTF-8 string");
						cp = ((cp << 18) & 0x1FFFFF) + (((*i & 0xFF) << 12) & 0x3FFFF);
						if (++i == p.end())
							throw std::runtime_error("Invalid UTF-8 string");
						cp += ((*i & 0xFF) << 6) & 0x0FFF;
						if (++i == p.end())
							throw std::runtime_error("Invalid UTF-8 string");
						cp += (*i) & 0x3F;
					}

					if (cp > WCHAR_MAX)
						throw std::runtime_error("Unsupported UTF-8 character");

					s.push_back(static_cast<wchar_t>(cp));
				}

                return s;
            }

#if defined(_WIN32)
            static std::wstring convertToNative(const std::wstring& p)
            {
                std::wstring result = p;

                for (auto& c : result)
                    if (c == L'/') c = L'\\';

                return result;
            }

            static std::wstring convertToUniversal(const std::wstring& p)
            {
                std::wstring result = p;

                for (auto& c : result)
                    if (c == L'\\') c = L'/';

                return result;
            }
#endif

            String path;
        };
    } // namespace storage
} // namespace ouzel

#endif
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2016 DeepCortex GmbH <legal@eventql.io>
 * Authors:
 *   - Paul Asmuth <paul@eventql.io>
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License ("the license") as
 * published by the Free Software Foundation, either version 3 of the License,
 * or any later version.
 *
 * In accordance with Section 7(e) of the license, the licensing of the Program
 * under the license does not imply a trademark license. Therefore any rights,
 * title and interest in our trademarks remain entirely with us.
 *
 * This program 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 license for more details.
 *
 * You can be released from the requirements of the license by purchasing a
 * commercial license. Buying such a license is mandatory as soon as you develop
 * commercial activities involving this program without disclosing the source
 * code of your own applications
 */
#include <eventql/util/stdtypes.h>
#include <eventql/util/logging.h>
#include <eventql/util/io/fileutil.h>
#include <eventql/util/io/mmappedfile.h>
#include <eventql/util/protobuf/msg.h>
#include <eventql/util/wallclock.h>
#include <eventql/util/application.h>
#include <eventql/db/compaction_worker.h>
#include <eventql/db/partition_writer.h>
#include <eventql/util/protobuf/MessageDecoder.h>
#include <eventql/io/cstable/RecordShredder.h>
#include <eventql/io/cstable/cstable_writer.h>

#include "eventql/eventql.h"

namespace eventql {

CompactionWorker::CompactionWorker(
    PartitionMap* pmap,
    size_t nthreads) :
    pmap_(pmap),
    nthreads_(nthreads),
    queue_([] (
        const Pair<uint64_t, RefPtr<Partition>>& a,
        const Pair<uint64_t, RefPtr<Partition>>& b) {
      return a.first < b.first;
    }),
    running_(false) {
  pmap->subscribeToPartitionChanges([this] (
      RefPtr<eventql::PartitionChangeNotification> change) {
    enqueuePartition(change->partition);
  });

  start();
}

CompactionWorker::~CompactionWorker() {
  stop();
}

void CompactionWorker::enqueuePartition(
    RefPtr<Partition> partition,
    bool immediate /* = false */) {
  if (immediate) {
    startImmediateCompaction(partition);
  } else {
    std::unique_lock<std::mutex> lk(mutex_);
    enqueuePartitionWithLock(partition);
  }
}

void CompactionWorker::startImmediateCompaction(RefPtr<Partition> partition) {
  auto uuid = partition->uuid();

  {
    std::unique_lock<std::mutex> lk(mutex_);
    if (immediate_set_.count(uuid) > 0) {
      return;
    }

    if (immediate_set_.size() > kImmediateCompactionMaxThreads) {
      enqueuePartitionWithLock(partition);
      return;
    }

    immediate_set_.emplace(uuid);
  }

  auto thread = std::thread([this, partition, uuid] {
    Application::setCurrentThreadName("evqld-compaction-immediate");
    compactPartition(partition);

    std::unique_lock<std::mutex> lk(mutex_);
    immediate_set_.erase(uuid);
  });

  thread.detach();
}

void CompactionWorker::enqueuePartitionWithLock(
    RefPtr<Partition> partition) {
  auto interval = partition->getTable()->commitInterval();

  auto uuid = partition->uuid();
  if (waitset_.count(uuid) > 0) {
    return;
  }

  queue_.emplace(
      WallClock::unixMicros() + interval.microseconds(),
      partition);

  waitset_.emplace(uuid);
  cv_.notify_all();
  evqld_stats()->compaction_queue_length.set(queue_.size());
}

void CompactionWorker::start() {
  running_ = true;

  for (int i = 0; i < nthreads_; ++i) {
    threads_.emplace_back(std::bind(&CompactionWorker::work, this));
  }
}

void CompactionWorker::stop() {
  if (!running_) {
    return;
  }

  running_ = false;
  cv_.notify_all();

  for (auto& t : threads_) {
    t.join();
  }
}

void CompactionWorker::work() {
  Application::setCurrentThreadName("evqld-compaction");

  std::unique_lock<std::mutex> lk(mutex_);

  while (running_) {
    if (queue_.size() == 0) {
      cv_.wait(lk);
    }

    if (queue_.size() == 0) {
      continue;
    }

    auto now = WallClock::unixMicros();
    if (now < queue_.begin()->first) {
      cv_.wait_for(
          lk,
          std::chrono::microseconds(queue_.begin()->first - now));

      continue;
    }

    auto partition = queue_.begin()->second;
    queue_.erase(queue_.begin());

    bool success = true;
    {
      lk.unlock();
      success = compactPartition(partition);
      lk.lock();
    }

    if (success) {
      waitset_.erase(partition->uuid());

      if (partition->getWriter()->needsCompaction()) {
        enqueuePartitionWithLock(partition);
      }
    } else {
      auto delay = 30 * kMicrosPerSecond; // FIXPAUL increasing delay..
      queue_.emplace(now + delay, partition);
    }

    evqld_stats()->compaction_queue_length.set(queue_.size());
  }
}

bool CompactionWorker::compactPartition(RefPtr<Partition> partition) try {
  auto writer = partition->getWriter();
  if (writer->compact()) {
    auto change = mkRef(new PartitionChangeNotification());
    change->partition = partition;
    pmap_->publishPartitionChange(change);
  }

  return true;
} catch (const StandardException& e) {
  auto snap = partition->getSnapshot();

  logCritical(
      "tsdb",
      e,
      "CompactionWorker error for partition $0/$1/$2",
      snap->state.tsdb_namespace(),
      snap->state.table_key(),
      snap->key.toString());

  return false;
}

} // namespace eventql
<commit_msg>add warning<commit_after>/**
 * Copyright (c) 2016 DeepCortex GmbH <legal@eventql.io>
 * Authors:
 *   - Paul Asmuth <paul@eventql.io>
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License ("the license") as
 * published by the Free Software Foundation, either version 3 of the License,
 * or any later version.
 *
 * In accordance with Section 7(e) of the license, the licensing of the Program
 * under the license does not imply a trademark license. Therefore any rights,
 * title and interest in our trademarks remain entirely with us.
 *
 * This program 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 license for more details.
 *
 * You can be released from the requirements of the license by purchasing a
 * commercial license. Buying such a license is mandatory as soon as you develop
 * commercial activities involving this program without disclosing the source
 * code of your own applications
 */
#include <eventql/util/stdtypes.h>
#include <eventql/util/logging.h>
#include <eventql/util/io/fileutil.h>
#include <eventql/util/io/mmappedfile.h>
#include <eventql/util/protobuf/msg.h>
#include <eventql/util/wallclock.h>
#include <eventql/util/application.h>
#include <eventql/db/compaction_worker.h>
#include <eventql/db/partition_writer.h>
#include <eventql/util/protobuf/MessageDecoder.h>
#include <eventql/io/cstable/RecordShredder.h>
#include <eventql/io/cstable/cstable_writer.h>

#include "eventql/eventql.h"

namespace eventql {

CompactionWorker::CompactionWorker(
    PartitionMap* pmap,
    size_t nthreads) :
    pmap_(pmap),
    nthreads_(nthreads),
    queue_([] (
        const Pair<uint64_t, RefPtr<Partition>>& a,
        const Pair<uint64_t, RefPtr<Partition>>& b) {
      return a.first < b.first;
    }),
    running_(false) {
  pmap->subscribeToPartitionChanges([this] (
      RefPtr<eventql::PartitionChangeNotification> change) {
    enqueuePartition(change->partition);
  });

  start();
}

CompactionWorker::~CompactionWorker() {
  stop();
}

void CompactionWorker::enqueuePartition(
    RefPtr<Partition> partition,
    bool immediate /* = false */) {
  if (immediate) {
    startImmediateCompaction(partition);
  } else {
    std::unique_lock<std::mutex> lk(mutex_);
    enqueuePartitionWithLock(partition);
  }
}

void CompactionWorker::startImmediateCompaction(RefPtr<Partition> partition) {
  auto uuid = partition->uuid();

  {
    std::unique_lock<std::mutex> lk(mutex_);
    if (immediate_set_.count(uuid) > 0) {
      return;
    }

    if (immediate_set_.size() > kImmediateCompactionMaxThreads) {
      logWarning(
          "evqld",
          "maximum number of immediate compaction threads reached -- "
          "kImmediateCompactionMaxThreads or num_compaction_threads too low?");

      enqueuePartitionWithLock(partition);
      return;
    }

    immediate_set_.emplace(uuid);
  }

  auto thread = std::thread([this, partition, uuid] {
    Application::setCurrentThreadName("evqld-compaction-immediate");
    compactPartition(partition);

    std::unique_lock<std::mutex> lk(mutex_);
    immediate_set_.erase(uuid);
  });

  thread.detach();
}

void CompactionWorker::enqueuePartitionWithLock(
    RefPtr<Partition> partition) {
  auto interval = partition->getTable()->commitInterval();

  auto uuid = partition->uuid();
  if (waitset_.count(uuid) > 0) {
    return;
  }

  queue_.emplace(
      WallClock::unixMicros() + interval.microseconds(),
      partition);

  waitset_.emplace(uuid);
  cv_.notify_all();
  evqld_stats()->compaction_queue_length.set(queue_.size());
}

void CompactionWorker::start() {
  running_ = true;

  for (int i = 0; i < nthreads_; ++i) {
    threads_.emplace_back(std::bind(&CompactionWorker::work, this));
  }
}

void CompactionWorker::stop() {
  if (!running_) {
    return;
  }

  running_ = false;
  cv_.notify_all();

  for (auto& t : threads_) {
    t.join();
  }
}

void CompactionWorker::work() {
  Application::setCurrentThreadName("evqld-compaction");

  std::unique_lock<std::mutex> lk(mutex_);

  while (running_) {
    if (queue_.size() == 0) {
      cv_.wait(lk);
    }

    if (queue_.size() == 0) {
      continue;
    }

    auto now = WallClock::unixMicros();
    if (now < queue_.begin()->first) {
      cv_.wait_for(
          lk,
          std::chrono::microseconds(queue_.begin()->first - now));

      continue;
    }

    auto partition = queue_.begin()->second;
    queue_.erase(queue_.begin());

    bool success = true;
    {
      lk.unlock();
      success = compactPartition(partition);
      lk.lock();
    }

    if (success) {
      waitset_.erase(partition->uuid());

      if (partition->getWriter()->needsCompaction()) {
        enqueuePartitionWithLock(partition);
      }
    } else {
      auto delay = 30 * kMicrosPerSecond; // FIXPAUL increasing delay..
      queue_.emplace(now + delay, partition);
    }

    evqld_stats()->compaction_queue_length.set(queue_.size());
  }
}

bool CompactionWorker::compactPartition(RefPtr<Partition> partition) try {
  auto writer = partition->getWriter();
  if (writer->compact()) {
    auto change = mkRef(new PartitionChangeNotification());
    change->partition = partition;
    pmap_->publishPartitionChange(change);
  }

  return true;
} catch (const StandardException& e) {
  auto snap = partition->getSnapshot();

  logCritical(
      "tsdb",
      e,
      "CompactionWorker error for partition $0/$1/$2",
      snap->state.tsdb_namespace(),
      snap->state.table_key(),
      snap->key.toString());

  return false;
}

} // namespace eventql
<|endoftext|>


<commit_before>/**
   @file   PlotStack.cc

   Source file of PlotStack, including the functions used for creating the histograms.

   @author Daniel Abercrombie <dabercro@mit.edu>
*/

#include <algorithm>

#include "TFile.h"
#include "TLegend.h"
#include "TProfile.h"

#include "HistHolder.h"
#include "PlotStack.h"

ClassImp(PlotStack)

//--------------------------------------------------------------------

/**
   The default constructor for PlotStack.
   It changes the value of PlotBase::fMakeRatio to be true by default.
 */

PlotStack::PlotStack()
{
  fMakeRatio = true;
}

//--------------------------------------------------------------------
PlotStack::~PlotStack()
{ }

//--------------------------------------------------------------------
void
PlotStack::MakeCanvas(TString FileBase, Int_t NumXBins, Double_t *XBins,
                      TString XLabel, TString YLabel, Bool_t logY)
{
  DisplayFunc(__func__);
  Message(eInfo, "Making File :   %s", FileBase.Data());
  Message(eInfo, "Plotting    :   %s", fDefaultExpr.Data());
  Message(eInfo, "Labeled     :   %s", XLabel.Data());
  Message(eInfo, "With cut    :   %s", fDefaultCut.GetTitle());

  if (YLabel == "") {
    if (fEventsPer == 0)
      YLabel = "Events/Bin";
    else if (fEventsPer < 1.0)
      YLabel.Form("Events/%.2f", fEventsPer);
    else
      YLabel.Form("Events/%.1f", fEventsPer);
  }

  SetLumiLabel(float(fLuminosity/1000.0));
  ResetLegend();

  fRatioLines.clear();

  std::vector<TFile*> TemplateFiles;
  TFile *templateFile = NULL;

  Message(eDebug, "Number of Templates: %i", fTemplateEntries.size());

  for (UInt_t iTemp = 0; iTemp != fTemplateEntries.size(); ++iTemp) {
    Message(eDebug, "Getting template: %i", iTemp);
    templateFile = TFile::Open(fTemplateFiles[iTemp]);
    TemplateFiles.push_back(templateFile);
  }

  SetIncludeErrorBars(true);
  std::vector<TH1D*> DataHists = GetHistList(NumXBins, XBins, kData);
  Message(eDebug, "Number of Data Histograms: %i", DataHists.size());
  SetIncludeErrorBars(false);
  std::vector<TH1D*> MCHists = GetHistList(NumXBins, XBins, kBackground);
  Message(eDebug, "Number of MC Histograms: %i", MCHists.size());
  std::vector<TH1D*> SignalHists;
  if (fSignalFileInfo.size() != 0)
    SignalHists = GetHistList(NumXBins, XBins, kSignal);
  Message(eDebug, "Number of Signal Histograms: %i", SignalHists.size());

  SetLegendFill(true);
  TH1D *DataHist = (TH1D*) DataHists[0]->Clone("DataHist");
  Message(eDebug, "Final Data Histogram created at %p", DataHist);
  DataHist->Reset("M");

  for (UInt_t iHist = 0; iHist < DataHists.size(); iHist++)
    DataHist->Add(DataHists[iHist]);

  Message(eInfo, "Number of data events: %i, integral: %f", (Int_t) DataHist->GetEntries(), DataHist->Integral("width"));

  TString previousEntry = "";
  TH1D *tempMCHist = NULL;
  HistHolder *tempHistHolder = NULL;
  std::vector<HistHolder*> HistHolders;

  for (UInt_t iHist = 0; iHist != MCHists.size(); ++iHist) {

    Message(eDebug, "About to process Histogram %i out of %i", iHist, MCHists.size());
    Message(eDebug, "Entry is \"%s\". Previous entry is \"%s\"",
            fMCFileInfo[iHist]->fEntry.Data(), previousEntry.Data());

    if (fMCFileInfo[iHist]->fEntry != previousEntry) {

      Message(eDebug, "Creating a new histogram");

      previousEntry = fMCFileInfo[iHist]->fEntry;
      TString tempName;
      tempName.Format("StackedHist_%d",iHist);
      tempMCHist = (TH1D*) MCHists[iHist]->Clone(tempName);
      tempHistHolder = new HistHolder(tempMCHist, fMCFileInfo[iHist]->fEntry,
                                      fMCFileInfo[iHist]->fColorStyle,
                                      fMCFileInfo[iHist]->fTreeName,
                                      (fForceTop == fMCFileInfo[iHist]->fEntry));
      HistHolders.push_back(tempHistHolder);

    } else {

      tempMCHist->Add(MCHists[iHist]);
      Message(eDebug, "Added to previous histogram.");

    }

    Message(eDebug, "Number of unique entries so far: %i", HistHolders.size());

  }

  for (UInt_t iTemp = 0; iTemp != fTemplateEntries.size(); ++iTemp) {

    for (UInt_t iHist = 0; iHist != HistHolders.size(); ++iHist) {

      if (fTemplateEntries[iTemp] == HistHolders[iHist]->fEntry) {

        Message(eInfo, "Replacing histogram %s with a template",
                fTemplateEntries[iTemp].Data());

        TH1D *templateHist = (TH1D*) TemplateFiles[iTemp]->Get(fTemplateHists[iTemp]);
        TH1D *toFormat = (TH1D*) templateHist->Rebin(NumXBins, "", XBins);
        toFormat->SetFillStyle(HistHolders[iHist]->fHist->GetFillStyle());
        toFormat->SetFillColor(HistHolders[iHist]->fHist->GetFillColor());
        toFormat->SetMarkerSize(HistHolders[iHist]->fHist->GetMarkerSize());
        HistHolders[iHist]->fHist = toFormat;

      }
    }
  }

  if (fDumpRootName != "") {

    Message(eInfo, "Dumping histograms into %s", fDumpRootName.Data());

    TH1D* tempHist;
    TFile* dumpFile = new TFile(fDumpRootName,"RECREATE");

    // Background Histograms

    for (UInt_t iHist = 0; iHist != HistHolders.size(); ++iHist) {

      tempHist = (TH1D*) HistHolders[iHist]->fHist->Clone();

      Message(eInfo, "%s  :  %f", HistHolders[iHist]->fEntry.Data(),
              tempHist->Integral(0, NumXBins + 1, "width"));

      dumpFile->WriteTObject(tempHist, TString::Format("%s-%s",
                                                       fDefaultExpr.Data(),
                                                       HistHolders[iHist]->fTree.Data()
                                                       )
                             );
    }

    // Signal Histograms

    for (UInt_t iHist = 0; iHist != SignalHists.size(); ++iHist) {

      tempHist = (TH1D*) SignalHists[iHist]->Clone();

      Message(eInfo, "%s  :  %f", fSignalFileInfo[iHist]->fTreeName.Data(),
              tempHist->Integral(0, NumXBins + 1, "width"));

      dumpFile->WriteTObject(tempHist, TString::Format("%s-%s",
                                                       fDefaultExpr.Data(),
                                                       fSignalFileInfo[iHist]->fTreeName.Data()
                                                       )
                             );

    }

    // Data Histogram

    tempHist = (TH1D*) DataHist->Clone();
    Message(eInfo, "Data     :  %f", tempHist->Integral(0, NumXBins + 1, "width"));
    dumpFile->WriteTObject(tempHist, TString::Format("%s-data", fDefaultExpr.Data()));
    dumpFile->Close();

  }

  if (fSortBackground) {
    std::sort(HistHolders.begin(), HistHolders.end(), SortHistHolders);
    Message(eInfo, "Backgrounds sorted");
  }

  Message(eDebug, "Number of unique histograms: %i", HistHolders.size());

  std::vector<TH1D*> AllHists;
  for (UInt_t iLarger = 0; iLarger != HistHolders.size(); ++iLarger) {

    Message(eDebug, "Stacking up histogram: %i", iLarger);
    Message(eInfo, "Entry %s has total integral %f",
            HistHolders[iLarger]->fEntry.Data(),
            HistHolders[iLarger]->fHist->Integral("width"));

    for (UInt_t iSmaller = iLarger + 1; iSmaller != HistHolders.size(); ++iSmaller) {
      Message(eDebug, "Adding %i to %i", iSmaller, iLarger);
      HistHolders[iLarger]->fHist->Add(HistHolders[iSmaller]->fHist);
    }

    Message(eDebug, "Histogram %i has integral %f", iLarger, HistHolders[iLarger]->fHist->Integral());

    if (HistHolders[iLarger]->fHist->Integral() > 0 || iLarger == 0) {

      if (iLarger != 0)
        SetZeroError(HistHolders[iLarger]->fHist);
      AllHists.push_back(HistHolders[iLarger]->fHist);

      if ((HistHolders[iLarger]->fHist->Integral() > fMinLegendFrac * HistHolders[0]->fHist->Integral()) ||  // If more than the fraction set
          (iLarger == HistHolders.size() - 1))                                                               // or the last histogram
        AddLegendEntry(HistHolders[iLarger]->fEntry, 1, fStackLineWidth, 1);                                 // Add legend properly
      else if ((HistHolders[iLarger]->fHist->Integral() > fIgnoreInLinear * HistHolders[0]->fHist->Integral()) ||
               logY) {                                                                                // Otherwise if not ignored
        if (HistHolders[iLarger + 1]->fHist->Integral() > 0) {                                               // Check if the next histogram contribute
          if (fOthersColor != 0)
            HistHolders[iLarger]->fHist->SetFillColor(fOthersColor);
          AddLegendEntry("Others", 1, fStackLineWidth, 1);                                                   // If so, make others legend
        }
        else                                                                                // If not,
          AddLegendEntry(HistHolders[iLarger]->fEntry, HistHolders[iLarger]->fColor, 1, 1);                  // Make normal legend entry
        break;                                                                                // Stop adding histograms
      } else {
        AllHists.pop_back();
        break;
      }
    }

    Message(eDebug, "There are now %i total histograms to plot.", AllHists.size());

  }

  Message(eInfo, "Total background contribution: %f", HistHolders[0]->fHist->Integral("width"));

  AddLegendEntry("Data", 1);
  SetDataIndex(int(AllHists.size()));
  AllHists.push_back(DataHist);

  for (UInt_t iHist = 0; iHist != SignalHists.size(); ++iHist) {
    Message(eDebug, "Processing Signal Hist %i of %i", iHist, SignalHists.size());

    if (fAddSignal) {                            // Do some clever things if we're adding signal to backgrounds

      if (fMakeRatio)                            // All possible signals show up on the ratio pad
        AddRatioLine(int(AllHists.size()));
      if (AllHists.size() > 1)
        SignalHists[iHist]->Add(AllHists[0]);    // Add the background to the signals

    }

    AllHists.push_back(SignalHists[iHist]);
    AddLegendEntry(fSignalFileInfo[iHist]->fEntry, 1, 2, fSignalFileInfo[iHist]->fColorStyle);
    Message(eDebug, "There are now %i total histograms to plot.", AllHists.size());
  }

  Message(eDebug, "There are now %i total histograms to plot.", AllHists.size());

  if (fMakeRatio)
    AddRatioLine(fDataIndex);

  SetRatioIndex(0);

  BaseCanvas(AddOutDir(FileBase), AllHists, XLabel, YLabel, logY);

  for (UInt_t iHist = 0; iHist != AllHists.size(); ++iHist)
    delete AllHists[iHist];
  for (UInt_t iHist = 0; iHist != MCHists.size(); ++iHist)
    delete MCHists[iHist];
  for (UInt_t iHist = 0; iHist != DataHists.size(); ++iHist)
    delete DataHists[iHist];

  for (UInt_t iTemp = 0; iTemp != fTemplateEntries.size(); ++iTemp)
    TemplateFiles[iTemp]->Close();

  CloseFiles();
}

//--------------------------------------------------------------------
void
PlotStack::MakeCanvas(TString FileBase, Int_t NumXBins, Double_t MinX, Double_t MaxX,
                      TString XLabel, TString YLabel, Bool_t logY)
{
  Double_t XBins[NumXBins+1];
  ConvertToArray(NumXBins,MinX,MaxX,XBins);
  MakeCanvas(FileBase,NumXBins,XBins,XLabel,YLabel,logY);
}

//--------------------------------------------------------------------
PlotStack*
PlotStack::Copy()
{
  PlotStack *newPlotter = new PlotStack();
  *newPlotter = *this;
  return newPlotter;
}
<commit_msg>Slightly nicer formatting.<commit_after>/**
   @file   PlotStack.cc

   Source file of PlotStack, including the functions used for creating the histograms.

   @author Daniel Abercrombie <dabercro@mit.edu>
*/

#include <algorithm>

#include "TFile.h"
#include "TLegend.h"
#include "TProfile.h"

#include "HistHolder.h"
#include "PlotStack.h"

ClassImp(PlotStack)

//--------------------------------------------------------------------

/**
   The default constructor for PlotStack.
   It changes the value of PlotBase::fMakeRatio to be true by default.
 */

PlotStack::PlotStack()
{
  fMakeRatio = true;
}

//--------------------------------------------------------------------
PlotStack::~PlotStack()
{ }

//--------------------------------------------------------------------
void
PlotStack::MakeCanvas(TString FileBase, Int_t NumXBins, Double_t *XBins,
                      TString XLabel, TString YLabel, Bool_t logY)
{
  DisplayFunc(__func__);
  Message(eInfo, "Making File :   %s", FileBase.Data());
  Message(eInfo, "Plotting    :   %s", fDefaultExpr.Data());
  Message(eInfo, "Labeled     :   %s", XLabel.Data());
  Message(eInfo, "With cut    :   %s", fDefaultCut.GetTitle());

  if (YLabel == "") {
    if (fEventsPer == 0)
      YLabel = "Events/Bin";
    else if (fEventsPer >= 10)
      YLabel.Form("Events/%.0f", fEventsPer);
    else if (fEventsPer < 1.0)
      YLabel.Form("Events/%.2f", fEventsPer);
    else
      YLabel.Form("Events/%.1f", fEventsPer);
  }

  SetLumiLabel(float(fLuminosity/1000.0));
  ResetLegend();

  fRatioLines.clear();

  std::vector<TFile*> TemplateFiles;
  TFile *templateFile = NULL;

  Message(eDebug, "Number of Templates: %i", fTemplateEntries.size());

  for (UInt_t iTemp = 0; iTemp != fTemplateEntries.size(); ++iTemp) {
    Message(eDebug, "Getting template: %i", iTemp);
    templateFile = TFile::Open(fTemplateFiles[iTemp]);
    TemplateFiles.push_back(templateFile);
  }

  SetIncludeErrorBars(true);
  std::vector<TH1D*> DataHists = GetHistList(NumXBins, XBins, kData);
  Message(eDebug, "Number of Data Histograms: %i", DataHists.size());
  SetIncludeErrorBars(false);
  std::vector<TH1D*> MCHists = GetHistList(NumXBins, XBins, kBackground);
  Message(eDebug, "Number of MC Histograms: %i", MCHists.size());
  std::vector<TH1D*> SignalHists;
  if (fSignalFileInfo.size() != 0)
    SignalHists = GetHistList(NumXBins, XBins, kSignal);
  Message(eDebug, "Number of Signal Histograms: %i", SignalHists.size());

  SetLegendFill(true);
  TH1D *DataHist = (TH1D*) DataHists[0]->Clone("DataHist");
  Message(eDebug, "Final Data Histogram created at %p", DataHist);
  DataHist->Reset("M");

  for (UInt_t iHist = 0; iHist < DataHists.size(); iHist++)
    DataHist->Add(DataHists[iHist]);

  Message(eInfo, "Number of data events: %i, integral: %f", (Int_t) DataHist->GetEntries(), DataHist->Integral("width"));

  TString previousEntry = "";
  TH1D *tempMCHist = NULL;
  HistHolder *tempHistHolder = NULL;
  std::vector<HistHolder*> HistHolders;

  for (UInt_t iHist = 0; iHist != MCHists.size(); ++iHist) {

    Message(eDebug, "About to process Histogram %i out of %i", iHist, MCHists.size());
    Message(eDebug, "Entry is \"%s\". Previous entry is \"%s\"",
            fMCFileInfo[iHist]->fEntry.Data(), previousEntry.Data());

    if (fMCFileInfo[iHist]->fEntry != previousEntry) {

      Message(eDebug, "Creating a new histogram");

      previousEntry = fMCFileInfo[iHist]->fEntry;
      TString tempName;
      tempName.Format("StackedHist_%d",iHist);
      tempMCHist = (TH1D*) MCHists[iHist]->Clone(tempName);
      tempHistHolder = new HistHolder(tempMCHist, fMCFileInfo[iHist]->fEntry,
                                      fMCFileInfo[iHist]->fColorStyle,
                                      fMCFileInfo[iHist]->fTreeName,
                                      (fForceTop == fMCFileInfo[iHist]->fEntry));
      HistHolders.push_back(tempHistHolder);

    } else {

      tempMCHist->Add(MCHists[iHist]);
      Message(eDebug, "Added to previous histogram.");

    }

    Message(eDebug, "Number of unique entries so far: %i", HistHolders.size());

  }

  for (UInt_t iTemp = 0; iTemp != fTemplateEntries.size(); ++iTemp) {

    for (UInt_t iHist = 0; iHist != HistHolders.size(); ++iHist) {

      if (fTemplateEntries[iTemp] == HistHolders[iHist]->fEntry) {

        Message(eInfo, "Replacing histogram %s with a template",
                fTemplateEntries[iTemp].Data());

        TH1D *templateHist = (TH1D*) TemplateFiles[iTemp]->Get(fTemplateHists[iTemp]);
        TH1D *toFormat = (TH1D*) templateHist->Rebin(NumXBins, "", XBins);
        toFormat->SetFillStyle(HistHolders[iHist]->fHist->GetFillStyle());
        toFormat->SetFillColor(HistHolders[iHist]->fHist->GetFillColor());
        toFormat->SetMarkerSize(HistHolders[iHist]->fHist->GetMarkerSize());
        HistHolders[iHist]->fHist = toFormat;

      }
    }
  }

  if (fDumpRootName != "") {

    Message(eInfo, "Dumping histograms into %s", fDumpRootName.Data());

    TH1D* tempHist;
    TFile* dumpFile = new TFile(fDumpRootName,"RECREATE");

    // Background Histograms

    for (UInt_t iHist = 0; iHist != HistHolders.size(); ++iHist) {

      tempHist = (TH1D*) HistHolders[iHist]->fHist->Clone();

      Message(eInfo, "%s  :  %f", HistHolders[iHist]->fEntry.Data(),
              tempHist->Integral(0, NumXBins + 1, "width"));

      dumpFile->WriteTObject(tempHist, TString::Format("%s-%s",
                                                       fDefaultExpr.Data(),
                                                       HistHolders[iHist]->fTree.Data()
                                                       )
                             );
    }

    // Signal Histograms

    for (UInt_t iHist = 0; iHist != SignalHists.size(); ++iHist) {

      tempHist = (TH1D*) SignalHists[iHist]->Clone();

      Message(eInfo, "%s  :  %f", fSignalFileInfo[iHist]->fTreeName.Data(),
              tempHist->Integral(0, NumXBins + 1, "width"));

      dumpFile->WriteTObject(tempHist, TString::Format("%s-%s",
                                                       fDefaultExpr.Data(),
                                                       fSignalFileInfo[iHist]->fTreeName.Data()
                                                       )
                             );

    }

    // Data Histogram

    tempHist = (TH1D*) DataHist->Clone();
    Message(eInfo, "Data     :  %f", tempHist->Integral(0, NumXBins + 1, "width"));
    dumpFile->WriteTObject(tempHist, TString::Format("%s-data", fDefaultExpr.Data()));
    dumpFile->Close();

  }

  if (fSortBackground) {
    std::sort(HistHolders.begin(), HistHolders.end(), SortHistHolders);
    Message(eInfo, "Backgrounds sorted");
  }

  Message(eDebug, "Number of unique histograms: %i", HistHolders.size());

  std::vector<TH1D*> AllHists;
  for (UInt_t iLarger = 0; iLarger != HistHolders.size(); ++iLarger) {

    Message(eDebug, "Stacking up histogram: %i", iLarger);
    Message(eInfo, "Entry %s has total integral %f",
            HistHolders[iLarger]->fEntry.Data(),
            HistHolders[iLarger]->fHist->Integral("width"));

    for (UInt_t iSmaller = iLarger + 1; iSmaller != HistHolders.size(); ++iSmaller) {
      Message(eDebug, "Adding %i to %i", iSmaller, iLarger);
      HistHolders[iLarger]->fHist->Add(HistHolders[iSmaller]->fHist);
    }

    Message(eDebug, "Histogram %i has integral %f", iLarger, HistHolders[iLarger]->fHist->Integral());

    if (HistHolders[iLarger]->fHist->Integral() > 0 || iLarger == 0) {

      if (iLarger != 0)
        SetZeroError(HistHolders[iLarger]->fHist);
      AllHists.push_back(HistHolders[iLarger]->fHist);

      if ((HistHolders[iLarger]->fHist->Integral() > fMinLegendFrac * HistHolders[0]->fHist->Integral()) ||  // If more than the fraction set
          (iLarger == HistHolders.size() - 1))                                                               // or the last histogram
        AddLegendEntry(HistHolders[iLarger]->fEntry, 1, fStackLineWidth, 1);                                 // Add legend properly
      else if ((HistHolders[iLarger]->fHist->Integral() > fIgnoreInLinear * HistHolders[0]->fHist->Integral()) ||
               logY) {                                                                                // Otherwise if not ignored
        if (HistHolders[iLarger + 1]->fHist->Integral() > 0) {                                               // Check if the next histogram contribute
          if (fOthersColor != 0)
            HistHolders[iLarger]->fHist->SetFillColor(fOthersColor);
          AddLegendEntry("Others", 1, fStackLineWidth, 1);                                                   // If so, make others legend
        }
        else                                                                                // If not,
          AddLegendEntry(HistHolders[iLarger]->fEntry, HistHolders[iLarger]->fColor, 1, 1);                  // Make normal legend entry
        break;                                                                                // Stop adding histograms
      } else {
        AllHists.pop_back();
        break;
      }
    }

    Message(eDebug, "There are now %i total histograms to plot.", AllHists.size());

  }

  Message(eInfo, "Total background contribution: %f", HistHolders[0]->fHist->Integral("width"));

  AddLegendEntry("Data", 1);
  SetDataIndex(int(AllHists.size()));
  AllHists.push_back(DataHist);

  for (UInt_t iHist = 0; iHist != SignalHists.size(); ++iHist) {
    Message(eDebug, "Processing Signal Hist %i of %i", iHist, SignalHists.size());

    if (fAddSignal) {                            // Do some clever things if we're adding signal to backgrounds

      if (fMakeRatio)                            // All possible signals show up on the ratio pad
        AddRatioLine(int(AllHists.size()));
      if (AllHists.size() > 1)
        SignalHists[iHist]->Add(AllHists[0]);    // Add the background to the signals

    }

    AllHists.push_back(SignalHists[iHist]);
    AddLegendEntry(fSignalFileInfo[iHist]->fEntry, 1, 2, fSignalFileInfo[iHist]->fColorStyle);
    Message(eDebug, "There are now %i total histograms to plot.", AllHists.size());
  }

  Message(eDebug, "There are now %i total histograms to plot.", AllHists.size());

  if (fMakeRatio)
    AddRatioLine(fDataIndex);

  SetRatioIndex(0);

  BaseCanvas(AddOutDir(FileBase), AllHists, XLabel, YLabel, logY);

  for (UInt_t iHist = 0; iHist != AllHists.size(); ++iHist)
    delete AllHists[iHist];
  for (UInt_t iHist = 0; iHist != MCHists.size(); ++iHist)
    delete MCHists[iHist];
  for (UInt_t iHist = 0; iHist != DataHists.size(); ++iHist)
    delete DataHists[iHist];

  for (UInt_t iTemp = 0; iTemp != fTemplateEntries.size(); ++iTemp)
    TemplateFiles[iTemp]->Close();

  CloseFiles();
}

//--------------------------------------------------------------------
void
PlotStack::MakeCanvas(TString FileBase, Int_t NumXBins, Double_t MinX, Double_t MaxX,
                      TString XLabel, TString YLabel, Bool_t logY)
{
  bool reset_per = (fEventsPer == 0);
  if (reset_per)
    SetEventsPer((MaxX - MinX)/NumXBins);

  Double_t XBins[NumXBins+1];
  ConvertToArray(NumXBins, MinX, MaxX, XBins);
  MakeCanvas(FileBase, NumXBins, XBins, XLabel, YLabel, logY);

  if (reset_per)
    SetEventsPer(0);
}

//--------------------------------------------------------------------
PlotStack*
PlotStack::Copy()
{
  PlotStack *newPlotter = new PlotStack();
  *newPlotter = *this;
  return newPlotter;
}
<|endoftext|>