<commit_before>/***

Copyright 2013-2016 Dave Cridland
Copyright 2014-2016 Surevine Ltd

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 <string>
#include <config.h>
#include <iostream>
#include <string.h>
#include <log.h>
#include <signal.h>
#include <fstream>
#include <router.h>
#include <windows.h>

namespace {
    class BootConfig {
    public:
        std::string config_file;
        std::string boot_method;

        BootConfig(int argc, char *argv[])
                : config_file("./metre.conf.xml"), boot_method() {
            for (int i = 1; argv[i]; ++i) {
                char opt;
                switch (argv[i][0]) {
                    case '-':
                    case '/':
                        opt = argv[i][1];
                        break;
                    default:
                        std::cerr << "Don't understand commandline arg " << argv[i] << std::endl;
                        exit(2);
                }
                ++i;
                if (!argv[i]) {
                    std::cerr << "Missing argument for option '" << opt << "'" << std::endl;
                    exit(2);
                }
                switch (opt) {
                    case 'c':
                        config_file = argv[i];
                        break;
                    case 'd':
                        boot_method = argv[i];
                        break;
                }
            }
        }
    };

    std::unique_ptr<BootConfig> bc;
    std::unique_ptr<Metre::Config> config;

    void hup_handler(int s) {
        //config.reset(new Metre::Config(bc->config_file));
        //Metre::Router::reload();
        METRE_LOG(Metre::Log::INFO, "NOT Reloading config.");
    }

    void term_handler(int s) {
        METRE_LOG(Metre::Log::INFO, "Shutdown received.");
        Metre::Router::quit();
    }
}

SERVICE_STATUS g_ServiceStatus = {0};
SERVICE_STATUS_HANDLE g_StatusHandle = NULL;
HANDLE g_ServiceStopEvent = INVALID_HANDLE_VALUE;

VOID WINAPI
ServiceMain (DWORD
argc,
LPTSTR *argv
);
VOID WINAPI
ServiceCtrlHandler (DWORD);
DWORD WINAPI
ServiceWorkerThread (LPVOID
lpParam);

#define SERVICE_NAME  _T("My Sample Service")

VOID WINAPI
ServiceMain (DWORD
argc,
LPTSTR *argv
)
{
DWORD Status = E_FAIL;

// Register our service control handler with the SCM
g_StatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceCtrlHandler);

if (g_StatusHandle == NULL) {
goto
EXIT;
}

// Tell the service controller we are starting
ZeroMemory (&g_ServiceStatus,
sizeof (g_ServiceStatus));
g_ServiceStatus.
dwServiceType = SERVICE_WIN32_OWN_PROCESS;
g_ServiceStatus.
dwControlsAccepted = 0;
g_ServiceStatus.
dwCurrentState = SERVICE_START_PENDING;
g_ServiceStatus.
dwWin32ExitCode = 0;
g_ServiceStatus.
dwServiceSpecificExitCode = 0;
g_ServiceStatus.
dwCheckPoint = 0;

if (
SetServiceStatus (g_StatusHandle, &g_ServiceStatus
) == FALSE) {
OutputDebugString(_T(
        "Metre: ServiceMain: SetServiceStatus returned error")
);
}

/*
 * Perform tasks necessary to start the service here
 */

// Create a service stop event to wait on later
g_ServiceStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (g_ServiceStopEvent == NULL) {
// Error creating event
// Tell service controller we are stopped and exit
g_ServiceStatus.
dwControlsAccepted = 0;
g_ServiceStatus.
dwCurrentState = SERVICE_STOPPED;
g_ServiceStatus.
dwWin32ExitCode = GetLastError();
g_ServiceStatus.
dwCheckPoint = 1;

if (
SetServiceStatus (g_StatusHandle, &g_ServiceStatus
) == FALSE) {
OutputDebugString(_T(
        "Metre: ServiceMain: SetServiceStatus returned error")
);
}
goto
EXIT;
}

bc = std::make_unique<BootConfig>(argc, argv);
config = std::make_unique<Metre::Config>(bc->config_file);
if (bc->boot_method.

empty()

) {
bc->
boot_mthod = config->boot_method();
}
if (bc->boot_method != "service") {
OutputDebugString(_T("Metre: ServiceMain: Wrong boot method")
);
goto
EXIT;
}

// Tell the service controller we are started
g_ServiceStatus.
dwControlsAccepted = SERVICE_ACCEPT_STOP;
g_ServiceStatus.
dwCurrentState = SERVICE_RUNNING;
g_ServiceStatus.
dwWin32ExitCode = 0;
g_ServiceStatus.
dwCheckPoint = 0;

if (
SetServiceStatus (g_StatusHandle, &g_ServiceStatus
) == FALSE)
{
OutputDebugString(_T(
        "Metre: ServiceMain: SetServiceStatus returned error")
);
}

// Start a thread that will perform the main task of the service
HANDLE hThread = CreateThread(NULL, 0, ServiceWorkerThread, NULL, 0, NULL);

// Wait until our worker thread exits signaling that the service needs to stop
WaitForSingleObject (hThread, INFINITE
);

/*
 * Perform any cleanup tasks
 */

CloseHandle (g_ServiceStopEvent);

// Tell the service controller we are stopped
g_ServiceStatus.
dwControlsAccepted = 0;
g_ServiceStatus.
dwCurrentState = SERVICE_STOPPED;
g_ServiceStatus.
dwWin32ExitCode = 0;
g_ServiceStatus.
dwCheckPoint = 3;

if (
SetServiceStatus (g_StatusHandle, &g_ServiceStatus
) == FALSE)
{
OutputDebugString(_T(
        "Metre: ServiceMain: SetServiceStatus returned error")
);
}

EXIT:
return;
}

int main(int argc, char *argv[]) {
    try {
        // Parse arguments.
        bc = std::make_unique<BootConfig>(argc, argv);
        if (!bc->boot_method.empty() && bc->boot_method == "service") {
            SERVICE_TABLE_ENTRY ServiceTable[] = {
                    {"Metre", (LPSERVICE_MAIN_FUNCTION) ServiceMain},
                    {NULL, NULL}
            };
            if (StartServiceCtrlDispatcher(ServiceTable) == FALSE) {
                return GetLastError();
            }
            return 0;
        }
        // Load config, first pass.
        config = std::make_unique<Metre::Config>(bc->config_file);
        if (bc->boot_method.empty()) {
            bc->boot_method = config->boot_method();
        }
    } catch (std::runtime_error &e) {
        std::cout << "Error while loading config: " << e.what() << std::endl;
        return 1;
    }
    try {
        if (bc->boot_method == "none") {
            config->log_init();
            config->write_runtime_config();
            Metre::Router::main();
        } else {
            std::cerr << "I don't know what " << bc->boot_method << " means." << std::endl;
            return 1;
        }
    } catch (std::runtime_error &e) {
        std::cout << "Error while loading config: " << e.what() << std::endl;
        return 2;
    }
    config.reset(nullptr);
    bc.reset(nullptr);
    return 0;
}

VOID WINAPI
ServiceCtrlHandler (DWORD
CtrlCode)
{
switch (CtrlCode) {
case SERVICE_CONTROL_STOP :

if (g_ServiceStatus.dwCurrentState != SERVICE_RUNNING)
break;

/*
 * Perform tasks necessary to stop the service here
 */

g_ServiceStatus.
dwControlsAccepted = 0;
g_ServiceStatus.
dwCurrentState = SERVICE_STOP_PENDING;
g_ServiceStatus.
dwWin32ExitCode = 0;
g_ServiceStatus.
dwCheckPoint = 4;

if (
SetServiceStatus (g_StatusHandle, &g_ServiceStatus
) == FALSE) {
OutputDebugString(_T(
        "Metre: ServiceCtrlHandler: SetServiceStatus returned error")
);
}

// This will signal the worker thread to start shutting down
SetEvent (g_ServiceStopEvent);

break;

default:
break;
}
}

DWORD WINAPI
ServiceWorkerThread (LPVOID
lpParam)
{
config->

log_init();

Metre::Router::Main([g_ServiceStopEvent]() {
return (
WaitForSingleObject(g_ServiceStopEvent,
0) == WAIT_OBJECT_0);
})

return
ERROR_SUCCESS;
}<commit_msg>Reformat and fix<commit_after>/***

Copyright 2013-2016 Dave Cridland
Copyright 2014-2016 Surevine Ltd

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 <string>
#include <config.h>
#include <iostream>
#include <string.h>
#include <log.h>
#include <signal.h>
#include <fstream>
#include <router.h>
#include <windows.h>
#include <tchar.h>

namespace {
    class BootConfig {
    public:
        std::string config_file;
        std::string boot_method;

        BootConfig(int argc, char *argv[])
                : config_file("./metre.conf.xml"), boot_method() {
            for (int i = 1; argv[i]; ++i) {
                char opt;
                switch (argv[i][0]) {
                    case '-':
                    case '/':
                        opt = argv[i][1];
                        break;
                    default:
                        std::cerr << "Don't understand commandline arg " << argv[i] << std::endl;
                        exit(2);
                }
                ++i;
                if (!argv[i]) {
                    std::cerr << "Missing argument for option '" << opt << "'" << std::endl;
                    exit(2);
                }
                switch (opt) {
                    case 'c':
                        config_file = argv[i];
                        break;
                    case 'd':
                        boot_method = argv[i];
                        break;
                }
            }
        }
    };

    std::unique_ptr<BootConfig> bc;
    std::unique_ptr<Metre::Config> config;

    void hup_handler(int s) {
        //config.reset(new Metre::Config(bc->config_file));
        //Metre::Router::reload();
        METRE_LOG(Metre::Log::INFO, "NOT Reloading config.");
    }

    void term_handler(int s) {
        METRE_LOG(Metre::Log::INFO, "Shutdown received.");
        Metre::Router::quit();
    }
}

SERVICE_STATUS g_ServiceStatus = {0};
SERVICE_STATUS_HANDLE g_StatusHandle = NULL;
HANDLE g_ServiceStopEvent = INVALID_HANDLE_VALUE;

VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv);

#define SERVICE_NAME  _T("My Sample Service")

DWORD WINAPI ServiceWorkerThread(LPVOID lpParam);

#define SERVICE_NAME  "My Sample Service"

VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv) {
    DWORD Status = E_FAIL;

    // Register our service control handler with the SCM
    g_StatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceCtrlHandler);

    if (g_StatusHandle == NULL) {
        goto EXIT;
    }

    // Tell the service controller we are starting
    ZeroMemory (&g_ServiceStatus,
                sizeof(g_ServiceStatus));
    g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
    g_ServiceStatus.dwControlsAccepted = 0;
    g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
    g_ServiceStatus.dwWin32ExitCode = 0;
    g_ServiceStatus.dwServiceSpecificExitCode = 0;
    g_ServiceStatus.dwCheckPoint = 0;

    if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) {
        OutputDebugString(_T("Metre: ServiceMain: SetServiceStatus returned error"));
    }

    /*
     * Perform tasks necessary to start the service here
     */

    // Create a service stop event to wait on later
    g_ServiceStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (g_ServiceStopEvent == NULL) {
        // Error creating event
        // Tell service controller we are stopped and exit
        g_ServiceStatus.dwControlsAccepted = 0;
        g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
        g_ServiceStatus.dwWin32ExitCode = GetLastError();
        g_ServiceStatus.dwCheckPoint = 1;

        if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) {
            OutputDebugString(_T("Metre: ServiceMain: SetServiceStatus returned error"));
        }
        goto EXIT;
    }

    bc = std::make_unique<BootConfig>(argc, argv);
    config = std::make_unique<Metre::Config>(bc->config_file);
    if (bc->boot_method.empty()) {
        bc->boot_method = config->boot_method();
    }
    if (bc->boot_method != "service") {
        OutputDebugString(_T("Metre: ServiceMain: Wrong boot method"));
        goto EXIT;
    }

    // Tell the service controller we are started
    g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
    g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
    g_ServiceStatus.dwWin32ExitCode = 0;
    g_ServiceStatus.dwCheckPoint = 0;

    if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) {
        OutputDebugString(_T("Metre: ServiceMain: SetServiceStatus returned error"));
    }

    // Start a thread that will perform the main task of the service
    HANDLE hThread = CreateThread(NULL, 0, ServiceWorkerThread, NULL, 0, NULL);

    // Wait until our worker thread exits signaling that the service needs to stop
    WaitForSingleObject(hThread, INFINITE);

    /*
     * Perform any cleanup tasks
     */

    CloseHandle(g_ServiceStopEvent);

    // Tell the service controller we are stopped
    g_ServiceStatus.dwControlsAccepted = 0;
    g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
    g_ServiceStatus.dwWin32ExitCode = 0;
    g_ServiceStatus.dwCheckPoint = 3;

    if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) {
        OutputDebugString(_T("Metre: ServiceMain: SetServiceStatus returned error"));
    }

EXIT:
    return;
}

int main(int argc, char *argv[]) {
    try {
        // Parse arguments.
        bc = std::make_unique<BootConfig>(argc, argv);
        if (!bc->boot_method.empty() && bc->boot_method == "service") {
            SERVICE_TABLE_ENTRY ServiceTable[] = {
                    {SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) ServiceMain},
                    {NULL, NULL}
            };
            if (StartServiceCtrlDispatcher(ServiceTable) == FALSE) {
                return GetLastError();
            }
            return 0;
        }
        // Load config, first pass.
        config = std::make_unique<Metre::Config>(bc->config_file);
        if (bc->boot_method.empty()) {
            bc->boot_method = config->boot_method();
        }
    } catch (std::runtime_error &e) {
        std::cout << "Error while loading config: " << e.what() << std::endl;
        return 1;
    }
    try {
        if (bc->boot_method == "none") {
            config->log_init();
            config->write_runtime_config();
            Metre::Router::main([](){
                return false;
            });
        } else {
            std::cerr << "I don't know what " << bc->boot_method << " means." << std::endl;
            return 1;
        }
    } catch (std::runtime_error &e) {
        std::cout << "Error while loading config: " << e.what() << std::endl;
        return 2;
    }
    config.reset(nullptr);
    bc.reset(nullptr);
    return 0;
}

VOID WINAPI ServiceCtrlHandler(DWORD CtrlCode) {
    switch (CtrlCode) {
    case SERVICE_CONTROL_STOP :
        if (g_ServiceStatus.dwCurrentState != SERVICE_RUNNING)
            break;

        /*
         * Perform tasks necessary to stop the service here
         */

        g_ServiceStatus.dwControlsAccepted = 0;
        g_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
        g_ServiceStatus.dwWin32ExitCode = 0;
        g_ServiceStatus.dwCheckPoint = 4;

        if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) {
            OutputDebugString(_T("Metre: ServiceCtrlHandler: SetServiceStatus returned error"));
        }

        // This will signal the worker thread to start shutting down
        SetEvent(g_ServiceStopEvent);

        break;

    default:
        break;
    }
}

DWORD WINAPI ServiceWorkerThread(LPVOID lpParam) {
    config->log_init();
    config->write_runtime_config();

    Metre::Router::main([]() {
        return (WaitForSingleObject(g_ServiceStopEvent, 0) == WAIT_OBJECT_0);
    });

    return ERROR_SUCCESS;
}
<|endoftext|>


<commit_before>#include <dlfcn.h>
#include <string.h>
#include <cstdio>
#include <cstdlib>
#include <sys/ioctl.h>
#include <unistd.h>

typedef ssize_t (*ReadSignature)(int, void*, size_t);
static ReadSignature real_read = nullptr;

static char __line[1024];
static int __line_index = 0;

#define cursor_forward(x) printf("\033[%dC", (x))
#define cursor_backward(x) printf("\033[%dD", (x))

int open_history_file(FILE **f) {

    char history[512], *home_dir = getenv("HOME");

    strcpy(history, home_dir);
    strcat(history, "/.bash_history");

    if ((*f = fopen(history, "r")) == NULL) {
        printf("No such file %s\n", history);
        return -1;
    }

    return 0;

}

void complete_from_history(char *pattern, char *result) {

    char *buffer = 0;
    size_t len = 0;

    FILE *f = 0;

    open_history_file(&f);

    while (getline(&buffer, &len, f) != -1) {
        *strchr(buffer, '\n') = 0;
        if (!strncmp(buffer, pattern, strlen(pattern))) {
            strcpy(result, buffer + strlen(pattern));
            break;
        }
    }

    fclose(f);

}

void interactive_completion(unsigned char c) {

    char buffer[2048];
    struct winsize w;

    ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); // TODO:

    switch (c) {
        case 0xd: // newline
            __line_index = 0;
            memset(__line, 0, 1024);
            memset(buffer, 0, 2048);
            break;

        case 0x7f: // backspace
            if (__line_index > 0)
                __line[--__line_index] = 0;
            break;

        default:
            __line[__line_index++] = c;
            __line[__line_index] = 0;
            complete_from_history(__line, buffer);
            if (strlen(buffer) > strlen(__line)) {
                cursor_forward(1);
                printf("\e[1;30m%s\e[0m", buffer);
                cursor_backward((int)strlen(buffer) + 1);
                fflush(stdout);
            }
            break;
   }

}

ssize_t read(int fd, void *buf, size_t count) {

    ssize_t ret;

    if (!real_read)
        real_read = reinterpret_cast<ReadSignature>(dlsym(RTLD_NEXT, "read"));
    ret = real_read(fd, buf, count);

    if (fd == 0)
        interactive_completion(*(unsigned char *)buf);

    return ret;

}

<commit_msg>added 1 TODO, moved real_read to function (still static)<commit_after>#include <dlfcn.h>
#include <string.h>
#include <cstdio>
#include <cstdlib>
#include <sys/ioctl.h>
#include <unistd.h>

typedef ssize_t (*ReadSignature)(int, void*, size_t);

// TODO: per-process memory?
static char __line[1024];
static int __line_index = 0;

#define cursor_forward(x) printf("\033[%dC", (x))
#define cursor_backward(x) printf("\033[%dD", (x))

int open_history_file(FILE **f) {
    char history[512], *home_dir = getenv("HOME");

    strcpy(history, home_dir);
    strcat(history, "/.bash_history");

    if ((*f = fopen(history, "r")) == NULL) {
        printf("No such file %s\n", history);
        return -1;
    }

    return 0;
}

void complete_from_history(char *pattern, char *result) {

    char *buffer = 0;
    size_t len = 0;

    FILE *f = 0;

    open_history_file(&f);

    while (getline(&buffer, &len, f) != -1) {
        *strchr(buffer, '\n') = 0;
        if (!strncmp(buffer, pattern, strlen(pattern))) {
            strcpy(result, buffer + strlen(pattern));
            break;
        }
    }

    fclose(f);

}

void interactive_completion(unsigned char c) {

    char buffer[2048];
    struct winsize w;

    ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); // TODO:

    switch (c) {
        case 0xd: // newline
            __line_index = 0;
            memset(__line, 0, 1024);
            memset(buffer, 0, 2048);
            break;

        case 0x7f: // backspace
            if (__line_index > 0)
                __line[--__line_index] = 0;
            break;

        default:
            __line[__line_index++] = c;
            __line[__line_index] = 0;
            complete_from_history(__line, buffer);
            if (strlen(buffer) > strlen(__line)) {
                cursor_forward(1);
                printf("\e[1;30m%s\e[0m", buffer);
                cursor_backward((int)strlen(buffer) + 1);
                fflush(stdout);
            }
            break;
   }

}

ssize_t read(int fd, void *buf, size_t count) {
    static ReadSignature real_read = reinterpret_cast<ReadSignature>(dlsym(RTLD_NEXT, "read"));
    ssize_t ret = real_read(fd, buf, count);

    if (0 == fd) {
        interactive_completion(*(unsigned char *)buf);
    }

    return ret;
}

<|endoftext|>


<commit_before>/******************************************************************************
**
** Copyright (C) 2009-2011 Kyle Lutz <kyle.r.lutz@gmail.com>
** All rights reserved.
**
** This file is a part of the chemkit project. For more information
** see <http://www.chemkit.org>.
**
** 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 the chemkit project 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.
**
******************************************************************************/

#include "ringtest.h"

#include <chemkit/chemkit.h>
#include <chemkit/ring.h>
#include <chemkit/molecule.h>
#include <chemkit/lineformat.h>

void RingTest::initTestCase()
{
    chemkit::LineFormat *inchi = chemkit::LineFormat::create("inchi");

    // benzene
    benzene = inchi->read("InChI=1/C6H6/c1-2-4-6-5-3-1/h1-6H");
    QVERIFY(benzene != 0);
    QCOMPARE(benzene->ringCount(), 1);
    benzeneRing = benzene->rings()[0];

    // furan
    furan = inchi->read("InChI=1/C4H4O/c1-2-4-5-3-1/h1-4H");
    QVERIFY(furan != 0);
    QCOMPARE(furan->ringCount(), 1);
    furanRing = furan->rings()[0];

    // cyclohexane
    cyclohexane = inchi->read("InChI=1S/C6H12/c1-2-4-6-5-3-1/h1-6H2");
    QVERIFY(cyclohexane != 0);
    QCOMPARE(cyclohexane->ringCount(), 1);
    cyclohexaneRing = cyclohexane->rings()[0];

    // cyclopropane
    cyclopropane = inchi->read("InChI=1/C3H6/c1-2-3-1/h1-3H2");
    QVERIFY(cyclopropane != 0);
    QCOMPARE(cyclopropane->ringCount(), 1);
    cyclopropaneRing = cyclopropane->rings()[0];

    delete inchi;
}

void RingTest::molecule()
{
    QCOMPARE(benzeneRing->molecule(), benzene);
    QCOMPARE(furanRing->molecule(), furan);
}

void RingTest::atoms()
{
    QCOMPARE(benzeneRing->atoms().size(), 6UL);
    foreach(chemkit::Atom *atom, benzeneRing->atoms()){
        QVERIFY(atom->molecule() == benzene);
        QVERIFY(benzene->contains(atom));

        QVERIFY(atom->is(chemkit::Atom::Carbon));
    }
}

void RingTest::atomCount()
{
    QCOMPARE(benzeneRing->atomCount(), 6);
    QCOMPARE(furanRing->atomCount(), 5);
    QCOMPARE(cyclohexaneRing->atomCount(), 6);
    QCOMPARE(cyclopropaneRing->atomCount(), 3);

    QCOMPARE(benzeneRing->atomCount(chemkit::Atom::Carbon), 6);
    QCOMPARE(benzeneRing->atomCount(chemkit::Atom::Hydrogen), 0);
    QCOMPARE(benzeneRing->atomCount(chemkit::Atom::Oxygen), 0);
    QCOMPARE(furanRing->atomCount(chemkit::Atom::Carbon), 4);
    QCOMPARE(furanRing->atomCount(chemkit::Atom::Hydrogen), 0);
    QCOMPARE(furanRing->atomCount(chemkit::Atom::Oxygen), 1);
}

void RingTest::size()
{
    QCOMPARE(benzeneRing->size(), 6);
    QCOMPARE(furanRing->size(), 5);
    QCOMPARE(cyclohexaneRing->size(), 6);
    QCOMPARE(cyclopropaneRing->size(), 3);
}

void RingTest::bonds()
{
    QCOMPARE(benzeneRing->bonds().size(), 6UL);
    foreach(chemkit::Bond *bond, benzeneRing->bonds()){
        QVERIFY(bond->molecule() == benzene);
        QVERIFY(benzene->contains(bond));

        QVERIFY(bond->atom1()->is(chemkit::Atom::Carbon));
        QVERIFY(bond->atom2()->is(chemkit::Atom::Carbon));
    }
}

void RingTest::bondCount()
{
    QCOMPARE(benzeneRing->bondCount(), 6);
    QCOMPARE(furanRing->bondCount(), 5);
    QCOMPARE(cyclohexaneRing->bondCount(), 6);
    QCOMPARE(cyclopropaneRing->bondCount(), 3);
}

void RingTest::root()
{
    QVERIFY(benzeneRing->root()->is(chemkit::Atom::Carbon));
    QVERIFY(furanRing->root()->is(chemkit::Atom::Oxygen));
}

void RingTest::position()
{
    chemkit::Atom *furanOxygen = furanRing->root();
    QVERIFY(furanOxygen->is(chemkit::Atom::Oxygen));
    foreach(chemkit::Atom *atom, furanRing->atoms()){
        if(atom->isBondedTo(furanOxygen)){
            QCOMPARE(furanRing->position(atom), 1);
            QCOMPARE(furanRing->position(atom, furanOxygen), 1);
        }
        else if(atom == furanOxygen){
            QCOMPARE(furanRing->position(atom), 0);
            QCOMPARE(furanRing->position(atom, furanOxygen), 0);
        }
        else{
            QCOMPARE(furanRing->position(atom), 2);
            QCOMPARE(furanRing->position(atom, furanOxygen), 2);
        }
    }

    // atom from another molecule
    QCOMPARE(furanRing->position(benzene->atoms()[0]), 0);
}

void RingTest::contains()
{
    foreach(chemkit::Atom *atom, benzene->atoms()){
        if(atom->is(chemkit::Atom::Carbon)){
            QCOMPARE(benzeneRing->contains(atom), true);
        }
        else{
            QCOMPARE(benzeneRing->contains(atom), false);
        }
    }
    foreach(chemkit::Bond *bond, benzene->bonds()){
        if(bond->atom1()->is(chemkit::Atom::Carbon) && bond->atom2()->is(chemkit::Atom::Carbon)){
            QCOMPARE(benzeneRing->contains(bond), true);
        }
        else{
            QCOMPARE(benzeneRing->contains(bond), false);
        }
    }
    QCOMPARE(benzeneRing->contains(chemkit::Atom::Carbon), true);
    QCOMPARE(benzeneRing->contains(chemkit::Atom::Hydrogen), false);
    QCOMPARE(benzeneRing->contains(chemkit::Atom::Oxygen), false);

    QCOMPARE(furanRing->contains(chemkit::Atom::Carbon), true);
    QCOMPARE(furanRing->contains(chemkit::Atom::Hydrogen), false);
    QCOMPARE(furanRing->contains(chemkit::Atom::Oxygen), true);
}

void RingTest::heteroatomCount()
{
    QCOMPARE(benzeneRing->heteroatomCount(), 0);
    QCOMPARE(furanRing->heteroatomCount(), 1);
}

void RingTest::isHeterocycle()
{
    QCOMPARE(benzeneRing->isHeterocycle(), false);
    QCOMPARE(furanRing->isHeterocycle(), true);
}

void RingTest::isAromatic()
{
    QCOMPARE(benzeneRing->isAromatic(), true);
    QCOMPARE(furanRing->isAromatic(), true);
    QCOMPARE(cyclohexaneRing->isAromatic(), false);
    QCOMPARE(cyclopropaneRing->isAromatic(), false);
}

void RingTest::cleanupTestCase()
{
    delete benzeneRing->molecule();
    delete furanRing->molecule();
    delete cyclohexaneRing->molecule();
    delete cyclopropaneRing->molecule();
}

QTEST_APPLESS_MAIN(RingTest)
<commit_msg>Fix compilation error in RingTest<commit_after>/******************************************************************************
**
** Copyright (C) 2009-2011 Kyle Lutz <kyle.r.lutz@gmail.com>
** All rights reserved.
**
** This file is a part of the chemkit project. For more information
** see <http://www.chemkit.org>.
**
** 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 the chemkit project 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.
**
******************************************************************************/

#include "ringtest.h"

#include <chemkit/chemkit.h>
#include <chemkit/ring.h>
#include <chemkit/molecule.h>
#include <chemkit/lineformat.h>

void RingTest::initTestCase()
{
    chemkit::LineFormat *inchi = chemkit::LineFormat::create("inchi");

    // benzene
    benzene = inchi->read("InChI=1/C6H6/c1-2-4-6-5-3-1/h1-6H");
    QVERIFY(benzene != 0);
    QCOMPARE(benzene->ringCount(), 1);
    benzeneRing = benzene->rings()[0];

    // furan
    furan = inchi->read("InChI=1/C4H4O/c1-2-4-5-3-1/h1-4H");
    QVERIFY(furan != 0);
    QCOMPARE(furan->ringCount(), 1);
    furanRing = furan->rings()[0];

    // cyclohexane
    cyclohexane = inchi->read("InChI=1S/C6H12/c1-2-4-6-5-3-1/h1-6H2");
    QVERIFY(cyclohexane != 0);
    QCOMPARE(cyclohexane->ringCount(), 1);
    cyclohexaneRing = cyclohexane->rings()[0];

    // cyclopropane
    cyclopropane = inchi->read("InChI=1/C3H6/c1-2-3-1/h1-3H2");
    QVERIFY(cyclopropane != 0);
    QCOMPARE(cyclopropane->ringCount(), 1);
    cyclopropaneRing = cyclopropane->rings()[0];

    delete inchi;
}

void RingTest::molecule()
{
    QCOMPARE(benzeneRing->molecule(), benzene);
    QCOMPARE(furanRing->molecule(), furan);
}

void RingTest::atoms()
{
    QCOMPARE(benzeneRing->atoms().size(), size_t(6));
    foreach(chemkit::Atom *atom, benzeneRing->atoms()){
        QVERIFY(atom->molecule() == benzene);
        QVERIFY(benzene->contains(atom));

        QVERIFY(atom->is(chemkit::Atom::Carbon));
    }
}

void RingTest::atomCount()
{
    QCOMPARE(benzeneRing->atomCount(), 6);
    QCOMPARE(furanRing->atomCount(), 5);
    QCOMPARE(cyclohexaneRing->atomCount(), 6);
    QCOMPARE(cyclopropaneRing->atomCount(), 3);

    QCOMPARE(benzeneRing->atomCount(chemkit::Atom::Carbon), 6);
    QCOMPARE(benzeneRing->atomCount(chemkit::Atom::Hydrogen), 0);
    QCOMPARE(benzeneRing->atomCount(chemkit::Atom::Oxygen), 0);
    QCOMPARE(furanRing->atomCount(chemkit::Atom::Carbon), 4);
    QCOMPARE(furanRing->atomCount(chemkit::Atom::Hydrogen), 0);
    QCOMPARE(furanRing->atomCount(chemkit::Atom::Oxygen), 1);
}

void RingTest::size()
{
    QCOMPARE(benzeneRing->size(), 6);
    QCOMPARE(furanRing->size(), 5);
    QCOMPARE(cyclohexaneRing->size(), 6);
    QCOMPARE(cyclopropaneRing->size(), 3);
}

void RingTest::bonds()
{
    QCOMPARE(benzeneRing->bonds().size(), size_t(6));
    foreach(chemkit::Bond *bond, benzeneRing->bonds()){
        QVERIFY(bond->molecule() == benzene);
        QVERIFY(benzene->contains(bond));

        QVERIFY(bond->atom1()->is(chemkit::Atom::Carbon));
        QVERIFY(bond->atom2()->is(chemkit::Atom::Carbon));
    }
}

void RingTest::bondCount()
{
    QCOMPARE(benzeneRing->bondCount(), 6);
    QCOMPARE(furanRing->bondCount(), 5);
    QCOMPARE(cyclohexaneRing->bondCount(), 6);
    QCOMPARE(cyclopropaneRing->bondCount(), 3);
}

void RingTest::root()
{
    QVERIFY(benzeneRing->root()->is(chemkit::Atom::Carbon));
    QVERIFY(furanRing->root()->is(chemkit::Atom::Oxygen));
}

void RingTest::position()
{
    chemkit::Atom *furanOxygen = furanRing->root();
    QVERIFY(furanOxygen->is(chemkit::Atom::Oxygen));
    foreach(chemkit::Atom *atom, furanRing->atoms()){
        if(atom->isBondedTo(furanOxygen)){
            QCOMPARE(furanRing->position(atom), 1);
            QCOMPARE(furanRing->position(atom, furanOxygen), 1);
        }
        else if(atom == furanOxygen){
            QCOMPARE(furanRing->position(atom), 0);
            QCOMPARE(furanRing->position(atom, furanOxygen), 0);
        }
        else{
            QCOMPARE(furanRing->position(atom), 2);
            QCOMPARE(furanRing->position(atom, furanOxygen), 2);
        }
    }

    // atom from another molecule
    QCOMPARE(furanRing->position(benzene->atoms()[0]), 0);
}

void RingTest::contains()
{
    foreach(chemkit::Atom *atom, benzene->atoms()){
        if(atom->is(chemkit::Atom::Carbon)){
            QCOMPARE(benzeneRing->contains(atom), true);
        }
        else{
            QCOMPARE(benzeneRing->contains(atom), false);
        }
    }
    foreach(chemkit::Bond *bond, benzene->bonds()){
        if(bond->atom1()->is(chemkit::Atom::Carbon) && bond->atom2()->is(chemkit::Atom::Carbon)){
            QCOMPARE(benzeneRing->contains(bond), true);
        }
        else{
            QCOMPARE(benzeneRing->contains(bond), false);
        }
    }
    QCOMPARE(benzeneRing->contains(chemkit::Atom::Carbon), true);
    QCOMPARE(benzeneRing->contains(chemkit::Atom::Hydrogen), false);
    QCOMPARE(benzeneRing->contains(chemkit::Atom::Oxygen), false);

    QCOMPARE(furanRing->contains(chemkit::Atom::Carbon), true);
    QCOMPARE(furanRing->contains(chemkit::Atom::Hydrogen), false);
    QCOMPARE(furanRing->contains(chemkit::Atom::Oxygen), true);
}

void RingTest::heteroatomCount()
{
    QCOMPARE(benzeneRing->heteroatomCount(), 0);
    QCOMPARE(furanRing->heteroatomCount(), 1);
}

void RingTest::isHeterocycle()
{
    QCOMPARE(benzeneRing->isHeterocycle(), false);
    QCOMPARE(furanRing->isHeterocycle(), true);
}

void RingTest::isAromatic()
{
    QCOMPARE(benzeneRing->isAromatic(), true);
    QCOMPARE(furanRing->isAromatic(), true);
    QCOMPARE(cyclohexaneRing->isAromatic(), false);
    QCOMPARE(cyclopropaneRing->isAromatic(), false);
}

void RingTest::cleanupTestCase()
{
    delete benzeneRing->molecule();
    delete furanRing->molecule();
    delete cyclohexaneRing->molecule();
    delete cyclopropaneRing->molecule();
}

QTEST_APPLESS_MAIN(RingTest)
<|endoftext|>


<commit_before>#include <string>
#include <vector>

#include "vtrc-server/vtrc-application.h"
#include "boost/program_options.hpp"
#include "boost/algorithm/string.hpp"

#include "vtrc-server/vtrc-application.h"
#include "vtrc-common/vtrc-pool-pair.h"
#include "remote-fs-impl.h"
#include "protocol/remotefs.pb.h"
#include "vtrc-common/vtrc-rpc-service-wrapper.h"

#include "vtrc-server/vtrc-listener-tcp.h"
#include "vtrc-server/vtrc-listener-local.h"

#include "vtrc-bind.h"
#include "vtrc-ref.h"

namespace po = boost::program_options;
using namespace vtrc;

class fs_application: public server::application {
    typedef fs_application this_type;
public:
    fs_application( common::pool_pair &pp )
        :server::application(pp)
    { }

    ~fs_application( )
    {
        google::protobuf::ShutdownProtobufLibrary( );
    }

    vtrc::shared_ptr<common::rpc_service_wrapper>
             get_service_by_name( common::connection_iface* connection,
                                  const std::string &service_name )
    {
        if( service_name == remote_fs::name( ) ) {
            return vtrc::make_shared<common::rpc_service_wrapper>
                    (remote_fs::create(connection));
        } else if(service_name == remote_file::name( )) {
            return vtrc::make_shared<common::rpc_service_wrapper>
                    (remote_file::create(connection));
        }

        /// empty service;
        return vtrc::shared_ptr<common::rpc_service_wrapper>( );
    }

    void on_new_connection( server::listener_sptr l,
                            const common::connection_iface *c )
    {
        std::cout << "New connection: "
                  << "\n\tep:     " << l->name( )
                  << "\n\tclient: " << c->name( )
                  << "\n"
                    ;
    }

    void on_stop_connection( server::listener_sptr l,
                             const common::connection_iface *c )
    {
        std::cout << "Close connection: "
                  << c->name( ) << "\n";
    }

    void attach_listener( server::listener_sptr listen )
    {
        listen->get_on_new_connection( ).connect(
                    vtrc::bind( &this_type::on_new_connection, this,
                                listen, _1 ));
        listen->get_on_stop_connection( ).connect(
                    vtrc::bind( &this_type::on_stop_connection, this,
                                listen, _1 ));
    }

};

void get_options( po::options_description& desc )
{
    desc.add_options( )
        ("help,?",   "help message")
        ("server,s", po::value<std::vector< std::string> >( ),
                     "endpoint name; <tcp address>:<port> or <pipe/file name>")

        ("io-pool-size,i",  po::value<unsigned>( ), "threads for io operations"
                                                    "; default = 1")
        ("rpc-pool-size,r", po::value<unsigned>( ), "threads for rpc calls"
                                                    "; default = 1")

        ;
}

server::listener_sptr create_from_string( const std::string &name,
                                          server::application &app)
{
    /// result endpoint
    server::listener_sptr result;

    std::vector<std::string> params;

    size_t delim_pos = name.find_last_of( ':' );
    if( delim_pos == std::string::npos ) {

        /// local: <localname>
        params.push_back( name );

    } else {

        /// tcp: <addres>:<port>
        params.push_back( std::string( name.begin( ),
                                       name.begin( ) + delim_pos ) );

        params.push_back( std::string( name.begin( ) + delim_pos + 1,
                                       name.end( ) ) );
    }

    if( params.size( ) == 1 ) {         /// local endpoint

        result = server::listeners::local::create( app, params[0] );

    } else if( params.size( ) == 2 ) {  /// TCP

        result = server::listeners::tcp::create( app,
                        params[0],
                        boost::lexical_cast<unsigned short>(params[1]));

    }
    return result;
}

int start( const po::variables_map &params )
{
    if( params.count( "server" ) == 0 ) {
        throw std::runtime_error("Server endpoint is not defined;\n"
                                 "Use --help for details");
    }

    unsigned io_size = params.count( "io-pool-size" )
            ? params["io-pool-size"].as<unsigned>( )
            : 1;

    if( io_size < 1 ) {
        throw std::runtime_error( "io-pool-size must be at least 1" );
    }

    unsigned rpc_size = params.count( "rpc-pool-size" )
            ? params["rpc-pool-size"].as<unsigned>( )
            : 1;

    if( rpc_size < 1 ) {
        throw std::runtime_error( "rpc-pool-size must be at least 1" );
    }

    typedef std::vector<std::string> string_vector;
    string_vector servers = params["server"].as< string_vector >( );

    common::pool_pair pp( io_size, rpc_size );
    fs_application app( pp );

    std::vector<server::listener_sptr> listeners;

    listeners.reserve(servers.size( ));

    for( string_vector::const_iterator b(servers.begin( )), e(servers.end( ));
                    b != e; ++b)
    {
        std::cout << "Starting listener at '" <<  *b << "'...";
        server::listener_sptr new_listener = create_from_string( *b, app );
        listeners.push_back(new_listener);
        app.attach_listener( new_listener );
        new_listener->start( );
        std::cout << "Ok\n";
    }

    pp.join_all( );

    return 0;
}
<commit_msg>examples. fs readme<commit_after>#include <string>
#include <vector>

#include "vtrc-server/vtrc-application.h"
#include "boost/program_options.hpp"
#include "boost/algorithm/string.hpp"

#include "vtrc-server/vtrc-application.h"
#include "vtrc-common/vtrc-pool-pair.h"
#include "remote-fs-impl.h"
#include "protocol/remotefs.pb.h"
#include "vtrc-common/vtrc-rpc-service-wrapper.h"

#include "vtrc-server/vtrc-listener-tcp.h"
#include "vtrc-server/vtrc-listener-local.h"

#include "vtrc-bind.h"
#include "vtrc-ref.h"

namespace po = boost::program_options;
using namespace vtrc;

class fs_application: public server::application {
    typedef fs_application this_type;
public:
    fs_application( common::pool_pair &pp )
        :server::application(pp)
    { }

    ~fs_application( )
    {
        google::protobuf::ShutdownProtobufLibrary( );
    }

    vtrc::shared_ptr<common::rpc_service_wrapper>
             get_service_by_name( common::connection_iface* connection,
                                  const std::string &service_name )
    {
        if( service_name == remote_fs::name( ) ) {
            return vtrc::make_shared<common::rpc_service_wrapper>
                    (remote_fs::create(connection));
        } else if(service_name == remote_file::name( )) {
            return vtrc::make_shared<common::rpc_service_wrapper>
                    (remote_file::create(connection));
        }

        /// empty service;
        return vtrc::shared_ptr<common::rpc_service_wrapper>( );
    }

    void on_new_connection( server::listener_sptr l,
                            const common::connection_iface *c )
    {
        std::cout << "New connection: "
                  << "\n\tep:     " << l->name( )
                  << "\n\tclient: " << c->name( )
                  << "\n"
                    ;
    }

    void on_stop_connection( server::listener_sptr l,
                             const common::connection_iface *c )
    {
        std::cout << "Close connection: "
                  << c->name( ) << "\n";
    }

    void attach_listener( server::listener_sptr listen )
    {
        listen->get_on_new_connection( ).connect(
                    vtrc::bind( &this_type::on_new_connection, this,
                                listen, _1 ));
        listen->get_on_stop_connection( ).connect(
                    vtrc::bind( &this_type::on_stop_connection, this,
                                listen, _1 ));
    }

};

void get_options( po::options_description& desc )
{
    desc.add_options( )
        ("help,?",   "help message")
        ("server,s", po::value<std::vector< std::string> >( ),
                     "endpoint name; <tcp address>:<port> or <pipe/file name>")

        ("io-pool-size,i",  po::value<unsigned>( ), "threads for io operations"
                                                    "; default = 1")
        ("rpc-pool-size,r", po::value<unsigned>( ), "threads for rpc calls"
                                                    "; default = 1")

        ;
}

server::listener_sptr create_from_string( const std::string &name,
                                          server::application &app)
{
    /// result endpoint
    server::listener_sptr result;

    std::vector<std::string> params;

    size_t delim_pos = name.find_last_of( ':' );
    if( delim_pos == std::string::npos ) {

        /// local: <localname>
        params.push_back( name );

    } else {

        /// tcp: <addres>:<port>
        params.push_back( std::string( name.begin( ),
                                       name.begin( ) + delim_pos ) );

        params.push_back( std::string( name.begin( ) + delim_pos + 1,
                                       name.end( ) ) );
    }

    if( params.size( ) == 1 ) {         /// local endpoint

        result = server::listeners::local::create( app, params[0] );

    } else if( params.size( ) == 2 ) {  /// TCP

        result = server::listeners::tcp::create( app,
                        params[0],
                        boost::lexical_cast<unsigned short>(params[1]));

    }
    return result;
}

int start( const po::variables_map &params )
{
    if( params.count( "server" ) == 0 ) {
        throw std::runtime_error("Server endpoint is not defined;\n"
                                 "Use --help for details");
    }

    unsigned io_size = params.count( "io-pool-size" )
            ? params["io-pool-size"].as<unsigned>( )
            : 1;

    if( io_size < 1 ) {
        throw std::runtime_error( "io-pool-size must be at least 1" );
    }

    unsigned rpc_size = params.count( "rpc-pool-size" )
            ? params["rpc-pool-size"].as<unsigned>( )
            : 1;

    if( rpc_size < 1 ) {
        throw std::runtime_error( "rpc-pool-size must be at least 1" );
    }

    typedef std::vector<std::string> string_vector;
    string_vector servers = params["server"].as<string_vector>( );

    common::pool_pair pp( io_size, rpc_size );
    fs_application app( pp );

    std::vector<server::listener_sptr> listeners;

    listeners.reserve(servers.size( ));

    for( string_vector::const_iterator b(servers.begin( )), e(servers.end( ));
                    b != e; ++b)
    {
        std::cout << "Starting listener at '" <<  *b << "'...";
        server::listener_sptr new_listener = create_from_string( *b, app );
        listeners.push_back(new_listener);
        app.attach_listener( new_listener );
        new_listener->start( );
        std::cout << "Ok\n";
    }

    pp.join_all( );

    return 0;
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    TripleTKMain.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "TripleTKMain.h"

/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%TripleTKMain Member functions%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

//------------------------------------------------------------
TripleTKMain ::TripleTKMain()
  {
  window = make_window();
  }

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

//------------------------------------------------------------
void TripleTKMain::synchronize2D(void)
  {
  float iwDiff  = tk2D->iwMax() - tk2D->iwMin();
  float b       = (float)((int)log10(iwDiff)-2);
  double iwMin  = ((int)(tk2D->iwMin()*pow(10, -b)))/pow(10,-b);
  double iwMax  = ((int)(tk2D->iwMax()*pow(10, -b)))/pow(10,-b);
  double iwStep = (iwMax-iwMin)/100.0;
  sliceNumberSlider->range(0.0f, tk2D->numSlices());
  sliceNumberSlider->value((float)((int)tk2D->numSlices()/2));
  levelOutput->range(iwMin-iwStep,iwMax+iwStep);
  windowOutput->range(iwMin-iwStep,iwMax+iwStep);
  levelOutput->step(iwStep);
  windowOutput->step(iwStep);
  levelOutput->value(iwMin);
  windowOutput->value(iwMax);
  tk2D->flipY(true);
  tk2D->setOriginalLevel(iwMin);
  tk2D->setOriginalWindow(iwMax);
  }

//-------------------------------------------------------------
void TripleTKMain::synchronize3D(void)
  {
  tk3D->viewAxial(true);
  tk3D->viewCoronal(false);
  tk3D->viewSaggital(false);
  tk3D->viewOutline(false);
  tk3D->viewVolRend(false);
  tk3D->opacity(1);
  tk3D->show();
  tk3D->update();
  }

//-------------------------------------------------------------
void TripleTKMain::SetImage(ImageType::Pointer img)
  {
  //Set a spacing
  double *spacing = (double*)img->GetSpacing();
  spacing[0] = 1;
  spacing[1] = 1;
  spacing[2] = 1;
  img->SetSpacing(spacing);

  //Pass image data to TripleTK2D/3D
  tk2D->SetInputImage(img);
  tk3D->SetInputImage(img);

  //Clean everything up
  synchronize2D();
  synchronize3D();
  }

//-------------------------------------------------------------
void TripleTKMain::show(void)
  {
  tk2D->show();
  tk3D->show();
  }

//-------------------------------------------------------------
void TripleTKMain::update(void)
  {
  tk2D->update();
  tk3D->update();
  }

//-------------------------------------------------------------
void TripleTKMain::redraw(void)
  {
  tk2D->redraw();
  tk3D->redraw();
  }

/*
*   Helper function to set slice num callback
*/
void selectSliceCB(void)
  {
  sliceNumberSlider->value(tk2D->sliceNum());
  if (coronal2D->value() == 1) tk3D->sliceCoronal(tk2D->sliceNum());
  else if (axial2D->value() == 1)tk3D->sliceAxial(tk2D->sliceNum());
  else if (sagittal2D->value() == 1)tk3D->sliceSaggital(tk2D->sliceNum());
  tk3D->update();
  tk2D->update();
  }

//-------------------------------------------------------------
void TripleTKMain::setCallBacks(void)
  {
  tk2D->sliceNumCallBack(selectSliceCB);
  }

//-------------------------------------------------------------
Fl_Window * TripleTKMain::getWindow()
  {
  return window;
  }

/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%SHINY BACKGROUND%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

static uchar color[8][3] =
  {
  {128,136,149},
  {63,54,21},
  {128,136,146},
  {223,223,223},
  {121,128,128},
  {192,206,220},
  {137,143,145},
  {99,81,64}
  };
static int thickness = 3;

int which = 0;

static Fl_Color pcolor;

static uchar C[8][3]; // actual colors for current button

static void calc_color(Fl_Color c)
  {
  uchar r[3];
  pcolor = c;
  Fl::get_color(c,r[0],r[1],r[2]);
  for (int x = 0; x<8; x++) for (int y=0; y<3; y++)
    {
    int i = r[y]-166+color[x][y];
    if (i<0) i = 0; else if (i>255) i = 255;
    C[x][y] = i;
    }
  }

//will be the box in the background of the window
void shiny_flat_box(int x, int y1, int w, int h, Fl_Color c)
  {
  if (c != pcolor) calc_color(c);
  int y = Fl_Window::current()->h()-(y1+h);
  gl_start();
  glBegin(GL_POLYGON);
  glColor3ub(C[4][0],C[4][1],C[4][2]);
  glVertex2i(x,y);
  glColor3ub(C[5][0],C[5][1],C[5][2]);
  glVertex2i(x+w,y);
  glColor3ub(C[6][0],C[6][1],C[6][2]);
  glVertex2i(x+w,y+h);
  glColor3ub(C[7][0],C[7][1],C[7][2]);
  glVertex2i(x,y+h);
  glEnd();

  gl_finish();
  Fl::flush();
  }

//define box for shiny background
#define SHINY_BOX (Fl_Boxtype)30

/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%MAIN%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

int main()
  {
  Fl::gl_visual(FL_DOUBLE | FL_RGB | FL_ALPHA | FL_DEPTH);
  Fl::visual(FL_DOUBLE | FL_RGB | FL_ALPHA | FL_DEPTH);
  Fl::set_boxtype(SHINY_BOX,shiny_flat_box,0,0,0,0);//shiny background

  //Specify Images to load
  char *metaImageFileName;
  metaImageFileName = fl_file_chooser("Pick a MetaImage file", "*.mh*", "/images");
  if(metaImageFileName == NULL)  return 0;

  std::cout << "Creating window..." << std::endl;

  //TripleTKMain viewer type
  typedef TripleTKMain ImageViewerType;
  ImageViewerType* viewer = new ImageViewerType;

  viewer->getWindow()->box(SHINY_BOX);
  viewer->getWindow()->show();
  viewer->setCallBacks();

  std::cout << "loading MetaImage..." << std::endl;

  //Define the Image type
  typedef itk::Image<short,3>  ImageType;
  ImageType::Pointer input_image;

  //Load the image
  typedef FileIOToImageFilter<ImageType> LoaderType;
  ObjectFactoryBase::RegisterFactory(new FileIOMetaImageFactory);
  LoaderType::Pointer loader = LoaderType::New();

  //set mh* file
  loader->SetFileName(metaImageFileName);
  loader->Update();
  input_image  = loader->GetOutput();

  std::cout << "Showing Images..." << std::endl;

  viewer->SetImage(input_image);
  viewer->show();
  viewer->getWindow()->redraw();

  return Fl::run();
  }
<commit_msg>FIX: unused variable removed.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    TripleTKMain.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "TripleTKMain.h"

/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%TripleTKMain Member functions%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

//------------------------------------------------------------
TripleTKMain ::TripleTKMain()
  {
  window = make_window();
  }

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

//------------------------------------------------------------
void TripleTKMain::synchronize2D(void)
  {
  float iwDiff  = tk2D->iwMax() - tk2D->iwMin();
  float b       = (float)((int)log10(iwDiff)-2);
  double iwMin  = ((int)(tk2D->iwMin()*pow(10, -b)))/pow(10,-b);
  double iwMax  = ((int)(tk2D->iwMax()*pow(10, -b)))/pow(10,-b);
  double iwStep = (iwMax-iwMin)/100.0;
  sliceNumberSlider->range(0.0f, tk2D->numSlices());
  sliceNumberSlider->value((float)((int)tk2D->numSlices()/2));
  levelOutput->range(iwMin-iwStep,iwMax+iwStep);
  windowOutput->range(iwMin-iwStep,iwMax+iwStep);
  levelOutput->step(iwStep);
  windowOutput->step(iwStep);
  levelOutput->value(iwMin);
  windowOutput->value(iwMax);
  tk2D->flipY(true);
  tk2D->setOriginalLevel(iwMin);
  tk2D->setOriginalWindow(iwMax);
  }

//-------------------------------------------------------------
void TripleTKMain::synchronize3D(void)
  {
  tk3D->viewAxial(true);
  tk3D->viewCoronal(false);
  tk3D->viewSaggital(false);
  tk3D->viewOutline(false);
  tk3D->viewVolRend(false);
  tk3D->opacity(1);
  tk3D->show();
  tk3D->update();
  }

//-------------------------------------------------------------
void TripleTKMain::SetImage(ImageType::Pointer img)
  {
  //Set a spacing
  double *spacing = (double*)img->GetSpacing();
  spacing[0] = 1;
  spacing[1] = 1;
  spacing[2] = 1;
  img->SetSpacing(spacing);

  //Pass image data to TripleTK2D/3D
  tk2D->SetInputImage(img);
  tk3D->SetInputImage(img);

  //Clean everything up
  synchronize2D();
  synchronize3D();
  }

//-------------------------------------------------------------
void TripleTKMain::show(void)
  {
  tk2D->show();
  tk3D->show();
  }

//-------------------------------------------------------------
void TripleTKMain::update(void)
  {
  tk2D->update();
  tk3D->update();
  }

//-------------------------------------------------------------
void TripleTKMain::redraw(void)
  {
  tk2D->redraw();
  tk3D->redraw();
  }

/*
*   Helper function to set slice num callback
*/
void selectSliceCB(void)
  {
  sliceNumberSlider->value(tk2D->sliceNum());
  if (coronal2D->value() == 1) tk3D->sliceCoronal(tk2D->sliceNum());
  else if (axial2D->value() == 1)tk3D->sliceAxial(tk2D->sliceNum());
  else if (sagittal2D->value() == 1)tk3D->sliceSaggital(tk2D->sliceNum());
  tk3D->update();
  tk2D->update();
  }

//-------------------------------------------------------------
void TripleTKMain::setCallBacks(void)
  {
  tk2D->sliceNumCallBack(selectSliceCB);
  }

//-------------------------------------------------------------
Fl_Window * TripleTKMain::getWindow()
  {
  return window;
  }

/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%SHINY BACKGROUND%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

static uchar color[8][3] =
  {
  {128,136,149},
  {63,54,21},
  {128,136,146},
  {223,223,223},
  {121,128,128},
  {192,206,220},
  {137,143,145},
  {99,81,64}
  };

int which = 0;

static Fl_Color pcolor;

static uchar C[8][3]; // actual colors for current button

static void calc_color(Fl_Color c)
  {
  uchar r[3];
  pcolor = c;
  Fl::get_color(c,r[0],r[1],r[2]);
  for (int x = 0; x<8; x++) for (int y=0; y<3; y++)
    {
    int i = r[y]-166+color[x][y];
    if (i<0) i = 0; else if (i>255) i = 255;
    C[x][y] = i;
    }
  }

//will be the box in the background of the window
void shiny_flat_box(int x, int y1, int w, int h, Fl_Color c)
  {
  if (c != pcolor) calc_color(c);
  int y = Fl_Window::current()->h()-(y1+h);
  gl_start();
  glBegin(GL_POLYGON);
  glColor3ub(C[4][0],C[4][1],C[4][2]);
  glVertex2i(x,y);
  glColor3ub(C[5][0],C[5][1],C[5][2]);
  glVertex2i(x+w,y);
  glColor3ub(C[6][0],C[6][1],C[6][2]);
  glVertex2i(x+w,y+h);
  glColor3ub(C[7][0],C[7][1],C[7][2]);
  glVertex2i(x,y+h);
  glEnd();

  gl_finish();
  Fl::flush();
  }

//define box for shiny background
#define SHINY_BOX (Fl_Boxtype)30

/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%MAIN%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

int main()
  {
  Fl::gl_visual(FL_DOUBLE | FL_RGB | FL_ALPHA | FL_DEPTH);
  Fl::visual(FL_DOUBLE | FL_RGB | FL_ALPHA | FL_DEPTH);
  Fl::set_boxtype(SHINY_BOX,shiny_flat_box,0,0,0,0);//shiny background

  //Specify Images to load
  char *metaImageFileName;
  metaImageFileName = fl_file_chooser("Pick a MetaImage file", "*.mh*", "/images");
  if(metaImageFileName == NULL)  return 0;

  std::cout << "Creating window..." << std::endl;

  //TripleTKMain viewer type
  typedef TripleTKMain ImageViewerType;
  ImageViewerType* viewer = new ImageViewerType;

  viewer->getWindow()->box(SHINY_BOX);
  viewer->getWindow()->show();
  viewer->setCallBacks();

  std::cout << "loading MetaImage..." << std::endl;

  //Define the Image type
  typedef itk::Image<short,3>  ImageType;
  ImageType::Pointer input_image;

  //Load the image
  typedef FileIOToImageFilter<ImageType> LoaderType;
  ObjectFactoryBase::RegisterFactory(new FileIOMetaImageFactory);
  LoaderType::Pointer loader = LoaderType::New();

  //set mh* file
  loader->SetFileName(metaImageFileName);
  loader->Update();
  input_image  = loader->GetOutput();

  std::cout << "Showing Images..." << std::endl;

  viewer->SetImage(input_image);
  viewer->show();
  viewer->getWindow()->redraw();

  return Fl::run();
  }
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/trace_processor/importers/json/json_trace_parser.h"

#include <inttypes.h>

#include <limits>
#include <string>

#include "perfetto/base/logging.h"
#include "perfetto/ext/base/string_view.h"
#include "perfetto/ext/base/utils.h"
#include "src/trace_processor/importers/json/json_tracker.h"
#include "src/trace_processor/importers/json/json_utils.h"
#include "src/trace_processor/process_tracker.h"
#include "src/trace_processor/slice_tracker.h"
#include "src/trace_processor/trace_processor_context.h"
#include "src/trace_processor/track_tracker.h"

namespace perfetto {
namespace trace_processor {

JsonTraceParser::JsonTraceParser(TraceProcessorContext* context)
    : context_(context), systrace_line_parser_(context) {}

JsonTraceParser::~JsonTraceParser() = default;

void JsonTraceParser::ParseFtracePacket(uint32_t,
                                        int64_t,
                                        TimestampedTracePiece) {
  PERFETTO_FATAL("Json Trace Parser cannot handle ftrace packets.");
}

void JsonTraceParser::ParseTracePacket(int64_t timestamp,
                                       TimestampedTracePiece ttp) {
  PERFETTO_DCHECK(json::IsJsonSupported());

#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
  PERFETTO_DCHECK(ttp.type == TimestampedTracePiece::Type::kJsonValue ||
                  ttp.type == TimestampedTracePiece::Type::kSystraceLine);
  if (ttp.type == TimestampedTracePiece::Type::kSystraceLine) {
    systrace_line_parser_.ParseLine(*ttp.systrace_line);
    return;
  }

  const Json::Value& value = *(ttp.json_value);

  ProcessTracker* procs = context_->process_tracker.get();
  TraceStorage* storage = context_->storage.get();
  SliceTracker* slice_tracker = context_->slice_tracker.get();

  auto& ph = value["ph"];
  if (!ph.isString())
    return;
  char phase = *ph.asCString();

  base::Optional<uint32_t> opt_pid;
  base::Optional<uint32_t> opt_tid;

  if (value.isMember("pid"))
    opt_pid = json::CoerceToUint32(value["pid"]);
  if (value.isMember("tid"))
    opt_tid = json::CoerceToUint32(value["tid"]);

  uint32_t pid = opt_pid.value_or(0);
  uint32_t tid = opt_tid.value_or(pid);

  base::StringView cat = value.isMember("cat")
                             ? base::StringView(value["cat"].asCString())
                             : base::StringView();
  base::StringView name = value.isMember("name")
                              ? base::StringView(value["name"].asCString())
                              : base::StringView();

  StringId cat_id = storage->InternString(cat);
  StringId name_id = storage->InternString(name);
  UniqueTid utid = procs->UpdateThread(tid, pid);

  switch (phase) {
    case 'B': {  // TRACE_EVENT_BEGIN.
      TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
      slice_tracker->Begin(timestamp, track_id, cat_id, name_id);
      break;
    }
    case 'E': {  // TRACE_EVENT_END.
      TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
      slice_tracker->End(timestamp, track_id, cat_id, name_id);
      break;
    }
    case 'X': {  // TRACE_EVENT (scoped event).
      base::Optional<int64_t> opt_dur =
          JsonTracker::GetOrCreate(context_)->CoerceToTs(value["dur"]);
      if (!opt_dur.has_value())
        return;
      TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
      slice_tracker->Scoped(timestamp, track_id, cat_id, name_id,
                            opt_dur.value());
      break;
    }
    case 'M': {  // Metadata events (process and thread names).
      if (strcmp(value["name"].asCString(), "thread_name") == 0 &&
          !value["args"]["name"].empty()) {
        const char* thread_name = value["args"]["name"].asCString();
        auto thread_name_id = context_->storage->InternString(thread_name);
        procs->UpdateThreadName(tid, thread_name_id);
        break;
      }
      if (strcmp(value["name"].asCString(), "process_name") == 0 &&
          !value["args"]["name"].empty()) {
        const char* proc_name = value["args"]["name"].asCString();
        procs->SetProcessMetadata(pid, base::nullopt, proc_name);
        break;
      }
    }
  }
#else
  perfetto::base::ignore_result(timestamp);
  perfetto::base::ignore_result(ttp);
  perfetto::base::ignore_result(context_);
  PERFETTO_ELOG("Cannot parse JSON trace due to missing JSON support");
#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
}

}  // namespace trace_processor
}  // namespace perfetto

<commit_msg>tp: ingest args from json events am: 8561f1e807<commit_after>/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/trace_processor/importers/json/json_trace_parser.h"

#include <inttypes.h>

#include <limits>
#include <string>

#include "perfetto/base/logging.h"
#include "perfetto/ext/base/string_view.h"
#include "perfetto/ext/base/utils.h"
#include "src/trace_processor/importers/json/json_tracker.h"
#include "src/trace_processor/importers/json/json_utils.h"
#include "src/trace_processor/process_tracker.h"
#include "src/trace_processor/slice_tracker.h"
#include "src/trace_processor/trace_processor_context.h"
#include "src/trace_processor/track_tracker.h"

namespace perfetto {
namespace trace_processor {

JsonTraceParser::JsonTraceParser(TraceProcessorContext* context)
    : context_(context), systrace_line_parser_(context) {}

JsonTraceParser::~JsonTraceParser() = default;

void JsonTraceParser::ParseFtracePacket(uint32_t,
                                        int64_t,
                                        TimestampedTracePiece) {
  PERFETTO_FATAL("Json Trace Parser cannot handle ftrace packets.");
}

void JsonTraceParser::ParseTracePacket(int64_t timestamp,
                                       TimestampedTracePiece ttp) {
  PERFETTO_DCHECK(json::IsJsonSupported());

#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
  PERFETTO_DCHECK(ttp.type == TimestampedTracePiece::Type::kJsonValue ||
                  ttp.type == TimestampedTracePiece::Type::kSystraceLine);
  if (ttp.type == TimestampedTracePiece::Type::kSystraceLine) {
    systrace_line_parser_.ParseLine(*ttp.systrace_line);
    return;
  }

  const Json::Value& value = *(ttp.json_value);

  ProcessTracker* procs = context_->process_tracker.get();
  TraceStorage* storage = context_->storage.get();
  SliceTracker* slice_tracker = context_->slice_tracker.get();

  auto& ph = value["ph"];
  if (!ph.isString())
    return;
  char phase = *ph.asCString();

  base::Optional<uint32_t> opt_pid;
  base::Optional<uint32_t> opt_tid;

  if (value.isMember("pid"))
    opt_pid = json::CoerceToUint32(value["pid"]);
  if (value.isMember("tid"))
    opt_tid = json::CoerceToUint32(value["tid"]);

  uint32_t pid = opt_pid.value_or(0);
  uint32_t tid = opt_tid.value_or(pid);

  base::StringView cat = value.isMember("cat")
                             ? base::StringView(value["cat"].asCString())
                             : base::StringView();
  base::StringView name = value.isMember("name")
                              ? base::StringView(value["name"].asCString())
                              : base::StringView();

  StringId cat_id = storage->InternString(cat);
  StringId name_id = storage->InternString(name);
  UniqueTid utid = procs->UpdateThread(tid, pid);

  auto args_inserter = [this, &value](ArgsTracker::BoundInserter* inserter) {
    if (value.isMember("args")) {
      json::AddJsonValueToArgs(value["args"], /* flat_key = */ "args",
                               /* key = */ "args", context_->storage.get(),
                               inserter);
    }
  };
  switch (phase) {
    case 'B': {  // TRACE_EVENT_BEGIN.
      TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
      slice_tracker->Begin(timestamp, track_id, cat_id, name_id, args_inserter);
      break;
    }
    case 'E': {  // TRACE_EVENT_END.
      TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
      slice_tracker->End(timestamp, track_id, cat_id, name_id, args_inserter);
      break;
    }
    case 'X': {  // TRACE_EVENT (scoped event).
      base::Optional<int64_t> opt_dur =
          JsonTracker::GetOrCreate(context_)->CoerceToTs(value["dur"]);
      if (!opt_dur.has_value())
        return;
      TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
      slice_tracker->Scoped(timestamp, track_id, cat_id, name_id,
                            opt_dur.value(), args_inserter);
      break;
    }
    case 'M': {  // Metadata events (process and thread names).
      if (strcmp(value["name"].asCString(), "thread_name") == 0 &&
          !value["args"]["name"].empty()) {
        const char* thread_name = value["args"]["name"].asCString();
        auto thread_name_id = context_->storage->InternString(thread_name);
        procs->UpdateThreadName(tid, thread_name_id);
        break;
      }
      if (strcmp(value["name"].asCString(), "process_name") == 0 &&
          !value["args"]["name"].empty()) {
        const char* proc_name = value["args"]["name"].asCString();
        procs->SetProcessMetadata(pid, base::nullopt, proc_name);
        break;
      }
    }
  }
#else
  perfetto::base::ignore_result(timestamp);
  perfetto::base::ignore_result(ttp);
  perfetto::base::ignore_result(context_);
  PERFETTO_ELOG("Cannot parse JSON trace due to missing JSON support");
#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
}

}  // namespace trace_processor
}  // namespace perfetto

<|endoftext|>


<commit_before>#include <amgcl/io/mm.hpp>
#include <amgcl/adapter/crs_tuple.hpp>
#include <amgcl/amg.hpp>
#include <amgcl/make_solver.hpp>
#include <amgcl/make_block_solver.hpp>
#include <amgcl/solver/bicgstab.hpp>
#include <amgcl/solver/gmres.hpp>
#include <amgcl/solver/runtime.hpp>
#include <amgcl/preconditioner/runtime.hpp>
#include <amgcl/amg.hpp>
#include <amgcl/coarsening/smoothed_aggregation.hpp>
#include <amgcl/coarsening/plain_aggregates.hpp>
#include <amgcl/coarsening/ruge_stuben.hpp>
#include <amgcl/coarsening/aggregation.hpp>
#include <amgcl/relaxation/spai0.hpp>
#include <amgcl/relaxation/ilu0.hpp>
#include <amgcl/adapter/crs_tuple.hpp>
#include <boost/program_options.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
// #include <format> // not yet supported

// ./amgcl-block-matrices -A ../data/B_test.mtx  -b 3

int main(int argc, char *argv[])
{
    namespace po = boost::program_options;
    namespace io = amgcl::io;

    using std::vector;
    using std::string;

    po::options_description desc("Options");

    desc.add_options()
        ("help,h", "Show this help.")
        ("prm-file,P",
         po::value<string>(),
         "Parameter file in json format. "
        )
        (
         "prm,p",
         po::value< vector<string> >()->multitoken(),
         "Parameters specified as name=value pairs. "
         "May be provided multiple times. Examples:\n"
         "  -p solver.tol=1e-3\n"
         "  -p precond.coarse_enough=300"
        )
        ("matrix,A",
         po::value<string>(),
         "System matrix in the MatrixMarket format. "
         "When not specified, solves a Poisson problem in 3D unit cube. "
        )
        (
         "block-size,b",
         po::value<int>()->default_value(1),
         "The block size of the system matrix. "
         "When specified, the system matrix is assumed to have block-wise structure. "
         "This usually is the case for problems in elasticity, structural mechanics, "
         "for coupled systems of PDE (such as Navier-Stokes equations), etc. "
        )
        ;

    po::positional_options_description p;
    p.add("prm", -1);

    po::variables_map vm;
    po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
    po::notify(vm);

    if (vm.count("help")) {
        std::cout << desc << std::endl;
        return 0;
    }

    for (int i = 0; i < argc; ++i) {
        if (i) std::cout << " ";
        std::cout << argv[i];
    }
    std::cout << std::endl;

    boost::property_tree::ptree prm;
    if (vm.count("prm-file")) {
        read_json(vm["prm-file"].as<string>(), prm);
    }

    if (vm.count("prm")) {
        for(const string &v : vm["prm"].as<vector<string>>()) {
            amgcl::put(prm, v);
        }
    }

    size_t n, block_size = 1;
    vector<ptrdiff_t> ptr, col;
    vector<double> val;

    if (vm.count("block-size")) {
        block_size = vm["block-size"].as<int>();
    }

    if (vm.count("matrix")) {
        string Afile  = vm["matrix"].as<string>();
        auto [rows, cols] = io::mm_reader(Afile)(ptr, col, val);

        std::cout << "rows: " << rows << std::endl;
        std::cout << "cols: " << cols << std::endl;
        n = rows;
    }

    // We use the tuple of CRS arrays to represent the system matrix.
    // Note that std::tie creates a tuple of references, so no data is actually
    // copied here:
    auto A = std::tie(n, ptr, col, val);
    std::vector<double> rhs (n, 1.0);
    std::vector<double> x   (n, 0.0);

    if (block_size == 1) { // scalar case
        using Backend = amgcl::backend::builtin<double>;

        using Solver1 = amgcl::make_solver<
        amgcl::runtime::preconditioner<Backend>,
        amgcl::runtime::solver::wrapper<Backend>>;

        //using Solver2 = amgcl::make_block_solver<
        using Solver2 = amgcl::make_solver<
        // Use AMG as preconditioner:
        amgcl::amg<
            Backend,
            amgcl::coarsening::smoothed_aggregation,
            amgcl::relaxation::spai0
            >,
        // And BiCGStab as iterative solver:
        amgcl::solver::bicgstab<Backend>>;

        using Solver3 = amgcl::make_solver<
        // Use AMG as preconditioner:
        amgcl::amg<
            Backend,
            amgcl::coarsening::ruge_stuben,
            amgcl::relaxation::spai0
            //amgcl::relaxation::ilu0
            >,
        // And GMRES as iterative solver:
        amgcl::solver::gmres<Backend>>;

        try {
            Solver2::params prm;
            Solver2::backend_params bprm;
            // prm.precond.direct_coarse = false;
            prm.precond.direct_coarse = true;
            //prm.precond.coarsening ...
            Solver2 solve( A, prm, bprm );
            auto [iters, error] = solve(A, rhs, x);

            // Output the number of iterations, the relative error:
            std::cout << "Iters: " << iters << std::endl
                      << "Error: " << error << std::endl;
            // std::cout << "x = [ ";
            // for (auto el : x) {
            //     std::cout << el << ", ";
            // }
            // std::cout << "]\n";
        } catch(std::runtime_error &e) {
            std::cout << "caught exception: " << e.what() << std::endl;
        }
    } else {
        // Compose the solver type
        using dmat_type = amgcl::static_matrix<double, 3, 3>;
        using dvec_type = amgcl::static_matrix<double, 3, 1>;
        using SBackend = amgcl::backend::builtin<double>;    // the outer iterative solver backend
        using PBackend = amgcl::backend::builtin<float>;     // the PSolver backend
        using UBackend = amgcl::backend::builtin<dmat_type>; // the USolver backend
        using BlockSolver = amgcl::make_block_solver<
                // preconditioner
                amgcl::amg<
                    UBackend,
                    amgcl::coarsening::aggregation,
                    amgcl::relaxation::ilu0
                    >,
                // solver
                amgcl::solver::gmres<UBackend>>;
        using Solver = amgcl::make_solver<
                // preconditioner
                amgcl::amg<
                    UBackend,
                    amgcl::coarsening::aggregation,
                    amgcl::relaxation::ilu0
                    >,
                // solver
                amgcl::solver::gmres<UBackend>>;
        try {
            // see `tutorial/3.CoupCons3D/coupcons3d.cpp`
            BlockSolver::params prm;
            BlockSolver::backend_params bprm;
            prm.precond.direct_coarse = false;
            auto Ab = amgcl::adapter::block_matrix<dmat_type>(A);
            auto rhsb = reinterpret_cast<dvec_type*>(rhs.data());
            auto xb = reinterpret_cast<dvec_type*>(x.data());
            auto RHS = amgcl::make_iterator_range(rhsb, rhsb + n / 3);
            auto X = amgcl::make_iterator_range(xb, xb + n / 3);
            Solver solve0( Ab, prm, bprm );
            auto [iters0, error0] = solve0(Ab, RHS, X);
            std::cout << "Iters0: " << iters0 << std::endl
                      << "Error0: " << error0 << std::endl;

            BlockSolver solve( A, prm, bprm );
            auto [iters, error] = solve(A, rhs, x);

            std::cout << "Iters: " << iters << std::endl
                      << "Error: " << error << std::endl;
            std::cout << "x = [ ";
            for (auto el : x) {
                std::cout << el << ", ";
            }
            std::cout << "]\n";

        } catch(std::runtime_error &e) {
            std::cout << "caught exception: " << e.what() << std::endl;
        }
    }
}
<commit_msg>Set RHS := Ax where x = 1<commit_after>#include <amgcl/io/mm.hpp>
#include <amgcl/adapter/crs_tuple.hpp>
#include <amgcl/amg.hpp>
#include <amgcl/make_solver.hpp>
#include <amgcl/make_block_solver.hpp>
#include <amgcl/solver/bicgstab.hpp>
#include <amgcl/solver/gmres.hpp>
#include <amgcl/solver/runtime.hpp>
#include <amgcl/preconditioner/runtime.hpp>
#include <amgcl/amg.hpp>
#include <amgcl/coarsening/smoothed_aggregation.hpp>
#include <amgcl/coarsening/plain_aggregates.hpp>
#include <amgcl/coarsening/ruge_stuben.hpp>
#include <amgcl/coarsening/aggregation.hpp>
#include <amgcl/relaxation/spai0.hpp>
#include <amgcl/relaxation/ilu0.hpp>
#include <amgcl/adapter/crs_tuple.hpp>
#include <boost/program_options.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
// #include <format> // not yet supported

// ./amgcl-block-matrices -A ../data/B_test.mtx  -b 3

int main(int argc, char *argv[])
{
    namespace po = boost::program_options;
    namespace io = amgcl::io;

    using std::vector;
    using std::string;

    po::options_description desc("Options");

    desc.add_options()
        ("help,h", "Show this help.")
        ("prm-file,P",
         po::value<string>(),
         "Parameter file in json format. "
        )
        (
         "prm,p",
         po::value< vector<string> >()->multitoken(),
         "Parameters specified as name=value pairs. "
         "May be provided multiple times. Examples:\n"
         "  -p solver.tol=1e-3\n"
         "  -p precond.coarse_enough=300"
        )
        ("matrix,A",
         po::value<string>(),
         "System matrix in the MatrixMarket format. "
         "When not specified, solves a Poisson problem in 3D unit cube. "
        )
        (
         "block-size,b",
         po::value<int>()->default_value(1),
         "The block size of the system matrix. "
         "When specified, the system matrix is assumed to have block-wise structure. "
         "This usually is the case for problems in elasticity, structural mechanics, "
         "for coupled systems of PDE (such as Navier-Stokes equations), etc. "
        )
        ;

    po::positional_options_description p;
    p.add("prm", -1);

    po::variables_map vm;
    po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
    po::notify(vm);

    if (vm.count("help")) {
        std::cout << desc << std::endl;
        return 0;
    }

    for (int i = 0; i < argc; ++i) {
        if (i) std::cout << " ";
        std::cout << argv[i];
    }
    std::cout << std::endl;

    boost::property_tree::ptree prm;
    if (vm.count("prm-file")) {
        read_json(vm["prm-file"].as<string>(), prm);
    }

    if (vm.count("prm")) {
        for(const string &v : vm["prm"].as<vector<string>>()) {
            amgcl::put(prm, v);
        }
    }

    size_t n, block_size = 1;
    vector<ptrdiff_t> ptr, col;
    vector<double> val;

    if (vm.count("block-size")) {
        block_size = vm["block-size"].as<int>();
    }

    if (vm.count("matrix")) {
        string Afile  = vm["matrix"].as<string>();
        auto [rows, cols] = io::mm_reader(Afile)(ptr, col, val);

        std::cout << "rows: " << rows << std::endl;
        std::cout << "cols: " << cols << std::endl;
        n = rows;
    }

    // We use the tuple of CRS arrays to represent the system matrix.
    // Note that std::tie creates a tuple of references, so no data is actually
    // copied here:
    auto A = std::tie(n, ptr, col, val);
    std::vector<double> rhs (n, 0.0);
    std::vector<double> x   (n, 0.0);

    // Set RHS := Ax where x = 1
    for (size_t i = 0; i < n; ++i) {
        double s = 0;
        for (ptrdiff_t j = ptr[i], e = ptr[i+1]; j < e; ++j) {
            s += val[j];
        }
        rhs[i] = s;
    }

    if (block_size == 1) { // scalar case
        using Backend = amgcl::backend::builtin<double>;

        using Solver1 = amgcl::make_solver<
        amgcl::runtime::preconditioner<Backend>,
        amgcl::runtime::solver::wrapper<Backend>>;

        //using Solver2 = amgcl::make_block_solver<
        using Solver2 = amgcl::make_solver<
        // Use AMG as preconditioner:
        amgcl::amg<
            Backend,
            amgcl::coarsening::smoothed_aggregation,
            amgcl::relaxation::spai0
            >,
        // And BiCGStab as iterative solver:
        amgcl::solver::bicgstab<Backend>>;

        using Solver3 = amgcl::make_solver<
        // Use AMG as preconditioner:
        amgcl::amg<
            Backend,
            amgcl::coarsening::ruge_stuben,
            amgcl::relaxation::spai0
            //amgcl::relaxation::ilu0
            >,
        // And GMRES as iterative solver:
        amgcl::solver::gmres<Backend>>;

        try {
            Solver2::params prm;
            Solver2::backend_params bprm;
            // prm.precond.direct_coarse = false;
            prm.precond.direct_coarse = true;
            //prm.precond.coarsening ...
            Solver2 solve( A, prm, bprm );
            auto [iters, error] = solve(A, rhs, x);

            // Output the number of iterations, the relative error:
            std::cout << "Iters: " << iters << std::endl
                      << "Error: " << error << std::endl;
            // std::cout << "x = [ ";
            // for (auto el : x) {
            //     std::cout << el << ", ";
            // }
            // std::cout << "]\n";
        } catch(std::runtime_error &e) {
            std::cout << "caught exception: " << e.what() << std::endl;
        }
    } else {
        // Compose the solver type
        using dmat_type = amgcl::static_matrix<double, 3, 3>;
        using dvec_type = amgcl::static_matrix<double, 3, 1>;
        using SBackend = amgcl::backend::builtin<double>;    // the outer iterative solver backend
        using PBackend = amgcl::backend::builtin<float>;     // the PSolver backend
        using UBackend = amgcl::backend::builtin<dmat_type>; // the USolver backend
        using BlockSolver = amgcl::make_block_solver<
                // preconditioner
                amgcl::amg<
                    UBackend,
                    amgcl::coarsening::aggregation,
                    amgcl::relaxation::ilu0
                    >,
                // solver
                amgcl::solver::gmres<UBackend>>;
        using Solver = amgcl::make_solver<
                // preconditioner
                amgcl::amg<
                    UBackend,
                    amgcl::coarsening::aggregation,
                    amgcl::relaxation::ilu0
                    >,
                // solver
                amgcl::solver::gmres<UBackend>>;
        try {
            // see `tutorial/3.CoupCons3D/coupcons3d.cpp`
            BlockSolver::params prm;
            BlockSolver::backend_params bprm;
            prm.precond.direct_coarse = false;
            auto Ab = amgcl::adapter::block_matrix<dmat_type>(A);
            auto rhsb = reinterpret_cast<dvec_type*>(rhs.data());
            auto xb = reinterpret_cast<dvec_type*>(x.data());
            auto RHS = amgcl::make_iterator_range(rhsb, rhsb + n / 3);
            auto X = amgcl::make_iterator_range(xb, xb + n / 3);
            Solver solve0( Ab, prm, bprm );
            auto [iters0, error0] = solve0(Ab, RHS, X);
            std::cout << "Iters0: " << iters0 << std::endl
                      << "Error0: " << error0 << std::endl;

            BlockSolver solve( A, prm, bprm );
            auto [iters, error] = solve(A, rhs, x);

            std::cout << "Iters: " << iters << std::endl
                      << "Error: " << error << std::endl;
            std::cout << "x = [ ";
            for (auto el : x) {
                std::cout << el << ", ";
            }
            std::cout << "]\n";

        } catch(std::runtime_error &e) {
            std::cout << "caught exception: " << e.what() << std::endl;
        }
    }
}
<|endoftext|>


<commit_before>//#define ENABLE_DEBUG_TRACES
#include <libport/compiler.hh>

#include <libport/unistd.h>
#include <libport/sysexits.hh>
#include <libport/windows.hh>
#include <iostream>
#include <fstream>
#include <algorithm>

#include <libport/cli.hh>
#include <libport/exception.hh>
#include <libport/foreach.hh>
#include <libport/program-name.hh>
#include <libport/read-stdin.hh>
#include <libport/tokenizer.hh>
#include <libport/utime.hh>

// Inclusion order matters for windows. Leave userver.hh after network.hh.
#include <network/bsdnet/network.hh>
#include "kernel/userver.hh"
#include "kernel/uconnection.hh"

#include "ubanner.hh"

class ConsoleServer
  : public UServer
{
public:
  ConsoleServer(bool fast)
    : UServer("console"), fast(fast), ctime(0)
  {
    if (const char* cp = getenv ("URBI_PATH"))
    {
      std::string up(cp);
      std::list<std::string> paths;
      foreach (const std::string& s, libport::make_tokenizer(up, ":"))
      {
	if (s[0] == '\\' && paths.back().length() == 1)
	  paths.back() += ':' + s;
	else
	  paths.push_back(s);
      }
      foreach (const std::string& s, paths)
	search_path.append_dir(s);
    }
  }

  virtual ~ConsoleServer()
  {}

  virtual void shutdown()
  {
    UServer::shutdown ();
    exit (EX_OK);
  }
  virtual void beforeWork()
  {
  }
  virtual void reset()
  {}

  virtual void reboot()
  {}

  virtual libport::utime_t getTime()
  {
    return fast ? ctime : libport::utime();
  }

  virtual ufloat getPower()
  {
    return ufloat(1);
  }

  //! Called to display the header at each coonection start
  virtual void getCustomHeader(int line, char* header, int maxlength)
  {
    // FIXME: This interface is really really ridiculous and fragile.
    strncpy(header, uconsole_banner[line], maxlength);
  }

  virtual
  UErrorValue
  save_file(const std::string& filename, const std::string& content)
  {
    //! \todo check this code
    std::ofstream os (filename.c_str ());
    os << content;
    os.close ();
    return os.good () ? USUCCESS : UFAIL;
  }

  virtual
  void effectiveDisplay(const char* t)
  {
    std::cout << t;
  }

  bool fast;
  libport::utime_t ctime;
};

namespace
{
  static
  void
  usage ()
  {
    std::cout <<
      "usage: " << libport::program_name << " [OPTIONS] [FILE]\n"
      "\n"
      "  FILE    to load\n"
      "\n"
      "Options:\n"
      "  -h, --help            display this message and exit successfully\n"
      "  -v, --version         display version information\n"
      "  -P, --period PERIOD   ignored for backward compatibility\n"
      "  -p, --port PORT       tcp port URBI will listen to.\n"
      "  -f, --fast            ignore system time, go as fast as possible\n"
      "  -i, --interactive     read and parse stdin in a nonblocking way\n"
      "  -w, --port-file FILE  write port number to specified file.\n"
      ;
    exit (EX_OK);
  }

  static
  void
  version ()
  {
    userver_package_info_dump(std::cout) << std::endl;
    exit (EX_OK);
  }
}

int
main (int argc, const char* argv[])
{
  libport::program_name = argv[0];

  // Input file.
  const char* in = "/dev/stdin";
  /// The port to use.  0 means automatic selection.
  int arg_port = 0;
  /// Where to write the port we use.
  const char* arg_port_filename = 0;
  /// fast mode
  bool fast = false;
  /// interactive mode
  bool interactive = false;
  // Parse the command line.
  {
    int argp = 1;
    for (int i = 1; i < argc; ++i)
    {
      std::string arg = argv[i];

      if (arg == "--fast" || arg == "-f")
	fast = true;
      else if (arg == "--help" || arg == "-h")
	usage();
      else if (arg == "--interactive" || arg == "-i")
	interactive = true;
      else if (arg == "--period" || arg == "-P")
	(void) libport::convert_argument<int> (arg, argv[++i]);
      else if (arg == "--port" || arg == "-p")
	arg_port = libport::convert_argument<int> (arg, argv[++i]);
      else if (arg == "--port-file" || arg == "-w")
	arg_port_filename = argv[++i];
      else if (arg == "--version" || arg == "-v")
	version();
      else if (arg[0] == '-')
	libport::invalid_option (arg);
      else
	// An argument.
	switch (argp++)
	{
	  case 1:
	    in = argv[i];
	    break;
	  default:
	    std::cerr << libport::program_name
		      << ": unexpected argument: " << arg << std::endl
		      << libport::exit (EX_USAGE);
	    break;
	}
    }
  }

  ConsoleServer s (fast);

  int port = Network::createTCPServer(arg_port, "localhost");
  if (!port)
    std::cerr << libport::program_name
	      << ": cannot bind to port " << arg_port
	      << " on localhost" << std::endl
	      << libport::exit (EX_UNAVAILABLE);

  if (arg_port_filename)
    std::ofstream(arg_port_filename, std::ios::out) << port << std::endl;

  s.initialize ();
  UConnection& c = s.getGhostConnection ();
  std::cerr << libport::program_name
	    << ": got ghost connection" << std::endl;

  if (!interactive)
    if (s.load_file(in, c.recv_queue_get ()) != USUCCESS)
      std::cerr << libport::program_name
		<< ": failed to process " << in << std::endl
		<< libport::exit(EX_NOINPUT);

  c.new_data_added_get() = true;

  std::cerr << libport::program_name << ": going to work..." << std::endl;
  libport::utime_t next_time = 0;
  while (true)
  {
    if (interactive)
    {
      std::string input;
      try
      {
	input = libport::read_stdin();
      }
      catch (libport::exception::Exception e)
      {
	std::cerr << e.what() << std::endl;
	interactive = false;
      }
      if (!input.empty())
	s.getGhostConnection().received(input.c_str(), input.length());
    }
    libport::utime_t select_time = 0;
    if (!fast)
    {
      libport::utime_t ctime = libport::utime();
      if (ctime < next_time)
	select_time = next_time - ctime;
      if (interactive)
	select_time = std::min(100000LL, select_time);
    }
    Network::selectAndProcess(select_time);

    next_time = s.work ();
    s.ctime = std::max (next_time, s.ctime + 1000L);
  }
}
<commit_msg>Don't read stdin by default.<commit_after>//#define ENABLE_DEBUG_TRACES
#include <libport/compiler.hh>

#include <libport/unistd.h>
#include <libport/sysexits.hh>
#include <libport/windows.hh>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <libport/cstring>

#include <libport/cli.hh>
#include <libport/exception.hh>
#include <libport/foreach.hh>
#include <libport/program-name.hh>
#include <libport/read-stdin.hh>
#include <libport/tokenizer.hh>
#include <libport/utime.hh>

// Inclusion order matters for windows. Leave userver.hh after network.hh.
#include <network/bsdnet/network.hh>
#include <kernel/userver.hh>
#include <kernel/uconnection.hh>

#include "ubanner.hh"

class ConsoleServer
  : public UServer
{
public:
  ConsoleServer(bool fast)
    : UServer("console"), fast(fast), ctime(0)
  {
    if (const char* cp = getenv ("URBI_PATH"))
    {
      std::string up(cp);
      std::list<std::string> paths;
      foreach (const std::string& s, libport::make_tokenizer(up, ":"))
      {
	if (s[0] == '\\' && paths.back().length() == 1)
	  paths.back() += ':' + s;
	else
	  paths.push_back(s);
      }
      foreach (const std::string& s, paths)
	search_path.append_dir(s);
    }
  }

  virtual ~ConsoleServer()
  {}

  virtual void shutdown()
  {
    UServer::shutdown ();
    exit (EX_OK);
  }
  virtual void beforeWork()
  {
  }
  virtual void reset()
  {}

  virtual void reboot()
  {}

  virtual libport::utime_t getTime()
  {
    return fast ? ctime : libport::utime();
  }

  virtual ufloat getPower()
  {
    return ufloat(1);
  }

  //! Called to display the header at each coonection start
  virtual void getCustomHeader(int line, char* header, int maxlength)
  {
    // FIXME: This interface is really really ridiculous and fragile.
    strncpy(header, uconsole_banner[line], maxlength);
  }

  virtual
  UErrorValue
  save_file(const std::string& filename, const std::string& content)
  {
    //! \todo check this code
    std::ofstream os (filename.c_str ());
    os << content;
    os.close ();
    return os.good () ? USUCCESS : UFAIL;
  }

  virtual
  void effectiveDisplay(const char* t)
  {
    std::cout << t;
  }

  bool fast;
  libport::utime_t ctime;
};

namespace
{
  static
  void
  usage ()
  {
    std::cout <<
      "usage: " << libport::program_name << " [OPTIONS] [FILE...]\n"
      "\n"
      "  FILE    to load.  `-' stands for standard input\n"
      "\n"
      "Options:\n"
      "  -h, --help            display this message and exit successfully\n"
      "  -v, --version         display version information\n"
      "  -P, --period PERIOD   ignored for backward compatibility\n"
      "  -p, --port PORT       tcp port URBI will listen to.\n"
      "  -f, --fast            ignore system time, go as fast as possible\n"
      "  -i, --interactive     read and parse stdin in a nonblocking way\n"
      "  -w, --port-file FILE  write port number to specified file.\n"
      ;
    exit (EX_OK);
  }

  static
  void
  version ()
  {
    userver_package_info_dump(std::cout) << std::endl;
    exit (EX_OK);
  }
}

int
main (int argc, const char* argv[])
{
  libport::program_name = argv[0];

  // Input files.
  typedef std::vector<const char*> files_type;
  files_type files;
  /// The port to use.  0 means automatic selection.
  int arg_port = 0;
  /// Where to write the port we use.
  const char* arg_port_filename = 0;
  /// fast mode
  bool fast = false;
  /// interactive mode
  bool interactive = false;
  // Parse the command line.
  {
    for (int i = 1; i < argc; ++i)
    {
      std::string arg = argv[i];

      if (arg == "--fast" || arg == "-f")
	fast = true;
      else if (arg == "--help" || arg == "-h")
	usage();
      else if (arg == "--interactive" || arg == "-i")
	interactive = true;
      else if (arg == "--period" || arg == "-P")
	(void) libport::convert_argument<int> (arg, argv[++i]);
      else if (arg == "--port" || arg == "-p")
	arg_port = libport::convert_argument<int> (arg, argv[++i]);
      else if (arg == "--port-file" || arg == "-w")
	arg_port_filename = argv[++i];
      else if (arg == "--version" || arg == "-v")
	version();
      else if (arg[0] == '-' && arg[1] != 0)
	libport::invalid_option (arg);
      else
	// An argument: a file.
        files.push_back(STREQ(argv[i], "-") ? "/dev/stdin" : argv[i]);
    }
  }

  ConsoleServer s(fast);

  int port = Network::createTCPServer(arg_port, "localhost");
  if (!port)
    std::cerr << libport::program_name
	      << ": cannot bind to port " << arg_port
	      << " on localhost" << std::endl
	      << libport::exit (EX_UNAVAILABLE);

  if (arg_port_filename)
    std::ofstream(arg_port_filename, std::ios::out) << port << std::endl;

  s.initialize ();
  UConnection& c = s.getGhostConnection ();
  std::cerr << libport::program_name
	    << ": got ghost connection" << std::endl;

  foreach (const char* f, files)
    if (s.load_file(f, c.recv_queue_get ()) != USUCCESS)
      std::cerr << libport::program_name
		<< ": failed to process " << f << std::endl
		<< libport::exit(EX_NOINPUT);

  c.new_data_added_get() = true;

  std::cerr << libport::program_name << ": going to work..." << std::endl;
  libport::utime_t next_time = 0;
  while (true)
  {
    if (interactive)
    {
      std::string input;
      try
      {
	input = libport::read_stdin();
      }
      catch (libport::exception::Exception e)
      {
	std::cerr << e.what() << std::endl;
	interactive = false;
      }
      if (!input.empty())
	s.getGhostConnection().received(input.c_str(), input.length());
    }
    libport::utime_t select_time = 0;
    if (!fast)
    {
      libport::utime_t ctime = libport::utime();
      if (ctime < next_time)
	select_time = next_time - ctime;
      if (interactive)
	select_time = std::min(100000LL, select_time);
    }
    Network::selectAndProcess(select_time);

    next_time = s.work ();
    s.ctime = std::max (next_time, s.ctime + 1000L);
  }
}
<|endoftext|>