<commit_before>/*
 * Copyright (C) 2015,2016,2017 deipi.com LLC and contributors. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "exception.h"

#include <cxxabi.h>           // for abi::__cxa_demangle
#include <execinfo.h>         // for backtrace, backtrace_symbols
#include <stdarg.h>           // for va_end, va_list, va_start
#include <stdio.h>            // for vsnprintf
#include <stdlib.h>           // for free
#include <string.h>           // for strtok_r

#include "ignore_unused.h"    // for ignore_unused

#define BUFFER_SIZE 1024

std::string traceback(const char *filename, int line) {
	std::string t;
#ifndef NDEBUG
	void* callstack[128];

	// retrieve current stack addresses
	int frames = backtrace(callstack, sizeof(callstack) / sizeof(void*));

	t = "\n== Traceback at (" + std::string(filename) + ":" + std::to_string(line) + "):";

	if (frames == 0) {
		t += "\n    <empty, possibly corrupt>";
		return t;
	}

	// resolve addresses into strings containing "filename(function+address)"
	char** strs = backtrace_symbols(callstack, frames);

	// iterate over the returned symbol lines. skip the first, it is the
	// address of this function.
	for (int i = 1; i < frames; ++i) {
		int status = 0;
		const char *sep = "\t ()+";
		char *mangled, *lasts;
		std::string result;
		for (mangled = strtok_r(strs[i], sep, &lasts); mangled; mangled = strtok_r(nullptr, sep, &lasts)) {
			char* unmangled = abi::__cxa_demangle(mangled, nullptr, 0, &status);
			if (!result.empty()) {
				result += " ";
			}
			if (status == 0) {
				result += unmangled;
			} else {
				result += mangled;
			}
			free(unmangled);
		}
		t += "\n    " + result;
	}

	free(strs);
#else
	ignore_unused(filename, line);
#endif
	return t;
}

BaseException::BaseException(const char *filename, int line, const char* type, const char *format, ...)
{
	char buffer[BUFFER_SIZE];

	va_list argptr;
	va_start(argptr, format);
	vsnprintf(buffer, BUFFER_SIZE, format, argptr);
	va_end(argptr);
	message.assign(buffer);
	if (message.empty()) {
		message.assign(type);
	}

	snprintf(buffer, BUFFER_SIZE, "%s:%d", filename, line);
	context.assign(std::string(buffer) + ": " + message);
#ifdef XAPIAND_TRACEBACKS
	traceback = ::traceback(filename, line);
#else
	traceback = "\n== Exception at (" + std::string(filename) + ":" + std::to_string(line) + ")";
#endif
}
<commit_msg>TRACEBACK() always available<commit_after>/*
 * Copyright (C) 2015,2016,2017 deipi.com LLC and contributors. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "exception.h"

#include <cxxabi.h>           // for abi::__cxa_demangle
#include <execinfo.h>         // for backtrace, backtrace_symbols
#include <stdarg.h>           // for va_end, va_list, va_start
#include <stdio.h>            // for vsnprintf
#include <stdlib.h>           // for free
#include <string.h>           // for strtok_r

#define BUFFER_SIZE 1024

std::string traceback(const char *filename, int line) {
	std::string t;
	void* callstack[128];

	// retrieve current stack addresses
	int frames = backtrace(callstack, sizeof(callstack) / sizeof(void*));

	t = "\n== Traceback at (" + std::string(filename) + ":" + std::to_string(line) + "):";

	if (frames == 0) {
		t += "\n    <empty, possibly corrupt>";
		return t;
	}

	// resolve addresses into strings containing "filename(function+address)"
	char** strs = backtrace_symbols(callstack, frames);

	// iterate over the returned symbol lines. skip the first, it is the
	// address of this function.
	for (int i = 1; i < frames; ++i) {
		int status = 0;
		const char *sep = "\t ()+";
		char *mangled, *lasts;
		std::string result;
		for (mangled = strtok_r(strs[i], sep, &lasts); mangled; mangled = strtok_r(nullptr, sep, &lasts)) {
			char* unmangled = abi::__cxa_demangle(mangled, nullptr, 0, &status);
			if (!result.empty()) {
				result += " ";
			}
			if (status == 0) {
				result += unmangled;
			} else {
				result += mangled;
			}
			free(unmangled);
		}
		t += "\n    " + result;
	}

	free(strs);
	return t;
}

BaseException::BaseException(const char *filename, int line, const char* type, const char *format, ...)
{
	char buffer[BUFFER_SIZE];

	va_list argptr;
	va_start(argptr, format);
	vsnprintf(buffer, BUFFER_SIZE, format, argptr);
	va_end(argptr);
	message.assign(buffer);
	if (message.empty()) {
		message.assign(type);
	}

	snprintf(buffer, BUFFER_SIZE, "%s:%d", filename, line);
	context.assign(std::string(buffer) + ": " + message);
#ifdef XAPIAND_TRACEBACKS
	traceback = ::traceback(filename, line);
#else
	traceback = "\n== Exception at (" + std::string(filename) + ":" + std::to_string(line) + ")";
#endif
}
<|endoftext|>


<commit_before>#include "fast++.hpp"
#include <phypp/core/main.hpp>

const char* fastpp_version = "0.1";

int phypp_main(int argc, char* argv[]) {
    std::string param_file = (argc >= 2 ? argv[1] : "fast.param");

    // Read input data
    options_t opts;
    input_state_t input;
    if (!read_input(opts, input, param_file)) {
        return 1;
    }

    // Initialize the grid
    output_state_t output;
    gridder_t gridder(opts, input, output);
    if (!gridder.check_options()) {
        return 1;
    }

    // Initizalize the fitter
    fitter_t fitter(opts, input, gridder, output);

    // Build/read the grid for this redshift
    if (!gridder.build_and_send(fitter)) {
        return 1;
    }

    fitter.find_best_fits();

    // Write output to disk
    write_output(opts, input, gridder, output);

    return 0;
}
<commit_msg>Fixed misleading comment<commit_after>#include "fast++.hpp"
#include <phypp/core/main.hpp>

const char* fastpp_version = "0.1";

int phypp_main(int argc, char* argv[]) {
    std::string param_file = (argc >= 2 ? argv[1] : "fast.param");

    // Read input data
    options_t opts;
    input_state_t input;
    if (!read_input(opts, input, param_file)) {
        return 1;
    }

    // Initialize the grid
    output_state_t output;
    gridder_t gridder(opts, input, output);
    if (!gridder.check_options()) {
        return 1;
    }

    // Initizalize the fitter
    fitter_t fitter(opts, input, gridder, output);

    // Build/read the grid and fit galaxies
    if (!gridder.build_and_send(fitter)) {
        return 1;
    }

    // Compile results
    fitter.find_best_fits();

    // Write output to disk
    write_output(opts, input, gridder, output);

    return 0;
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <iostream>
#include <fstream>
#include <sstream>

#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
//#include <boost/date_time/date_parsing.hpp>

#include "expenses.hpp"
#include "data.hpp"
#include "guid.hpp"
#include "config.hpp"
#include "utils.hpp"
#include "console.hpp"

using namespace budget;

static data_handler<expense> expenses;

int budget::handle_expenses(const std::vector<std::string>& args){
    load_expenses();

    if(args.size() == 1){
        show_expenses();
    } else {
        auto& subcommand = args[1];

        if(subcommand == "show"){
            if(args.size() == 2){
                show_expenses();
            } else if(args.size() == 3){
                show_expenses(boost::gregorian::greg_month(to_number<unsigned short>(args[2])));
            } else if(args.size() == 4){
                show_expenses(
                    boost::gregorian::greg_month(to_number<unsigned short>(args[2])),
                    boost::gregorian::greg_year(to_number<unsigned short>(args[3])));
            } else {
                std::cout << "Too many arguments to expense show" << std::endl;

                return 1;
            }
        } else if(subcommand == "all"){
            all_expenses();
        } else if(subcommand == "add"){
            if(args.size() < 4){
                std::cout << "Not enough args for expense add" << std::endl;

                return 1;
            }

            expense expense;
            expense.guid = generate_guid();
            expense.expense_date = boost::gregorian::day_clock::local_day();

            std::string amount_string = args[2];
            expense.amount = parse_money(amount_string);

            if(expense.amount.dollars < 0 || expense.amount.cents < 0){
                std::cout << "Amount of the expense cannot be negative" << std::endl;

                return 1;
            }

            for(std::size_t i = 3; i < args.size(); ++i){
                expense.name += args[i] + " ";
            }

            add_data(expenses, std::move(expense));
        } else if(subcommand == "addd"){
            if(args.size() < 5){
                std::cout << "Not enough args for expense add date" << std::endl;

                return 1;
            }

            expense expense;
            expense.guid = generate_guid();
            expense.expense_date = boost::gregorian::from_string(args[2]);

            std::string amount_string = args[3];
            expense.amount = parse_money(amount_string);

            if(expense.amount.dollars < 0 || expense.amount.cents < 0){
                std::cout << "Amount of the expense cannot be negative" << std::endl;

                return 1;
            }

            for(std::size_t i = 4; i < args.size(); ++i){
                expense.name += args[i] + " ";
            }

            add_data(expenses, std::move(expense));
        } else if(subcommand == "delete"){
            std::size_t id = to_number<std::size_t>(args[2]);

            if(exists(expenses, id)){
                remove(expenses, id);

                std::cout << "Expense " << id << " has been deleted" << std::endl;
            } else {
                std::cout << "There are no expense with id " << id << std::endl;

                return 1;
            }
        } else {
            std::cout << "Invalid subcommand \"" << subcommand << "\"" << std::endl;

            return 1;
        }
    }

    save_expenses();

    return 0;
}

void budget::load_expenses(){
    load_data(expenses, "expenses.data");
}

void budget::save_expenses(){
    save_data(expenses, "expenses.data");
}

void budget::show_expenses(){
    date today = boost::gregorian::day_clock::local_day();

    show_expenses(today.month(), today.year());
}

void budget::show_expenses(boost::gregorian::greg_month month){
    date today = boost::gregorian::day_clock::local_day();

    show_expenses(month, today.year());
}

void budget::show_expenses(boost::gregorian::greg_month month, boost::gregorian::greg_year year){
    std::vector<std::string> columns = {"ID", "Date", "Name", "Amount"};
    std::vector<std::vector<std::string>> contents;

    money total;

    for(auto& expense : expenses.data){
        if(expense.expense_date.year() == year && expense.expense_date.month() == month){
            contents.push_back({to_string(expense.id), to_string(expense.expense_date), expense.name, to_string(expense.amount)});

            total += expense.amount;
        }
    }

    contents.push_back({"", "", "Total", to_string(total)});

    display_table(columns, contents);
}

void budget::all_expenses(){
    std::vector<std::string> columns = {"ID", "Date", "Name", "Amount"};
    std::vector<std::vector<std::string>> contents;

    for(auto& expense : expenses.data){
        contents.push_back({to_string(expense.id), to_string(expense.expense_date), expense.name, to_string(expense.amount)});
    }

    display_table(columns, contents);
}

std::ostream& budget::operator<<(std::ostream& stream, const expense& expense){
    return stream << expense.id  << ':' << expense.guid << ':' << expense.name << ':' << expense.amount << ':' << to_string(expense.expense_date);
}

void budget::operator>>(const std::vector<std::string>& parts, expense& expense){
    expense.id = to_number<std::size_t>(parts[0]);
    expense.guid = parts[1];
    expense.name = parts[2];
    expense.amount = parse_money(parts[3]);
    expense.expense_date = boost::gregorian::from_string(parts[4]);
}
<commit_msg>Add simple message if nothing to display<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <iostream>
#include <fstream>
#include <sstream>

#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
//#include <boost/date_time/date_parsing.hpp>

#include "expenses.hpp"
#include "data.hpp"
#include "guid.hpp"
#include "config.hpp"
#include "utils.hpp"
#include "console.hpp"

using namespace budget;

static data_handler<expense> expenses;

int budget::handle_expenses(const std::vector<std::string>& args){
    load_expenses();

    if(args.size() == 1){
        show_expenses();
    } else {
        auto& subcommand = args[1];

        if(subcommand == "show"){
            if(args.size() == 2){
                show_expenses();
            } else if(args.size() == 3){
                show_expenses(boost::gregorian::greg_month(to_number<unsigned short>(args[2])));
            } else if(args.size() == 4){
                show_expenses(
                    boost::gregorian::greg_month(to_number<unsigned short>(args[2])),
                    boost::gregorian::greg_year(to_number<unsigned short>(args[3])));
            } else {
                std::cout << "Too many arguments to expense show" << std::endl;

                return 1;
            }
        } else if(subcommand == "all"){
            all_expenses();
        } else if(subcommand == "add"){
            if(args.size() < 4){
                std::cout << "Not enough args for expense add" << std::endl;

                return 1;
            }

            expense expense;
            expense.guid = generate_guid();
            expense.expense_date = boost::gregorian::day_clock::local_day();

            std::string amount_string = args[2];
            expense.amount = parse_money(amount_string);

            if(expense.amount.dollars < 0 || expense.amount.cents < 0){
                std::cout << "Amount of the expense cannot be negative" << std::endl;

                return 1;
            }

            for(std::size_t i = 3; i < args.size(); ++i){
                expense.name += args[i] + " ";
            }

            add_data(expenses, std::move(expense));
        } else if(subcommand == "addd"){
            if(args.size() < 5){
                std::cout << "Not enough args for expense add date" << std::endl;

                return 1;
            }

            expense expense;
            expense.guid = generate_guid();
            expense.expense_date = boost::gregorian::from_string(args[2]);

            std::string amount_string = args[3];
            expense.amount = parse_money(amount_string);

            if(expense.amount.dollars < 0 || expense.amount.cents < 0){
                std::cout << "Amount of the expense cannot be negative" << std::endl;

                return 1;
            }

            for(std::size_t i = 4; i < args.size(); ++i){
                expense.name += args[i] + " ";
            }

            add_data(expenses, std::move(expense));
        } else if(subcommand == "delete"){
            std::size_t id = to_number<std::size_t>(args[2]);

            if(exists(expenses, id)){
                remove(expenses, id);

                std::cout << "Expense " << id << " has been deleted" << std::endl;
            } else {
                std::cout << "There are no expense with id " << id << std::endl;

                return 1;
            }
        } else {
            std::cout << "Invalid subcommand \"" << subcommand << "\"" << std::endl;

            return 1;
        }
    }

    save_expenses();

    return 0;
}

void budget::load_expenses(){
    load_data(expenses, "expenses.data");
}

void budget::save_expenses(){
    save_data(expenses, "expenses.data");
}

void budget::show_expenses(){
    date today = boost::gregorian::day_clock::local_day();

    show_expenses(today.month(), today.year());
}

void budget::show_expenses(boost::gregorian::greg_month month){
    date today = boost::gregorian::day_clock::local_day();

    show_expenses(month, today.year());
}

void budget::show_expenses(boost::gregorian::greg_month month, boost::gregorian::greg_year year){
    std::vector<std::string> columns = {"ID", "Date", "Name", "Amount"};
    std::vector<std::vector<std::string>> contents;

    money total;
    std::size_t count = 0;

    for(auto& expense : expenses.data){
        if(expense.expense_date.year() == year && expense.expense_date.month() == month){
            contents.push_back({to_string(expense.id), to_string(expense.expense_date), expense.name, to_string(expense.amount)});

            total += expense.amount;
            ++count;
        }
    }

    if(count == 0){
        std::cout << "No expenses for " << month << "-" << year << std::endl;
    } else {
        contents.push_back({"", "", "Total", to_string(total)});

        display_table(columns, contents);
    }
}

void budget::all_expenses(){
    std::vector<std::string> columns = {"ID", "Date", "Name", "Amount"};
    std::vector<std::vector<std::string>> contents;

    for(auto& expense : expenses.data){
        contents.push_back({to_string(expense.id), to_string(expense.expense_date), expense.name, to_string(expense.amount)});
    }

    display_table(columns, contents);
}

std::ostream& budget::operator<<(std::ostream& stream, const expense& expense){
    return stream << expense.id  << ':' << expense.guid << ':' << expense.name << ':' << expense.amount << ':' << to_string(expense.expense_date);
}

void budget::operator>>(const std::vector<std::string>& parts, expense& expense){
    expense.id = to_number<std::size_t>(parts[0]);
    expense.guid = parts[1];
    expense.name = parts[2];
    expense.amount = parse_money(parts[3]);
    expense.expense_date = boost::gregorian::from_string(parts[4]);
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2005 Tommi Maekitalo
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <tntdb/connect.h>
#include <tntdb/connection.h>
#include <tntdb/error.h>
#include <tntdb/librarymanager.h>
#include <tntdb/iface/iconnectionmanager.h>
#include <tntdb/connectionpool.h>
#include <cxxtools/log.h>
#include <map>
#include "config.h"

#ifdef WITH_STATIC_POSTGRESQL
# include <tntdb/postgresql/impl/connectionmanager.h>
#endif

#ifdef WITH_STATIC_MYSQL
# include <tntdb/mysql/impl/connectionmanager.h>
#endif

#ifdef WITH_STATIC_SQLITE
# include <tntdb/sqlite/impl/connectionmanager.h>
#endif

#ifdef WITH_STATIC_ORACLE
# include <tntdb/oracle/connectionmanager.h>
#endif

log_define("tntdb.connect")

namespace tntdb
{
  typedef std::map<std::string, LibraryManager> librariesType;
  static librariesType libraries;

  Connection connect(const std::string& url)
  {
    log_debug("connect(\"" << url << "\")");

    std::string::size_type n = url.find(':');
    if (n == std::string::npos)
#ifdef WITH_STATIC_POSTGRESQL
      return connectionManager_postgresql.connect(url);
#elif WITH_STATIC_MYSQL
      return connectionManager_mysql.connect(url);
#elif WITH_STATIC_SQLITE
      return connectionManager_sqlite.connect(url);
#elif WITH_STATIC_ORACLE
      return connectionManager_oracle.connect(url);
#else
      throw Error("invalid dburl \"" + url + '"');
#endif

    std::string driverName =  url.substr(0, n);
#ifdef WITH_STATIC_POSTGRESQL
    if (driverName == "postgresql")
      return connectionManager_postgresql.connect(url.substr(n + 1));
#elif WITH_STATIC_MYSQL
    if (driverName == "mysql")
      return connectionManager_mysql.connect(url.substr(n + 1));
#elif WITH_STATIC_SQLITE
    if (driverName == "sqlite")
      return connectionManager_sqlite.connect(url.substr(n + 1));
#elif WITH_STATIC_ORACLE
    if (driverName == "oracle")
      return connectionManager_oracle.connect(url.substr(n + 1));
#endif

    std::string libraryUrl = url.substr(n + 1);
    log_debug("driver \"" << driverName << "\" url=\"" << libraryUrl << '"');

    // lookup library-manager
    LibraryManager libraryManager;
    librariesType::const_iterator it = libraries.find(driverName);
    if (it == libraries.end())
    {
      libraryManager = LibraryManager(driverName);
      libraries[driverName] = libraryManager;
    }
    else
      libraryManager = it->second;

    return libraryManager.connect(libraryUrl);
  }

  static ConnectionPools connectionPools;

  Connection connectCached(const std::string& url)
  {
    log_debug("connectCached(\"" << url << "\")");
    return connectionPools.connect(url);
  }

  void dropCached(unsigned keep)
  {
    connectionPools.drop(keep);
  }

  void dropCached(const std::string& url, unsigned keep)
  {
    connectionPools.drop(url, keep);
  }

  void setMaxPoolSize(unsigned max)
  {
    connectionPools.setMaximumSize(max);
  }

  unsigned getMaxPoolSize()
  {
    return connectionPools.getMaximumSize();
  }
}
<commit_msg>make tntdb::connect thread safe<commit_after>/*
 * Copyright (C) 2005 Tommi Maekitalo
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <tntdb/connect.h>
#include <tntdb/connection.h>
#include <tntdb/error.h>
#include <tntdb/librarymanager.h>
#include <tntdb/iface/iconnectionmanager.h>
#include <tntdb/connectionpool.h>
#include <cxxtools/log.h>
#include <map>
#include "config.h"

#ifdef WITH_STATIC_POSTGRESQL
# include <tntdb/postgresql/impl/connectionmanager.h>
#endif

#ifdef WITH_STATIC_MYSQL
# include <tntdb/mysql/impl/connectionmanager.h>
#endif

#ifdef WITH_STATIC_SQLITE
# include <tntdb/sqlite/impl/connectionmanager.h>
#endif

#ifdef WITH_STATIC_ORACLE
# include <tntdb/oracle/connectionmanager.h>
#endif

log_define("tntdb.connect")

namespace tntdb
{
  typedef std::map<std::string, LibraryManager> librariesType;
  static librariesType libraries;
  static cxxtools::Mutex mutex;

  Connection connect(const std::string& url)
  {
    log_debug("connect(\"" << url << "\")");

    cxxtools::MutexLock lock(mutex);

    std::string::size_type n = url.find(':');
    if (n == std::string::npos)
#ifdef WITH_STATIC_POSTGRESQL
      return connectionManager_postgresql.connect(url);
#elif WITH_STATIC_MYSQL
      return connectionManager_mysql.connect(url);
#elif WITH_STATIC_SQLITE
      return connectionManager_sqlite.connect(url);
#elif WITH_STATIC_ORACLE
      return connectionManager_oracle.connect(url);
#else
      throw Error("invalid dburl \"" + url + '"');
#endif

    std::string driverName =  url.substr(0, n);
#ifdef WITH_STATIC_POSTGRESQL
    if (driverName == "postgresql")
      return connectionManager_postgresql.connect(url.substr(n + 1));
#elif WITH_STATIC_MYSQL
    if (driverName == "mysql")
      return connectionManager_mysql.connect(url.substr(n + 1));
#elif WITH_STATIC_SQLITE
    if (driverName == "sqlite")
      return connectionManager_sqlite.connect(url.substr(n + 1));
#elif WITH_STATIC_ORACLE
    if (driverName == "oracle")
      return connectionManager_oracle.connect(url.substr(n + 1));
#endif

    std::string libraryUrl = url.substr(n + 1);
    log_debug("driver \"" << driverName << "\" url=\"" << libraryUrl << '"');

    // lookup library-manager
    LibraryManager libraryManager;
    librariesType::const_iterator it = libraries.find(driverName);
    if (it == libraries.end())
    {
      libraryManager = LibraryManager(driverName);
      libraries[driverName] = libraryManager;
    }
    else
      libraryManager = it->second;

    return libraryManager.connect(libraryUrl);
  }

  static ConnectionPools connectionPools;

  Connection connectCached(const std::string& url)
  {
    log_debug("connectCached(\"" << url << "\")");
    return connectionPools.connect(url);
  }

  void dropCached(unsigned keep)
  {
    connectionPools.drop(keep);
  }

  void dropCached(const std::string& url, unsigned keep)
  {
    connectionPools.drop(url, keep);
  }

  void setMaxPoolSize(unsigned max)
  {
    connectionPools.setMaximumSize(max);
  }

  unsigned getMaxPoolSize()
  {
    return connectionPools.getMaximumSize();
  }
}
<|endoftext|>


<commit_before>/**
 * ClassicalWorldAssets.cpp
 *
 * (cc) Creative Commons Attribution-Noncommercial 3.0 Licence
 * Callum Hay, 2012
 *
 * You may not use this work for commercial purposes.
 * If you alter, transform, or build upon this work, you may distribute the
 * resulting work only under the same or similar licence to this one.
 */

#include "ClassicalWorldAssets.h"

#include "../ResourceManager.h"

// TODO: Get rid of this
#include "DecoSkybox.h"

ClassicalWorldAssets::ClassicalWorldAssets() :
GameWorldAssets(new DecoSkybox(),
    ResourceManager::GetInstance()->GetObjMeshResource(GameViewConstants::GetInstance()->CLASSICAL_BACKGROUND_MESH),
    ResourceManager::GetInstance()->GetObjMeshResource(GameViewConstants::GetInstance()->CLASSICAL_PADDLE_MESH),
    ResourceManager::GetInstance()->GetObjMeshResource(GameViewConstants::GetInstance()->CLASSICAL_BLOCK_MESH)), cloudTex(NULL),
fireColourFader(ColourRGBA(1.0f, 0.9f, 0.0f, 1.0f), ColourRGBA(0.3f, 0.10f, 0.0f, 0.2f)),
fireParticleScaler(1.0f, 0.025f), fireAccel1(Vector3D(1,1,1)), fireAccel2(Vector3D(1,1,1))

//smokeParticleScaler(1.0f, 1.75f),
//smokeRotatorCW(Randomizer::GetInstance()->RandomUnsignedInt() % 360, 0.25f, ESPParticleRotateEffector::CLOCKWISE),
//smokeRotatorCCW(Randomizer::GetInstance()->RandomUnsignedInt() % 360, 0.25f, ESPParticleRotateEffector::COUNTER_CLOCKWISE)
{

    // Change the colours for the background mesh from the default to something a bit more washed out ... more classical architectury
    std::vector<Colour> colours;
    colours.reserve(8);
    colours.push_back(Colour(0.4375f, 0.5f, 0.5647f));             // slate greyish-blue
    colours.push_back(Colour(0.2745098f, 0.5098039f, 0.70588f));   // steel blue
    colours.push_back(Colour(0.51372549f, 0.4352941f, 1.0f));      // slate purple
    colours.push_back(Colour(0.8588235f, 0.439215686f, 0.57647f)); // pale violet
    colours.push_back(Colour(0.6784f, 0.847f, 0.9019f));           // light steel blue
    colours.push_back(Colour(0.3725f, 0.6196078f, 0.62745098f));   // cadet (olive-) blue
    colours.push_back(Colour(0.4f, 0.8039215f, 0.666667f));		   // deep aquamarine
    colours.push_back(Colour(0.737f, 0.933f, 0.4078f));            // olive
    this->UpdateColourChangeList(colours);

    // Initialize textures...
	this->cloudTex = static_cast<Texture2D*>(ResourceManager::GetInstance()->GetImgTextureResource(GameViewConstants::GetInstance()->TEXTURE_CLOUD, Texture::Trilinear));
	assert(this->cloudTex != NULL);

    /*
	if (this->smokeTextures.empty()) {
		this->smokeTextures.reserve(6);
		Texture2D* temp = static_cast<Texture2D*>(ResourceManager::GetInstance()->GetImgTextureResource(GameViewConstants::GetInstance()->TEXTURE_SMOKE1, Texture::Trilinear));
		assert(temp != NULL);
		this->smokeTextures.push_back(temp);
		temp = static_cast<Texture2D*>(ResourceManager::GetInstance()->GetImgTextureResource(GameViewConstants::GetInstance()->TEXTURE_SMOKE2, Texture::Trilinear));
		assert(temp != NULL);
		this->smokeTextures.push_back(temp);
		temp = static_cast<Texture2D*>(ResourceManager::GetInstance()->GetImgTextureResource(GameViewConstants::GetInstance()->TEXTURE_SMOKE3, Texture::Trilinear));
		assert(temp != NULL);
		this->smokeTextures.push_back(temp);
		temp = static_cast<Texture2D*>(ResourceManager::GetInstance()->GetImgTextureResource(GameViewConstants::GetInstance()->TEXTURE_SMOKE4, Texture::Trilinear));
		assert(temp != NULL);
		this->smokeTextures.push_back(temp);
		temp = static_cast<Texture2D*>(ResourceManager::GetInstance()->GetImgTextureResource(GameViewConstants::GetInstance()->TEXTURE_SMOKE5, Texture::Trilinear));
		assert(temp != NULL);
		this->smokeTextures.push_back(temp);
		temp = static_cast<Texture2D*>(ResourceManager::GetInstance()->GetImgTextureResource(GameViewConstants::GetInstance()->TEXTURE_SMOKE6, Texture::Trilinear));
		assert(temp != NULL);
		this->smokeTextures.push_back(temp);
	}
    */

    this->InitializeEmitters();
}

ClassicalWorldAssets::~ClassicalWorldAssets() {
    bool success = false;

    success = ResourceManager::GetInstance()->ReleaseTextureResource(this->cloudTex);
    assert(success);

    /*
	for (std::vector<Texture2D*>::iterator iter = this->smokeTextures.begin();
		iter != this->smokeTextures.end(); ++iter) {

		success = ResourceManager::GetInstance()->ReleaseTextureResource(*iter);
		assert(success);
	}
	this->smokeTextures.clear();

    for (std::vector<ESPPointEmitter*>::iterator iter = this->smokeEmitters1.begin();
         iter != this->smokeEmitters1.end(); ++iter) {
        ESPPointEmitter* currEmitter = *iter;
        delete currEmitter;
        currEmitter = NULL;
    }
    this->smokeEmitters1.clear();
    */

    UNUSED_VARIABLE(success);
}

void ClassicalWorldAssets::DrawBackgroundModel(const Camera& camera, const BasicPointLight& bgKeyLight,
                                               const BasicPointLight& bgFillLight) {

    const Colour& currBGModelColour = this->currBGMeshColourAnim.GetInterpolantValue();

    // Draw the model with the current background colour
	glPushAttrib(GL_CURRENT_BIT);
	glColor4f(currBGModelColour.R(), currBGModelColour.G(), currBGModelColour.B(), this->bgFadeAnim.GetInterpolantValue());
	this->background->Draw(camera, bgKeyLight, bgFillLight);
	glPopAttrib();
}

void ClassicalWorldAssets::InitializeEmitters() {
    assert(this->cloudTex != NULL);

    static const float FIRE_SIZE_MIN = 2.6f;
    static const float FIRE_SIZE_MAX = 3.5f;
    static const float FIRE_LIFE_IN_SECS_MIN = 1.6f;
    static const float FIRE_LIFE_IN_SECS_MAX = 1.8f;
    static const float FIRE_SPAWN_DELTA_MIN = 0.025f;
    static const float FIRE_SPAWN_DELTA_MAX = 0.045f;
    static const float OFF_CENTER_AMT = 0.15f;
    static const int NUM_FIRE_PARTICLES = static_cast<int>(FIRE_LIFE_IN_SECS_MAX / FIRE_SPAWN_DELTA_MIN);
    static const float FIRE_SPEED_MIN = 4.0f;
    static const float FIRE_SPEED_MAX = 9.0f;

    static const float X_FLAME1_POS = 8.38f;
    static const float X_FLAME2_POS = -8.38f;
    static const float Y_FLAME_POS = 6.24f;
    static const float Y_FLAME_POS_WITH_OFFSET = Y_FLAME_POS - 0.75f;
    static const float Z_FLAME_POS  = -9.25f;

    static const float FLAME_FREQ = 0.25f;
    static const float FLAME_SCALE = 0.33f;

	this->fireEffect1.SetTechnique(CgFxVolumetricEffect::FIRESPRITE_TECHNIQUE_NAME);
	this->fireEffect1.SetColour(Colour(1.0f, 1.0f, 1.0f));
	this->fireEffect1.SetScale(FLAME_SCALE);
	this->fireEffect1.SetFrequency(FLAME_FREQ);
	this->fireEffect1.SetFlowDirection(Vector3D(0, 0, 1));
	this->fireEffect1.SetMaskTexture(this->cloudTex);

	this->fireEffect2.SetTechnique(CgFxVolumetricEffect::FIRESPRITE_TECHNIQUE_NAME);
	this->fireEffect2.SetColour(Colour(1.0f, 1.0f, 1.0f));
	this->fireEffect2.SetScale(FLAME_SCALE);
	this->fireEffect2.SetFrequency(FLAME_FREQ);
	this->fireEffect2.SetFlowDirection(Vector3D(0, 0, 1));
	this->fireEffect2.SetMaskTexture(this->cloudTex);

    bool result = false;

	fireEmitter1.SetSpawnDelta(ESPInterval(FIRE_SPAWN_DELTA_MIN, FIRE_SPAWN_DELTA_MAX));
	fireEmitter1.SetInitialSpd(ESPInterval(FIRE_SPEED_MIN, FIRE_SPEED_MAX));
	fireEmitter1.SetParticleLife(ESPInterval(FIRE_LIFE_IN_SECS_MIN, FIRE_LIFE_IN_SECS_MAX));
	fireEmitter1.SetParticleSize(ESPInterval(FIRE_SIZE_MIN, FIRE_SIZE_MAX));
	fireEmitter1.SetEmitAngleInDegrees(5);
	fireEmitter1.SetParticleRotation(ESPInterval(-180.0f, 180.0f));
	fireEmitter1.SetRadiusDeviationFromCenter(ESPInterval(0.0f, OFF_CENTER_AMT), ESPInterval(0), ESPInterval(0.0f, OFF_CENTER_AMT));
	fireEmitter1.SetParticleAlignment(ESP::ScreenAligned);
	fireEmitter1.SetEmitPosition(Point3D(X_FLAME1_POS, Y_FLAME_POS_WITH_OFFSET, Z_FLAME_POS));
    fireEmitter1.SetEmitDirection(Vector3D(0,1,0));
	fireEmitter1.AddEffector(&this->fireColourFader);
	fireEmitter1.AddEffector(&this->fireParticleScaler);
	fireEmitter1.AddEffector(&this->fireAccel1);
	result = fireEmitter1.SetParticles(NUM_FIRE_PARTICLES, &this->fireEffect1);
	assert(result);

	fireEmitter2.SetSpawnDelta(ESPInterval(FIRE_SPAWN_DELTA_MIN, FIRE_SPAWN_DELTA_MAX));
	fireEmitter2.SetInitialSpd(ESPInterval(FIRE_SPEED_MIN, FIRE_SPEED_MAX));
	fireEmitter2.SetParticleLife(ESPInterval(FIRE_LIFE_IN_SECS_MIN, FIRE_LIFE_IN_SECS_MAX));
	fireEmitter2.SetParticleSize(ESPInterval(FIRE_SIZE_MIN, FIRE_SIZE_MAX));
	fireEmitter2.SetEmitAngleInDegrees(5);
	fireEmitter2.SetParticleRotation(ESPInterval(-180.0f, 180.0f));
	fireEmitter2.SetRadiusDeviationFromCenter(ESPInterval(0.0f, OFF_CENTER_AMT), ESPInterval(0), ESPInterval(0.0f, OFF_CENTER_AMT));
	fireEmitter2.SetParticleAlignment(ESP::ScreenAligned);
	fireEmitter2.SetEmitPosition(Point3D(X_FLAME2_POS, Y_FLAME_POS_WITH_OFFSET, Z_FLAME_POS));
    fireEmitter2.SetEmitDirection(Vector3D(0,1,0));
	fireEmitter2.AddEffector(&this->fireColourFader);
	fireEmitter2.AddEffector(&this->fireParticleScaler);
	fireEmitter2.AddEffector(&this->fireAccel2);
	result = fireEmitter2.SetParticles(NUM_FIRE_PARTICLES, &this->fireEffect2);
	assert(result);

    /*
    static const float SMOKE_SPAWN_DELTA = FIRE_SPAWN_DELTA * static_cast<float>(this->smokeTextures.size());
    static const float SMOKE_LIFE_MIN = FIRE_LIFE_IN_SECS_MAX;
    static const float SMOKE_LIFE_MAX = 1.1f * FIRE_LIFE_IN_SECS_MAX;
    static const int NUM_SMOKE_PARTICLES_PER_EMITTER = static_cast<int>(SMOKE_LIFE_MAX / SMOKE_SPAWN_DELTA);
    this->smokeEmitters1.reserve(this->smokeTextures.size());

    for (int i = 0; i < static_cast<int>(this->smokeTextures.size()); i++) {

        ESPPointEmitter* smokeEmitter1 = new ESPPointEmitter();
	    smokeEmitter1->SetSpawnDelta(ESPInterval(SMOKE_SPAWN_DELTA));
	    smokeEmitter1->SetInitialSpd(ESPInterval(FIRE_SPEED_MAX, 1.25f * FIRE_SPEED_MAX));
	    smokeEmitter1->SetParticleLife(ESPInterval(SMOKE_LIFE_MIN, SMOKE_LIFE_MAX));
	    smokeEmitter1->SetParticleSize(ESPInterval(0.4f * FIRE_SIZE_MIN, 0.8f * FIRE_SIZE_MIN));
	    smokeEmitter1->SetEmitAngleInDegrees(10);
	    smokeEmitter1->SetEmitDirection(Vector3D(0, 1, 0));
	    smokeEmitter1->SetRadiusDeviationFromCenter(ESPInterval(0.0f, OFF_CENTER_AMT), ESPInterval(0.0f), ESPInterval(0.0f));
	    smokeEmitter1->SetParticleAlignment(ESP::ScreenAligned);
	    smokeEmitter1->SetEmitPosition(Point3D(X_FLAME1_POS, Y_FLAME_POS, Z_FLAME_POS));
	    smokeEmitter1->AddEffector(&this->fireColourFader);
        smokeEmitter1->AddEffector(&this->smokeParticleScaler);
        if (Randomizer::GetInstance()->RandomUnsignedInt() % 2 == 0) {
            smokeEmitter1->AddEffector(&this->smokeRotatorCW);
        }
        else {
            smokeEmitter1->AddEffector(&this->smokeRotatorCCW);
        }
	    result = smokeEmitter1->SetParticles(NUM_SMOKE_PARTICLES_PER_EMITTER, this->smokeTextures[i]);
	    assert(result);

        smokeEmitter1->SimulateTicking(i / static_cast<float>(this->smokeTextures.size()) * SMOKE_LIFE_MIN);

        this->smokeEmitters1.push_back(smokeEmitter1);
    }
    */

    UNUSED_VARIABLE(result);

	// Tick all the emitters for a bit to get them to look like they've been spawning for awhile
	for (int i = 0; i < 60; i++) {
		this->fireEmitter1.Tick(0.5);
		this->fireEmitter2.Tick(0.5);
	}
}<commit_msg>Changed classical background a bit.<commit_after>/**
 * ClassicalWorldAssets.cpp
 *
 * (cc) Creative Commons Attribution-Noncommercial 3.0 Licence
 * Callum Hay, 2012
 *
 * You may not use this work for commercial purposes.
 * If you alter, transform, or build upon this work, you may distribute the
 * resulting work only under the same or similar licence to this one.
 */

#include "ClassicalWorldAssets.h"

#include "../ResourceManager.h"

// TODO: Get rid of this
#include "DecoSkybox.h"

ClassicalWorldAssets::ClassicalWorldAssets() :
GameWorldAssets(new DecoSkybox(),
    ResourceManager::GetInstance()->GetObjMeshResource(GameViewConstants::GetInstance()->CLASSICAL_BACKGROUND_MESH),
    ResourceManager::GetInstance()->GetObjMeshResource(GameViewConstants::GetInstance()->CLASSICAL_PADDLE_MESH),
    ResourceManager::GetInstance()->GetObjMeshResource(GameViewConstants::GetInstance()->CLASSICAL_BLOCK_MESH)), cloudTex(NULL),
fireColourFader(ColourRGBA(1.0f, 0.9f, 0.0f, 1.0f), ColourRGBA(0.3f, 0.10f, 0.0f, 0.2f)),
fireParticleScaler(1.0f, 0.025f), fireAccel1(Vector3D(1,1,1)), fireAccel2(Vector3D(1,1,1))

//smokeParticleScaler(1.0f, 1.75f),
//smokeRotatorCW(Randomizer::GetInstance()->RandomUnsignedInt() % 360, 0.25f, ESPParticleRotateEffector::CLOCKWISE),
//smokeRotatorCCW(Randomizer::GetInstance()->RandomUnsignedInt() % 360, 0.25f, ESPParticleRotateEffector::COUNTER_CLOCKWISE)
{

    // Change the colours for the background mesh from the default to something a bit more washed out ... more classical architectury
    std::vector<Colour> colours;
    colours.reserve(8);
    colours.push_back(Colour(0.4375f, 0.5f, 0.5647f));             // slate greyish-blue
    colours.push_back(Colour(0.2745098f, 0.5098039f, 0.70588f));   // steel blue
    colours.push_back(Colour(0.51372549f, 0.4352941f, 1.0f));      // slate purple
    colours.push_back(Colour(0.8588235f, 0.439215686f, 0.57647f)); // pale violet
    colours.push_back(Colour(0.6784f, 0.847f, 0.9019f));           // light steel blue
    colours.push_back(Colour(0.3725f, 0.6196078f, 0.62745098f));   // cadet (olive-) blue
    colours.push_back(Colour(0.4f, 0.8039215f, 0.666667f));		   // deep aquamarine
    colours.push_back(Colour(0.737f, 0.933f, 0.4078f));            // olive
    this->UpdateColourChangeList(colours);

    // Initialize textures...
	this->cloudTex = static_cast<Texture2D*>(ResourceManager::GetInstance()->GetImgTextureResource(GameViewConstants::GetInstance()->TEXTURE_CLOUD, Texture::Trilinear));
	assert(this->cloudTex != NULL);

    /*
	if (this->smokeTextures.empty()) {
		this->smokeTextures.reserve(6);
		Texture2D* temp = static_cast<Texture2D*>(ResourceManager::GetInstance()->GetImgTextureResource(GameViewConstants::GetInstance()->TEXTURE_SMOKE1, Texture::Trilinear));
		assert(temp != NULL);
		this->smokeTextures.push_back(temp);
		temp = static_cast<Texture2D*>(ResourceManager::GetInstance()->GetImgTextureResource(GameViewConstants::GetInstance()->TEXTURE_SMOKE2, Texture::Trilinear));
		assert(temp != NULL);
		this->smokeTextures.push_back(temp);
		temp = static_cast<Texture2D*>(ResourceManager::GetInstance()->GetImgTextureResource(GameViewConstants::GetInstance()->TEXTURE_SMOKE3, Texture::Trilinear));
		assert(temp != NULL);
		this->smokeTextures.push_back(temp);
		temp = static_cast<Texture2D*>(ResourceManager::GetInstance()->GetImgTextureResource(GameViewConstants::GetInstance()->TEXTURE_SMOKE4, Texture::Trilinear));
		assert(temp != NULL);
		this->smokeTextures.push_back(temp);
		temp = static_cast<Texture2D*>(ResourceManager::GetInstance()->GetImgTextureResource(GameViewConstants::GetInstance()->TEXTURE_SMOKE5, Texture::Trilinear));
		assert(temp != NULL);
		this->smokeTextures.push_back(temp);
		temp = static_cast<Texture2D*>(ResourceManager::GetInstance()->GetImgTextureResource(GameViewConstants::GetInstance()->TEXTURE_SMOKE6, Texture::Trilinear));
		assert(temp != NULL);
		this->smokeTextures.push_back(temp);
	}
    */

    this->InitializeEmitters();
}

ClassicalWorldAssets::~ClassicalWorldAssets() {
    bool success = false;

    success = ResourceManager::GetInstance()->ReleaseTextureResource(this->cloudTex);
    assert(success);

    /*
	for (std::vector<Texture2D*>::iterator iter = this->smokeTextures.begin();
		iter != this->smokeTextures.end(); ++iter) {

		success = ResourceManager::GetInstance()->ReleaseTextureResource(*iter);
		assert(success);
	}
	this->smokeTextures.clear();

    for (std::vector<ESPPointEmitter*>::iterator iter = this->smokeEmitters1.begin();
         iter != this->smokeEmitters1.end(); ++iter) {
        ESPPointEmitter* currEmitter = *iter;
        delete currEmitter;
        currEmitter = NULL;
    }
    this->smokeEmitters1.clear();
    */

    UNUSED_VARIABLE(success);
}

void ClassicalWorldAssets::DrawBackgroundModel(const Camera& camera, const BasicPointLight& bgKeyLight,
                                               const BasicPointLight& bgFillLight) {

    const Colour& currBGModelColour = this->currBGMeshColourAnim.GetInterpolantValue();

    // Draw the model with the current background colour
	glPushAttrib(GL_CURRENT_BIT);
	glColor4f(currBGModelColour.R(), currBGModelColour.G(), currBGModelColour.B(), this->bgFadeAnim.GetInterpolantValue());
	this->background->Draw(camera, bgKeyLight, bgFillLight);
	glPopAttrib();
}

void ClassicalWorldAssets::InitializeEmitters() {
    assert(this->cloudTex != NULL);

    static const float FIRE_SIZE_MIN = 2.6f;
    static const float FIRE_SIZE_MAX = 3.5f;
    static const float FIRE_LIFE_IN_SECS_MIN = 1.6f;
    static const float FIRE_LIFE_IN_SECS_MAX = 1.8f;
    static const float FIRE_SPAWN_DELTA_MIN = 0.025f;
    static const float FIRE_SPAWN_DELTA_MAX = 0.045f;
    static const float OFF_CENTER_AMT = 0.15f;
    static const int NUM_FIRE_PARTICLES = static_cast<int>(FIRE_LIFE_IN_SECS_MAX / FIRE_SPAWN_DELTA_MIN);
    static const float FIRE_SPEED_MIN = 4.0f;
    static const float FIRE_SPEED_MAX = 9.0f;

    static const float X_FLAME1_POS = 8.38f;
    static const float X_FLAME2_POS = -8.38f;
    static const float Y_FLAME_POS = 6.24f;
    static const float Y_FLAME_POS_WITH_OFFSET = Y_FLAME_POS - 0.75f;
    static const float Z_FLAME_POS  = -11.25f;

    static const float FLAME_FREQ = 0.25f;
    static const float FLAME_SCALE = 0.33f;

	this->fireEffect1.SetTechnique(CgFxVolumetricEffect::FIRESPRITE_TECHNIQUE_NAME);
	this->fireEffect1.SetColour(Colour(1.0f, 1.0f, 1.0f));
	this->fireEffect1.SetScale(FLAME_SCALE);
	this->fireEffect1.SetFrequency(FLAME_FREQ);
	this->fireEffect1.SetFlowDirection(Vector3D(0, 0, 1));
	this->fireEffect1.SetMaskTexture(this->cloudTex);

	this->fireEffect2.SetTechnique(CgFxVolumetricEffect::FIRESPRITE_TECHNIQUE_NAME);
	this->fireEffect2.SetColour(Colour(1.0f, 1.0f, 1.0f));
	this->fireEffect2.SetScale(FLAME_SCALE);
	this->fireEffect2.SetFrequency(FLAME_FREQ);
	this->fireEffect2.SetFlowDirection(Vector3D(0, 0, 1));
	this->fireEffect2.SetMaskTexture(this->cloudTex);

    bool result = false;

	fireEmitter1.SetSpawnDelta(ESPInterval(FIRE_SPAWN_DELTA_MIN, FIRE_SPAWN_DELTA_MAX));
	fireEmitter1.SetInitialSpd(ESPInterval(FIRE_SPEED_MIN, FIRE_SPEED_MAX));
	fireEmitter1.SetParticleLife(ESPInterval(FIRE_LIFE_IN_SECS_MIN, FIRE_LIFE_IN_SECS_MAX));
	fireEmitter1.SetParticleSize(ESPInterval(FIRE_SIZE_MIN, FIRE_SIZE_MAX));
	fireEmitter1.SetEmitAngleInDegrees(5);
	fireEmitter1.SetParticleRotation(ESPInterval(-180.0f, 180.0f));
	fireEmitter1.SetRadiusDeviationFromCenter(ESPInterval(0.0f, OFF_CENTER_AMT), ESPInterval(0), ESPInterval(0.0f, OFF_CENTER_AMT));
	fireEmitter1.SetParticleAlignment(ESP::ScreenAligned);
	fireEmitter1.SetEmitPosition(Point3D(X_FLAME1_POS, Y_FLAME_POS_WITH_OFFSET, Z_FLAME_POS));
    fireEmitter1.SetEmitDirection(Vector3D(0,1,0));
	fireEmitter1.AddEffector(&this->fireColourFader);
	fireEmitter1.AddEffector(&this->fireParticleScaler);
	fireEmitter1.AddEffector(&this->fireAccel1);
	result = fireEmitter1.SetParticles(NUM_FIRE_PARTICLES, &this->fireEffect1);
	assert(result);

	fireEmitter2.SetSpawnDelta(ESPInterval(FIRE_SPAWN_DELTA_MIN, FIRE_SPAWN_DELTA_MAX));
	fireEmitter2.SetInitialSpd(ESPInterval(FIRE_SPEED_MIN, FIRE_SPEED_MAX));
	fireEmitter2.SetParticleLife(ESPInterval(FIRE_LIFE_IN_SECS_MIN, FIRE_LIFE_IN_SECS_MAX));
	fireEmitter2.SetParticleSize(ESPInterval(FIRE_SIZE_MIN, FIRE_SIZE_MAX));
	fireEmitter2.SetEmitAngleInDegrees(5);
	fireEmitter2.SetParticleRotation(ESPInterval(-180.0f, 180.0f));
	fireEmitter2.SetRadiusDeviationFromCenter(ESPInterval(0.0f, OFF_CENTER_AMT), ESPInterval(0), ESPInterval(0.0f, OFF_CENTER_AMT));
	fireEmitter2.SetParticleAlignment(ESP::ScreenAligned);
	fireEmitter2.SetEmitPosition(Point3D(X_FLAME2_POS, Y_FLAME_POS_WITH_OFFSET, Z_FLAME_POS));
    fireEmitter2.SetEmitDirection(Vector3D(0,1,0));
	fireEmitter2.AddEffector(&this->fireColourFader);
	fireEmitter2.AddEffector(&this->fireParticleScaler);
	fireEmitter2.AddEffector(&this->fireAccel2);
	result = fireEmitter2.SetParticles(NUM_FIRE_PARTICLES, &this->fireEffect2);
	assert(result);

    /*
    static const float SMOKE_SPAWN_DELTA = FIRE_SPAWN_DELTA * static_cast<float>(this->smokeTextures.size());
    static const float SMOKE_LIFE_MIN = FIRE_LIFE_IN_SECS_MAX;
    static const float SMOKE_LIFE_MAX = 1.1f * FIRE_LIFE_IN_SECS_MAX;
    static const int NUM_SMOKE_PARTICLES_PER_EMITTER = static_cast<int>(SMOKE_LIFE_MAX / SMOKE_SPAWN_DELTA);
    this->smokeEmitters1.reserve(this->smokeTextures.size());

    for (int i = 0; i < static_cast<int>(this->smokeTextures.size()); i++) {

        ESPPointEmitter* smokeEmitter1 = new ESPPointEmitter();
	    smokeEmitter1->SetSpawnDelta(ESPInterval(SMOKE_SPAWN_DELTA));
	    smokeEmitter1->SetInitialSpd(ESPInterval(FIRE_SPEED_MAX, 1.25f * FIRE_SPEED_MAX));
	    smokeEmitter1->SetParticleLife(ESPInterval(SMOKE_LIFE_MIN, SMOKE_LIFE_MAX));
	    smokeEmitter1->SetParticleSize(ESPInterval(0.4f * FIRE_SIZE_MIN, 0.8f * FIRE_SIZE_MIN));
	    smokeEmitter1->SetEmitAngleInDegrees(10);
	    smokeEmitter1->SetEmitDirection(Vector3D(0, 1, 0));
	    smokeEmitter1->SetRadiusDeviationFromCenter(ESPInterval(0.0f, OFF_CENTER_AMT), ESPInterval(0.0f), ESPInterval(0.0f));
	    smokeEmitter1->SetParticleAlignment(ESP::ScreenAligned);
	    smokeEmitter1->SetEmitPosition(Point3D(X_FLAME1_POS, Y_FLAME_POS, Z_FLAME_POS));
	    smokeEmitter1->AddEffector(&this->fireColourFader);
        smokeEmitter1->AddEffector(&this->smokeParticleScaler);
        if (Randomizer::GetInstance()->RandomUnsignedInt() % 2 == 0) {
            smokeEmitter1->AddEffector(&this->smokeRotatorCW);
        }
        else {
            smokeEmitter1->AddEffector(&this->smokeRotatorCCW);
        }
	    result = smokeEmitter1->SetParticles(NUM_SMOKE_PARTICLES_PER_EMITTER, this->smokeTextures[i]);
	    assert(result);

        smokeEmitter1->SimulateTicking(i / static_cast<float>(this->smokeTextures.size()) * SMOKE_LIFE_MIN);

        this->smokeEmitters1.push_back(smokeEmitter1);
    }
    */

    UNUSED_VARIABLE(result);

	// Tick all the emitters for a bit to get them to look like they've been spawning for awhile
	for (int i = 0; i < 60; i++) {
		this->fireEmitter1.Tick(0.5);
		this->fireEmitter2.Tick(0.5);
	}
}<|endoftext|>


<commit_before>/*
 *     Copyright 2015 Couchbase, Inc.
 *
 *   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.
 */

#define LCB_NO_DEPR_CXX_CTORS

#include "config.h"
#include <sys/types.h>
#include <libcouchbase/couchbase.h>
#include <libcouchbase/api3.h>
#include <libcouchbase/n1ql.h>
#include <libcouchbase/vbucket.h>
#include <iostream>
#include <list>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cerrno>
#include <fstream>
#include <algorithm> // random_shuffle
#include <stdexcept>
#include <sstream>
#ifndef WIN32
#include <pthread.h>
#include <unistd.h> // isatty()
#endif
#include "common/options.h"

using namespace cbc;
using namespace cliopts;
using std::vector;
using std::string;
using std::cerr;
using std::endl;

static void do_or_die(lcb_error_t rc)
{
    if (rc != LCB_SUCCESS) {
        std::stringstream ss;
        ss << "[" << std::hex << rc << "] " << lcb_strerror(NULL, rc);
        throw std::runtime_error(ss.str());
    }
}

class Metrics {
public:
    Metrics()
    : n_rows(0), n_queries(0), n_errors(0) {
        last_update = time(NULL);
    }

    void update_row(size_t n = 1) { n_rows += n; update_display(); }
    void update_done(size_t n = 1) { n_queries += n; update_display(); }
    void update_error(size_t n = 1) { n_errors += n; update_display(); }

#ifndef _WIN32
    bool is_tty() const { return isatty(STDERR_FILENO); }
    void lock() { pthread_mutex_lock(&m_lock); }
    void unlock() { pthread_mutex_unlock(&m_lock); }
#else
    void lock(){}
    void unlock(){}
    bool is_tty() const { return false; }
#endif
    void prepare_screen()
    {
        if (is_tty()) {
            printf("\n\n\n");
        }
    }

private:
    void update_display()
    {
        if (!is_tty()) {
            return;
        }

        time_t now = time(NULL);
        time_t duration = now - last_update;

        if (!duration) {
            return;
        }

        last_update = now;

        // Move up 3 cursors
        printf("\x1B[2A");
        printf("\x1B[KQUERIES/SEC: %lu\n", n_queries / duration);
        printf("\x1B[KROWS/SEC:    %lu\n", n_rows / duration);
        printf("\x1B[KERRORS:      %lu\r", n_errors);
        fflush(stdout);

        n_queries = 0;
        n_rows = 0;
    }

    size_t n_rows;
    size_t n_queries;
    size_t n_errors;
    time_t last_update;
#ifndef _WIN32
    pthread_mutex_t m_lock;
#endif
};

Metrics GlobalMetrics;

class Configuration
{
public:
    Configuration() : o_file("queryfile"), o_threads("num-threads") {
        o_file.mandatory(true);
        o_file.description(
            "Path to a file containing all the queries to execute. "
            "Each line should contain the full query body");
        o_file.abbrev('f');

        o_threads.description("Number of threads to run");
        o_threads.abbrev('t');
        o_threads.setDefault(1);
    }

    void addToParser(Parser& parser)
    {
        parser.addOption(o_file);
        parser.addOption(o_threads);
        m_params.addToParser(parser);
    }

    void processOptions()
    {
        std::ifstream ifs(o_file.const_result().c_str());
        if (!ifs.is_open()) {
            int ec_save = errno;
            string errstr(o_file.const_result());
            errstr += ": ";
            errstr += strerror(ec_save);
            throw std::runtime_error(errstr);
        }

        string curline;
        while (std::getline(ifs, curline).good() && !ifs.eof()) {
            m_queries.push_back(curline);
        }
    }

    void set_cropts(lcb_create_st &opts) { m_params.fillCropts(opts); }
    const vector<string>& queries() const { return m_queries; }
    size_t nthreads() { return o_threads.result(); }

private:
    vector<string> m_queries;
    StringOption o_file;
    UIntOption o_threads;
    ConnParams m_params;
};

extern "C" { static void n1qlcb(lcb_t, int, const lcb_RESPN1QL *resp); }
extern "C" { static void* pthrfunc(void*); }

class ThreadContext {
public:
    void run()
    {
        while (!m_cancelled) {
            vector<string>::const_iterator ii = m_queries.begin();
            for (; ii != m_queries.end(); ++ii) {
                run_one_query(*ii);
            }
        }
    }

#ifndef _WIN32
    void start()
    {
        assert(m_thr == NULL);
        m_thr = new pthread_t;
        int rc = pthread_create(m_thr, NULL, pthrfunc, this);
        if (rc != 0) {
            throw std::runtime_error(strerror(rc));
        }
    }

    void join()
    {
        assert(m_thr != NULL);
        void *arg = NULL;
        pthread_join(*m_thr, &arg);
    }

    ~ThreadContext()
    {
        if (m_thr != NULL) {
            join();
            delete m_thr;
            m_thr = NULL;
        }
    }
#else
    void start() { run(); }
    void join() {}
#endif

    void handle_response(const lcb_RESPN1QL *resp)
    {
        if (resp->rflags & LCB_RESP_F_FINAL) {
            if (resp->rc != LCB_SUCCESS) {
                log_error(resp->rc);
            }
        } else {
            last_nrow++;
        }
    }

    ThreadContext(lcb_t instance, const vector<string>& initial_queries)
    : m_instance(instance), last_nerr(0), last_nrow(0),
      m_metrics(&GlobalMetrics), m_cancelled(false), m_thr(NULL)
    {
        memset(&m_cmd, 0, sizeof m_cmd);
        m_cmd.content_type = "application/json";
        m_cmd.callback = n1qlcb;

        // Shuffle the list
        m_queries = initial_queries;
        std::random_shuffle(m_queries.begin(), m_queries.end());
    }

private:

    void log_error(lcb_error_t)
    {
        m_metrics->lock();
        m_metrics->update_error();
        m_metrics->unlock();
    }

    void run_one_query(const string& txt)
    {
        // Reset counters
        last_nrow = 0;
        last_nerr = 0;

        m_cmd.query = txt.c_str();
        m_cmd.nquery = txt.size();

        lcb_error_t rc = lcb_n1ql_query(m_instance, this, &m_cmd);
        if (rc != LCB_SUCCESS) {
            log_error(rc);
        } else {
            lcb_wait(m_instance);
            m_metrics->lock();
            m_metrics->update_row(last_nrow);
            m_metrics->update_done(1);
            m_metrics->unlock();
        }
    }

    lcb_t m_instance;
    vector<string> m_queries;
    size_t last_nerr;
    size_t last_nrow;
    lcb_CMDN1QL m_cmd;
    Metrics *m_metrics;
    volatile bool m_cancelled;
    #ifndef _WIN32
    pthread_t *m_thr;
    #else
    void *m_thr;
    #endif
};

static void n1qlcb(lcb_t, int, const lcb_RESPN1QL *resp)
{
    reinterpret_cast<ThreadContext*>(resp->cookie)->handle_response(resp);
}

static void* pthrfunc(void *arg)
{
    reinterpret_cast<ThreadContext*>(arg)->run();
    return NULL;
}

static bool
instance_has_n1ql(lcb_t instance) {
    // Check that the instance supports N1QL
    lcbvb_CONFIG *vbc;
    do_or_die(lcb_cntl(instance, LCB_CNTL_GET, LCB_CNTL_VBCONFIG, &vbc));

    int sslmode = 0;
    lcbvb_SVCMODE svcmode = LCBVB_SVCMODE_PLAIN;

    do_or_die(lcb_cntl(instance, LCB_CNTL_GET, LCB_CNTL_SSL_MODE, &sslmode));

    if (sslmode & LCB_SSL_ENABLED) {
        svcmode = LCBVB_SVCMODE_SSL;
    }

    int hix = lcbvb_get_randhost(vbc, LCBVB_SVCTYPE_N1QL, svcmode);
    return hix > -1;
}

static void real_main(int argc, char **argv) {
    Configuration config;
    Parser parser;
    config.addToParser(parser);
    parser.parse(argc, argv);

    vector<ThreadContext*> threads;
    vector<lcb_t> instances;

    lcb_create_st cropts = { 0 };
    config.set_cropts(cropts);
    config.processOptions();

    for (size_t ii = 0; ii < config.nthreads(); ii++) {
        lcb_t instance;
        do_or_die(lcb_create(&instance, &cropts));
        do_or_die(lcb_connect(instance));
        lcb_wait(instance);
        do_or_die(lcb_get_bootstrap_status(instance));

        if (ii == 0 && !instance_has_n1ql(instance)) {
            throw std::runtime_error("Cluster does not support N1QL!");
        }

        ThreadContext* cx = new ThreadContext(instance, config.queries());
        threads.push_back(cx);
        instances.push_back(instance);
    }

    GlobalMetrics.prepare_screen();

    for (size_t ii = 0; ii < threads.size(); ++ii) {
        threads[ii]->start();
    }
    for (size_t ii = 0; ii < threads.size(); ++ii) {
        threads[ii]->join();
    }
    for (size_t ii = 0; ii < instances.size(); ++ii) {
        lcb_destroy(instances[ii]);
    }
}

int main(int argc, char **argv)
{
    try {
        real_main(argc, argv);
        return 0;
    } catch (std::exception& exc) {
        cerr << exc.what() << endl;
        exit(EXIT_FAILURE);
    }
}
<commit_msg>CCBC-624: Make n1qlback record timings for queries (3/3)<commit_after>/*
 *     Copyright 2015 Couchbase, Inc.
 *
 *   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.
 */

#define LCB_NO_DEPR_CXX_CTORS

#include "config.h"
#include <sys/types.h>
#include <libcouchbase/couchbase.h>
#include <libcouchbase/api3.h>
#include <libcouchbase/n1ql.h>
#include <libcouchbase/vbucket.h>
#include <iostream>
#include <list>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cerrno>
#include <fstream>
#include <algorithm> // random_shuffle
#include <stdexcept>
#include <sstream>
#ifndef WIN32
#include <pthread.h>
#include <unistd.h> // isatty()
#endif
#include "common/options.h"
#include "common/histogram.h"

using namespace cbc;
using namespace cliopts;
using std::vector;
using std::string;
using std::cerr;
using std::endl;

static void do_or_die(lcb_error_t rc)
{
    if (rc != LCB_SUCCESS) {
        std::stringstream ss;
        ss << "[" << std::hex << rc << "] " << lcb_strerror(NULL, rc);
        throw std::runtime_error(ss.str());
    }
}

class Metrics {
public:
    Metrics()
    : n_rows(0), n_queries(0), n_errors(0), last_update(time(NULL)), hg(NULL)
    {
        #ifndef _WIN32
        if (pthread_mutex_init(&m_lock, NULL) != 0) {
            abort();
        }
        #endif
    }

    void update_row(size_t n = 1) { n_rows += n; update_display(); }
    void update_done(size_t n = 1) { n_queries += n; update_display(); }
    void update_error(size_t n = 1) { n_errors += n; update_display(); }

    void update_timings(lcb_U64 duration) {
        if (hg != NULL) {
            hg->record(duration);
        }
    }

#ifndef _WIN32
    bool is_tty() const { return isatty(STDERR_FILENO); }
    void lock() { pthread_mutex_lock(&m_lock); }
    void unlock() { pthread_mutex_unlock(&m_lock); }
#else
    void lock(){}
    void unlock(){}
    bool is_tty() const { return false; }
#endif
    void prepare_screen()
    {
        if (is_tty()) {
            printf("\n\n\n");
        }
    }

    void prepare_timings()
    {
        if (hg == NULL) {
            hg = new Histogram();
            hg->installStandalone(stdout);
        }
    }

private:
    void update_display()
    {
        if (!is_tty()) {
            return;
        }

        time_t now = time(NULL);
        time_t duration = now - last_update;

        if (!duration) {
            return;
        }

        last_update = now;

        // Move up 3 cursors
        printf("\x1B[2A");
        printf("\x1B[KQUERIES/SEC: %lu\n", n_queries / duration);
        printf("\x1B[KROWS/SEC:    %lu\n", n_rows / duration);
        printf("\x1B[KERRORS:      %lu\r", n_errors);
        if (hg != NULL) {
            hg->write();
        }
        fflush(stdout);

        n_queries = 0;
        n_rows = 0;
    }

    size_t n_rows;
    size_t n_queries;
    size_t n_errors;
    time_t last_update;
    cbc::Histogram *hg;
#ifndef _WIN32
    pthread_mutex_t m_lock;
#endif
};

Metrics GlobalMetrics;

class Configuration
{
public:
    Configuration() : o_file("queryfile"), o_threads("num-threads") {
        o_file.mandatory(true);
        o_file.description(
            "Path to a file containing all the queries to execute. "
            "Each line should contain the full query body");
        o_file.abbrev('f');

        o_threads.description("Number of threads to run");
        o_threads.abbrev('t');
        o_threads.setDefault(1);
    }

    void addToParser(Parser& parser)
    {
        parser.addOption(o_file);
        parser.addOption(o_threads);
        m_params.addToParser(parser);
    }

    void processOptions()
    {
        std::ifstream ifs(o_file.const_result().c_str());
        if (!ifs.is_open()) {
            int ec_save = errno;
            string errstr(o_file.const_result());
            errstr += ": ";
            errstr += strerror(ec_save);
            throw std::runtime_error(errstr);
        }

        string curline;
        while (std::getline(ifs, curline).good() && !ifs.eof()) {
            m_queries.push_back(curline);
        }
        if (m_params.useTimings()) {
            GlobalMetrics.prepare_timings();
        }
    }

    void set_cropts(lcb_create_st &opts) { m_params.fillCropts(opts); }
    const vector<string>& queries() const { return m_queries; }
    size_t nthreads() { return o_threads.result(); }

private:
    vector<string> m_queries;
    StringOption o_file;
    UIntOption o_threads;
    ConnParams m_params;
};

extern "C" { static void n1qlcb(lcb_t, int, const lcb_RESPN1QL *resp); }
extern "C" { static void* pthrfunc(void*); }

class ThreadContext;
struct QueryContext {
    lcb_U64 begin;
    bool received; // whether any row was received
    ThreadContext *ctx; // Parent

    QueryContext(ThreadContext *tctx)
    : begin(lcb_nstime()), received(false), ctx(tctx) {}
};

class ThreadContext {
public:
    void run()
    {
        while (!m_cancelled) {
            vector<string>::const_iterator ii = m_queries.begin();
            for (; ii != m_queries.end(); ++ii) {
                run_one_query(*ii);
            }
        }
    }

#ifndef _WIN32
    void start()
    {
        assert(m_thr == NULL);
        m_thr = new pthread_t;
        int rc = pthread_create(m_thr, NULL, pthrfunc, this);
        if (rc != 0) {
            throw std::runtime_error(strerror(rc));
        }
    }

    void join()
    {
        assert(m_thr != NULL);
        void *arg = NULL;
        pthread_join(*m_thr, &arg);
    }

    ~ThreadContext()
    {
        if (m_thr != NULL) {
            join();
            delete m_thr;
            m_thr = NULL;
        }
    }
#else
    void start() { run(); }
    void join() {}
#endif

    void handle_response(const lcb_RESPN1QL *resp, QueryContext *ctx)
    {
        if (!ctx->received) {
            lcb_U64 duration = lcb_nstime() - ctx->begin;
            m_metrics->lock();
            m_metrics->update_timings(duration);
            m_metrics->unlock();

            ctx->received = true;
        }

        if (resp->rflags & LCB_RESP_F_FINAL) {
            if (resp->rc != LCB_SUCCESS) {
                log_error(resp->rc);
            }
        } else {
            last_nrow++;
        }
    }

    ThreadContext(lcb_t instance, const vector<string>& initial_queries)
    : m_instance(instance), last_nerr(0), last_nrow(0),
      m_metrics(&GlobalMetrics), m_cancelled(false), m_thr(NULL)
    {
        memset(&m_cmd, 0, sizeof m_cmd);
        m_cmd.content_type = "application/json";
        m_cmd.callback = n1qlcb;

        // Shuffle the list
        m_queries = initial_queries;
        std::random_shuffle(m_queries.begin(), m_queries.end());
    }

private:

    void log_error(lcb_error_t)
    {
        m_metrics->lock();
        m_metrics->update_error();
        m_metrics->unlock();
    }

    void run_one_query(const string& txt)
    {
        // Reset counters
        last_nrow = 0;
        last_nerr = 0;

        m_cmd.query = txt.c_str();
        m_cmd.nquery = txt.size();

        // Set up our context
        QueryContext qctx(this);

        lcb_error_t rc = lcb_n1ql_query(m_instance, &qctx, &m_cmd);
        if (rc != LCB_SUCCESS) {
            log_error(rc);
        } else {
            lcb_wait(m_instance);
            m_metrics->lock();
            m_metrics->update_row(last_nrow);
            m_metrics->update_done(1);
            m_metrics->unlock();
        }
    }

    lcb_t m_instance;
    vector<string> m_queries;
    size_t last_nerr;
    size_t last_nrow;
    lcb_CMDN1QL m_cmd;
    Metrics *m_metrics;
    volatile bool m_cancelled;
    #ifndef _WIN32
    pthread_t *m_thr;
    #else
    void *m_thr;
    #endif
};

static void n1qlcb(lcb_t, int, const lcb_RESPN1QL *resp)
{
    QueryContext *qctx = reinterpret_cast<QueryContext*>(resp->cookie);
    qctx->ctx->handle_response(resp, qctx);
}

static void* pthrfunc(void *arg)
{
    reinterpret_cast<ThreadContext*>(arg)->run();
    return NULL;
}

static bool
instance_has_n1ql(lcb_t instance) {
    // Check that the instance supports N1QL
    lcbvb_CONFIG *vbc;
    do_or_die(lcb_cntl(instance, LCB_CNTL_GET, LCB_CNTL_VBCONFIG, &vbc));

    int sslmode = 0;
    lcbvb_SVCMODE svcmode = LCBVB_SVCMODE_PLAIN;

    do_or_die(lcb_cntl(instance, LCB_CNTL_GET, LCB_CNTL_SSL_MODE, &sslmode));

    if (sslmode & LCB_SSL_ENABLED) {
        svcmode = LCBVB_SVCMODE_SSL;
    }

    int hix = lcbvb_get_randhost(vbc, LCBVB_SVCTYPE_N1QL, svcmode);
    return hix > -1;
}

static void real_main(int argc, char **argv) {
    Configuration config;
    Parser parser;
    config.addToParser(parser);
    parser.parse(argc, argv);

    vector<ThreadContext*> threads;
    vector<lcb_t> instances;

    lcb_create_st cropts = { 0 };
    config.set_cropts(cropts);
    config.processOptions();

    for (size_t ii = 0; ii < config.nthreads(); ii++) {
        lcb_t instance;
        do_or_die(lcb_create(&instance, &cropts));
        do_or_die(lcb_connect(instance));
        lcb_wait(instance);
        do_or_die(lcb_get_bootstrap_status(instance));

        if (ii == 0 && !instance_has_n1ql(instance)) {
            throw std::runtime_error("Cluster does not support N1QL!");
        }

        ThreadContext* cx = new ThreadContext(instance, config.queries());
        threads.push_back(cx);
        instances.push_back(instance);
    }

    GlobalMetrics.prepare_screen();

    for (size_t ii = 0; ii < threads.size(); ++ii) {
        threads[ii]->start();
    }
    for (size_t ii = 0; ii < threads.size(); ++ii) {
        threads[ii]->join();
    }
    for (size_t ii = 0; ii < instances.size(); ++ii) {
        lcb_destroy(instances[ii]);
    }
}

int main(int argc, char **argv)
{
    try {
        real_main(argc, argv);
        return 0;
    } catch (std::exception& exc) {
        cerr << exc.what() << endl;
        exit(EXIT_FAILURE);
    }
}
<|endoftext|>


<commit_before>#include "fileCache.h"
#include "glog/logging.h"
#include "helpers/storageHelperFactory.h"

#define MAX_BLOCK_SIZE 10

namespace veil {
namespace helpers {

using namespace std;

FileCache::FileCache(uint32_t blockSize, bool isBuffer)
  : m_byteSize(0),
    m_isBuffer(isBuffer),
    m_curBlockNo(1),
    m_blockSize(blockSize)
{
}

FileCache::~FileCache()
{
}

bool FileCache::readData(off_t offset, size_t size, std::string &buff)
{
    boost::unique_lock<boost::recursive_mutex> guard(m_fileBlocksMutex);
    debugPrint();
    discardExpired();
    buff.resize(0);

    list<block_ptr>::const_iterator it = upper_bound(m_fileBlocks.begin(), m_fileBlocks.end(), offset, OrderByOffset);

    if(it == m_fileBlocks.begin())
        return false;

    for(--it; it != m_fileBlocks.end() && buff.size() < size; ++it)
    {
        if((*it)->offset > offset + buff.size())
            break;

        off_t startFrom = offset + buff.size() - (*it)->offset;
        if(startFrom < (*it)->size) {
            buff += (*it)->data.substr( startFrom ,  min( (size_t)size - buff.size(), (size_t)startFrom - (*it)->size ));
        }
    }

    return buff.size() > 0;
}

bool FileCache::writeData(off_t offset, const std::string &buff)
{
    boost::unique_lock<boost::recursive_mutex> guard(m_fileBlocksMutex);

    discardExpired();

    FileBlock block(offset, buff);

    return insertBlock(block);
}

void FileCache::debugPrint()
{
    return;
    cout << "BlockList:" << endl;
    list<block_ptr>::iterator it = m_fileBlocks.begin();
    while(it != m_fileBlocks.end())
    {
        printf("\t Offset: %d, Size: %d, Data: %s, valid_to: %lld\n", (*it)->offset, (*it)->size, (*it)->data.c_str(), (*it)->valid_to);
        ++it;
    }
}

block_ptr FileCache::removeOldestBlock()
{
    boost::unique_lock<boost::recursive_mutex> guard(m_fileBlocksMutex);

    if(m_blockExpire.empty())
        return block_ptr();

    discardExpired();

    // cout << "Queue: " << m_blockExpire.size() << endl;

    block_ptr tmp = *m_blockExpire.begin();
    m_blockExpire.erase(m_blockExpire.begin());
    m_fileBlocks.remove(tmp);

    m_byteSize -= tmp->size;

    return tmp;
}

bool FileCache::insertBlock(const FileBlock &block)
{
    boost::unique_lock<boost::recursive_mutex> guard(m_fileBlocksMutex);

    discardExpired();

    string cBuff = block.data;
    off_t offset = block.offset;

    do
    {
        // cout << "do..." << endl;
        list<block_ptr>::iterator it = upper_bound(m_fileBlocks.begin(), m_fileBlocks.end(), offset, OrderByOffset);
        list<block_ptr>::iterator next;
        // cout << "UpperBound: " << offset << " " << cBuff << endl;
        if(it != m_fileBlocks.begin())
            --it;

        while(it != m_fileBlocks.end() && cBuff.size() > 0)
        {
            next = it;
            if((*it)->offset <= offset)
                ++next;

            // cout << "FileCache: dbg_in: offset(" << offset << "), (*it)->offset(" << (*it)->offset << "), (*next)->offset(" << ( next != m_fileBlocks.end() ? (*next)->offset : -1) << ")" << endl;

            if( ((*it)->offset < offset && (*it)->offset + (*it)->size <= offset) || ((*it)->offset > offset) )
            {
                size_t tmpSize = next == m_fileBlocks.end() ? cBuff.size() : min((size_t)((*next)->offset - offset ), cBuff.size());
                block_ptr tmp = block_ptr(new FileBlock(offset, cBuff.substr(0, tmpSize)));
                // cout << "FileCache: ?: offset(" << offset << "), size(" << tmpSize << "), buff(" << cBuff.substr(0, tmpSize) << ")" << endl;
                // cout << "FileCache: dbg: offset(" << offset << "), (*it)->offset(" << (*it)->offset << "), (*next)->offset(" << ( next != m_fileBlocks.end() ? (*next)->offset : -1)<< ")" << endl;

                // cout << cBuff.size() << endl;
                cBuff = cBuff.substr(tmpSize);
                offset += tmpSize;

                forceInsertBlock(tmp, next);

                break;
            }
            else if ( (*it)->offset <= offset && (*it)->offset + (*it)->size > offset)
            {
                off_t tStart = offset - (*it)->offset;
                off_t sStart = 0;
                size_t toCpy = min( (size_t)((*it)->offset + (*it)->size - offset), cBuff.size() );
                // cout << "FileCache: override: offset(" << offset << "), size(" << toCpy << "), buff(" << cBuff.substr(0, toCpy) << ")" << endl;

                (*it)->data.replace(tStart, toCpy, cBuff.substr(0, toCpy));
                cBuff = cBuff.substr(toCpy);
                offset += toCpy;

                //continue;
            }

            ++it;
        }

        if(it == m_fileBlocks.end())
        {
            // cout << "it is at the end" << endl;
            block_ptr tmp = block_ptr(new FileBlock(offset, cBuff));
            forceInsertBlock(tmp, it);

            // cout << "FileCache: push_back: offset(" << offset << "), size(" << cBuff.size() << "), buff(" << cBuff << ")" << endl;
            cBuff = "";

        }

    } while (cBuff.size() > 0);

    return true;
}

void FileCache::forceInsertBlock(block_ptr block, std::list<block_ptr>::iterator whereTo)
{
    boost::unique_lock<boost::recursive_mutex> guard(m_fileBlocksMutex);

    if(block->valid_to == 0)
        block->valid_to = m_isBuffer ? ++m_curBlockNo : utils::mtime<uint64_t>();

    list<block_ptr>::iterator it, next, origNext;
    it = next = origNext = m_fileBlocks.insert(whereTo, block);
    m_blockExpire.insert(block);
    m_byteSize += block->size;

    // cout << "Insert: " << block->data << endl;
    debugPrint();

    if(m_blockExpire.size() == 1)
        return;

    if(it != m_fileBlocks.begin()){
        --it;
    } else {
        ++next;
    }

    ++origNext;

    do {
        if((*it)->offset + (*it)->size == (*next)->offset && (*it)->size < m_blockSize)
        {
            size_t toCpy = min(m_blockSize - (*it)->size, (*next)->size);
            (*it)->data += (*next)->data.substr(0, toCpy);
            (*next)->data = (*next)->data.substr(toCpy);
            (*next)->size = (*next)->data.size();
            (*next)->offset += toCpy;
            (*it)->size += toCpy;

            if((*next)->size == 0) {
                m_blockExpire.erase(*next);
                next = m_fileBlocks.erase(next);

            }
        } else if(next != origNext) {
            break;
        } else {
            ++it, ++next;
        }

    } while(it != m_fileBlocks.end() && next != m_fileBlocks.end());
}

size_t FileCache::byteSize()
{
    boost::unique_lock<boost::recursive_mutex> guard(m_fileBlocksMutex);
    return m_byteSize;
}

size_t FileCache::blockCount()
{
    boost::unique_lock<boost::recursive_mutex> guard(m_fileBlocksMutex);
    return m_fileBlocks.size();
}

void FileCache::discardExpired(bool rebuildQueue)
{
    boost::unique_lock<boost::recursive_mutex> guard(m_fileBlocksMutex);

    while(!m_blockExpire.empty())
    {
        block_ptr tmp;
        if(m_blockExpire.begin() != m_blockExpire.end())
            tmp = *m_blockExpire.begin();

        if(!tmp || (!m_isBuffer && tmp->valid_to < utils::mtime<uint64_t>() ) ) {
            list<block_ptr>::iterator it = upper_bound(m_fileBlocks.begin(), m_fileBlocks.end(), tmp->offset, OrderByOffset);
            while(it != m_fileBlocks.begin() && (*it)->offset >= tmp->offset) {
                if((*it) == tmp)
                {
                    m_fileBlocks.erase(it);
                    m_byteSize -= tmp->size;
                    break;
                }
                --it;
            }

            m_blockExpire.erase(m_blockExpire.begin());
        } else {
            break;
        }

    }
}

} // namespace helpers
} // namespace veil
<commit_msg>VFS-292: improve read speed<commit_after>#include "fileCache.h"
#include "glog/logging.h"
#include "helpers/storageHelperFactory.h"

#define MAX_BLOCK_SIZE 10

namespace veil {
namespace helpers {

using namespace std;

FileCache::FileCache(uint32_t blockSize, bool isBuffer)
  : m_byteSize(0),
    m_isBuffer(isBuffer),
    m_curBlockNo(1),
    m_blockSize(blockSize)
{
}

FileCache::~FileCache()
{
}

bool FileCache::readData(off_t offset, size_t size, std::string &buff)
{
    boost::unique_lock<boost::recursive_mutex> guard(m_fileBlocksMutex);
    debugPrint();
    discardExpired();
    buff.resize(0);

    list<block_ptr>::const_iterator it = upper_bound(m_fileBlocks.begin(), m_fileBlocks.end(), offset, OrderByOffset);

    if(it == m_fileBlocks.begin())
        return false;

    for(--it; it != m_fileBlocks.end() && buff.size() < size; ++it)
    {
        if((*it)->offset > offset + buff.size())
            break;

        off_t startFrom = offset + buff.size() - (*it)->offset;
        if(startFrom < (*it)->size) {
            buff += (*it)->data.substr( startFrom ,  min( (size_t)size - buff.size(), (size_t)startFrom - (*it)->size ));
        }
    }

    return buff.size() > 0;
}

bool FileCache::writeData(off_t offset, const std::string &buff)
{
    boost::unique_lock<boost::recursive_mutex> guard(m_fileBlocksMutex);

    discardExpired();

    FileBlock block(offset, buff);

    return insertBlock(block);
}

void FileCache::debugPrint()
{
    return;
    cout << "BlockList:" << endl;
    list<block_ptr>::iterator it = m_fileBlocks.begin();
    while(it != m_fileBlocks.end())
    {
        printf("\t Offset: %d, Size: %d, Data: %s, valid_to: %lld\n", (*it)->offset, (*it)->size, (*it)->data.c_str(), (*it)->valid_to);
        ++it;
    }
}

block_ptr FileCache::removeOldestBlock()
{
    boost::unique_lock<boost::recursive_mutex> guard(m_fileBlocksMutex);

    if(m_blockExpire.empty())
        return block_ptr();

    discardExpired();

    // cout << "Queue: " << m_blockExpire.size() << endl;

    block_ptr tmp = *m_blockExpire.begin();
    m_blockExpire.erase(m_blockExpire.begin());
    m_fileBlocks.remove(tmp);

    m_byteSize -= tmp->size;

    return tmp;
}

bool FileCache::insertBlock(const FileBlock &block)
{
    boost::unique_lock<boost::recursive_mutex> guard(m_fileBlocksMutex);

    discardExpired();

    string cBuff = block.data;
    off_t offset = block.offset;

    do
    {
        // cout << "do..." << endl;
        list<block_ptr>::iterator it = upper_bound(m_fileBlocks.begin(), m_fileBlocks.end(), offset, OrderByOffset);
        list<block_ptr>::iterator next;
        // cout << "UpperBound: " << offset << " " << cBuff << endl;
        if(it != m_fileBlocks.begin())
            --it;

        while(it != m_fileBlocks.end() && cBuff.size() > 0)
        {
            next = it;
            if((*it)->offset <= offset)
                ++next;

            // cout << "FileCache: dbg_in: offset(" << offset << "), (*it)->offset(" << (*it)->offset << "), (*next)->offset(" << ( next != m_fileBlocks.end() ? (*next)->offset : -1) << ")" << endl;

            if( ((*it)->offset < offset && (*it)->offset + (*it)->size <= offset) || ((*it)->offset > offset) )
            {
                size_t tmpSize = next == m_fileBlocks.end() ? cBuff.size() : min((size_t)((*next)->offset - offset ), cBuff.size());
                block_ptr tmp = block_ptr(new FileBlock(offset, cBuff.substr(0, tmpSize)));
                // cout << "FileCache: ?: offset(" << offset << "), size(" << tmpSize << "), buff(" << cBuff.substr(0, tmpSize) << ")" << endl;
                // cout << "FileCache: dbg: offset(" << offset << "), (*it)->offset(" << (*it)->offset << "), (*next)->offset(" << ( next != m_fileBlocks.end() ? (*next)->offset : -1)<< ")" << endl;

                // cout << cBuff.size() << endl;
                cBuff = cBuff.substr(tmpSize);
                offset += tmpSize;

                forceInsertBlock(tmp, next);

                break;
            }
            else if ( (*it)->offset <= offset && (*it)->offset + (*it)->size > offset)
            {
                off_t tStart = offset - (*it)->offset;
                off_t sStart = 0;
                size_t toCpy = min( (size_t)((*it)->offset + (*it)->size - offset), cBuff.size() );
                // cout << "FileCache: override: offset(" << offset << "), size(" << toCpy << "), buff(" << cBuff.substr(0, toCpy) << ")" << endl;

                (*it)->data.replace(tStart, toCpy, cBuff.substr(0, toCpy));
                cBuff = cBuff.substr(toCpy);
                offset += toCpy;

                //continue;
            }

            ++it;
        }

        if(it == m_fileBlocks.end())
        {
            // cout << "it is at the end" << endl;
            block_ptr tmp = block_ptr(new FileBlock(offset, cBuff));
            forceInsertBlock(tmp, it);

            // cout << "FileCache: push_back: offset(" << offset << "), size(" << cBuff.size() << "), buff(" << cBuff << ")" << endl;
            cBuff = "";

        }

    } while (cBuff.size() > 0);

    return true;
}

void FileCache::forceInsertBlock(block_ptr block, std::list<block_ptr>::iterator whereTo)
{
    boost::unique_lock<boost::recursive_mutex> guard(m_fileBlocksMutex);

    if(block->valid_to == 0)
        block->valid_to = m_isBuffer ? ++m_curBlockNo : utils::mtime<uint64_t>();

    list<block_ptr>::iterator it, next, origNext;
    it = next = origNext = m_fileBlocks.insert(whereTo, block);
    m_blockExpire.insert(block);
    m_byteSize += block->size;

    // cout << "Insert: " << block->data << endl;
    debugPrint();

    if(m_blockExpire.size() == 1)
        return;

    if(it != m_fileBlocks.begin()){
        --it;
    } else {
        ++next;
    }

    ++origNext;

    do {
        if((*it)->offset + (*it)->size == (*next)->offset && (*it)->size < m_blockSize)
        {
            size_t toCpy = min(m_blockSize - (*it)->size, (*next)->size);
            (*it)->data += (*next)->data.substr(0, toCpy);
            (*next)->data = (*next)->data.substr(toCpy);
            (*next)->size = (*next)->data.size();
            (*next)->offset += toCpy;
            (*it)->size += toCpy;

            if((*next)->size == 0) {
                m_blockExpire.erase(*next);
                next = m_fileBlocks.erase(next);

            }
        } else if(next != origNext) {
            break;
        } else {
            ++it, ++next;
        }

    } while(it != m_fileBlocks.end() && next != m_fileBlocks.end());
}

size_t FileCache::byteSize()
{
    boost::unique_lock<boost::recursive_mutex> guard(m_fileBlocksMutex);
    return m_byteSize;
}

size_t FileCache::blockCount()
{
    boost::unique_lock<boost::recursive_mutex> guard(m_fileBlocksMutex);
    return m_fileBlocks.size();
}

void FileCache::discardExpired(bool rebuildQueue)
{
    boost::unique_lock<boost::recursive_mutex> guard(m_fileBlocksMutex);

    while(!m_blockExpire.empty())
    {
        block_ptr tmp;
        if(m_blockExpire.begin() != m_blockExpire.end())
            tmp = *m_blockExpire.begin();

        if(tmp && (!m_isBuffer && tmp->valid_to < utils::mtime<uint64_t>() ) ) {
            list<block_ptr>::iterator it = upper_bound(m_fileBlocks.begin(), m_fileBlocks.end(), tmp->offset, OrderByOffset);
            while(it != m_fileBlocks.begin() && (*it)->offset >= tmp->offset) {
                if((*it) == tmp)
                {
                    m_fileBlocks.erase(it);
                    m_byteSize -= tmp->size;
                    break;
                }
                --it;
            }

            m_blockExpire.erase(m_blockExpire.begin());
        } else {
            break;
        }

    }
}

} // namespace helpers
} // namespace veil
<|endoftext|>