<commit_before>// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#include "osgsimpleviewerWX.h"
#include <osgGA/TrackballManipulator>
#include <osgDB/ReadFile>
#include <wx/image.h>
#include <wx/menu.h>

// `Main program' equivalent, creating windows and returning main app frame
bool wxOsgApp::OnInit()
{
    // Create the main frame window
    MainFrame *frame = new MainFrame(NULL, wxT("wxWidgets OSG Sample"),
        wxDefaultPosition, wxDefaultSize);

    // create osg canvas
    //    - initialize
    SimpleViewerWX *viewerWindow = new SimpleViewerWX(frame, wxID_ANY, wxDefaultPosition,
        wxSize(200, 200), wxSUNKEN_BORDER);

    // load the scene.
    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFile(argv[1]);
    if (!loadedModel)
    {
        return false;
    }
    viewerWindow->setSceneData(loadedModel.get());
    viewerWindow->setCameraManipulator(new osgGA::TrackballManipulator);

    frame->SetSimpleViewer(viewerWindow);

    /* Show the frame */
    frame->Show(true);

    return true;
}

IMPLEMENT_APP(wxOsgApp)

BEGIN_EVENT_TABLE(MainFrame, wxFrame)
    EVT_IDLE(MainFrame::OnIdle)
END_EVENT_TABLE()

/* My frame constructor */
MainFrame::MainFrame(wxFrame *frame, const wxString& title, const wxPoint& pos,
    const wxSize& size, long style)
    : wxFrame(frame, wxID_ANY, title, pos, size, style)
{
    _viewerWindow = NULL;
}

void MainFrame::SetSimpleViewer(SimpleViewerWX *viewer)
{
    _viewerWindow = viewer;
}

void MainFrame::OnIdle(wxIdleEvent &event)
{
    _viewerWindow->render();
    event.RequestMore();
}

BEGIN_EVENT_TABLE(GraphicsWindowWX, wxGLCanvas)
    EVT_SIZE            (GraphicsWindowWX::OnSize            )
    EVT_PAINT            (GraphicsWindowWX::OnPaint            )
    EVT_ERASE_BACKGROUND(GraphicsWindowWX::OnEraseBackground)
    EVT_KEY_DOWN        (GraphicsWindowWX::OnKeyDown        )
    EVT_KEY_UP            (GraphicsWindowWX::OnKeyUp            )
    EVT_MOUSE_EVENTS    (GraphicsWindowWX::OnMouse            )
END_EVENT_TABLE()

GraphicsWindowWX::GraphicsWindowWX(wxWindow *parent, wxWindowID id,
    const wxPoint& pos, const wxSize& size, long style, const wxString& name)
    : wxGLCanvas(parent, id, pos, size, style|wxFULL_REPAINT_ON_RESIZE, name)
{
    // default cursor to standard
    _oldCursor = *wxSTANDARD_CURSOR;
}

GraphicsWindowWX::~GraphicsWindowWX()
{
}

void GraphicsWindowWX::OnPaint( wxPaintEvent& WXUNUSED(event) )
{
    /* must always be here */
    wxPaintDC dc(this);
}

void GraphicsWindowWX::OnSize(wxSizeEvent& event)
{
    // this is also necessary to update the context on some platforms
    wxGLCanvas::OnSize(event);

    // set GL viewport (not called by wxGLCanvas::OnSize on all platforms...)
    int width, height;
    GetClientSize(&width, &height);

    // update the window dimensions, in case the window has been resized.
    getEventQueue()->windowResize(0, 0, width, height);
}

void GraphicsWindowWX::OnEraseBackground(wxEraseEvent& WXUNUSED(event))
{
    /* Do nothing, to avoid flashing on MSW */
}

void GraphicsWindowWX::OnKeyDown(wxKeyEvent &event)
{
    int key = event.GetKeyCode();
    getEventQueue()->keyPress(key);

    // propagate event
    event.Skip();
}

void GraphicsWindowWX::OnKeyUp(wxKeyEvent &event)
{
    int key = event.GetKeyCode();
    getEventQueue()->keyRelease(key);

    // propagate event
    event.Skip();
}

void GraphicsWindowWX::OnMouse(wxMouseEvent& event)
{
    if (event.ButtonDown()) {
        int button = event.GetButton();
        getEventQueue()->mouseButtonPress(event.GetX(), event.GetY(), button);
    }
    else if (event.ButtonUp()) {
        int button = event.GetButton();
        getEventQueue()->mouseButtonRelease(event.GetX(), event.GetY(), button);
    }
    else if (event.Dragging()) {
        getEventQueue()->mouseMotion(event.GetX(), event.GetY());
    }
}

void GraphicsWindowWX::grabFocus()
{
    // focus this window
    SetFocus();
}

void GraphicsWindowWX::grabFocusIfPointerInWindow()
{
    // focus this window, if the pointer is in the window
    wxPoint pos = wxGetMousePosition();
    if (this == wxFindWindowAtPoint(pos)) {
        SetFocus();
    }
}

void GraphicsWindowWX::useCursor(bool cursorOn)
{
    if (cursorOn) {

        // show the old cursor
        SetCursor(_oldCursor);
    }
    else {

        // remember the old cursor
        _oldCursor = GetCursor();

        // hide the cursor
        //    - can't find a way to do this neatly, so create a 1x1, transparent image
        wxImage image(1,1);
        image.SetMask(true);
        image.SetMaskColour(0, 0, 0);
        wxCursor cursor(image);
        SetCursor(cursor);
    }
}

bool GraphicsWindowWX::makeCurrentImplementation()
{
    SetCurrent();
    return true;
}

void GraphicsWindowWX::swapBuffersImplementation()
{
    SwapBuffers();
}
<commit_msg>Reverting Luigi's addition of argv[1] as it breaks the build.<commit_after>// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#include "osgsimpleviewerWX.h"
#include <osgGA/TrackballManipulator>
#include <osgDB/ReadFile>
#include <wx/image.h>
#include <wx/menu.h>

// `Main program' equivalent, creating windows and returning main app frame
bool wxOsgApp::OnInit()
{
    // Create the main frame window
    MainFrame *frame = new MainFrame(NULL, wxT("wxWidgets OSG Sample"),
        wxDefaultPosition, wxDefaultSize);

    // create osg canvas
    //    - initialize
    SimpleViewerWX *viewerWindow = new SimpleViewerWX(frame, wxID_ANY, wxDefaultPosition,
        wxSize(200, 200), wxSUNKEN_BORDER);

    // load the scene.
    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFile("cow.osg");
    if (!loadedModel)
    {
        return false;
    }
    viewerWindow->setSceneData(loadedModel.get());
    viewerWindow->setCameraManipulator(new osgGA::TrackballManipulator);

    frame->SetSimpleViewer(viewerWindow);

    /* Show the frame */
    frame->Show(true);

    return true;
}

IMPLEMENT_APP(wxOsgApp)

BEGIN_EVENT_TABLE(MainFrame, wxFrame)
    EVT_IDLE(MainFrame::OnIdle)
END_EVENT_TABLE()

/* My frame constructor */
MainFrame::MainFrame(wxFrame *frame, const wxString& title, const wxPoint& pos,
    const wxSize& size, long style)
    : wxFrame(frame, wxID_ANY, title, pos, size, style)
{
    _viewerWindow = NULL;
}

void MainFrame::SetSimpleViewer(SimpleViewerWX *viewer)
{
    _viewerWindow = viewer;
}

void MainFrame::OnIdle(wxIdleEvent &event)
{
    _viewerWindow->render();
    event.RequestMore();
}

BEGIN_EVENT_TABLE(GraphicsWindowWX, wxGLCanvas)
    EVT_SIZE            (GraphicsWindowWX::OnSize            )
    EVT_PAINT            (GraphicsWindowWX::OnPaint            )
    EVT_ERASE_BACKGROUND(GraphicsWindowWX::OnEraseBackground)
    EVT_KEY_DOWN        (GraphicsWindowWX::OnKeyDown        )
    EVT_KEY_UP            (GraphicsWindowWX::OnKeyUp            )
    EVT_MOUSE_EVENTS    (GraphicsWindowWX::OnMouse            )
END_EVENT_TABLE()

GraphicsWindowWX::GraphicsWindowWX(wxWindow *parent, wxWindowID id,
    const wxPoint& pos, const wxSize& size, long style, const wxString& name)
    : wxGLCanvas(parent, id, pos, size, style|wxFULL_REPAINT_ON_RESIZE, name)
{
    // default cursor to standard
    _oldCursor = *wxSTANDARD_CURSOR;
}

GraphicsWindowWX::~GraphicsWindowWX()
{
}

void GraphicsWindowWX::OnPaint( wxPaintEvent& WXUNUSED(event) )
{
    /* must always be here */
    wxPaintDC dc(this);
}

void GraphicsWindowWX::OnSize(wxSizeEvent& event)
{
    // this is also necessary to update the context on some platforms
    wxGLCanvas::OnSize(event);

    // set GL viewport (not called by wxGLCanvas::OnSize on all platforms...)
    int width, height;
    GetClientSize(&width, &height);

    // update the window dimensions, in case the window has been resized.
    getEventQueue()->windowResize(0, 0, width, height);
}

void GraphicsWindowWX::OnEraseBackground(wxEraseEvent& WXUNUSED(event))
{
    /* Do nothing, to avoid flashing on MSW */
}

void GraphicsWindowWX::OnKeyDown(wxKeyEvent &event)
{
    int key = event.GetKeyCode();
    getEventQueue()->keyPress(key);

    // propagate event
    event.Skip();
}

void GraphicsWindowWX::OnKeyUp(wxKeyEvent &event)
{
    int key = event.GetKeyCode();
    getEventQueue()->keyRelease(key);

    // propagate event
    event.Skip();
}

void GraphicsWindowWX::OnMouse(wxMouseEvent& event)
{
    if (event.ButtonDown()) {
        int button = event.GetButton();
        getEventQueue()->mouseButtonPress(event.GetX(), event.GetY(), button);
    }
    else if (event.ButtonUp()) {
        int button = event.GetButton();
        getEventQueue()->mouseButtonRelease(event.GetX(), event.GetY(), button);
    }
    else if (event.Dragging()) {
        getEventQueue()->mouseMotion(event.GetX(), event.GetY());
    }
}

void GraphicsWindowWX::grabFocus()
{
    // focus this window
    SetFocus();
}

void GraphicsWindowWX::grabFocusIfPointerInWindow()
{
    // focus this window, if the pointer is in the window
    wxPoint pos = wxGetMousePosition();
    if (this == wxFindWindowAtPoint(pos)) {
        SetFocus();
    }
}

void GraphicsWindowWX::useCursor(bool cursorOn)
{
    if (cursorOn) {

        // show the old cursor
        SetCursor(_oldCursor);
    }
    else {

        // remember the old cursor
        _oldCursor = GetCursor();

        // hide the cursor
        //    - can't find a way to do this neatly, so create a 1x1, transparent image
        wxImage image(1,1);
        image.SetMask(true);
        image.SetMaskColour(0, 0, 0);
        wxCursor cursor(image);
        SetCursor(cursor);
    }
}

bool GraphicsWindowWX::makeCurrentImplementation()
{
    SetCurrent();
    return true;
}

void GraphicsWindowWX::swapBuffersImplementation()
{
    SwapBuffers();
}
<|endoftext|>


<commit_before>/*
 * Copyright 2007-2017 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * 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.
 *
 * 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
 * FOUNDATION 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 "direct.hxx"
#include "CommandLine.hxx"
#include "Instance.hxx"
#include "Connection.hxx"
#include "Worker.hxx"
#include "Global.hxx"
#include "crash.hxx"
#include "pool/pool.hxx"
#include "fb_pool.hxx"
#include "session_manager.hxx"
#include "session_save.hxx"
#include "tcp_stock.hxx"
#include "translation/Stock.hxx"
#include "translation/Cache.hxx"
#include "tcp_balancer.hxx"
#include "fs/Stock.hxx"
#include "fs/Balancer.hxx"
#include "stock/MapStock.hxx"
#include "http_cache.hxx"
#include "lhttp_stock.hxx"
#include "fcgi/Stock.hxx"
#include "was/Stock.hxx"
#include "delegate/Stock.hxx"
#include "fcache.hxx"
#include "thread_pool.hxx"
#include "stopwatch.hxx"
#include "bulldog.hxx"
#include "pipe_stock.hxx"
#include "nfs/Stock.hxx"
#include "nfs/Cache.hxx"
#include "DirectResourceLoader.hxx"
#include "CachedResourceLoader.hxx"
#include "FilterResourceLoader.hxx"
#include "bp/Control.hxx"
#include "access_log/Glue.hxx"
#include "ua_classification.hxx"
#include "ssl/Init.hxx"
#include "ssl/Client.hxx"
#include "system/SetupProcess.hxx"
#include "system/ProcessName.hxx"
#include "system/Error.hxx"
#include "capabilities.hxx"
#include "spawn/Local.hxx"
#include "spawn/Glue.hxx"
#include "spawn/Client.hxx"
#include "event/Duration.hxx"
#include "address_list.hxx"
#include "net/SocketAddress.hxx"
#include "net/StaticSocketAddress.hxx"
#include "net/FailureManager.hxx"
#include "io/Logger.hxx"
#include "util/Macros.hxx"
#include "util/PrintException.hxx"

#include <systemd/sd-daemon.h>

#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <sys/signal.h>
#include <stdlib.h>
#include <stdio.h>

#ifndef NDEBUG
bool debug_mode = false;
#endif

static constexpr cap_value_t cap_keep_list[] = {
    /* allow libnfs to bind to privileged ports, which in turn allows
       disabling the "insecure" flag on the NFS server */
    CAP_NET_BIND_SERVICE,
};

void
BpInstance::EnableListeners()
{
    for (auto &listener : listeners)
        listener.AddEvent();
}

void
BpInstance::DisableListeners()
{
    for (auto &listener : listeners)
        listener.RemoveEvent();
}

void
BpInstance::ShutdownCallback()
{
    if (should_exit)
        return;

    should_exit = true;
    DisableSignals();
    thread_pool_stop();

    spawn->Shutdown();

    listeners.clear();

    connections.clear_and_dispose(BpConnection::Disposer());

    pool_commit();

    avahi_client.Close();

    compress_timer.Cancel();

    spawn_worker_event.Cancel();

    child_process_registry.SetVolatile();

    thread_pool_join();

    KillAllWorkers();

    background_manager.AbortAll();

    session_save_timer.Cancel();
    session_save_deinit();
    session_manager_deinit();

    FreeStocksAndCaches();

    local_control_handler_deinit(this);
    global_control_handler_deinit(this);

    pool_commit();
}

void
BpInstance::ReloadEventCallback(int)
{
    LogConcat(3, "main", "caught SIGHUP, flushing all caches (pid=",
              (int)getpid(), ")");

    translate_cache_flush(*translate_cache);
    http_cache_flush(*http_cache);
    if (filter_cache != nullptr)
        filter_cache_flush(*filter_cache);
    Compress();
}

void
BpInstance::EnableSignals()
{
    shutdown_listener.Enable();
    sighup_event.Enable();
}

void
BpInstance::DisableSignals()
{
    shutdown_listener.Disable();
    sighup_event.Disable();
}

void
BpInstance::AddListener(const BpConfig::Listener &c)
{
    listeners.emplace_front(*this, c.tag.empty() ? nullptr : c.tag.c_str(),
                            c.ssl ? &c.ssl_config : nullptr);
    auto &listener = listeners.front();

    const char *const interface = c.interface.empty()
        ? nullptr
        : c.interface.c_str();

    listener.Listen(c.Create(SOCK_STREAM));

    if (!c.zeroconf_service.empty()) {
        /* ask the kernel for the effective address via getsockname(),
           because it may have changed, e.g. if the kernel has
           selected a port for us */
        const auto local_address = listener.GetLocalAddress();
        if (local_address.IsDefined())
            avahi_client.AddService(c.zeroconf_service.c_str(),
                                    interface, local_address);
    }
}

void
BpInstance::AddTcpListener(int port)
{
    listeners.emplace_front(*this, nullptr, nullptr);
    auto &listener = listeners.front();
    listener.ListenTCP(port);
    listener.SetTcpDeferAccept(10);
}

int main(int argc, char **argv)
try {
    InitProcessName(argc, argv);

#ifndef NDEBUG
    if (geteuid() != 0)
        debug_mode = true;
#endif

    const ScopeFbPoolInit fb_pool_init;

    BpInstance instance;

    /* configuration */

    ParseCommandLine(instance.cmdline, instance.config, argc, argv);

    if (instance.cmdline.config_file != nullptr)
        LoadConfigFile(instance.config, instance.cmdline.config_file);

    if (instance.config.ports.empty() && instance.config.listen.empty())
        instance.config.ports.push_back(debug_mode ? 8080 : 80);

    /* initialize */

    if (instance.config.stopwatch)
        stopwatch_enable();

    SetupProcess();

    const ScopeSslGlobalInit ssl_init;
    ssl_client_init(instance.config.ssl_client);

    direct_global_init();

    instance.EnableSignals();

    for (auto i : instance.config.ports)
        instance.AddTcpListener(i);

    for (const auto &i : instance.config.listen)
        instance.AddListener(i);

    global_control_handler_init(&instance);

    if (instance.config.num_workers == 1)
        /* in single-worker mode with watchdog master process, let
           only the one worker handle control commands */
        global_control_handler_disable(instance);

    /* note: this function call passes a temporary SpawnConfig copy,
       because the reference will be evaluated in the child process
       after ~BpInstance() has been called */
    instance.spawn = StartSpawnServer(SpawnConfig(instance.config.spawn),
                                      instance.child_process_registry,
                                      nullptr,
                                      [&instance](){
            instance.event_loop.Reinit();

            global_control_handler_deinit(&instance);
            instance.listeners.clear();
            instance.DisableSignals();

            instance.~BpInstance();
        });
    instance.spawn_service = instance.spawn;

    if (!crash_global_init()) {
        fprintf(stderr, "crash_global_init() failed\n");
        return EXIT_FAILURE;
    }

    session_manager_init(instance.event_loop,
                         instance.config.session_idle_timeout,
                         instance.config.cluster_size,
                         instance.config.cluster_node);

    if (!instance.config.session_save_path.empty()) {
        session_save_init(instance.config.session_save_path.c_str());
        instance.ScheduleSaveSessions();
    }

    local_control_handler_init(&instance);

    try {
        local_control_handler_open(&instance);
    } catch (const std::exception &e) {
        PrintException(e);
    }

    instance.tcp_stock = new TcpStock(instance.event_loop,
                                      instance.config.tcp_stock_limit);
    instance.tcp_balancer = new TcpBalancer(*instance.tcp_stock,
                                            instance.failure_manager);

    instance.fs_stock = new FilteredSocketStock(instance.event_loop,
                                                instance.config.tcp_stock_limit);
    instance.fs_balancer = new FilteredSocketBalancer(*instance.fs_stock,
                                                      instance.failure_manager);

    if (instance.config.translation_socket != nullptr) {
        instance.translate_stock =
            tstock_new(instance.event_loop,
                       instance.config.translation_socket,
                       instance.config.translate_stock_limit);

        instance.translate_cache = translate_cache_new(instance.root_pool,
                                                       instance.event_loop,
                                                       *instance.translate_stock,
                                                       instance.config.translate_cache_size,
                                                       false);
    }

    instance.lhttp_stock = lhttp_stock_new(0, 16, instance.event_loop,
                                           *instance.spawn_service);

    instance.fcgi_stock = fcgi_stock_new(instance.config.fcgi_stock_limit,
                                         instance.config.fcgi_stock_max_idle,
                                         instance.event_loop,
                                         *instance.spawn_service);

    instance.was_stock = was_stock_new(instance.config.was_stock_limit,
                                       instance.config.was_stock_max_idle,
                                       instance.event_loop,
                                       *instance.spawn_service);

    instance.delegate_stock = delegate_stock_new(instance.event_loop,
                                                 *instance.spawn_service);

    instance.nfs_stock = nfs_stock_new(instance.event_loop,
                                       instance.root_pool);
    instance.nfs_cache = nfs_cache_new(instance.root_pool,
                                       instance.config.nfs_cache_size,
                                       *instance.nfs_stock,
                                       instance.event_loop);

    instance.direct_resource_loader =
        new DirectResourceLoader(instance.event_loop,
                                 instance.tcp_balancer,
                                 *instance.fs_balancer,
                                 *instance.spawn_service,
                                 instance.lhttp_stock,
                                 instance.fcgi_stock,
                                 instance.was_stock,
                                 instance.delegate_stock,
                                 instance.nfs_cache);

    instance.http_cache = http_cache_new(instance.root_pool,
                                         instance.config.http_cache_size,
                                         instance.event_loop,
                                         *instance.direct_resource_loader);

    instance.cached_resource_loader =
        new CachedResourceLoader(*instance.http_cache);

    instance.pipe_stock = pipe_stock_new(instance.event_loop);

    if (instance.config.filter_cache_size > 0) {
        instance.filter_cache = filter_cache_new(instance.root_pool,
                                                 instance.config.filter_cache_size,
                                                 instance.event_loop,
                                                 *instance.direct_resource_loader);
        instance.filter_resource_loader =
            new FilterResourceLoader(*instance.filter_cache);
    } else
        instance.filter_resource_loader = instance.direct_resource_loader;

    bulldog_init(instance.config.bulldog_path);

    global_translate_cache = instance.translate_cache;
    global_pipe_stock = instance.pipe_stock;

    /* launch the access logger */

    instance.access_log.reset(AccessLogGlue::Create(instance.config.access_log,
                                                    &instance.cmdline.logger_user));

    /* daemonize II */

    if (!instance.cmdline.user.IsEmpty())
        capabilities_pre_setuid();

    instance.cmdline.user.Apply();

    if (!instance.cmdline.user.IsEmpty())
        capabilities_post_setuid(cap_keep_list, ARRAY_SIZE(cap_keep_list));

    /* create worker processes */

    if (instance.config.num_workers > 0) {
        /* the master process shouldn't work */
        instance.DisableListeners();

        /* spawn the first worker really soon */
        instance.spawn_worker_event.Add(EventDuration<0, 10000>::value);
    } else {
        instance.InitWorker();
    }

    /* tell systemd we're ready */
    sd_notify(0, "READY=1");

    /* main loop */

    instance.event_loop.Dispatch();

    /* cleanup */

    bulldog_deinit();

    delete instance.spawn;

    thread_pool_deinit();

    ssl_client_deinit();

    crash_global_deinit();

    ua_classification_deinit();
} catch (const std::exception &e) {
    PrintException(e);
    return EXIT_FAILURE;
}
<commit_msg>bp/Main: initialize the logger before the ResourceLoader<commit_after>/*
 * Copyright 2007-2017 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * 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.
 *
 * 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
 * FOUNDATION 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 "direct.hxx"
#include "CommandLine.hxx"
#include "Instance.hxx"
#include "Connection.hxx"
#include "Worker.hxx"
#include "Global.hxx"
#include "crash.hxx"
#include "pool/pool.hxx"
#include "fb_pool.hxx"
#include "session_manager.hxx"
#include "session_save.hxx"
#include "tcp_stock.hxx"
#include "translation/Stock.hxx"
#include "translation/Cache.hxx"
#include "tcp_balancer.hxx"
#include "fs/Stock.hxx"
#include "fs/Balancer.hxx"
#include "stock/MapStock.hxx"
#include "http_cache.hxx"
#include "lhttp_stock.hxx"
#include "fcgi/Stock.hxx"
#include "was/Stock.hxx"
#include "delegate/Stock.hxx"
#include "fcache.hxx"
#include "thread_pool.hxx"
#include "stopwatch.hxx"
#include "bulldog.hxx"
#include "pipe_stock.hxx"
#include "nfs/Stock.hxx"
#include "nfs/Cache.hxx"
#include "DirectResourceLoader.hxx"
#include "CachedResourceLoader.hxx"
#include "FilterResourceLoader.hxx"
#include "bp/Control.hxx"
#include "access_log/Glue.hxx"
#include "ua_classification.hxx"
#include "ssl/Init.hxx"
#include "ssl/Client.hxx"
#include "system/SetupProcess.hxx"
#include "system/ProcessName.hxx"
#include "system/Error.hxx"
#include "capabilities.hxx"
#include "spawn/Local.hxx"
#include "spawn/Glue.hxx"
#include "spawn/Client.hxx"
#include "event/Duration.hxx"
#include "address_list.hxx"
#include "net/SocketAddress.hxx"
#include "net/StaticSocketAddress.hxx"
#include "net/FailureManager.hxx"
#include "io/Logger.hxx"
#include "util/Macros.hxx"
#include "util/PrintException.hxx"

#include <systemd/sd-daemon.h>

#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <sys/signal.h>
#include <stdlib.h>
#include <stdio.h>

#ifndef NDEBUG
bool debug_mode = false;
#endif

static constexpr cap_value_t cap_keep_list[] = {
    /* allow libnfs to bind to privileged ports, which in turn allows
       disabling the "insecure" flag on the NFS server */
    CAP_NET_BIND_SERVICE,
};

void
BpInstance::EnableListeners()
{
    for (auto &listener : listeners)
        listener.AddEvent();
}

void
BpInstance::DisableListeners()
{
    for (auto &listener : listeners)
        listener.RemoveEvent();
}

void
BpInstance::ShutdownCallback()
{
    if (should_exit)
        return;

    should_exit = true;
    DisableSignals();
    thread_pool_stop();

    spawn->Shutdown();

    listeners.clear();

    connections.clear_and_dispose(BpConnection::Disposer());

    pool_commit();

    avahi_client.Close();

    compress_timer.Cancel();

    spawn_worker_event.Cancel();

    child_process_registry.SetVolatile();

    thread_pool_join();

    KillAllWorkers();

    background_manager.AbortAll();

    session_save_timer.Cancel();
    session_save_deinit();
    session_manager_deinit();

    FreeStocksAndCaches();

    local_control_handler_deinit(this);
    global_control_handler_deinit(this);

    pool_commit();
}

void
BpInstance::ReloadEventCallback(int)
{
    LogConcat(3, "main", "caught SIGHUP, flushing all caches (pid=",
              (int)getpid(), ")");

    translate_cache_flush(*translate_cache);
    http_cache_flush(*http_cache);
    if (filter_cache != nullptr)
        filter_cache_flush(*filter_cache);
    Compress();
}

void
BpInstance::EnableSignals()
{
    shutdown_listener.Enable();
    sighup_event.Enable();
}

void
BpInstance::DisableSignals()
{
    shutdown_listener.Disable();
    sighup_event.Disable();
}

void
BpInstance::AddListener(const BpConfig::Listener &c)
{
    listeners.emplace_front(*this, c.tag.empty() ? nullptr : c.tag.c_str(),
                            c.ssl ? &c.ssl_config : nullptr);
    auto &listener = listeners.front();

    const char *const interface = c.interface.empty()
        ? nullptr
        : c.interface.c_str();

    listener.Listen(c.Create(SOCK_STREAM));

    if (!c.zeroconf_service.empty()) {
        /* ask the kernel for the effective address via getsockname(),
           because it may have changed, e.g. if the kernel has
           selected a port for us */
        const auto local_address = listener.GetLocalAddress();
        if (local_address.IsDefined())
            avahi_client.AddService(c.zeroconf_service.c_str(),
                                    interface, local_address);
    }
}

void
BpInstance::AddTcpListener(int port)
{
    listeners.emplace_front(*this, nullptr, nullptr);
    auto &listener = listeners.front();
    listener.ListenTCP(port);
    listener.SetTcpDeferAccept(10);
}

int main(int argc, char **argv)
try {
    InitProcessName(argc, argv);

#ifndef NDEBUG
    if (geteuid() != 0)
        debug_mode = true;
#endif

    const ScopeFbPoolInit fb_pool_init;

    BpInstance instance;

    /* configuration */

    ParseCommandLine(instance.cmdline, instance.config, argc, argv);

    if (instance.cmdline.config_file != nullptr)
        LoadConfigFile(instance.config, instance.cmdline.config_file);

    if (instance.config.ports.empty() && instance.config.listen.empty())
        instance.config.ports.push_back(debug_mode ? 8080 : 80);

    /* initialize */

    if (instance.config.stopwatch)
        stopwatch_enable();

    SetupProcess();

    const ScopeSslGlobalInit ssl_init;
    ssl_client_init(instance.config.ssl_client);

    direct_global_init();

    instance.EnableSignals();

    for (auto i : instance.config.ports)
        instance.AddTcpListener(i);

    for (const auto &i : instance.config.listen)
        instance.AddListener(i);

    global_control_handler_init(&instance);

    if (instance.config.num_workers == 1)
        /* in single-worker mode with watchdog master process, let
           only the one worker handle control commands */
        global_control_handler_disable(instance);

    /* note: this function call passes a temporary SpawnConfig copy,
       because the reference will be evaluated in the child process
       after ~BpInstance() has been called */
    instance.spawn = StartSpawnServer(SpawnConfig(instance.config.spawn),
                                      instance.child_process_registry,
                                      nullptr,
                                      [&instance](){
            instance.event_loop.Reinit();

            global_control_handler_deinit(&instance);
            instance.listeners.clear();
            instance.DisableSignals();

            instance.~BpInstance();
        });
    instance.spawn_service = instance.spawn;

    if (!crash_global_init()) {
        fprintf(stderr, "crash_global_init() failed\n");
        return EXIT_FAILURE;
    }

    session_manager_init(instance.event_loop,
                         instance.config.session_idle_timeout,
                         instance.config.cluster_size,
                         instance.config.cluster_node);

    if (!instance.config.session_save_path.empty()) {
        session_save_init(instance.config.session_save_path.c_str());
        instance.ScheduleSaveSessions();
    }

    local_control_handler_init(&instance);

    try {
        local_control_handler_open(&instance);
    } catch (const std::exception &e) {
        PrintException(e);
    }

    /* launch the access logger */

    instance.access_log.reset(AccessLogGlue::Create(instance.config.access_log,
                                                    &instance.cmdline.logger_user));

    /* initialize ResourceLoader and all its dependencies */

    instance.tcp_stock = new TcpStock(instance.event_loop,
                                      instance.config.tcp_stock_limit);
    instance.tcp_balancer = new TcpBalancer(*instance.tcp_stock,
                                            instance.failure_manager);

    instance.fs_stock = new FilteredSocketStock(instance.event_loop,
                                                instance.config.tcp_stock_limit);
    instance.fs_balancer = new FilteredSocketBalancer(*instance.fs_stock,
                                                      instance.failure_manager);

    if (instance.config.translation_socket != nullptr) {
        instance.translate_stock =
            tstock_new(instance.event_loop,
                       instance.config.translation_socket,
                       instance.config.translate_stock_limit);

        instance.translate_cache = translate_cache_new(instance.root_pool,
                                                       instance.event_loop,
                                                       *instance.translate_stock,
                                                       instance.config.translate_cache_size,
                                                       false);
    }

    instance.lhttp_stock = lhttp_stock_new(0, 16, instance.event_loop,
                                           *instance.spawn_service);

    instance.fcgi_stock = fcgi_stock_new(instance.config.fcgi_stock_limit,
                                         instance.config.fcgi_stock_max_idle,
                                         instance.event_loop,
                                         *instance.spawn_service);

    instance.was_stock = was_stock_new(instance.config.was_stock_limit,
                                       instance.config.was_stock_max_idle,
                                       instance.event_loop,
                                       *instance.spawn_service);

    instance.delegate_stock = delegate_stock_new(instance.event_loop,
                                                 *instance.spawn_service);

    instance.nfs_stock = nfs_stock_new(instance.event_loop,
                                       instance.root_pool);
    instance.nfs_cache = nfs_cache_new(instance.root_pool,
                                       instance.config.nfs_cache_size,
                                       *instance.nfs_stock,
                                       instance.event_loop);

    instance.direct_resource_loader =
        new DirectResourceLoader(instance.event_loop,
                                 instance.tcp_balancer,
                                 *instance.fs_balancer,
                                 *instance.spawn_service,
                                 instance.lhttp_stock,
                                 instance.fcgi_stock,
                                 instance.was_stock,
                                 instance.delegate_stock,
                                 instance.nfs_cache);

    instance.http_cache = http_cache_new(instance.root_pool,
                                         instance.config.http_cache_size,
                                         instance.event_loop,
                                         *instance.direct_resource_loader);

    instance.cached_resource_loader =
        new CachedResourceLoader(*instance.http_cache);

    instance.pipe_stock = pipe_stock_new(instance.event_loop);

    if (instance.config.filter_cache_size > 0) {
        instance.filter_cache = filter_cache_new(instance.root_pool,
                                                 instance.config.filter_cache_size,
                                                 instance.event_loop,
                                                 *instance.direct_resource_loader);
        instance.filter_resource_loader =
            new FilterResourceLoader(*instance.filter_cache);
    } else
        instance.filter_resource_loader = instance.direct_resource_loader;

    bulldog_init(instance.config.bulldog_path);

    global_translate_cache = instance.translate_cache;
    global_pipe_stock = instance.pipe_stock;

    /* daemonize II */

    if (!instance.cmdline.user.IsEmpty())
        capabilities_pre_setuid();

    instance.cmdline.user.Apply();

    if (!instance.cmdline.user.IsEmpty())
        capabilities_post_setuid(cap_keep_list, ARRAY_SIZE(cap_keep_list));

    /* create worker processes */

    if (instance.config.num_workers > 0) {
        /* the master process shouldn't work */
        instance.DisableListeners();

        /* spawn the first worker really soon */
        instance.spawn_worker_event.Add(EventDuration<0, 10000>::value);
    } else {
        instance.InitWorker();
    }

    /* tell systemd we're ready */
    sd_notify(0, "READY=1");

    /* main loop */

    instance.event_loop.Dispatch();

    /* cleanup */

    bulldog_deinit();

    delete instance.spawn;

    thread_pool_deinit();

    ssl_client_deinit();

    crash_global_deinit();

    ua_classification_deinit();
} catch (const std::exception &e) {
    PrintException(e);
    return EXIT_FAILURE;
}
<|endoftext|>


<commit_before>#ifndef STAN_MATH_REV_MAT_FUNCTOR_KINSOL_SOLVE_HPP
#define STAN_MATH_REV_MAT_FUNCTOR_KINSOL_SOLVE_HPP

#include <stan/math/prim/mat/fun/to_array_1d.hpp>
#include <stan/math/prim/mat/fun/to_vector.hpp>
#include <stan/math/rev/mat/functor/kinsol_data.hpp>
#include <stan/math/rev/mat/functor/algebra_system.hpp>
#include <stan/math/prim/mat/err/check_flag.hpp>

#include <kinsol/kinsol.h>
#include <sunmatrix/sunmatrix_dense.h>
#include <sunlinsol/sunlinsol_dense.h>
#include <nvector/nvector_serial.h>

#include <vector>

namespace stan {
namespace math {

/**
 * Return the solution to the specified algebraic system,
 * given an initial guess. Invokes the Kinsol solver from Sundials.
 *
 * @tparam F type of equation system function.
 * @tparam T type of initial guess vector.
 * @param[in] f Functor that evaluated the system of equations.
 * @param[in] x Vector of starting values.
 * @param[in] y Parameter vector for the equation system. The function
 *            is overloaded to treat y as a vector of doubles or of a
 *            a template type T.
 * @param[in] dat Continuous data vector for the equation system.
 * @param[in] dat_int Integer data vector for the equation system.
 * @param[in, out] msgs The print stream for warning messages.
 * @param[in] scaling_step_size Scaled-step stopping tolerance. If
 *            a Newton step is smaller than the scaling step
 *            tolerance, the code breaks, assuming the solver is no
 *            longer making significant progress (i.e. is stuck)
 * @param[in] function_tolerance determines whether roots are acceptable.
 * @param[in] max_num_steps Maximum number of function evaluations.
 * @param[in] custom_jacobian If 0, use Kinsol's default to compute the
 *            jacobian for the Newton step, namely Quotient Difference
 *            (finite difference). If 1, use reverse-mode AD, unless
 *            the user specifies their own method.
 * @param[in] J_F A functor that computes the Jacobian for the Newton step.
 *            Defaults to reverse-mode AD.
 * @param[in] steps_eval_jacobian Maximum number of steps before the
 *            Jacobian gets recomputed. Note that Kinsol's default is 10.
 *            If equal to 1, the algorithm computes exact Newton steps.
 * @param[in] global_line_search does the solver use a global line search?
 *            If equal to KIN_NONE, no, if KIN_LINESEARCH, yes.
 * @return x_solution Vector of solutions to the system of equations.
 * @throw std::invalid_argument if Kinsol returns a negative
 *        flag when setting up the solver.
 * @throw boost::math::evaluation_error if Kinsol returns a
 *        negative flag after attempting to solve the equation.
 */
template <typename F1, typename F2 = kinsol_J_f>
Eigen::VectorXd kinsol_solve(
    const F1& f, const Eigen::VectorXd& x, const Eigen::VectorXd& y,
    const std::vector<double>& dat, const std::vector<int>& dat_int,
    std::ostream* msgs = nullptr, double scaling_step_tol = 1e-3,
    double function_tolerance = 1e-6,
    long int max_num_steps = 1e+3,  // NOLINT(runtime/int)
    bool custom_jacobian = 1, const F2& J_f = kinsol_J_f(),
    int steps_eval_jacobian = 10, int global_line_search = KIN_LINESEARCH) {
  int N = x.size();
  typedef kinsol_system_data<F1, F2> system_data;
  system_data kinsol_data(f, J_f, x, y, dat, dat_int, msgs);

  void* kinsol_memory = KINCreate();

  check_flag(
      KINInit(kinsol_memory, &system_data::kinsol_f_system, kinsol_data.nv_x_),
      "KINInit");

  N_Vector scaling = N_VNew_Serial(N);
  N_VConst_Serial(1.0, scaling);  // no scaling

  check_flag(KINSetFuncNormTol(kinsol_memory, function_tolerance),
             "KINSetFuncNormTol");
  check_flag(KINSetScaledStepTol(kinsol_memory, scaling_step_tol),
             "KINSetScaledStepTol");
  check_flag(KINSetMaxSetupCalls(kinsol_memory, steps_eval_jacobian),
             "KINSetMaxSetupCalls");

  // CHECK
  // The default value is 1000 * ||u_0||_D where ||u_0|| is the initial guess.
  // So we run into issues if ||u_0|| = 0.
  // If the norm is non-zero, use kinsol's default (accessed with 0),
  // else use the dimension of x -- CHECK - find optimal length.
  double max_newton_step = (x.norm() == 0) ? x.size() : 0;
  check_flag(KINSetMaxNewtonStep(kinsol_memory, max_newton_step),
             "KINSetMaxNewtonStep");
  check_flag(
      KINSetUserData(kinsol_memory, reinterpret_cast<void*>(&kinsol_data)),
      "KINSetUserData");

  // construct Linear solver
  check_flag(KINSetLinearSolver(kinsol_memory, kinsol_data.LS_, kinsol_data.J_),
             "KINSetLinearSolver");

  if (custom_jacobian)
    check_flag(KINSetJacFn(kinsol_memory, &system_data::kinsol_jacobian),
               "KINSetJacFn");

  N_Vector nv_x = N_VNew_Serial(N);
  realtype* nv_x_data = N_VGetArrayPointer_Serial(nv_x);
  for (int i = 0; i < N; i++)
    nv_x_data[i] = x(i);

  check_flag_kinsol(
      KINSol(kinsol_memory, nv_x, global_line_search, scaling, scaling),
      max_num_steps);

  KINFree(&kinsol_memory);

  Eigen::VectorXd x_solution(N);
  for (int i = 0; i < N; i++)
    x_solution(i) = nv_x_data[i];

  return x_solution;
}

}  // namespace math
}  // namespace stan
#endif
<commit_msg>Correct doxygen documentation.<commit_after>#ifndef STAN_MATH_REV_MAT_FUNCTOR_KINSOL_SOLVE_HPP
#define STAN_MATH_REV_MAT_FUNCTOR_KINSOL_SOLVE_HPP

#include <stan/math/prim/mat/fun/to_array_1d.hpp>
#include <stan/math/prim/mat/fun/to_vector.hpp>
#include <stan/math/rev/mat/functor/kinsol_data.hpp>
#include <stan/math/rev/mat/functor/algebra_system.hpp>
#include <stan/math/prim/mat/err/check_flag.hpp>

#include <kinsol/kinsol.h>
#include <sunmatrix/sunmatrix_dense.h>
#include <sunlinsol/sunlinsol_dense.h>
#include <nvector/nvector_serial.h>

#include <vector>

namespace stan {
namespace math {

/**
 * Return the solution to the specified algebraic system,
 * given an initial guess. Invokes the Kinsol solver from Sundials.
 *
 * @tparam F type of equation system function.
 * @tparam T type of initial guess vector.
 * @param[in] f Functor that evaluated the system of equations.
 * @param[in] x Vector of starting values.
 * @param[in] y Parameter vector for the equation system. The function
 *            is overloaded to treat y as a vector of doubles or of a
 *            a template type T.
 * @param[in] dat Continuous data vector for the equation system.
 * @param[in] dat_int Integer data vector for the equation system.
 * @param[in, out] msgs The print stream for warning messages.
 * @param[in] scaling_step_tol Scaled-step stopping tolerance. If
 *            a Newton step is smaller than the scaling step
 *            tolerance, the code breaks, assuming the solver is no
 *            longer making significant progress (i.e. is stuck)
 * @param[in] function_tolerance determines whether roots are acceptable.
 * @param[in] max_num_steps Maximum number of function evaluations.
 * @param[in] custom_jacobian If 0, use Kinsol's default to compute the
 *            jacobian for the Newton step, namely Quotient Difference
 *            (finite difference). If 1, use reverse-mode AD, unless
 *            the user specifies their own method.
 * @param[in] J_F A functor that computes the Jacobian for the Newton step.
 *            Defaults to reverse-mode AD.
 * @param[in] steps_eval_jacobian Maximum number of steps before the
 *            Jacobian gets recomputed. Note that Kinsol's default is 10.
 *            If equal to 1, the algorithm computes exact Newton steps.
 * @param[in] global_line_search does the solver use a global line search?
 *            If equal to KIN_NONE, no, if KIN_LINESEARCH, yes.
 * @return x_solution Vector of solutions to the system of equations.
 * @throw std::invalid_argument if Kinsol returns a negative
 *        flag when setting up the solver.
 * @throw boost::math::evaluation_error if Kinsol returns a
 *        negative flag after attempting to solve the equation.
 */
template <typename F1, typename F2 = kinsol_J_f>
Eigen::VectorXd kinsol_solve(
    const F1& f, const Eigen::VectorXd& x, const Eigen::VectorXd& y,
    const std::vector<double>& dat, const std::vector<int>& dat_int,
    std::ostream* msgs = nullptr, double scaling_step_tol = 1e-3,
    double function_tolerance = 1e-6,
    long int max_num_steps = 1e+3,  // NOLINT(runtime/int)
    bool custom_jacobian = 1, const F2& J_f = kinsol_J_f(),
    int steps_eval_jacobian = 10, int global_line_search = KIN_LINESEARCH) {
  int N = x.size();
  typedef kinsol_system_data<F1, F2> system_data;
  system_data kinsol_data(f, J_f, x, y, dat, dat_int, msgs);

  void* kinsol_memory = KINCreate();

  check_flag(
      KINInit(kinsol_memory, &system_data::kinsol_f_system, kinsol_data.nv_x_),
      "KINInit");

  N_Vector scaling = N_VNew_Serial(N);
  N_VConst_Serial(1.0, scaling);  // no scaling

  check_flag(KINSetFuncNormTol(kinsol_memory, function_tolerance),
             "KINSetFuncNormTol");
  check_flag(KINSetScaledStepTol(kinsol_memory, scaling_step_tol),
             "KINSetScaledStepTol");
  check_flag(KINSetMaxSetupCalls(kinsol_memory, steps_eval_jacobian),
             "KINSetMaxSetupCalls");

  // CHECK
  // The default value is 1000 * ||u_0||_D where ||u_0|| is the initial guess.
  // So we run into issues if ||u_0|| = 0.
  // If the norm is non-zero, use kinsol's default (accessed with 0),
  // else use the dimension of x -- CHECK - find optimal length.
  double max_newton_step = (x.norm() == 0) ? x.size() : 0;
  check_flag(KINSetMaxNewtonStep(kinsol_memory, max_newton_step),
             "KINSetMaxNewtonStep");
  check_flag(
      KINSetUserData(kinsol_memory, reinterpret_cast<void*>(&kinsol_data)),
      "KINSetUserData");

  // construct Linear solver
  check_flag(KINSetLinearSolver(kinsol_memory, kinsol_data.LS_, kinsol_data.J_),
             "KINSetLinearSolver");

  if (custom_jacobian)
    check_flag(KINSetJacFn(kinsol_memory, &system_data::kinsol_jacobian),
               "KINSetJacFn");

  N_Vector nv_x = N_VNew_Serial(N);
  realtype* nv_x_data = N_VGetArrayPointer_Serial(nv_x);
  for (int i = 0; i < N; i++)
    nv_x_data[i] = x(i);

  check_flag_kinsol(
      KINSol(kinsol_memory, nv_x, global_line_search, scaling, scaling),
      max_num_steps);

  KINFree(&kinsol_memory);

  Eigen::VectorXd x_solution(N);
  for (int i = 0; i < N; i++)
    x_solution(i) = nv_x_data[i];

  return x_solution;
}

}  // namespace math
}  // namespace stan
#endif
<|endoftext|>


<commit_before>/* -*- mode: c++; indent-tabs-mode: nil -*-
 *
 *  $Id: persistent_charheap.cpp,v 1.1 2006/10/09 07:07:59 Paul Pedersen Exp $
 *
 *
 */

#include "persistent_charheap.h"

#include <sys/types.h>
#include <sys/mman.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string>
#include <sstream>
#include <iostream>

#include "xqpexception.h"

using namespace std;
namespace xqp {

// iterator implementations

persistent_charheap::persistent_charheap_iterator::persistent_charheap_iterator(
	persistent_charheap const* pch,
	uint32_t initial_offset)
:
	_begin(initial_offset ? (pch->data+initial_offset) : (pch->data + sizeof(off_t))),
	_end(pch->data + sizeof(off_t) + pch->size()),
	current((char*)_begin),
	parent(pch)
{
}

persistent_charheap::persistent_charheap_iterator::~persistent_charheap_iterator()
{
}

char const* persistent_charheap::persistent_charheap_iterator::operator++()
{
	uint32_t len = strlen(current);
	const char * result = current;
	current += (len+1);
	return result;
}

char const* persistent_charheap::persistent_charheap_iterator::operator*() const
{
	return current;
}

bool operator!=(persistent_charheap::persistent_charheap_iterator const& x,
                persistent_charheap::persistent_charheap_iterator const& y)
{
	if (x.parent!=y.parent) return true;
	if (x.current!=y.current) return true;
	return false;
}

// heap implementations

/*______________________________________________________________________

	The first sizeoff(off_t) bytes contain an offset to the first
	unused byte of the memory-mapped array.  The eofoff points to
	the end of the allocated array.  No need to store the eofoff
	since it can be computed from the backing file size.

        eoffoff ________________________________________________
                                                                v
  heap: [offset|s1,0,s2,0,...          sk,0| ..unused..        ]
           |________________________________^

	______________________________________________________________________*/

persistent_charheap::persistent_charheap(
	const string& _path)
:
	path(_path)
{
  fd = open(path.c_str(), O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
  if (fd < 0 ) {
    ostringstream oerr;
    oerr << "open failed on '" << path << "' with error: " << strerror(errno);
    throw xqpexception("persistent_charheap::ctor", oerr.str());
  }
  if ((eofoff = lseek(fd, 0, SEEK_END)) == -1) {
    ostringstream oerr;
    oerr << "lseek to EOF failed on '" << path << "' with error: " << strerror(errno);
    throw xqpexception("persistent_charheap::ctor", oerr.str());
  }
  if (eofoff==0) { initialize(); }
  if ((data = (char*)mmap(0, eofoff, PROT_READ|PROT_WRITE,
                           MAP_FILE|MAP_SHARED, fd, 0))==MAP_FAILED)
  {
    ostringstream oerr;
    oerr << "mmap failed on '" << path << "' with error: " << strerror(errno);
    throw xqpexception("persistent_charheap::ctor", oerr.str());
  }
  offset_p = reinterpret_cast<off_t*>(data);
}

persistent_charheap::~persistent_charheap()
{
  unmap();
  if (close(fd) == -1) {
    ostringstream oerr;
    oerr << "close failed on '" << path << "' with error: " << strerror(errno);
    throw xqpexception("persistent_charheap::dtor", oerr.str());
  }
}

/*
**
**  end ______________________________________
**  begin ________                            |
**                v                           v
**  heap: [offset|s1,0,s2,0,...          sk,0| ..unused..        ]
**           |________________________________^
**
*/
persistent_charheap::persistent_charheap_iterator persistent_charheap::begin()
{
	return persistent_charheap_iterator(this,0);
}

/*
**
**  end ______________________________________
**  begin ____________________________________|
**                                            v
**  heap: [offset|s1,0,s2,0,...          sk,0| ..unused..        ]
**           |________________________________^
**
*/
persistent_charheap::persistent_charheap_iterator persistent_charheap::end()
{
	return persistent_charheap_iterator(this,*offset_p);
}

off_t persistent_charheap::put(
  const char* buf,				// buffer containing segment to put
  uint32_t seg_offset,		// starting offset of segment in buffer
  uint32_t seg_len)				// length of segment
{
  // check if we need to expand
  while (*offset_p+seg_len+1 > eofoff) expand();

  try {
    memcpy(&data[*offset_p], &buf[seg_offset], seg_len);
    data[*offset_p+seg_len] = 0;
  } catch (...) {
    throw xqpexception("persistent_charheap::put", "exception in memcpy");
  }
  off_t id = *offset_p;
  *offset_p += (seg_len+1);
  return id;
}

void persistent_charheap::put(
	off_t id,								// offset replace location
  const char* buf,				// buffer containing segment to put
  uint32_t seg_offset,		// starting offset of segment in buffer
  uint32_t seg_len)				// length of segment
{
  // check if we have enough room
	if (strlen(&data[id]) < seg_len) {
		cout << "strlen(&data[id]) = " << strlen(&data[id]) << endl;
		cout << "seg_len = " << seg_len << endl;
    throw xqpexception("persistent_charheap::put", "insufficient space for put/replace");
	}
  try {
    memcpy(&data[id], &buf[seg_offset], seg_len);
    data[id+seg_len] = 0;
  } catch (...) {
    throw xqpexception("persistent_charheap::put", "exception in memcpy");
  }
}

void persistent_charheap::get(
  off_t id,								// segment id
  char* seg_buf,					// buffer into which to place block
  uint32_t seg_offset,		// offset for block in buffer
  uint32_t seg_maxlen)		// maximum output size, truncate if larger
const
{
  // transfer the data
  try {
    uint32_t len = strlen(&data[id]);
    if (seg_maxlen < len+1) len = seg_maxlen-1;
    memcpy(&seg_buf[seg_offset], &data[id], len+1);  // includes the trailing 0
  } catch (...) {
    ostringstream oerr;
    oerr << "persistent_charheap::get() : exception in memcpy";
    cerr << oerr.str() << endl;
  }
}

uint32_t persistent_charheap::get_length(off_t id) const
{
  return strlen(&data[id]);
}

void persistent_charheap::initialize()
{
  if (lseek(fd, 4095, SEEK_END)==-1) {  // Note 4096-1
    ostringstream oerr;
    oerr << "lseek to 4095 failed with error: " << strerror(errno);
    throw xqpexception("persistent_charheap::initialize", oerr.str());
  }

  // write one byte to create the new allocation
  char buf[1] = { '\0' };
  if (write(fd, buf, 1) == -1) {				// Get 4095+1
    ostringstream oerr;
    oerr << "write to 4095 failed with error: " << strerror(errno);
    throw xqpexception("persistent_charheap::expand", oerr.str());
  }

  if ((data = (char*)mmap(0, 4096, PROT_READ|PROT_WRITE,
                           MAP_FILE|MAP_SHARED, fd, 0))==MAP_FAILED)
  {
    ostringstream oerr;
    oerr << "mmap failed with error: " << strerror(errno);
    throw xqpexception("persistent_charheap::initialize", oerr.str());
  }
  offset_p = reinterpret_cast<off_t*>(data);
  *offset_p = sizeof(off_t);      // reserve for size
  eofoff = 4096;
}

void persistent_charheap::expand()
{
  unmap();

  // find the end
  if ( (eofoff = lseek(fd, 0, SEEK_END)) == -1) {
    ostringstream oerr;
    oerr << "lseek to EOF failed with error: " << strerror(errno);
    throw xqpexception("persistent_charheap::expand", oerr.str());
  }

  // double past the end
  if (lseek(fd, eofoff-1, SEEK_END)==-1) {  // Note the -1
    ostringstream oerr;
    oerr << "lseek to 2*EOF failed with error: " << strerror(errno);
    throw xqpexception("persistent_charheap::expand", oerr.str());
  }

  // write one byte to create the hole equal
  // in size to the original file
  char buf[1] = { '\0' };
  if (write(fd, buf, 1) == -1) {            // Get back the -1
    ostringstream oerr;
    oerr << "write to 2*EOF failed with error: " << strerror(errno);
    throw xqpexception("persistent_charheap::expand", oerr.str());
  }

  // remap the file
  eofoff <<= 1;
  if ((data = (char*)mmap(0, eofoff, PROT_READ|PROT_WRITE,
                           MAP_FILE|MAP_SHARED, fd, 0))==MAP_FAILED)
  {
    ostringstream oerr;
    oerr << "mmap failed with error: " << strerror(errno);
    throw xqpexception("persistent_charheap::expand", oerr.str());
  }
  offset_p = reinterpret_cast<off_t*>(data);
}

void persistent_charheap::unmap()
{
  if (munmap(data, eofoff)==-1) {
    ostringstream oerr;
    oerr << "munmap failed with error: " << strerror(errno);
    throw xqpexception("persistent_charheap:unmap", oerr.str());
  }
}

}  /* namespace xqp */
<commit_msg>Minor bug fixes.<commit_after>/* -*- mode: c++; indent-tabs-mode: nil -*-
 *
 *  $Id: persistent_charheap.cpp,v 1.1 2006/10/09 07:07:59 Paul Pedersen Exp $
 *
 *
 */

#include "persistent_charheap.h"

#include <sys/types.h>
#include <sys/mman.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string>
#include <sstream>
#include <iostream>

#include "xqpexception.h"

using namespace std;
namespace xqp {

// iterator implementations

persistent_charheap::persistent_charheap_iterator::persistent_charheap_iterator(
	persistent_charheap const* pch,
	uint32_t initial_offset)
:
	_begin(initial_offset ? (pch->data+initial_offset) : (pch->data + sizeof(off_t))),
	_end(pch->data + sizeof(off_t) + pch->size()),
	current((char *)_begin),
	parent(pch)
{
}

persistent_charheap::persistent_charheap_iterator::~persistent_charheap_iterator()
{
}

char const* persistent_charheap::persistent_charheap_iterator::operator++()
{
	uint32_t len = strlen(current);
	const char * result = current;
	current += (len+1);
	return result;
}

char const* persistent_charheap::persistent_charheap_iterator::operator*() const
{
	return current;
}

bool operator!=(persistent_charheap::persistent_charheap_iterator const& x,
                persistent_charheap::persistent_charheap_iterator const& y)
{
	if (x.parent!=y.parent) return true;
	if (x.current!=y.current) return true;
	return false;
}

// heap implementations

/*______________________________________________________________________

	The first sizeoff(off_t) bytes contain an offset to the first
	unused byte of the memory-mapped array.  The eofoff points to
	the end of the allocated array.  No need to store the eofoff
	since it can be computed from the backing file size.

        eoffoff ________________________________________________
                                                                v
  heap: [offset|s1,0,s2,0,...          sk,0| ..unused..        ]
           |________________________________^

	______________________________________________________________________*/

persistent_charheap::persistent_charheap(
	const string& _path)
:
	path(_path)
{
  fd = open(path.c_str(), O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
  if (fd < 0 ) {
    ostringstream oerr;
    oerr << "open failed on '" << path << "' with error: " << strerror(errno);
    throw xqpexception("persistent_charheap::ctor", oerr.str());
  }
  if ((eofoff = lseek(fd, 0, SEEK_END)) == -1) {
    ostringstream oerr;
    oerr << "lseek to EOF failed on '" << path << "' with error: " << strerror(errno);
    throw xqpexception("persistent_charheap::ctor", oerr.str());
  }
  if (eofoff==0) { initialize(); }
  if ((data = (char*)mmap(0, eofoff, PROT_READ|PROT_WRITE,
                           MAP_FILE|MAP_SHARED, fd, 0))==MAP_FAILED)
  {
    ostringstream oerr;
    oerr << "mmap failed on '" << path << "' with error: " << strerror(errno);
    throw xqpexception("persistent_charheap::ctor", oerr.str());
  }
  offset_p = reinterpret_cast<off_t*>(data);
}

persistent_charheap::~persistent_charheap()
{
  unmap();
  if (close(fd) == -1) {
    ostringstream oerr;
    oerr << "close failed on '" << path << "' with error: " << strerror(errno);
    throw xqpexception("persistent_charheap::dtor", oerr.str());
  }
}

/*
**
**  end ______________________________________
**  begin ________                            |
**                v                           v
**  heap: [offset|s1,0,s2,0,...          sk,0| ..unused..        ]
**           |________________________________^
**
*/
persistent_charheap::persistent_charheap_iterator persistent_charheap::begin()
{
	return persistent_charheap_iterator(this,0);
}

/*
**
**  end ______________________________________
**  begin ____________________________________|
**                                            v
**  heap: [offset|s1,0,s2,0,...          sk,0| ..unused..        ]
**           |________________________________^
**
*/
persistent_charheap::persistent_charheap_iterator persistent_charheap::end()
{
	return persistent_charheap_iterator(this,*offset_p);
}

off_t persistent_charheap::put(
  const char* buf,				// buffer containing segment to put
  uint32_t seg_offset,		// starting offset of segment in buffer
  uint32_t seg_len)				// length of segment
{
  // check if we need to expand
  while (*offset_p+seg_len+1 > eofoff) expand();

  try {
    memcpy(&data[*offset_p], &buf[seg_offset], seg_len);
    data[*offset_p+seg_len] = 0;
  } catch (...) {
    throw xqpexception("persistent_charheap::put", "exception in memcpy");
  }
  off_t id = *offset_p;
  *offset_p += (seg_len+1);
  return id;
}

void persistent_charheap::put(
	off_t id,								// offset replace location
  const char* buf,				// buffer containing segment to put
  uint32_t seg_offset,		// starting offset of segment in buffer
  uint32_t seg_len)				// length of segment
{
  // check if we have enough room
	if (strlen(&data[id]) < seg_len) {
		cout << "strlen(&data[id]) = " << strlen(&data[id]) << endl;
		cout << "seg_len = " << seg_len << endl;
    throw xqpexception("persistent_charheap::put", "insufficient space for put/replace");
	}
  try {
    memcpy(&data[id], &buf[seg_offset], seg_len);
    data[id+seg_len] = 0;
  } catch (...) {
    throw xqpexception("persistent_charheap::put", "exception in memcpy");
  }
}

void persistent_charheap::get(
  off_t id,								// segment id
  char* seg_buf,					// buffer into which to place block
  uint32_t seg_offset,		// offset for block in buffer
  uint32_t seg_maxlen)		// maximum output size, truncate if larger
const
{
  // transfer the data
  try {
    uint32_t len = strlen(&data[id]);
    if (seg_maxlen < len+1) len = seg_maxlen-1;
    memcpy(&seg_buf[seg_offset], &data[id], len+1);  // includes the trailing 0
  } catch (...) {
    ostringstream oerr;
    oerr << "persistent_charheap::get() : exception in memcpy";
    cerr << oerr.str() << endl;
  }
}

uint32_t persistent_charheap::get_length(off_t id) const
{
  return strlen(&data[id]);
}

void persistent_charheap::initialize()
{
  if (lseek(fd, 4095, SEEK_END)==-1) {  // Note 4096-1
    ostringstream oerr;
    oerr << "lseek to 4095 failed with error: " << strerror(errno);
    throw xqpexception("persistent_charheap::initialize", oerr.str());
  }

  // write one byte to create the new allocation
  char buf[1] = { '\0' };
  if (write(fd, buf, 1) == -1) {				// Get 4095+1
    ostringstream oerr;
    oerr << "write to 4095 failed with error: " << strerror(errno);
    throw xqpexception("persistent_charheap::expand", oerr.str());
  }

  if ((data = (char*)mmap(0, 4096, PROT_READ|PROT_WRITE,
                           MAP_FILE|MAP_SHARED, fd, 0))==MAP_FAILED)
  {
    ostringstream oerr;
    oerr << "mmap failed with error: " << strerror(errno);
    throw xqpexception("persistent_charheap::initialize", oerr.str());
  }
  offset_p = reinterpret_cast<off_t*>(data);
  *offset_p = sizeof(off_t);      // reserve for size
  eofoff = 4096;
}

void persistent_charheap::expand()
{
  unmap();

  // find the end
  if ( (eofoff = lseek(fd, 0, SEEK_END)) == -1) {
    ostringstream oerr;
    oerr << "lseek to EOF failed with error: " << strerror(errno);
    throw xqpexception("persistent_charheap::expand", oerr.str());
  }

  // double past the end
  if (lseek(fd, eofoff-1, SEEK_END)==-1) {  // Note the -1
    ostringstream oerr;
    oerr << "lseek to 2*EOF failed with error: " << strerror(errno);
    throw xqpexception("persistent_charheap::expand", oerr.str());
  }

  // write one byte to create the hole equal
  // in size to the original file
  char buf[1] = { '\0' };
  if (write(fd, buf, 1) == -1) {            // Get back the -1
    ostringstream oerr;
    oerr << "write to 2*EOF failed with error: " << strerror(errno);
    throw xqpexception("persistent_charheap::expand", oerr.str());
  }

  // remap the file
  eofoff <<= 1;
  if ((data = (char*)mmap(0, eofoff, PROT_READ|PROT_WRITE,
                           MAP_FILE|MAP_SHARED, fd, 0))==MAP_FAILED)
  {
    ostringstream oerr;
    oerr << "mmap failed with error: " << strerror(errno);
    throw xqpexception("persistent_charheap::expand", oerr.str());
  }
  offset_p = reinterpret_cast<off_t*>(data);
}

void persistent_charheap::unmap()
{
  if (munmap(data, eofoff)==-1) {
    ostringstream oerr;
    oerr << "munmap failed with error: " << strerror(errno);
    throw xqpexception("persistent_charheap:unmap", oerr.str());
  }
}

}  /* namespace xqp */
<|endoftext|>


<commit_before>#include "module_code_base.h"
#include <iostream>

#include <assert.h>
#include <algorithm>

//has to be the last include statement
// because of heavy #define usage
extern "C" {
	#include "../neko_mod.h"
	#include "../opcodes.h"
}

namespace {
	std::vector<unsigned int> get_function_addresses(neko_module const * m) {
		std::cout << "get_function_addresses" << std::endl;
		std::vector<unsigned int> function_addresses;

		for (unsigned int k = 0; k < m->nglobals; k++) {
			if (val_is_function(m->globals[k])) {
				function_addresses.push_back((unsigned int)((vfunction*)m->globals[k])->addr);
			}
		}

		//check special case for main function
		if (*m->code == Jump) {
			function_addresses.push_back(*(m->code + 1));
		} else {
			//no jumps in front means main functions have started right away
			assert(function_addresses.empty()); //maybe we should add additional check though
			function_addresses.push_back((unsigned int)m->code);
		}

		return function_addresses;
	}

	std::pair<const unsigned int, Function> make_function(NekoCodeChunk const & chunk) {
		return std::make_pair(chunk.getFromAddress(), Function(chunk));
	}

	ModuleCodeBase::functions_container get_functions(neko_module const * m, NekoCodeChunk const & chunk) {
		std::cout << "get_functions" << std::endl;
		std::vector<unsigned int> const function_addresses = get_function_addresses(m);
		std::vector<NekoCodeChunk> const chunks = chunk.splitByAddresses(function_addresses);

		std::vector<NekoCodeChunk>::const_iterator begin = chunks.begin();
		if (chunks.size() > 1) {
			//chunks size > 1 means we have more than one function
			//  this also means that the first opcode in the program was a Jump to main function
			//  There's no point making a standalone function for that Jump, so we can just remove it.
			assert(*m->code == Jump);
			assert((OPCODE *)begin->getToAddress() - (OPCODE *)begin->getFromAddress() == 2
					 && *(OPCODE *)begin->getFromAddress() == Jump);
			++begin;
		}

		ModuleCodeBase::functions_container result;

		std::transform(begin, chunks.end(),
					   std::inserter(result, result.begin()),
					   std::ptr_fun(make_function));

		return result;
	}
}

ModuleCodeBase::ModuleCodeBase(neko_module const * m) : code_container(m), functions(get_functions(m, code_container.getNekoCodeChunk()))
{
	std::cout << "module code base created!" << std::endl;
}

void ModuleCodeBase::neko_dump(std::string const & indent) const {
	const_iterator last_func = end(); --last_func; //last func is always main one.
	for (const_iterator it = begin();
		 it != end();
		 ++it) {
		std::cout << "def ";
		if (it == last_func) {
			std::cout << "main";
		} else {
			std::cout << it->first;
		}
		std::cout << "() ";
		it->second.neko_dump(indent + "\t");
	}
}
<commit_msg>With tests there's no need to SPAM std::cout<commit_after>#include "module_code_base.h"
#include <iostream>

#include <assert.h>
#include <algorithm>

//has to be the last include statement
// because of heavy #define usage
extern "C" {
	#include "../neko_mod.h"
	#include "../opcodes.h"
}

namespace {
	std::vector<unsigned int> get_function_addresses(neko_module const * m) {
		std::vector<unsigned int> function_addresses;

		for (unsigned int k = 0; k < m->nglobals; k++) {
			if (val_is_function(m->globals[k])) {
				function_addresses.push_back((unsigned int)((vfunction*)m->globals[k])->addr);
			}
		}

		//check special case for main function
		if (*m->code == Jump) {
			function_addresses.push_back(*(m->code + 1));
		} else {
			//no jumps in front means main functions have started right away
			assert(function_addresses.empty()); //maybe we should add additional check though
			function_addresses.push_back((unsigned int)m->code);
		}

		return function_addresses;
	}

	std::pair<const unsigned int, Function> make_function(NekoCodeChunk const & chunk) {
		return std::make_pair(chunk.getFromAddress(), Function(chunk));
	}

	ModuleCodeBase::functions_container get_functions(neko_module const * m, NekoCodeChunk const & chunk) {
		std::vector<unsigned int> const function_addresses = get_function_addresses(m);
		std::vector<NekoCodeChunk> const chunks = chunk.splitByAddresses(function_addresses);

		std::vector<NekoCodeChunk>::const_iterator begin = chunks.begin();
		if (chunks.size() > 1) {
			//chunks size > 1 means we have more than one function
			//  this also means that the first opcode in the program was a Jump to main function
			//  There's no point making a standalone function for that Jump, so we can just remove it.
			assert(*m->code == Jump);
			assert((OPCODE *)begin->getToAddress() - (OPCODE *)begin->getFromAddress() == 2
					 && *(OPCODE *)begin->getFromAddress() == Jump);
			++begin;
		}

		ModuleCodeBase::functions_container result;

		std::transform(begin, chunks.end(),
					   std::inserter(result, result.begin()),
					   std::ptr_fun(make_function));

		return result;
	}
}

ModuleCodeBase::ModuleCodeBase(neko_module const * m) : code_container(m)
													  , functions(get_functions(m, code_container.getNekoCodeChunk()))
{}

void ModuleCodeBase::neko_dump(std::string const & indent) const {
	const_iterator last_func = end(); --last_func; //last func is always main one.
	for (const_iterator it = begin();
		 it != end();
		 ++it) {
		std::cout << "def ";
		if (it == last_func) {
			std::cout << "main";
		} else {
			std::cout << it->first;
		}
		std::cout << "() ";
		it->second.neko_dump(indent + "\t");
	}
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: XMLIndexAlphabeticalSourceContext.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 15:56:01 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"

#ifndef _XMLOFF_XMLINDEXALPHABETICALSOURCECONTEXT_HXX_
#include "XMLIndexAlphabeticalSourceContext.hxx"
#endif

#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif

#ifndef _COM_SUN_STAR_CONTAINER_XINDEXREPLACE_HPP_
#include <com/sun/star/container/XIndexReplace.hpp>
#endif

#ifndef _XMLOFF_XMLINDEXTEMPLATECONTEXT_HXX_
#include "XMLIndexTemplateContext.hxx"
#endif

#ifndef _XMLOFF_XMLINDEXTITLETEMPLATECONTEXT_HXX_
#include "XMLIndexTitleTemplateContext.hxx"
#endif

#ifndef _XMLOFF_XMLINDEXTOCSTYLESCONTEXT_HXX_
#include "XMLIndexTOCStylesContext.hxx"
#endif

#ifndef _XMLOFF_XMLICTXT_HXX
#include <xmloff/xmlictxt.hxx>
#endif

#ifndef _XMLOFF_XMLIMP_HXX
#include <xmloff/xmlimp.hxx>
#endif

#ifndef _XMLOFF_TEXTIMP_HXX_
#include <xmloff/txtimp.hxx>
#endif

#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif

#ifndef _XMLOFF_NMSPMAP_HXX
#include <xmloff/nmspmap.hxx>
#endif

#ifndef _XMLOFF_XMLTOKEN_HXX
#include <xmloff/xmltoken.hxx>
#endif

#ifndef _XMLOFF_XMLUCONV_HXX
#include <xmloff/xmluconv.hxx>
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

using ::rtl::OUString;
using ::com::sun::star::beans::XPropertySet;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Any;
using ::com::sun::star::xml::sax::XAttributeList;
using ::xmloff::token::IsXMLToken;
using ::xmloff::token::XML_ALPHABETICAL_INDEX_ENTRY_TEMPLATE;
using ::xmloff::token::XML_OUTLINE_LEVEL;

const sal_Char sAPI_MainEntryCharacterStyleName[] = "MainEntryCharacterStyleName";
const sal_Char sAPI_UseAlphabeticalSeparators[] = "UseAlphabeticalSeparators";
const sal_Char sAPI_UseCombinedEntries[] = "UseCombinedEntries";
const sal_Char sAPI_IsCaseSensitive[] = "IsCaseSensitive";
const sal_Char sAPI_UseKeyAsEntry[] = "UseKeyAsEntry";
const sal_Char sAPI_UseUpperCase[] = "UseUpperCase";
const sal_Char sAPI_UseDash[] = "UseDash";
const sal_Char sAPI_UsePP[] = "UsePP";
const sal_Char sAPI_SortAlgorithm[] = "SortAlgorithm";
const sal_Char sAPI_Locale[] = "Locale";

TYPEINIT1( XMLIndexAlphabeticalSourceContext, XMLIndexSourceBaseContext );

XMLIndexAlphabeticalSourceContext::XMLIndexAlphabeticalSourceContext(
    SvXMLImport& rImport,
    sal_uInt16 nPrfx,
    const OUString& rLocalName,
    Reference<XPropertySet> & rPropSet)
:   XMLIndexSourceBaseContext(rImport, nPrfx, rLocalName, rPropSet, sal_False)
,   sMainEntryCharacterStyleName(RTL_CONSTASCII_USTRINGPARAM(sAPI_MainEntryCharacterStyleName))
,   sUseAlphabeticalSeparators(RTL_CONSTASCII_USTRINGPARAM(sAPI_UseAlphabeticalSeparators))
,   sUseCombinedEntries(RTL_CONSTASCII_USTRINGPARAM(sAPI_UseCombinedEntries))
,   sIsCaseSensitive(RTL_CONSTASCII_USTRINGPARAM(sAPI_IsCaseSensitive))
,   sUseKeyAsEntry(RTL_CONSTASCII_USTRINGPARAM(sAPI_UseKeyAsEntry))
,   sUseUpperCase(RTL_CONSTASCII_USTRINGPARAM(sAPI_UseUpperCase))
,   sUseDash(RTL_CONSTASCII_USTRINGPARAM(sAPI_UseDash))
,   sUsePP(RTL_CONSTASCII_USTRINGPARAM(sAPI_UsePP))
,   sIsCommaSeparated(RTL_CONSTASCII_USTRINGPARAM("IsCommaSeparated"))
,   sSortAlgorithm(RTL_CONSTASCII_USTRINGPARAM(sAPI_SortAlgorithm))
,   sLocale(RTL_CONSTASCII_USTRINGPARAM(sAPI_Locale))
,   bMainEntryStyleNameOK(sal_False)
,   bSeparators(sal_False)
,   bCombineEntries(sal_True)
,   bCaseSensitive(sal_True)
,   bEntry(sal_False)
,   bUpperCase(sal_False)
,   bCombineDash(sal_False)
,   bCombinePP(sal_True)
,   bCommaSeparated(sal_False)
{
}

XMLIndexAlphabeticalSourceContext::~XMLIndexAlphabeticalSourceContext()
{
}

void XMLIndexAlphabeticalSourceContext::ProcessAttribute(
    enum IndexSourceParamEnum eParam,
    const OUString& rValue)
{
    sal_Bool bTmp;

    switch (eParam)
    {
        case XML_TOK_INDEXSOURCE_MAIN_ENTRY_STYLE:
            sMainEntryStyleName = rValue;
            bMainEntryStyleNameOK = sal_True;
            break;

        case XML_TOK_INDEXSOURCE_IGNORE_CASE:
            if (SvXMLUnitConverter::convertBool(bTmp, rValue))
            {
                bCaseSensitive = !bTmp;
            }
            break;

        case XML_TOK_INDEXSOURCE_SEPARATORS:
            if (SvXMLUnitConverter::convertBool(bTmp, rValue))
            {
                bSeparators = bTmp;
            }
            break;

        case XML_TOK_INDEXSOURCE_COMBINE_ENTRIES:
            if (SvXMLUnitConverter::convertBool(bTmp, rValue))
            {
                bCombineEntries = bTmp;
            }
            break;

        case XML_TOK_INDEXSOURCE_COMBINE_WITH_DASH:
            if (SvXMLUnitConverter::convertBool(bTmp, rValue))
            {
                bCombineDash = bTmp;
            }
            break;
        case XML_TOK_INDEXSOURCE_KEYS_AS_ENTRIES:
            if (SvXMLUnitConverter::convertBool(bTmp, rValue))
            {
                bEntry = bTmp;
            }
            break;

        case XML_TOK_INDEXSOURCE_COMBINE_WITH_PP:
            if (SvXMLUnitConverter::convertBool(bTmp, rValue))
            {
                bCombinePP = bTmp;
            }
            break;

        case XML_TOK_INDEXSOURCE_CAPITALIZE:
            if (SvXMLUnitConverter::convertBool(bTmp, rValue))
            {
                bUpperCase = bTmp;
            }
            break;

        case XML_TOK_INDEXSOURCE_COMMA_SEPARATED:
            if (SvXMLUnitConverter::convertBool(bTmp, rValue))
            {
                bCommaSeparated = bTmp;
            }
            break;

        case XML_TOK_INDEXSOURCE_SORT_ALGORITHM:
            sAlgorithm = rValue;
            break;
        case XML_TOK_INDEXSOURCE_LANGUAGE:
            aLocale.Language = rValue;
            break;
        case XML_TOK_INDEXSOURCE_COUNTRY:
            aLocale.Country = rValue;
            break;

        default:
            XMLIndexSourceBaseContext::ProcessAttribute(eParam, rValue);
            break;
    }
}

void XMLIndexAlphabeticalSourceContext::EndElement()
{

    Any aAny;

    if (bMainEntryStyleNameOK)
    {
        aAny <<= GetImport().GetStyleDisplayName(
                            XML_STYLE_FAMILY_TEXT_TEXT, sMainEntryStyleName );
        rIndexPropertySet->setPropertyValue(sMainEntryCharacterStyleName,aAny);
    }

    aAny.setValue(&bSeparators, ::getBooleanCppuType());
    rIndexPropertySet->setPropertyValue(sUseAlphabeticalSeparators, aAny);

    aAny.setValue(&bCombineEntries, ::getBooleanCppuType());
    rIndexPropertySet->setPropertyValue(sUseCombinedEntries, aAny);

    aAny.setValue(&bCaseSensitive, ::getBooleanCppuType());
    rIndexPropertySet->setPropertyValue(sIsCaseSensitive, aAny);

    aAny.setValue(&bEntry, ::getBooleanCppuType());
    rIndexPropertySet->setPropertyValue(sUseKeyAsEntry, aAny);

    aAny.setValue(&bUpperCase, ::getBooleanCppuType());
    rIndexPropertySet->setPropertyValue(sUseUpperCase, aAny);

    aAny.setValue(&bCombineDash, ::getBooleanCppuType());
    rIndexPropertySet->setPropertyValue(sUseDash, aAny);

    aAny.setValue(&bCombinePP, ::getBooleanCppuType());
    rIndexPropertySet->setPropertyValue(sUsePP, aAny);

    aAny.setValue(&bCommaSeparated, ::getBooleanCppuType());
    rIndexPropertySet->setPropertyValue(sIsCommaSeparated, aAny);

    if (sAlgorithm.getLength() > 0)
    {
        aAny <<= sAlgorithm;
        rIndexPropertySet->setPropertyValue(sSortAlgorithm, aAny);
    }

    if ( (aLocale.Language.getLength() > 0) &&
         (aLocale.Country.getLength() > 0)      )
    {
        aAny <<= aLocale;
        rIndexPropertySet->setPropertyValue(sLocale, aAny);
    }

    XMLIndexSourceBaseContext::EndElement();
}

SvXMLImportContext* XMLIndexAlphabeticalSourceContext::CreateChildContext(
    sal_uInt16 nPrefix,
    const OUString& rLocalName,
    const Reference<XAttributeList> & xAttrList )
{
    if ( (XML_NAMESPACE_TEXT == nPrefix) &&
         IsXMLToken( rLocalName, XML_ALPHABETICAL_INDEX_ENTRY_TEMPLATE ) )
    {
        return new XMLIndexTemplateContext(GetImport(), rIndexPropertySet,
                                           nPrefix, rLocalName,
                                           aLevelNameAlphaMap,
                                           XML_OUTLINE_LEVEL,
                                           aLevelStylePropNameAlphaMap,
                                           aAllowedTokenTypesAlpha);
    }
    else
    {
        return XMLIndexSourceBaseContext::CreateChildContext(nPrefix,
                                                             rLocalName,
                                                             xAttrList);
    }
}
<commit_msg>INTEGRATION: CWS swqbf101 (1.9.12); FILE MERGED 2007/07/11 07:49:17 ama 1.9.12.1: Fix #i76279#: Remove unused style names<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: XMLIndexAlphabeticalSourceContext.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: rt $ $Date: 2007-07-26 08:15:26 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"

#ifndef _XMLOFF_XMLINDEXALPHABETICALSOURCECONTEXT_HXX_
#include "XMLIndexAlphabeticalSourceContext.hxx"
#endif

#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif

#ifndef _COM_SUN_STAR_CONTAINER_XINDEXREPLACE_HPP_
#include <com/sun/star/container/XIndexReplace.hpp>
#endif

#ifndef _XMLOFF_XMLINDEXTEMPLATECONTEXT_HXX_
#include "XMLIndexTemplateContext.hxx"
#endif

#ifndef _XMLOFF_XMLINDEXTITLETEMPLATECONTEXT_HXX_
#include "XMLIndexTitleTemplateContext.hxx"
#endif

#ifndef _XMLOFF_XMLINDEXTOCSTYLESCONTEXT_HXX_
#include "XMLIndexTOCStylesContext.hxx"
#endif

#ifndef _XMLOFF_XMLICTXT_HXX
#include <xmloff/xmlictxt.hxx>
#endif

#ifndef _XMLOFF_XMLIMP_HXX
#include <xmloff/xmlimp.hxx>
#endif

#ifndef _XMLOFF_TEXTIMP_HXX_
#include <xmloff/txtimp.hxx>
#endif

#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif

#ifndef _XMLOFF_NMSPMAP_HXX
#include <xmloff/nmspmap.hxx>
#endif

#ifndef _XMLOFF_XMLTOKEN_HXX
#include <xmloff/xmltoken.hxx>
#endif

#ifndef _XMLOFF_XMLUCONV_HXX
#include <xmloff/xmluconv.hxx>
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

using ::rtl::OUString;
using ::com::sun::star::beans::XPropertySet;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Any;
using ::com::sun::star::xml::sax::XAttributeList;
using ::xmloff::token::IsXMLToken;
using ::xmloff::token::XML_ALPHABETICAL_INDEX_ENTRY_TEMPLATE;
using ::xmloff::token::XML_OUTLINE_LEVEL;

const sal_Char sAPI_MainEntryCharacterStyleName[] = "MainEntryCharacterStyleName";
const sal_Char sAPI_UseAlphabeticalSeparators[] = "UseAlphabeticalSeparators";
const sal_Char sAPI_UseCombinedEntries[] = "UseCombinedEntries";
const sal_Char sAPI_IsCaseSensitive[] = "IsCaseSensitive";
const sal_Char sAPI_UseKeyAsEntry[] = "UseKeyAsEntry";
const sal_Char sAPI_UseUpperCase[] = "UseUpperCase";
const sal_Char sAPI_UseDash[] = "UseDash";
const sal_Char sAPI_UsePP[] = "UsePP";
const sal_Char sAPI_SortAlgorithm[] = "SortAlgorithm";
const sal_Char sAPI_Locale[] = "Locale";

TYPEINIT1( XMLIndexAlphabeticalSourceContext, XMLIndexSourceBaseContext );

XMLIndexAlphabeticalSourceContext::XMLIndexAlphabeticalSourceContext(
    SvXMLImport& rImport,
    sal_uInt16 nPrfx,
    const OUString& rLocalName,
    Reference<XPropertySet> & rPropSet)
:   XMLIndexSourceBaseContext(rImport, nPrfx, rLocalName, rPropSet, sal_False)
,   sMainEntryCharacterStyleName(RTL_CONSTASCII_USTRINGPARAM(sAPI_MainEntryCharacterStyleName))
,   sUseAlphabeticalSeparators(RTL_CONSTASCII_USTRINGPARAM(sAPI_UseAlphabeticalSeparators))
,   sUseCombinedEntries(RTL_CONSTASCII_USTRINGPARAM(sAPI_UseCombinedEntries))
,   sIsCaseSensitive(RTL_CONSTASCII_USTRINGPARAM(sAPI_IsCaseSensitive))
,   sUseKeyAsEntry(RTL_CONSTASCII_USTRINGPARAM(sAPI_UseKeyAsEntry))
,   sUseUpperCase(RTL_CONSTASCII_USTRINGPARAM(sAPI_UseUpperCase))
,   sUseDash(RTL_CONSTASCII_USTRINGPARAM(sAPI_UseDash))
,   sUsePP(RTL_CONSTASCII_USTRINGPARAM(sAPI_UsePP))
,   sIsCommaSeparated(RTL_CONSTASCII_USTRINGPARAM("IsCommaSeparated"))
,   sSortAlgorithm(RTL_CONSTASCII_USTRINGPARAM(sAPI_SortAlgorithm))
,   sLocale(RTL_CONSTASCII_USTRINGPARAM(sAPI_Locale))
,   bMainEntryStyleNameOK(sal_False)
,   bSeparators(sal_False)
,   bCombineEntries(sal_True)
,   bCaseSensitive(sal_True)
,   bEntry(sal_False)
,   bUpperCase(sal_False)
,   bCombineDash(sal_False)
,   bCombinePP(sal_True)
,   bCommaSeparated(sal_False)
{
}

XMLIndexAlphabeticalSourceContext::~XMLIndexAlphabeticalSourceContext()
{
}

void XMLIndexAlphabeticalSourceContext::ProcessAttribute(
    enum IndexSourceParamEnum eParam,
    const OUString& rValue)
{
    sal_Bool bTmp;

    switch (eParam)
    {
        case XML_TOK_INDEXSOURCE_MAIN_ENTRY_STYLE:
            {
                sMainEntryStyleName = rValue;
                OUString sDisplayStyleName = GetImport().GetStyleDisplayName(
                    XML_STYLE_FAMILY_TEXT_TEXT, sMainEntryStyleName );
                const Reference < ::com::sun::star::container::XNameContainer >&
                    rStyles = GetImport().GetTextImport()->GetTextStyles();
                bMainEntryStyleNameOK = rStyles.is() && rStyles->hasByName( sDisplayStyleName );
            }
            break;

        case XML_TOK_INDEXSOURCE_IGNORE_CASE:
            if (SvXMLUnitConverter::convertBool(bTmp, rValue))
            {
                bCaseSensitive = !bTmp;
            }
            break;

        case XML_TOK_INDEXSOURCE_SEPARATORS:
            if (SvXMLUnitConverter::convertBool(bTmp, rValue))
            {
                bSeparators = bTmp;
            }
            break;

        case XML_TOK_INDEXSOURCE_COMBINE_ENTRIES:
            if (SvXMLUnitConverter::convertBool(bTmp, rValue))
            {
                bCombineEntries = bTmp;
            }
            break;

        case XML_TOK_INDEXSOURCE_COMBINE_WITH_DASH:
            if (SvXMLUnitConverter::convertBool(bTmp, rValue))
            {
                bCombineDash = bTmp;
            }
            break;
        case XML_TOK_INDEXSOURCE_KEYS_AS_ENTRIES:
            if (SvXMLUnitConverter::convertBool(bTmp, rValue))
            {
                bEntry = bTmp;
            }
            break;

        case XML_TOK_INDEXSOURCE_COMBINE_WITH_PP:
            if (SvXMLUnitConverter::convertBool(bTmp, rValue))
            {
                bCombinePP = bTmp;
            }
            break;

        case XML_TOK_INDEXSOURCE_CAPITALIZE:
            if (SvXMLUnitConverter::convertBool(bTmp, rValue))
            {
                bUpperCase = bTmp;
            }
            break;

        case XML_TOK_INDEXSOURCE_COMMA_SEPARATED:
            if (SvXMLUnitConverter::convertBool(bTmp, rValue))
            {
                bCommaSeparated = bTmp;
            }
            break;

        case XML_TOK_INDEXSOURCE_SORT_ALGORITHM:
            sAlgorithm = rValue;
            break;
        case XML_TOK_INDEXSOURCE_LANGUAGE:
            aLocale.Language = rValue;
            break;
        case XML_TOK_INDEXSOURCE_COUNTRY:
            aLocale.Country = rValue;
            break;

        default:
            XMLIndexSourceBaseContext::ProcessAttribute(eParam, rValue);
            break;
    }
}

void XMLIndexAlphabeticalSourceContext::EndElement()
{

    Any aAny;

    if (bMainEntryStyleNameOK)
    {
        aAny <<= GetImport().GetStyleDisplayName(
                            XML_STYLE_FAMILY_TEXT_TEXT, sMainEntryStyleName );
        rIndexPropertySet->setPropertyValue(sMainEntryCharacterStyleName,aAny);
    }

    aAny.setValue(&bSeparators, ::getBooleanCppuType());
    rIndexPropertySet->setPropertyValue(sUseAlphabeticalSeparators, aAny);

    aAny.setValue(&bCombineEntries, ::getBooleanCppuType());
    rIndexPropertySet->setPropertyValue(sUseCombinedEntries, aAny);

    aAny.setValue(&bCaseSensitive, ::getBooleanCppuType());
    rIndexPropertySet->setPropertyValue(sIsCaseSensitive, aAny);

    aAny.setValue(&bEntry, ::getBooleanCppuType());
    rIndexPropertySet->setPropertyValue(sUseKeyAsEntry, aAny);

    aAny.setValue(&bUpperCase, ::getBooleanCppuType());
    rIndexPropertySet->setPropertyValue(sUseUpperCase, aAny);

    aAny.setValue(&bCombineDash, ::getBooleanCppuType());
    rIndexPropertySet->setPropertyValue(sUseDash, aAny);

    aAny.setValue(&bCombinePP, ::getBooleanCppuType());
    rIndexPropertySet->setPropertyValue(sUsePP, aAny);

    aAny.setValue(&bCommaSeparated, ::getBooleanCppuType());
    rIndexPropertySet->setPropertyValue(sIsCommaSeparated, aAny);

    if (sAlgorithm.getLength() > 0)
    {
        aAny <<= sAlgorithm;
        rIndexPropertySet->setPropertyValue(sSortAlgorithm, aAny);
    }

    if ( (aLocale.Language.getLength() > 0) &&
         (aLocale.Country.getLength() > 0)      )
    {
        aAny <<= aLocale;
        rIndexPropertySet->setPropertyValue(sLocale, aAny);
    }

    XMLIndexSourceBaseContext::EndElement();
}

SvXMLImportContext* XMLIndexAlphabeticalSourceContext::CreateChildContext(
    sal_uInt16 nPrefix,
    const OUString& rLocalName,
    const Reference<XAttributeList> & xAttrList )
{
    if ( (XML_NAMESPACE_TEXT == nPrefix) &&
         IsXMLToken( rLocalName, XML_ALPHABETICAL_INDEX_ENTRY_TEMPLATE ) )
    {
        return new XMLIndexTemplateContext(GetImport(), rIndexPropertySet,
                                           nPrefix, rLocalName,
                                           aLevelNameAlphaMap,
                                           XML_OUTLINE_LEVEL,
                                           aLevelStylePropNameAlphaMap,
                                           aAllowedTokenTypesAlpha);
    }
    else
    {
        return XMLIndexSourceBaseContext::CreateChildContext(nPrefix,
                                                             rLocalName,
                                                             xAttrList);
    }
}
<|endoftext|>