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

#include "NetIO/Lobby.h"
#include "NetIO/CryptIO.h"
#include "GateKeeper/GateServ.h"
#include "FileServ/FileServer.h"
#include "AuthServ/AuthServer.h"
#include "GameServ/GameServer.h"
#include "SDL/DescriptorDb.h"
#include "strings.h"
#include "errors.h"
#include "settings.h"
#include "encodings.h"
#include <readline.h>
#include <history.h>
#include <signal.h>
#include <execinfo.h>
#include <cstdio>

#ifdef DEBUG
extern bool s_commdebug;
#endif

static char** dup_strlist(const char* text, const char** strlist, size_t count)
{
    char** dupe;
    if (count == 1) {
        dupe = reinterpret_cast<char**>(malloc(sizeof(char*) * 2));
        dupe[0] = strdup(strlist[0]);
        dupe[1] = 0;
    } else {
        dupe = reinterpret_cast<char**>(malloc(sizeof(char*) * (count + 2)));
        dupe[0] = strdup(text);
        for (size_t i=0; i<count; ++i)
            dupe[i+1] = strdup(strlist[i]);
        dupe[count+1] = 0;
    }
    return dupe;
}

static char** console_completer(const char* text, int start, int end)
{
    static const char* completions[] = {
        /* Commands */
        "clients", "commdebug", "help", "keygen", "quit", "restart",
        /* Services */
        "auth", "lobby",
    };

    rl_attempted_completion_over = true;
    if (strlen(text) == 0)
        return dup_strlist(text, completions, sizeof(completions) / sizeof(completions[0]));

    std::vector<const char*> matches;
    for (size_t i=0; i<sizeof(completions) / sizeof(completions[0]); ++i) {
        if (strncmp(text, completions[i], strlen(text)) == 0)
            matches.push_back(completions[i]);
    }
    if (matches.size() == 0)
        return 0;
    return dup_strlist(text, matches.data(), matches.size());
}

static void print_trace(const char* text)
{
    const size_t max_depth = 100;
    size_t stack_depth;
    void* stack_addrs[max_depth];
    char** stack_strings;

    stack_depth = backtrace(stack_addrs, max_depth);
    stack_strings = backtrace_symbols(stack_addrs, stack_depth);

    fprintf(stderr, "%s at %s\n", text, stack_strings[0]);
    for (size_t i=1; i<stack_depth; ++i)
        fprintf(stderr, "    from %s\n", stack_strings[i]);
    free(stack_strings);
}

static void sigh_segv(int)
{
    print_trace("Segfault");
    abort();
}

static void exception_filter()
{
    print_trace("Unhandled exception");
    abort();
}

int main(int argc, char* argv[])
{
    if (argc == 1) {
        fprintf(stderr, "Warning: No config file specified. Using defaults...\n");
        DS::Settings::UseDefaults();
    } else if (!DS::Settings::LoadFrom(argv[1])) {
        return 1;
    }

    // Show a stackdump in case we crash
    std::set_terminate(&exception_filter);
    signal(SIGSEGV, &sigh_segv);

    // Ignore sigpipe and force send() to return EPIPE
    signal(SIGPIPE, SIG_IGN);

    SDL::DescriptorDb::LoadDescriptors(DS::Settings::SdlPath());
    DS::FileServer_Init();
    DS::AuthServer_Init();
    DS::GameServer_Init();
    DS::GateKeeper_Init();
    DS::StartLobby();

    char* cmdbuf = 0;
    rl_attempted_completion_function = &console_completer;
    for ( ;; ) {
        cmdbuf = readline("");
        if (!cmdbuf)
            break;

        std::vector<DS::String> args = DS::String(cmdbuf).strip('#').split();
        if (args.size() == 0) {
            free(cmdbuf);
            continue;
        }
        add_history(cmdbuf);
        free(cmdbuf);

        if (args[0] == "quit") {
            break;
        } else if (args[0] == "restart") {
            if (args.size() < 2) {
                fprintf(stderr, "Error: No services specified\n");
                continue;
            }
            for (std::vector<DS::String>::iterator svc = args.begin() + 1;
                 svc != args.end(); ++svc) {
                if (*svc == "lobby") {
                    DS::StopLobby();
                    DS::StartLobby();
                } else if (*svc == "auth") {
                    DS::AuthServer_Shutdown();
                    DS::AuthServer_Init();
                    printf("Auth server restarted\n");
                } else {
                    fprintf(stderr, "Error: Service %s cannot be restarted\n", svc->c_str());
                }
            }
        } else if (args[0] == "keygen") {
            uint8_t xbuffer[64];
            if (args.size() != 2) {
                fprintf(stderr, "Please specify new, ue or pc\n");
            } else if (args[1] == "new") {
                uint8_t nbuffer[3][64], kbuffer[3][64];
                printf("Generating new server keys...  This will take a while.");
                fflush(stdout);
                for (size_t i=0; i<3; ++i)
                    DS::GenPrimeKeys(nbuffer[i], kbuffer[i]);

                printf("\n--------------------\n");
                printf("Server keys:\n");
                printf("Key.Auth.N = %s\n", DS::Base64Encode(nbuffer[0], 64).c_str());
                printf("Key.Auth.K = %s\n", DS::Base64Encode(kbuffer[0], 64).c_str());
                printf("Key.Game.N = %s\n", DS::Base64Encode(nbuffer[1], 64).c_str());
                printf("Key.Game.K = %s\n", DS::Base64Encode(kbuffer[1], 64).c_str());
                printf("Key.Gate.N = %s\n", DS::Base64Encode(nbuffer[2], 64).c_str());
                printf("Key.Gate.K = %s\n", DS::Base64Encode(kbuffer[2], 64).c_str());

                printf("--------------------\n");
                printf("UruExplorer:\n");
                printf("Auth client keys:\n");
                DS::CryptCalcX(xbuffer, nbuffer[0], kbuffer[0], CRYPT_BASE_AUTH);
                DS::PrintClientKeys(xbuffer, nbuffer[0]);

                printf("Game client keys:\n");
                DS::CryptCalcX(xbuffer, nbuffer[1], kbuffer[1], CRYPT_BASE_GAME);
                DS::PrintClientKeys(xbuffer, nbuffer[1]);

                printf("GateKeeper client keys:\n");
                DS::CryptCalcX(xbuffer, nbuffer[2], kbuffer[2], CRYPT_BASE_GATE);
                DS::PrintClientKeys(xbuffer, nbuffer[2]);

                printf("--------------------\n");
                printf("PlasmaClient:\n");
                DS::CryptCalcX(xbuffer, nbuffer[0], kbuffer[0], CRYPT_BASE_AUTH);
                printf("Server.Auth.N %s\n", DS::Base64Encode(nbuffer[0], 64).c_str());
                printf("Server.Auth.X %s\n", DS::Base64Encode(xbuffer, 64).c_str());
                DS::CryptCalcX(xbuffer, nbuffer[1], kbuffer[1], CRYPT_BASE_GAME);
                printf("Server.Game.N %s\n", DS::Base64Encode(nbuffer[1], 64).c_str());
                printf("Server.Game.X %s\n", DS::Base64Encode(xbuffer, 64).c_str());
                DS::CryptCalcX(xbuffer, nbuffer[2], kbuffer[2], CRYPT_BASE_GATE);
                printf("Server.Gate.N %s\n", DS::Base64Encode(nbuffer[2], 64).c_str());
                printf("Server.Gate.X %s\n", DS::Base64Encode(xbuffer, 64).c_str());
                printf("--------------------\n");
            } else if (args[1] == "ue") {
                uint8_t xbuffer[64];
                DS::CryptCalcX(xbuffer, DS::Settings::CryptKey(DS::e_KeyAuth_N),
                               DS::Settings::CryptKey(DS::e_KeyAuth_K), CRYPT_BASE_AUTH);
                printf("Auth client keys:\n");
                DS::PrintClientKeys(xbuffer, DS::Settings::CryptKey(DS::e_KeyAuth_N));

                DS::CryptCalcX(xbuffer, DS::Settings::CryptKey(DS::e_KeyGame_N),
                               DS::Settings::CryptKey(DS::e_KeyGame_K), CRYPT_BASE_GAME);
                printf("Game client keys:\n");
                DS::PrintClientKeys(xbuffer, DS::Settings::CryptKey(DS::e_KeyGame_N));

                DS::CryptCalcX(xbuffer, DS::Settings::CryptKey(DS::e_KeyGate_N),
                               DS::Settings::CryptKey(DS::e_KeyGate_K), CRYPT_BASE_GATE);
                printf("GateKeeper client keys:\n");
                DS::PrintClientKeys(xbuffer, DS::Settings::CryptKey(DS::e_KeyGate_N));
            } else if (args[1] == "pc") {
                DS::CryptCalcX(xbuffer, DS::Settings::CryptKey(DS::e_KeyAuth_N),
                               DS::Settings::CryptKey(DS::e_KeyAuth_K), CRYPT_BASE_AUTH);
                printf("Server.Auth.N %s\n", DS::Base64Encode(DS::Settings::CryptKey(DS::e_KeyAuth_N), 64).c_str());
                printf("Server.Auth.X %s\n", DS::Base64Encode(xbuffer, 64).c_str());
                DS::CryptCalcX(xbuffer, DS::Settings::CryptKey(DS::e_KeyGame_N),
                               DS::Settings::CryptKey(DS::e_KeyGame_K), CRYPT_BASE_GAME);
                printf("Server.Game.N %s\n", DS::Base64Encode(DS::Settings::CryptKey(DS::e_KeyGame_N), 64).c_str());
                printf("Server.Game.X %s\n", DS::Base64Encode(xbuffer, 64).c_str());
                DS::CryptCalcX(xbuffer, DS::Settings::CryptKey(DS::e_KeyGate_N),
                               DS::Settings::CryptKey(DS::e_KeyGate_K), CRYPT_BASE_GATE);
                printf("Server.Gate.N %s\n", DS::Base64Encode(DS::Settings::CryptKey(DS::e_KeyGate_N), 64).c_str());
                printf("Server.Gate.X %s\n", DS::Base64Encode(xbuffer, 64).c_str());
            } else {
                fprintf(stderr, "Error: %s is not a valid keygen target\n", args[1].c_str());
                continue;
            }
        } else if (args[0] == "clients") {
            DS::GateKeeper_DisplayClients();
            DS::FileServer_DisplayClients();
            DS::AuthServer_DisplayClients();
            DS::GameServer_DisplayClients();
        } else if (args[0] == "commdebug") {
#ifdef DEBUG
            if (args.size() == 1)
                printf("Comm debugging is currently %s\n", s_commdebug ? "on" : "off");
            else if (args[1] == "on")
                s_commdebug = true;
            else if (args[1] == "off")
                s_commdebug = false;
            else
                fprintf(stderr, "Error: must specify on or off\n");
#else
            fprintf(stderr, "Error: COMM debugging is only enabled in debug builds\n");
#endif
        } else if (args[0] == "help") {
            printf("DirtSand v1.0 Console supported commands:\n"
                   "    clients\n"
                   "    commdebug <on|off>\n"
                   "    help\n"
                   "    keygen <new|ue|pc>\n"
                   "    quit\n"
                   "    restart <auth|lobby>\n"
                  );
        } else {
            fprintf(stderr, "Error: Unrecognized command: %s\n", args[0].c_str());
        }
    }

    DS::StopLobby();
    DS::GateKeeper_Shutdown();
    DS::GameServer_Shutdown();
    DS::AuthServer_Shutdown();
    DS::FileServer_Shutdown();
    return 0;
}
<commit_msg>Change key output to the correct console command<commit_after>/******************************************************************************
 * This file is part of dirtsand.                                             *
 *                                                                            *
 * dirtsand is free software: you can redistribute it and/or modify           *
 * it under the terms of the GNU General Public License as published by       *
 * the Free Software Foundation, either version 3 of the License, or          *
 * (at your option) any later version.                                        *
 *                                                                            *
 * dirtsand is distributed in the hope that it will be useful,                *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
 * GNU General Public License for more details.                               *
 *                                                                            *
 * You should have received a copy of the GNU General Public License          *
 * along with dirtsand.  If not, see <http://www.gnu.org/licenses/>.          *
 ******************************************************************************/

#include "NetIO/Lobby.h"
#include "NetIO/CryptIO.h"
#include "GateKeeper/GateServ.h"
#include "FileServ/FileServer.h"
#include "AuthServ/AuthServer.h"
#include "GameServ/GameServer.h"
#include "SDL/DescriptorDb.h"
#include "strings.h"
#include "errors.h"
#include "settings.h"
#include "encodings.h"
#include <readline.h>
#include <history.h>
#include <signal.h>
#include <execinfo.h>
#include <cstdio>

#ifdef DEBUG
extern bool s_commdebug;
#endif

static char** dup_strlist(const char* text, const char** strlist, size_t count)
{
    char** dupe;
    if (count == 1) {
        dupe = reinterpret_cast<char**>(malloc(sizeof(char*) * 2));
        dupe[0] = strdup(strlist[0]);
        dupe[1] = 0;
    } else {
        dupe = reinterpret_cast<char**>(malloc(sizeof(char*) * (count + 2)));
        dupe[0] = strdup(text);
        for (size_t i=0; i<count; ++i)
            dupe[i+1] = strdup(strlist[i]);
        dupe[count+1] = 0;
    }
    return dupe;
}

static char** console_completer(const char* text, int start, int end)
{
    static const char* completions[] = {
        /* Commands */
        "clients", "commdebug", "help", "keygen", "quit", "restart",
        /* Services */
        "auth", "lobby",
    };

    rl_attempted_completion_over = true;
    if (strlen(text) == 0)
        return dup_strlist(text, completions, sizeof(completions) / sizeof(completions[0]));

    std::vector<const char*> matches;
    for (size_t i=0; i<sizeof(completions) / sizeof(completions[0]); ++i) {
        if (strncmp(text, completions[i], strlen(text)) == 0)
            matches.push_back(completions[i]);
    }
    if (matches.size() == 0)
        return 0;
    return dup_strlist(text, matches.data(), matches.size());
}

static void print_trace(const char* text)
{
    const size_t max_depth = 100;
    size_t stack_depth;
    void* stack_addrs[max_depth];
    char** stack_strings;

    stack_depth = backtrace(stack_addrs, max_depth);
    stack_strings = backtrace_symbols(stack_addrs, stack_depth);

    fprintf(stderr, "%s at %s\n", text, stack_strings[0]);
    for (size_t i=1; i<stack_depth; ++i)
        fprintf(stderr, "    from %s\n", stack_strings[i]);
    free(stack_strings);
}

static void sigh_segv(int)
{
    print_trace("Segfault");
    abort();
}

static void exception_filter()
{
    print_trace("Unhandled exception");
    abort();
}

int main(int argc, char* argv[])
{
    if (argc == 1) {
        fprintf(stderr, "Warning: No config file specified. Using defaults...\n");
        DS::Settings::UseDefaults();
    } else if (!DS::Settings::LoadFrom(argv[1])) {
        return 1;
    }

    // Show a stackdump in case we crash
    std::set_terminate(&exception_filter);
    signal(SIGSEGV, &sigh_segv);

    // Ignore sigpipe and force send() to return EPIPE
    signal(SIGPIPE, SIG_IGN);

    SDL::DescriptorDb::LoadDescriptors(DS::Settings::SdlPath());
    DS::FileServer_Init();
    DS::AuthServer_Init();
    DS::GameServer_Init();
    DS::GateKeeper_Init();
    DS::StartLobby();

    char* cmdbuf = 0;
    rl_attempted_completion_function = &console_completer;
    for ( ;; ) {
        cmdbuf = readline("");
        if (!cmdbuf)
            break;

        std::vector<DS::String> args = DS::String(cmdbuf).strip('#').split();
        if (args.size() == 0) {
            free(cmdbuf);
            continue;
        }
        add_history(cmdbuf);
        free(cmdbuf);

        if (args[0] == "quit") {
            break;
        } else if (args[0] == "restart") {
            if (args.size() < 2) {
                fprintf(stderr, "Error: No services specified\n");
                continue;
            }
            for (std::vector<DS::String>::iterator svc = args.begin() + 1;
                 svc != args.end(); ++svc) {
                if (*svc == "lobby") {
                    DS::StopLobby();
                    DS::StartLobby();
                } else if (*svc == "auth") {
                    DS::AuthServer_Shutdown();
                    DS::AuthServer_Init();
                    printf("Auth server restarted\n");
                } else {
                    fprintf(stderr, "Error: Service %s cannot be restarted\n", svc->c_str());
                }
            }
        } else if (args[0] == "keygen") {
            uint8_t xbuffer[64];
            if (args.size() != 2) {
                fprintf(stderr, "Please specify new, ue or pc\n");
            } else if (args[1] == "new") {
                uint8_t nbuffer[3][64], kbuffer[3][64];
                printf("Generating new server keys...  This will take a while.");
                fflush(stdout);
                for (size_t i=0; i<3; ++i)
                    DS::GenPrimeKeys(nbuffer[i], kbuffer[i]);

                printf("\n--------------------\n");
                printf("Server keys:\n");
                printf("Server.Auth.N = %s\n", DS::Base64Encode(nbuffer[0], 64).c_str());
                printf("Server.Auth.K = %s\n", DS::Base64Encode(kbuffer[0], 64).c_str());
                printf("Server.Game.N = %s\n", DS::Base64Encode(nbuffer[1], 64).c_str());
                printf("Server.Game.K = %s\n", DS::Base64Encode(kbuffer[1], 64).c_str());
                printf("Server.Gate.N = %s\n", DS::Base64Encode(nbuffer[2], 64).c_str());
                printf("Server.Gate.K = %s\n", DS::Base64Encode(kbuffer[2], 64).c_str());

                printf("--------------------\n");
                printf("UruExplorer:\n");
                printf("Auth client keys:\n");
                DS::CryptCalcX(xbuffer, nbuffer[0], kbuffer[0], CRYPT_BASE_AUTH);
                DS::PrintClientKeys(xbuffer, nbuffer[0]);

                printf("Game client keys:\n");
                DS::CryptCalcX(xbuffer, nbuffer[1], kbuffer[1], CRYPT_BASE_GAME);
                DS::PrintClientKeys(xbuffer, nbuffer[1]);

                printf("GateKeeper client keys:\n");
                DS::CryptCalcX(xbuffer, nbuffer[2], kbuffer[2], CRYPT_BASE_GATE);
                DS::PrintClientKeys(xbuffer, nbuffer[2]);

                printf("--------------------\n");
                printf("PlasmaClient:\n");
                DS::CryptCalcX(xbuffer, nbuffer[0], kbuffer[0], CRYPT_BASE_AUTH);
                printf("Server.Auth.N %s\n", DS::Base64Encode(nbuffer[0], 64).c_str());
                printf("Server.Auth.X %s\n", DS::Base64Encode(xbuffer, 64).c_str());
                DS::CryptCalcX(xbuffer, nbuffer[1], kbuffer[1], CRYPT_BASE_GAME);
                printf("Server.Game.N %s\n", DS::Base64Encode(nbuffer[1], 64).c_str());
                printf("Server.Game.X %s\n", DS::Base64Encode(xbuffer, 64).c_str());
                DS::CryptCalcX(xbuffer, nbuffer[2], kbuffer[2], CRYPT_BASE_GATE);
                printf("Server.Gate.N %s\n", DS::Base64Encode(nbuffer[2], 64).c_str());
                printf("Server.Gate.X %s\n", DS::Base64Encode(xbuffer, 64).c_str());
                printf("--------------------\n");
            } else if (args[1] == "ue") {
                uint8_t xbuffer[64];
                DS::CryptCalcX(xbuffer, DS::Settings::CryptKey(DS::e_KeyAuth_N),
                               DS::Settings::CryptKey(DS::e_KeyAuth_K), CRYPT_BASE_AUTH);
                printf("Auth client keys:\n");
                DS::PrintClientKeys(xbuffer, DS::Settings::CryptKey(DS::e_KeyAuth_N));

                DS::CryptCalcX(xbuffer, DS::Settings::CryptKey(DS::e_KeyGame_N),
                               DS::Settings::CryptKey(DS::e_KeyGame_K), CRYPT_BASE_GAME);
                printf("Game client keys:\n");
                DS::PrintClientKeys(xbuffer, DS::Settings::CryptKey(DS::e_KeyGame_N));

                DS::CryptCalcX(xbuffer, DS::Settings::CryptKey(DS::e_KeyGate_N),
                               DS::Settings::CryptKey(DS::e_KeyGate_K), CRYPT_BASE_GATE);
                printf("GateKeeper client keys:\n");
                DS::PrintClientKeys(xbuffer, DS::Settings::CryptKey(DS::e_KeyGate_N));
            } else if (args[1] == "pc") {
                DS::CryptCalcX(xbuffer, DS::Settings::CryptKey(DS::e_KeyAuth_N),
                               DS::Settings::CryptKey(DS::e_KeyAuth_K), CRYPT_BASE_AUTH);
                printf("Server.Auth.N %s\n", DS::Base64Encode(DS::Settings::CryptKey(DS::e_KeyAuth_N), 64).c_str());
                printf("Server.Auth.X %s\n", DS::Base64Encode(xbuffer, 64).c_str());
                DS::CryptCalcX(xbuffer, DS::Settings::CryptKey(DS::e_KeyGame_N),
                               DS::Settings::CryptKey(DS::e_KeyGame_K), CRYPT_BASE_GAME);
                printf("Server.Game.N %s\n", DS::Base64Encode(DS::Settings::CryptKey(DS::e_KeyGame_N), 64).c_str());
                printf("Server.Game.X %s\n", DS::Base64Encode(xbuffer, 64).c_str());
                DS::CryptCalcX(xbuffer, DS::Settings::CryptKey(DS::e_KeyGate_N),
                               DS::Settings::CryptKey(DS::e_KeyGate_K), CRYPT_BASE_GATE);
                printf("Server.Gate.N %s\n", DS::Base64Encode(DS::Settings::CryptKey(DS::e_KeyGate_N), 64).c_str());
                printf("Server.Gate.X %s\n", DS::Base64Encode(xbuffer, 64).c_str());
            } else {
                fprintf(stderr, "Error: %s is not a valid keygen target\n", args[1].c_str());
                continue;
            }
        } else if (args[0] == "clients") {
            DS::GateKeeper_DisplayClients();
            DS::FileServer_DisplayClients();
            DS::AuthServer_DisplayClients();
            DS::GameServer_DisplayClients();
        } else if (args[0] == "commdebug") {
#ifdef DEBUG
            if (args.size() == 1)
                printf("Comm debugging is currently %s\n", s_commdebug ? "on" : "off");
            else if (args[1] == "on")
                s_commdebug = true;
            else if (args[1] == "off")
                s_commdebug = false;
            else
                fprintf(stderr, "Error: must specify on or off\n");
#else
            fprintf(stderr, "Error: COMM debugging is only enabled in debug builds\n");
#endif
        } else if (args[0] == "help") {
            printf("DirtSand v1.0 Console supported commands:\n"
                   "    clients\n"
                   "    commdebug <on|off>\n"
                   "    help\n"
                   "    keygen <new|ue|pc>\n"
                   "    quit\n"
                   "    restart <auth|lobby>\n"
                  );
        } else {
            fprintf(stderr, "Error: Unrecognized command: %s\n", args[0].c_str());
        }
    }

    DS::StopLobby();
    DS::GateKeeper_Shutdown();
    DS::GameServer_Shutdown();
    DS::AuthServer_Shutdown();
    DS::FileServer_Shutdown();
    return 0;
}
<|endoftext|>


<commit_before>#include "macros.hpp"
#include "ConfigParser.hpp"
#include "FileUtils.hpp"
#include <string>
#include <vector>
#include <iostream>
#include <boost/program_options.hpp>
#include <boost/program_options/parsers.hpp>

namespace po = boost::program_options;
using std::string;
using std::vector;
using std::cout;
using std::endl;

COLD ConfigParser::ConfigParser(int argc, char** argv) {
    // Declare the supported options.
    po::options_description desc("Options");
    string configFileName;
    repEndpoints = {"tcp://localhost:7100","ipc:///tmp/yakserver-rep"};
    pullEndpoints = {"tcp://localhost:7101","ipc:///tmp/yakserver-pull"};
    subEndpoints = {"tcp://localhost:7102","ipc:///tmp/yakserver-sub"};
    desc.add_options()
        ("help", "Print help message")
        ("l,logfile", po::value<string>(&logFile)->default_value(""), "The file the log will be written to")
        ("c,config",
            po::value<string>(&configFileName)->default_value("yak.cfg"),
            "The configuration file to use")
        ("req-endpoint",
            po::value<vector<string> >(&repEndpoints),
            "The endpoints the REP backend will bind to.\nDefaults to tcp://localhost:7100, ipc:///tmp/yakserver-rep")
        ("pull-endpoint", po::value<vector<string> >(&pullEndpoints),
            "The endpoints the PULL backend will bind to.\nDefaults to tcp://localhost:7101, ipc:///tmp/yakserver-pull")
        ("sub-endpoint", po::value<vector<string> >(&pullEndpoints),
            "The endpoints the SUB backend will bind to.\nDefaults to tcp://localhost:7102, ipc:///tmp/yakserver-sub")
    ;

    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);
    po::notify(vm);
    //Parse the config file
    if(fexists(configFileName)) {
        po::store(po::parse_config_file<char>(configFileName.c_str(), desc, true), vm);
    }
    po::notify(vm);

    if (vm.count("help")) {
        cout << desc << endl;
        exit(1);
    }
}

const std::string& ConfigParser::getLogFile() {
    return logFile;
}

const std::vector<std::string>& ConfigParser::getREPEndpoints() {
    return repEndpoints;
}

const std::vector<std::string>& ConfigParser::getPullEndpoints() {
    return pullEndpoints;
}

const std::vector<std::string>& ConfigParser::getSubEndpoints() {
    return subEndpoints;
}<commit_msg>Started to add more config stuff<commit_after>#include "macros.hpp"
#include "ConfigParser.hpp"
#include "FileUtils.hpp"
#include <string>
#include <vector>
#include <iostream>
#include <boost/program_options.hpp>
#include <boost/program_options/parsers.hpp>

namespace po = boost::program_options;
using std::string;
using std::vector;
using std::cout;
using std::endl;

COLD ConfigParser::ConfigParser(int argc, char** argv) {
    // Declare the supported options.
    po::options_description desc("Options");
    string configFileName;
    repEndpoints = {"tcp://localhost:7100","ipc:///tmp/yakserver-rep"};
    pullEndpoints = {"tcp://localhost:7101","ipc:///tmp/yakserver-pull"};
    subEndpoints = {"tcp://localhost:7102","ipc:///tmp/yakserver-sub"};
    desc.add_options()
        ("help", "Print help message")
        ("logfile,l", po::value<string>(&logFile)->default_value(""), "The file the log will be written to")
        ("config,c",
            po::value<string>(&configFileName)->default_value("yak.cfg"),
            "The configuration file to use")
        ("req-endpoint",
            po::value<vector<string> >(&repEndpoints),
            "The endpoints the REP backend will bind to.\nDefaults to tcp://localhost:7100, ipc:///tmp/yakserver-rep")
        ("pull-endpoint", po::value<vector<string> >(&pullEndpoints),
            "The endpoints the PULL backend will bind to.\nDefaults to tcp://localhost:7101, ipc:///tmp/yakserver-pull")
        ("sub-endpoint", po::value<vector<string> >(&pullEndpoints),
            "The endpoints the SUB backend will bind to.\nDefaults to tcp://localhost:7102, ipc:///tmp/yakserver-sub")
    ;

    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);
    po::notify(vm);
    //Parse the config file
    if(fexists(configFileName)) {
        po::store(po::parse_config_file<char>(configFileName.c_str(), desc, true), vm);
    }
    po::notify(vm);

    if (vm.count("help")) {
        cout << desc << endl;
        exit(1);
    }
}

const std::string& ConfigParser::getLogFile() {
    return logFile;
}

const std::vector<std::string>& ConfigParser::getREPEndpoints() {
    return repEndpoints;
}

const std::vector<std::string>& ConfigParser::getPullEndpoints() {
    return pullEndpoints;
}

const std::vector<std::string>& ConfigParser::getSubEndpoints() {
    return subEndpoints;
}<|endoftext|>


<commit_before>#include <iostream>
#include <stdexcept>
#include <algorithm>
#include <vector>
#include "inventory.h"
#include "db.h"
#include "book.h"
using namespace std;

#define DEFAULT_INV_FILE "tools/books.db"

Inventory::Inventory()                 { m_db = NULL; }
Inventory::Inventory(DB::Database* db) { m_db = db;   }

Inventory::~Inventory() {
  if(m_db != NULL) delete m_db;
}

void Inventory::setDatabase(DB::Database* db) {
  try {
    if(db == NULL) throw domain_error("Argument is NULL");
    m_db = db;
    return;
  } catch(exception& e) {
    cerr << "Inventory::setDatabase: " << e.what() << endl;
    return;
  }
}

void Inventory::setDatabaseFile(string filename = DEFAULT_INV_FILE) {
  try {
    if(filename == "") throw domain_error("Argument is empty");
    m_dbFileName = filename;
    return;
  } catch(exception& e) {
    cerr << "Inventory::setDatabaseFile: " << e.what() << endl;
    return;
  }
}

// Mutators
bool Inventory::addBook(Book* book) {
  try {
    if(book == NULL) throw domain_error("Domain Error: Argument is NULL");

    // TODO: Issue #26: Should change quantity if book exists
    // Add book to list, for writing to file later
    m_addList.push_back(book);
  } catch(exception& e) {
    cerr << "Inventory::addBook: " << e.what() << endl;
  }
  return 0;
}

bool Inventory::updBook(Book* book) {
  try {
    vector<unsigned>::iterator first = m_deltaList.begin();
    vector<unsigned>::iterator last = m_deltaList.end();

    // if file index does not exist in delta list
    if(find(first, last, book->getFileIndex()) == last) {
      // Push index to delta list
      m_deltaList.push_back(book->getFileIndex());
    }
  } catch(exception& e) {
    cerr << "Inventory::updBook(): "  << e.what() << endl;
  }
  return 0;
}

bool Inventory::delBook(Book* book) {
  try {
    vector<unsigned>::iterator first = m_deleteList.begin();
    vector<unsigned>::iterator last = m_deleteList.end();

    // if file index does not exist in delete list
    if(find(first, last, book->getFileIndex()) == last) {
      // Push index to delta list
      m_deleteList.push_back(book->getFileIndex());
      return true;
    } else {
      return false;
    }
  } catch(exception& e) {
    cerr << "Inventory::delBook(): "  << e.what() << endl;
  }
  return 0;
}

bool Inventory::sync() {
  try {
    // Open database
    m_db->open(DEFAULT_INV_FILE);

    // for elements in delta list
    for(unsigned i = 0; i < m_deltaList.size(); i++) {
      // Find book by index
      Book* temp = getBook(m_deltaList[i]);
      // Write book to record
      //if(!m_db->change(temp)) throw runtime_error("Could not modify database");
    }

    // Sort delete list in reverse... order matters when deleting from arrays!
    sort(m_deleteList.begin(), m_deleteList.end());
    reverse(m_deleteList.begin(), m_deleteList.end()); // TODO: Inefficient...?
    //for(unsigned i = m_deleteList.size(); i >= 0; i--) {
      //Book* temp = getBook(m_deleteList[i]);
      ////if(!m_db->remove(temp)) throw runtime_error("Could not remove from database");
      //delete temp;        // Deallocate
      //m_deleteList.erase(m_deleteList.begin() + i); // Erase from vector
    //}

    // for elements in add list
    for(unsigned i = 0; i < m_addList.size(); i++) {
      // Push element to book list
      m_bookList.push_back(m_addList[i]);
      // Write book to database
      //if(!m_db->add(m_addList[i])) throw runtime_error("Could not add to database");
    }

    m_db->close();
    reset();
    return true;
  } catch(exception& e) {
    cerr << "Inventory::sync: " << e.what() << endl;
    return false;
  }
}

bool Inventory::reset() {
  try {
    // Clear delta list, add list, and delete list
    m_deltaList.clear(); m_addList.clear(); m_deleteList.clear();
    clearBookList(); // Clear book list

    // Open database
    m_db->open(DEFAULT_INV_FILE);
    m_db->start(); // Start reading from beginning

    while(!m_db->eof()) {
      Book buffer; // Create temporary book (on stack)
      if(m_db->read(&buffer)) {
        // Read record into book, and if succeeds...?
        Book* book = new Book; // Create new book (on heap)
        *book = buffer;        // Copy buffer book to new
        m_bookList.push_back(book); // Push to book list
      } else {
        throw runtime_error("Unable to read record");
      }
    }

    m_db->close(); // Close database
    return true;
  } catch(exception& e) {
    cerr << "Inventory::reset(): " << e.what() << endl;
    return false;
  }
}

unsigned Inventory::getSize()               {
  // Return number of books in inventory
  return m_bookList.size();
}

vector<Book*> Inventory::getRange(int first, int last) {
  // Create empty book list
  vector<Book*> retval;

  try {
    if(first >= last) throw domain_error("Domain Error: first >= last");

    // check if first/last are within book list bounds
    // Auto throws out of range exception
    m_bookList.at(first);
    m_bookList.at(last);

    // Assign empty vector with bounds from book list
    vector<Book*> sub(m_bookList.begin() + first, m_bookList.begin() + last);
    retval = sub;

  } catch(exception &e) {
    cerr << "Inventory::getRange: "  << e.what() << endl;
  }
  return retval;
}

vector<Book*> Inventory::findBook(Book::field field, void* search) {
  // Create temp book list
  vector<Book*> retval;

  // for all books in book list
  for(unsigned i = 0; i < m_bookList.size(); i++) {
    Book* book = m_bookList[i];
    switch(field) {
      case Book::ISBN:
        if(book->getISBN() == *((string*) search))
          retval.push_back(book);
        break;
      case Book::TITLE:
        if(book->getTitle() == *((string*) search))
          retval.push_back(book);
        break;
      case Book::AUTHOR:
        if(book->getAuthor() == *((string*) search))
          retval.push_back(book);
        break;
      case Book::QUANTITY:
        if(book->getQuantity() == *((int*) search))
          retval.push_back(book);
        break;
      case Book::WHOLECOST:
        if(book->getWholeCost() == *((double*) search))
          retval.push_back(book);
        break;
      case Book::RETAILPRICE:
        if(book->getRetailPrice() == *((double*) search))
          retval.push_back(book);
        break;
      case Book::DATEADDED:
        if(book->getDateAdded() == *((date*) search))
          retval.push_back(book);
        break;
      default:
        break;
    }
  }
  return retval;
}

// Private methods
Book* Inventory::getBook(unsigned index) {
  try {
    if(index >= m_bookList.size()) throw out_of_range("Out of Range");

    // For all items in book list
    // TODO: critical: book file indices must start at 0, not 1
    for(unsigned i = 0; i < m_bookList.size(); i++) {
      if(m_bookList[i]->getFileIndex() == index)
        return m_bookList[i];
    }

    return NULL;
  } catch(exception& e) {
    cerr << "Inventory::getBook: " << e.what() << endl;
    return NULL;
  }
}

void Inventory::clearBookList() {
  for(unsigned i = 0; i < m_bookList.size(); i++) {
    delete m_bookList[i];
  }
}
<commit_msg>#31: Inventory adds to quantity<commit_after>#include <iostream>
#include <stdexcept>
#include <algorithm>
#include <vector>
#include "inventory.h"
#include "db.h"
#include "book.h"
using namespace std;

#define DEFAULT_INV_FILE "tools/books.db"

Inventory::Inventory()                 { m_db = NULL; }
Inventory::Inventory(DB::Database* db) { m_db = db;   }

Inventory::~Inventory() {
  if(m_db != NULL) delete m_db;
}

void Inventory::setDatabase(DB::Database* db) {
  try {
    if(db == NULL) throw domain_error("Argument is NULL");
    m_db = db;
    return;
  } catch(exception& e) {
    cerr << "Inventory::setDatabase: " << e.what() << endl;
    return;
  }
}

void Inventory::setDatabaseFile(string filename = DEFAULT_INV_FILE) {
  try {
    if(filename == "") throw domain_error("Argument is empty");
    m_dbFileName = filename;
    return;
  } catch(exception& e) {
    cerr << "Inventory::setDatabaseFile: " << e.what() << endl;
    return;
  }
}

// Mutators
bool Inventory::addBook(Book* book) {
  try {
    if(book == NULL) throw domain_error("Domain Error: Argument is NULL");

    // ISBN numbers are unique: search if exists
    // Only add to FIRST book found
    vector<Book*> search = findBook(Book::ISBN, &(book->getISBN()));
    if(search.empty()) {
      // Add book to list, for writing to file later
      m_addList.push_back(book);
    } else {
      // Change quantity of found book
      search[0]->setQuantity( search[0]->getQuantity() + 1);
      // Mark book for update
      updBook(search[0]);
    }
  } catch(exception& e) {
    cerr << "Inventory::addBook: " << e.what() << endl;
  }
  return 0;
}

bool Inventory::updBook(Book* book) {
  try {
    vector<unsigned>::iterator first = m_deltaList.begin();
    vector<unsigned>::iterator last = m_deltaList.end();

    // if file index does not exist in delta list
    if(find(first, last, book->getFileIndex()) == last) {
      // Push index to delta list
      m_deltaList.push_back(book->getFileIndex());
    }
  } catch(exception& e) {
    cerr << "Inventory::updBook(): "  << e.what() << endl;
  }
  return 0;
}

bool Inventory::delBook(Book* book) {
  try {
    vector<unsigned>::iterator first = m_deleteList.begin();
    vector<unsigned>::iterator last = m_deleteList.end();

    // if file index does not exist in delete list
    if(find(first, last, book->getFileIndex()) == last) {
      // Push index to delta list
      m_deleteList.push_back(book->getFileIndex());
      return true;
    } else {
      return false;
    }
  } catch(exception& e) {
    cerr << "Inventory::delBook(): "  << e.what() << endl;
  }
  return 0;
}

bool Inventory::sync() {
  try {
    // Open database
    m_db->open(DEFAULT_INV_FILE);

    // for elements in delta list
    for(unsigned i = 0; i < m_deltaList.size(); i++) {
      // Find book by index
      Book* temp = getBook(m_deltaList[i]);
      // Write book to record
      //if(!m_db->change(temp)) throw runtime_error("Could not modify database");
    }

    // Sort delete list in reverse... order matters when deleting from arrays!
    sort(m_deleteList.begin(), m_deleteList.end());
    reverse(m_deleteList.begin(), m_deleteList.end()); // TODO: Inefficient...?
    //for(unsigned i = m_deleteList.size(); i >= 0; i--) {
      //Book* temp = getBook(m_deleteList[i]);
      ////if(!m_db->remove(temp)) throw runtime_error("Could not remove from database");
      //delete temp;        // Deallocate
      //m_deleteList.erase(m_deleteList.begin() + i); // Erase from vector
    //}

    // for elements in add list
    for(unsigned i = 0; i < m_addList.size(); i++) {
      // Push element to book list
      m_bookList.push_back(m_addList[i]);
      // Write book to database
      //if(!m_db->add(m_addList[i])) throw runtime_error("Could not add to database");
    }

    m_db->close();
    reset();
    return true;
  } catch(exception& e) {
    cerr << "Inventory::sync: " << e.what() << endl;
    return false;
  }
}

bool Inventory::reset() {
  try {
    // Clear delta list, add list, and delete list
    m_deltaList.clear(); m_addList.clear(); m_deleteList.clear();
    clearBookList(); // Clear book list

    // Open database
    m_db->open(DEFAULT_INV_FILE);
    m_db->start(); // Start reading from beginning

    while(!m_db->eof()) {
      Book buffer; // Create temporary book (on stack)
      if(m_db->read(&buffer)) {
        // Read record into book, and if succeeds...?
        Book* book = new Book; // Create new book (on heap)
        *book = buffer;        // Copy buffer book to new
        m_bookList.push_back(book); // Push to book list
      } else {
        throw runtime_error("Unable to read record");
      }
    }

    m_db->close(); // Close database
    return true;
  } catch(exception& e) {
    cerr << "Inventory::reset(): " << e.what() << endl;
    return false;
  }
}

unsigned Inventory::getSize()               {
  // Return number of books in inventory
  return m_bookList.size();
}

vector<Book*> Inventory::getRange(int first, int last) {
  // Create empty book list
  vector<Book*> retval;

  try {
    if(first >= last) throw domain_error("Domain Error: first >= last");

    // check if first/last are within book list bounds
    // Auto throws out of range exception
    m_bookList.at(first);
    m_bookList.at(last);

    // Assign empty vector with bounds from book list
    vector<Book*> sub(m_bookList.begin() + first, m_bookList.begin() + last);
    retval = sub;

  } catch(exception &e) {
    cerr << "Inventory::getRange: "  << e.what() << endl;
  }
  return retval;
}

vector<Book*> Inventory::findBook(Book::field field, void* search) {
  // Create temp book list
  vector<Book*> retval;

  // for all books in book list
  for(unsigned i = 0; i < m_bookList.size(); i++) {
    Book* book = m_bookList[i];
    switch(field) {
      case Book::ISBN:
        if(book->getISBN() == *((string*) search))
          retval.push_back(book);
        break;
      case Book::TITLE:
        if(book->getTitle() == *((string*) search))
          retval.push_back(book);
        break;
      case Book::AUTHOR:
        if(book->getAuthor() == *((string*) search))
          retval.push_back(book);
        break;
      case Book::QUANTITY:
        if(book->getQuantity() == *((int*) search))
          retval.push_back(book);
        break;
      case Book::WHOLECOST:
        if(book->getWholeCost() == *((double*) search))
          retval.push_back(book);
        break;
      case Book::RETAILPRICE:
        if(book->getRetailPrice() == *((double*) search))
          retval.push_back(book);
        break;
      case Book::DATEADDED:
        if(book->getDateAdded() == *((date*) search))
          retval.push_back(book);
        break;
      default:
        break;
    }
  }
  return retval;
}

// Private methods
Book* Inventory::getBook(unsigned index) {
  try {
    if(index >= m_bookList.size()) throw out_of_range("Out of Range");

    // For all items in book list
    // TODO: critical: book file indices must start at 0, not 1
    for(unsigned i = 0; i < m_bookList.size(); i++) {
      if(m_bookList[i]->getFileIndex() == index)
        return m_bookList[i];
    }

    return NULL;
  } catch(exception& e) {
    cerr << "Inventory::getBook: " << e.what() << endl;
    return NULL;
  }
}

void Inventory::clearBookList() {
  for(unsigned i = 0; i < m_bookList.size(); i++) {
    delete m_bookList[i];
  }
}
<|endoftext|>


<commit_before>#include "Extractor.h"

namespace BibOcr {
  Extractor::Extractor(const std::string filename) : filename_(filename) {
    image_ = cv::imread(filename);

    filter();
  }

  Extractor::~Extractor() {
  }

  std::vector<cv::Mat> Extractor::extract() {
    std::vector<cv::Mat> objects;

    return objects;
  }

  void Extractor::filter() {
    cv::blur(image_, image_, cv::Size(3, 3));
    save("blur", image_);
    cv::Canny(image_, image_, 120, 200);
    save("canny", image_);

  }

  void Extractor::save(const std::string category, const cv::Mat data) {
    std::string filename(filename_);

    filename.replace(filename.find("input/"), 6, "output/");
    filename.replace(filename.find(".jpg"), 4, "." + category + ".jpg");

    cv::imwrite(filename, data);
  }
}
<commit_msg>canny's builtin blur<commit_after>#include "Extractor.h"

namespace BibOcr {
  Extractor::Extractor(const std::string filename) : filename_(filename) {
    image_ = cv::imread(filename);

    filter();
  }

  Extractor::~Extractor() {
  }

  std::vector<cv::Mat> Extractor::extract() {
    std::vector<cv::Mat> objects;

    return objects;
  }

  void Extractor::filter() {
    cv::Canny(image_, image_, 120, 200, 3);
    save("canny", image_);

  }

  void Extractor::save(const std::string category, const cv::Mat data) {
    std::string filename(filename_);

    filename.replace(filename.find("input/"), 6, "output/");
    filename.replace(filename.find(".jpg"), 4, "." + category + ".jpg");

    cv::imwrite(filename, data);
  }
}
<|endoftext|>


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

#ifndef _FAIR_MESSAGE_QUEUE_HPP_
#define _FAIR_MESSAGE_QUEUE_HPP_

#include "Time.hpp"
#include "Queue.hpp"

namespace CBR {

/** Predicate for FairQueue which never rejects the item being considered. */
struct AlwaysUsePredicate {
    template<typename Key, typename Message>
    bool operator()(const Key& key, const Message* msg) const {
        return true;
    }
};

/** Fair Queue with one input queue of Messages per Key, backed by a TQueue. Each
 *  input queue can be assigned a weight and selection happens according to FairQueuing,
 *  with the additional constraint that each potential front element will be checked
 *  against a Predicate to give the user a chance to block certain queues from being used
 *  (for instance, if the downstream queue couldn't handle it).
 */
template <class Message,class Key,class TQueue,class Predicate=AlwaysUsePredicate> class FairQueue {
public:
    struct ServerQueueInfo {
    private:
        ServerQueueInfo():nextFinishTime(0) {
            messageQueue=NULL;
            weight=1.0;
        }
    public:
        ServerQueueInfo(Key serverName, TQueue* queue, float w)
          : messageQueue(queue), weight(w), nextFinishTime(0),mKey(serverName) {}

        TQueue* messageQueue;
        float weight;
        Time nextFinishTime;
        Key mKey;

        struct FinishTimeOrder {
            bool operator()(const ServerQueueInfo* lhs, const ServerQueueInfo* rhs) {
                return (lhs->nextFinishTime < rhs->nextFinishTime);
            }
        };
    };

    typedef std::map<Key, ServerQueueInfo> ServerQueueInfoMap;
    typedef TQueue MessageQueue;

    FairQueue(const Predicate pred = Predicate())
        :mCurrentVirtualTime(0),
         mServerQueues(),
         mPredicate(pred)
    {
    }

    ~FairQueue() {
        typename ServerQueueInfoMap::iterator it = mServerQueues.begin();
        for(; it != mServerQueues.end(); it++) {
            ServerQueueInfo* queue_info = &it->second;
            delete queue_info->messageQueue;
        }
    }

    void addQueue(MessageQueue *mq, Key server, float weight) {
        //assert(mq->empty());

        ServerQueueInfo queue_info (server, mq, weight);

        mServerQueues.insert(std::pair<Key,ServerQueueInfo>(server, queue_info));
    }
    void setQueueWeight(Key server, float weight) {
        typename ServerQueueInfoMap::iterator where=mServerQueues.find(server);
        bool retval=( where != mServerQueues.end() );
        if (where != mServerQueues.end()) {
            where->second.weight = weight;
        }
    }
    float getQueueWeight(Key server) const {
        typename ServerQueueInfoMap::const_iterator where=mServerQueues.find(server);

        if (where != mServerQueues.end()) {
          return where->second.weight;
        }

        return 0;
    }

    bool deprioritize(Key server,float factor, float affine, float minval,float maxval) {
        return changepriority(server,factor,affine,minval,maxval,true);
    }
    bool reprioritize(Key server,float factor, float affine, float minval,float maxval) {
        return changepriority(server,factor,affine,minval,maxval,false);
    }
    bool changepriority(Key server,float factor, float affine, float minval,float maxval, bool passOnDeprioritize) {
        typename ServerQueueInfoMap::iterator where=mServerQueues.find(server);
        if ( where == mServerQueues.end() )
            return false;
        float oldweight=where->second.weight;
        oldweight*=factor;
        oldweight+=affine;
        if (oldweight<minval){
            oldweight=minval;
        }
        this->setQueueWeight(server,oldweight);
        return true;
    }
    bool removeQueue(Key server) {
        typename ServerQueueInfoMap::iterator where=mServerQueues.find(server);
        bool retval=( where != mServerQueues.end() );
        if (retval) {
            delete where->second.messageQueue;
            mServerQueues.erase(where);
        }
        return retval;
    }
    bool hasQueue(Key server) const{
        return ( mServerQueues.find(server) != mServerQueues.end() );
    }
    unsigned int numQueues() const {
        return (unsigned int)mServerQueues.size();
    }
    QueueEnum::PushResult push(Key dest_server, Message *msg){
        typename ServerQueueInfoMap::iterator qi_it = mServerQueues.find(dest_server);

        assert( qi_it != mServerQueues.end() );

        ServerQueueInfo* queue_info = &qi_it->second;

        // If the queue was empty then the new packet is first and its finish time needs to be computed.
        if (queue_info->messageQueue->empty())
            queue_info->nextFinishTime = finishTime(msg->size(), queue_info->weight);
        return queue_info->messageQueue->push(msg);
    }

    // Returns the next message to deliver, given the number of bytes available for transmission
    // \param bytes number of bytes available; updated appropriately for intermediate null messages when returns
    // \returns the next message, or NULL if the queue is empty or the next message cannot be handled
    //          given the number of bytes allocated
    Message* front(uint64* bytes, Key*keyAtFront) {
        Message* result = NULL;
        Time vftime(0);
        ServerQueueInfo* min_queue_info = NULL;

        nextMessage(bytes, &result, &vftime, &min_queue_info);
        if (result != NULL) {
            assert( *bytes >= result->size() );
            *keyAtFront=min_queue_info->mKey;
            return result;
        }

        return NULL;
    }

    // Returns the next message to deliver, given the number of bytes available for transmission
    // \param bytes number of bytes available; updated appropriately when returns
    // \returns the next message, or NULL if the queue is empty or the next message cannot be handled
    //          given the number of bytes allotted
    Message* pop(uint64* bytes) {
        Message* result = NULL;
        Time vftime(0);
        ServerQueueInfo* min_queue_info = NULL;

        nextMessage(bytes, &result, &vftime, &min_queue_info);
        if (result != NULL) {
            mCurrentVirtualTime = vftime;

            assert(min_queue_info != NULL);

            assert( *bytes >= result->size() );
            *bytes -= result->size();

            min_queue_info->messageQueue->pop();

            // update the next finish time if there's anything in the queue
            if (!min_queue_info->messageQueue->empty())
                min_queue_info->nextFinishTime = finishTime(min_queue_info->messageQueue->front()->size(), min_queue_info->weight);
        }

        return result;
    }

    bool empty() const {
        // FIXME we could track a count ourselves instead of checking all these queues
        for(typename ServerQueueInfoMap::const_iterator it = mServerQueues.begin(); it != mServerQueues.end(); it++) {
            const ServerQueueInfo* queue_info = &it->second;
            if (!queue_info->messageQueue->empty())
                return false;
        }
        return true;
    }

    // Returns the total amount of space that can be allocated for the destination
    uint32 maxSize(Key dest) const {
        typename ServerQueueInfoMap::const_iterator it = mServerQueues.find(dest);
        if (it == mServerQueues.end()) return 0;
        return it->second.messageQueue->maxSize();
    }

    // Returns the total amount of space currently used for the destination
    uint32 size(Key dest) const {
        typename ServerQueueInfoMap::const_iterator it = mServerQueues.find(dest);
        if (it == mServerQueues.end()) return 0;
        return it->second.messageQueue->size();
    }

protected:

    // Retrieves the next message to deliver, along with its virtual finish time, given the number of bytes available
    // for transmission.  May update bytes for null messages, but does not update it to remove bytes to be used for
    // the returned message.  Returns null either if the number of bytes is not sufficient or the queue is empty.
    void nextMessage(uint64* bytes, Message** result_out, Time* vftime_out, ServerQueueInfo** min_queue_info_out) {
        // Create a list of queues, sorted by nextFinishTime.  FIXME we should probably track this instead of regenerating it every time
        std::vector<ServerQueueInfo*> queues_by_finish_time;
        queues_by_finish_time.reserve(mServerQueues.size());
        for(typename ServerQueueInfoMap::iterator it = mServerQueues.begin(); it != mServerQueues.end(); it++) {
            ServerQueueInfo* queue_info = &it->second;
            if (queue_info->messageQueue->empty()) continue;
            queues_by_finish_time.push_back(queue_info);
        }

        // If this list ends up empty then there are no enqueued messages
        if (queues_by_finish_time.empty()) {
            *result_out = NULL;
            return;
        }

        std::sort(queues_by_finish_time.begin(), queues_by_finish_time.end(), typename ServerQueueInfo::FinishTimeOrder());

        // Loop through until we find one that has data and can be handled.
        for(uint32 i = 0; i < queues_by_finish_time.size(); i++) {
            ServerQueueInfo* min_queue_info = queues_by_finish_time[i];

            // Check that we have enough bytes to deliver.  If not stop the search and return since doing otherwise
            // would violate the ordering.
            if (*bytes < min_queue_info->messageQueue->front()->size()) {
                *result_out = NULL;
                return;
            }

            // Now give the user a chance to veto this packet.  If they can use it, set output and return.
            // Otherwise just continue trying the rest of the options.
            if (mPredicate(min_queue_info->mKey, min_queue_info->messageQueue->front())) {
                *min_queue_info_out = min_queue_info;
                *vftime_out = min_queue_info->nextFinishTime;
                *result_out = min_queue_info->messageQueue->front();
                return;
            }
        }

        // If we get here then we've tried everything and nothing has satisfied our constraints. Give up.
        *result_out = NULL;
        return;
    }

    Time finishTime(uint32 size, float weight) const{
        float queue_frac = weight;
        Duration transmitTime = Duration::seconds( size / queue_frac );
        if (transmitTime == Duration(0)) transmitTime = Duration(1); // just make sure we take *some* time

        return mCurrentVirtualTime + transmitTime;
    }

protected:
    uint32 mRate;
    Time mCurrentVirtualTime;
    ServerQueueInfoMap mServerQueues;
    Predicate mPredicate;
}; // class FairQueue

} // namespace CBR

#endif //_FAIR_MESSAGE_QUEUE_HPP_
<commit_msg>Calculate nextFinishTime properly depending on whether the packet was added when there were others in the queue or not.  Handle updating of current virtual time properly so that it is guaranteed to increase monotonically.<commit_after>/*  cbr
 *  FairQueue.hpp
 *
 *  Copyright (c) 2009, Ewen Cheslack-Postava
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of cbr nor the names of its contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _FAIR_MESSAGE_QUEUE_HPP_
#define _FAIR_MESSAGE_QUEUE_HPP_

#include "Time.hpp"
#include "Queue.hpp"

namespace CBR {

/** Predicate for FairQueue which never rejects the item being considered. */
struct AlwaysUsePredicate {
    template<typename Key, typename Message>
    bool operator()(const Key& key, const Message* msg) const {
        return true;
    }
};

/** Fair Queue with one input queue of Messages per Key, backed by a TQueue. Each
 *  input queue can be assigned a weight and selection happens according to FairQueuing,
 *  with the additional constraint that each potential front element will be checked
 *  against a Predicate to give the user a chance to block certain queues from being used
 *  (for instance, if the downstream queue couldn't handle it).
 */
template <class Message,class Key,class TQueue,class Predicate=AlwaysUsePredicate> class FairQueue {
public:
    struct ServerQueueInfo {
    private:
        ServerQueueInfo():nextFinishTime(0) {
            messageQueue=NULL;
            weight=1.0;
        }
    public:
        ServerQueueInfo(Key serverName, TQueue* queue, float w)
          : messageQueue(queue), weight(w), nextFinishTime(0),mKey(serverName) {}

        TQueue* messageQueue;
        float weight;
        Time nextFinishTime;
        Key mKey;

        struct FinishTimeOrder {
            bool operator()(const ServerQueueInfo* lhs, const ServerQueueInfo* rhs) {
                return (lhs->nextFinishTime < rhs->nextFinishTime);
            }
        };
    };

    typedef std::map<Key, ServerQueueInfo> ServerQueueInfoMap;
    typedef TQueue MessageQueue;

    FairQueue(const Predicate pred = Predicate())
        :mCurrentVirtualTime(0),
         mServerQueues(),
         mPredicate(pred)
    {
    }

    ~FairQueue() {
        typename ServerQueueInfoMap::iterator it = mServerQueues.begin();
        for(; it != mServerQueues.end(); it++) {
            ServerQueueInfo* queue_info = &it->second;
            delete queue_info->messageQueue;
        }
    }

    void addQueue(MessageQueue *mq, Key server, float weight) {
        //assert(mq->empty());

        ServerQueueInfo queue_info (server, mq, weight);

        mServerQueues.insert(std::pair<Key,ServerQueueInfo>(server, queue_info));
    }
    void setQueueWeight(Key server, float weight) {
        typename ServerQueueInfoMap::iterator where=mServerQueues.find(server);
        bool retval=( where != mServerQueues.end() );
        if (where != mServerQueues.end()) {
            where->second.weight = weight;
        }
    }
    float getQueueWeight(Key server) const {
        typename ServerQueueInfoMap::const_iterator where=mServerQueues.find(server);

        if (where != mServerQueues.end()) {
          return where->second.weight;
        }

        return 0;
    }

    bool deprioritize(Key server,float factor, float affine, float minval,float maxval) {
        return changepriority(server,factor,affine,minval,maxval,true);
    }
    bool reprioritize(Key server,float factor, float affine, float minval,float maxval) {
        return changepriority(server,factor,affine,minval,maxval,false);
    }
    bool changepriority(Key server,float factor, float affine, float minval,float maxval, bool passOnDeprioritize) {
        typename ServerQueueInfoMap::iterator where=mServerQueues.find(server);
        if ( where == mServerQueues.end() )
            return false;
        float oldweight=where->second.weight;
        oldweight*=factor;
        oldweight+=affine;
        if (oldweight<minval){
            oldweight=minval;
        }
        this->setQueueWeight(server,oldweight);
        return true;
    }
    bool removeQueue(Key server) {
        typename ServerQueueInfoMap::iterator where=mServerQueues.find(server);
        bool retval=( where != mServerQueues.end() );
        if (retval) {
            delete where->second.messageQueue;
            mServerQueues.erase(where);
        }
        return retval;
    }
    bool hasQueue(Key server) const{
        return ( mServerQueues.find(server) != mServerQueues.end() );
    }
    unsigned int numQueues() const {
        return (unsigned int)mServerQueues.size();
    }
    QueueEnum::PushResult push(Key dest_server, Message *msg){
        typename ServerQueueInfoMap::iterator qi_it = mServerQueues.find(dest_server);

        assert( qi_it != mServerQueues.end() );

        ServerQueueInfo* queue_info = &qi_it->second;

        // If the queue was empty then the new packet is first and its finish time needs to be computed.
        if (queue_info->messageQueue->empty())
            queue_info->nextFinishTime = finishTime(msg->size(), queue_info->weight);
        return queue_info->messageQueue->push(msg);
    }

    // Returns the next message to deliver, given the number of bytes available for transmission
    // \param bytes number of bytes available; updated appropriately for intermediate null messages when returns
    // \returns the next message, or NULL if the queue is empty or the next message cannot be handled
    //          given the number of bytes allocated
    Message* front(uint64* bytes, Key*keyAtFront) {
        Message* result = NULL;
        Time vftime(0);
        ServerQueueInfo* min_queue_info = NULL;

        nextMessage(bytes, &result, &vftime, &min_queue_info);
        if (result != NULL) {
            assert( *bytes >= result->size() );
            *keyAtFront=min_queue_info->mKey;
            return result;
        }

        return NULL;
    }

    // Returns the next message to deliver, given the number of bytes available for transmission
    // \param bytes number of bytes available; updated appropriately when returns
    // \returns the next message, or NULL if the queue is empty or the next message cannot be handled
    //          given the number of bytes allotted
    Message* pop(uint64* bytes) {
        Message* result = NULL;
        Time vftime(0);
        ServerQueueInfo* min_queue_info = NULL;

        nextMessage(bytes, &result, &vftime, &min_queue_info);
        if (result != NULL) {
            // Note: we may have skipped a msg using the predicate, so we use max here to make sure
            // the virtual time increases monotonically.
            mCurrentVirtualTime = std::max(vftime, mCurrentVirtualTime);

            assert(min_queue_info != NULL);

            assert( *bytes >= result->size() );
            *bytes -= result->size();

            min_queue_info->messageQueue->pop();

            // update the next finish time if there's anything in the queue
            if (!min_queue_info->messageQueue->empty())
                min_queue_info->nextFinishTime = finishTime(min_queue_info->messageQueue->front()->size(), min_queue_info->weight, min_queue_info->nextFinishTime);
        }

        return result;
    }

    bool empty() const {
        // FIXME we could track a count ourselves instead of checking all these queues
        for(typename ServerQueueInfoMap::const_iterator it = mServerQueues.begin(); it != mServerQueues.end(); it++) {
            const ServerQueueInfo* queue_info = &it->second;
            if (!queue_info->messageQueue->empty())
                return false;
        }
        return true;
    }

    // Returns the total amount of space that can be allocated for the destination
    uint32 maxSize(Key dest) const {
        typename ServerQueueInfoMap::const_iterator it = mServerQueues.find(dest);
        if (it == mServerQueues.end()) return 0;
        return it->second.messageQueue->maxSize();
    }

    // Returns the total amount of space currently used for the destination
    uint32 size(Key dest) const {
        typename ServerQueueInfoMap::const_iterator it = mServerQueues.find(dest);
        if (it == mServerQueues.end()) return 0;
        return it->second.messageQueue->size();
    }

protected:

    // Retrieves the next message to deliver, along with its virtual finish time, given the number of bytes available
    // for transmission.  May update bytes for null messages, but does not update it to remove bytes to be used for
    // the returned message.  Returns null either if the number of bytes is not sufficient or the queue is empty.
    void nextMessage(uint64* bytes, Message** result_out, Time* vftime_out, ServerQueueInfo** min_queue_info_out) {
        // Create a list of queues, sorted by nextFinishTime.  FIXME we should probably track this instead of regenerating it every time
        std::vector<ServerQueueInfo*> queues_by_finish_time;
        queues_by_finish_time.reserve(mServerQueues.size());
        for(typename ServerQueueInfoMap::iterator it = mServerQueues.begin(); it != mServerQueues.end(); it++) {
            ServerQueueInfo* queue_info = &it->second;
            if (queue_info->messageQueue->empty()) continue;
            queues_by_finish_time.push_back(queue_info);
        }

        // If this list ends up empty then there are no enqueued messages
        if (queues_by_finish_time.empty()) {
            *result_out = NULL;
            return;
        }

        std::sort(queues_by_finish_time.begin(), queues_by_finish_time.end(), typename ServerQueueInfo::FinishTimeOrder());

        // Loop through until we find one that has data and can be handled.
        for(uint32 i = 0; i < queues_by_finish_time.size(); i++) {
            ServerQueueInfo* min_queue_info = queues_by_finish_time[i];

            // Check that we have enough bytes to deliver.  If not stop the search and return since doing otherwise
            // would violate the ordering.
            if (*bytes < min_queue_info->messageQueue->front()->size()) {
                *result_out = NULL;
                return;
            }

            // Now give the user a chance to veto this packet.  If they can use it, set output and return.
            // Otherwise just continue trying the rest of the options.
            if (mPredicate(min_queue_info->mKey, min_queue_info->messageQueue->front())) {
                *min_queue_info_out = min_queue_info;
                *vftime_out = min_queue_info->nextFinishTime;
                *result_out = min_queue_info->messageQueue->front();
                return;
            }
        }

        // If we get here then we've tried everything and nothing has satisfied our constraints. Give up.
        *result_out = NULL;
        return;
    }

    /** Finish time for a packet that was inserted into a non-empty queue, i.e. based on the previous packet's
     *  finish time. */
    Time finishTime(uint32 size, float weight, const Time& last_finish_time) const {
        float queue_frac = weight;
        Duration transmitTime = Duration::seconds( size / queue_frac );
        if (transmitTime == Duration(0)) transmitTime = Duration(1); // just make sure we take *some* time

        return last_finish_time + transmitTime;
    }

    /** Finish time for a packet inserted into an empty queue, i.e. based on the most recent virtual time. */
    Time finishTime(uint32 size, float weight) const {
        float queue_frac = weight;
        Duration transmitTime = Duration::seconds( size / queue_frac );
        if (transmitTime == Duration(0)) transmitTime = Duration(1); // just make sure we take *some* time

        return mCurrentVirtualTime + transmitTime;
    }

protected:
    uint32 mRate;
    Time mCurrentVirtualTime;
    ServerQueueInfoMap mServerQueues;
    Predicate mPredicate;
}; // class FairQueue

} // namespace CBR

#endif //_FAIR_MESSAGE_QUEUE_HPP_
<|endoftext|>


<commit_before>// FbCommands.hh for Fluxbox
// Copyright (c) 2003 Henrik Kinnunen (fluxgen at users.sourceforge.net)
//
// 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.

// $Id: FbCommands.hh,v 1.20 2004/10/06 11:40:28 akir Exp $

// \file contains basic commands to restart, reconfigure, execute command and exit fluxbox

#ifndef FBCOMMANDS_HH
#define FBCOMMANDS_HH

#include "Command.hh"

#include <string>

namespace FbCommands {

/// executes a system command
class ExecuteCmd: public FbTk::Command {
public:
    ExecuteCmd(const std::string &cmd, int screen_num = -1);
    void execute();
private:
    std::string m_cmd;
    const int m_screen_num;
};

/// sets environment
class ExportCmd : public FbTk::Command {
public:
    ExportCmd(const std::string& name, const std::string& value);
    void execute();
private:
    std::string m_name;
    std::string m_value;
};

/// exit fluxbox
class ExitFluxboxCmd: public FbTk::Command {
public:
    void execute();
};

/// saves resources
class SaveResources: public FbTk::Command {
public:
    void execute();
};

/// restarts fluxbox
class RestartFluxboxCmd: public FbTk::Command {
public:
    RestartFluxboxCmd(const std::string &cmd);
    void execute();
private:
    std::string m_cmd;
};

/// reconfigures fluxbox
class ReconfigureFluxboxCmd: public FbTk::Command {
public:
    void execute();
};

class ReloadStyleCmd: public FbTk::Command {
public:
    void execute();
};

class SetStyleCmd: public FbTk::Command {
public:
    explicit SetStyleCmd(const std::string &filename);
    void execute();
private:
    std::string m_filename;
};

class ShowRootMenuCmd: public FbTk::Command {
public:
    void execute();
};

class ShowWorkspaceMenuCmd: public FbTk::Command {
public:
    void execute();
};

class SetWorkspaceNameCmd: public FbTk::Command {
public:
    SetWorkspaceNameCmd(const std::string &name, int spaceid = -1);
    void execute();
private:
    std::string m_name;
    int m_workspace;
};

class WorkspaceNameDialogCmd: public FbTk::Command {
public:
    void execute();
};

class CommandDialogCmd: public FbTk::Command {
public:
    void execute();
};

} // end namespace FbCommands

class SetResourceValueCmd: public FbTk::Command {
public:
    SetResourceValueCmd(const std::string &resourcename, const std::string &value);
    void execute();
private:
    const std::string m_resname;
    const std::string m_value;
};

class SetResourceValueDialogCmd: public FbTk::Command {
public:
    void execute();
};

class BindKeyCmd: public FbTk::Command {
public:
    BindKeyCmd(const std::string &keybind);
    void execute();
private:
    const std::string m_keybind;
};

/// deiconifies iconified windows
class DeiconifyCmd: public FbTk::Command {
public:
    enum Mode {
        LAST,
        LASTWORKSPACE,
        ALL,
        ALLWORKSPACE
    };

    enum Destination {
        CURRENT, /// deiconification on current workspace
        ORIGIN,  /// deiconification on origin workspace, change to that ws
        ORIGINQUIET /// deiconification on origin workspace, dont change ws
    };

    DeiconifyCmd(const Mode mode= LASTWORKSPACE,
                 const Destination dest= CURRENT);
    void execute();
private:
    Mode m_mode;
    Destination m_dest;
};

#endif // FBCOMMANDS_HH
<commit_msg>fix for wrong placed end of namespace }; (thanx mipspro :))<commit_after>// FbCommands.hh for Fluxbox
// Copyright (c) 2003 Henrik Kinnunen (fluxgen at users.sourceforge.net)
//
// 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.

// $Id: FbCommands.hh,v 1.21 2004/10/21 10:23:58 akir Exp $

// \file contains basic commands to restart, reconfigure, execute command and exit fluxbox

#ifndef FBCOMMANDS_HH
#define FBCOMMANDS_HH

#include "Command.hh"

#include <string>

namespace FbCommands {

/// executes a system command
class ExecuteCmd: public FbTk::Command {
public:
    ExecuteCmd(const std::string &cmd, int screen_num = -1);
    void execute();
private:
    std::string m_cmd;
    const int m_screen_num;
};

/// sets environment
class ExportCmd : public FbTk::Command {
public:
    ExportCmd(const std::string& name, const std::string& value);
    void execute();
private:
    std::string m_name;
    std::string m_value;
};

/// exit fluxbox
class ExitFluxboxCmd: public FbTk::Command {
public:
    void execute();
};

/// saves resources
class SaveResources: public FbTk::Command {
public:
    void execute();
};

/// restarts fluxbox
class RestartFluxboxCmd: public FbTk::Command {
public:
    RestartFluxboxCmd(const std::string &cmd);
    void execute();
private:
    std::string m_cmd;
};

/// reconfigures fluxbox
class ReconfigureFluxboxCmd: public FbTk::Command {
public:
    void execute();
};

class ReloadStyleCmd: public FbTk::Command {
public:
    void execute();
};

class SetStyleCmd: public FbTk::Command {
public:
    explicit SetStyleCmd(const std::string &filename);
    void execute();
private:
    std::string m_filename;
};

class ShowRootMenuCmd: public FbTk::Command {
public:
    void execute();
};

class ShowWorkspaceMenuCmd: public FbTk::Command {
public:
    void execute();
};

class SetWorkspaceNameCmd: public FbTk::Command {
public:
    SetWorkspaceNameCmd(const std::string &name, int spaceid = -1);
    void execute();
private:
    std::string m_name;
    int m_workspace;
};

class WorkspaceNameDialogCmd: public FbTk::Command {
public:
    void execute();
};

class CommandDialogCmd: public FbTk::Command {
public:
    void execute();
};

class SetResourceValueCmd: public FbTk::Command {
public:
    SetResourceValueCmd(const std::string &resourcename, const std::string &value);
    void execute();
private:
    const std::string m_resname;
    const std::string m_value;
};

class SetResourceValueDialogCmd: public FbTk::Command {
public:
    void execute();
};

class BindKeyCmd: public FbTk::Command {
public:
    BindKeyCmd(const std::string &keybind);
    void execute();
private:
    const std::string m_keybind;
};

/// deiconifies iconified windows
class DeiconifyCmd: public FbTk::Command {
public:
    enum Mode {
        LAST,
        LASTWORKSPACE,
        ALL,
        ALLWORKSPACE
    };

    enum Destination {
        CURRENT, /// deiconification on current workspace
        ORIGIN,  /// deiconification on origin workspace, change to that ws
        ORIGINQUIET /// deiconification on origin workspace, dont change ws
    };

    DeiconifyCmd(const Mode mode= LASTWORKSPACE,
                 const Destination dest= CURRENT);
    void execute();
private:
    Mode m_mode;
    Destination m_dest;
};

} // end namespace FbCommands

#endif // FBCOMMANDS_HH
<|endoftext|>