<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  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.
 */
/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#pragma once

#include <seastar/net/stack.hh>
#include <iostream>
#include <seastar/net/inet_address.hh>

namespace seastar {

namespace net {

using namespace seastar;

template <typename Protocol>
class native_server_socket_impl;

template <typename Protocol>
class native_connected_socket_impl;

class native_network_stack;

// native_server_socket_impl
template <typename Protocol>
class native_server_socket_impl : public server_socket_impl {
    typename Protocol::listener _listener;
public:
    native_server_socket_impl(Protocol& proto, uint16_t port, listen_options opt);
    virtual future<accept_result> accept() override;
    virtual void abort_accept() override;
    virtual socket_address local_address() const override;
};

template <typename Protocol>
native_server_socket_impl<Protocol>::native_server_socket_impl(Protocol& proto, uint16_t port, listen_options opt)
    : _listener(proto.listen(port)) {
}

template <typename Protocol>
future<accept_result>
native_server_socket_impl<Protocol>::accept() {
    return _listener.accept().then([] (typename Protocol::connection conn) {
        // Save "conn" contents before call below function
        // "conn" is moved in 1st argument, and used in 2nd argument
        // It causes trouble on Arm which passes arguments from left to right
        auto ip = conn.foreign_ip().ip;
        auto port = conn.foreign_port();
        return make_ready_future<accept_result>(accept_result{
                connected_socket(std::make_unique<native_connected_socket_impl<Protocol>>(make_lw_shared(std::move(conn)))),
                make_ipv4_address(ip, port)});
    });
}

template <typename Protocol>
void
native_server_socket_impl<Protocol>::abort_accept() {
    _listener.abort_accept();
}

template <typename Protocol>
socket_address native_server_socket_impl<Protocol>::local_address() const {
    return socket_address(_listener.get_tcp().inet().inet().host_address(), _listener.port());
}

// native_connected_socket_impl
template <typename Protocol>
class native_connected_socket_impl : public connected_socket_impl {
    lw_shared_ptr<typename Protocol::connection> _conn;
    class native_data_source_impl;
    class native_data_sink_impl;
public:
    explicit native_connected_socket_impl(lw_shared_ptr<typename Protocol::connection> conn)
        : _conn(std::move(conn)) {}
    virtual data_source source() override;
    virtual data_sink sink() override;
    virtual void shutdown_input() override;
    virtual void shutdown_output() override;
    virtual void set_nodelay(bool nodelay) override;
    virtual bool get_nodelay() const override;
    void set_keepalive(bool keepalive) override;
    bool get_keepalive() const override;
    void set_keepalive_parameters(const keepalive_params&) override;
    keepalive_params get_keepalive_parameters() const override;
    int get_sockopt(int level, int optname, void* data, size_t len) const;
    void set_sockopt(int level, int optname, const void* data, size_t len);
};

template <typename Protocol>
class native_socket_impl final : public socket_impl {
    Protocol& _proto;
    lw_shared_ptr<typename Protocol::connection> _conn;
public:
    explicit native_socket_impl(Protocol& proto)
        : _proto(proto), _conn(nullptr) { }

    virtual future<connected_socket> connect(socket_address sa, socket_address local, transport proto = transport::TCP) override {
        //TODO: implement SCTP
        assert(proto == transport::TCP);

        // FIXME: local is ignored since native stack does not support multiple IPs yet
        assert(sa.as_posix_sockaddr().sa_family == AF_INET);

        _conn = make_lw_shared<typename Protocol::connection>(_proto.connect(sa));
        return _conn->connected().then([conn = _conn]() mutable {
            auto csi = std::make_unique<native_connected_socket_impl<Protocol>>(std::move(conn));
            return make_ready_future<connected_socket>(connected_socket(std::move(csi)));
        });
    }

    virtual void set_reuseaddr(bool reuseaddr) override {
        // FIXME: implement
        std::cerr << "Reuseaddr is not supported by native stack" << std::endl;
    }

    virtual bool get_reuseaddr() const override {
        // FIXME: implement
        return false;
    }

    virtual void shutdown() override {
        if (_conn) {
            _conn->shutdown_connect();
        }
    }
};

template <typename Protocol>
class native_connected_socket_impl<Protocol>::native_data_source_impl final
    : public data_source_impl {
    typedef typename Protocol::connection connection_type;
    lw_shared_ptr<connection_type> _conn;
    size_t _cur_frag = 0;
    bool _eof = false;
    packet _buf;
public:
    explicit native_data_source_impl(lw_shared_ptr<connection_type> conn)
        : _conn(std::move(conn)) {}
    virtual future<temporary_buffer<char>> get() override {
        if (_eof) {
            return make_ready_future<temporary_buffer<char>>(temporary_buffer<char>(0));
        }
        if (_cur_frag != _buf.nr_frags()) {
            auto& f = _buf.fragments()[_cur_frag++];
            return make_ready_future<temporary_buffer<char>>(
                    temporary_buffer<char>(f.base, f.size,
                            make_deleter(deleter(), [p = _buf.share()] () mutable {})));
        }
        return _conn->wait_for_data().then([this] {
            _buf = _conn->read();
            _cur_frag = 0;
            _eof = !_buf.len();
            return get();
        });
    }
    future<> close() override {
        _conn->close_write();
        return make_ready_future<>();
    }
};

template <typename Protocol>
class native_connected_socket_impl<Protocol>::native_data_sink_impl final
    : public data_sink_impl {
    typedef typename Protocol::connection connection_type;
    lw_shared_ptr<connection_type> _conn;
public:
    explicit native_data_sink_impl(lw_shared_ptr<connection_type> conn)
        : _conn(std::move(conn)) {}
    using data_sink_impl::put;
    virtual future<> put(packet p) override {
        return _conn->send(std::move(p));
    }
    virtual future<> close() override {
        _conn->close_write();
        return make_ready_future<>();
    }
};

template <typename Protocol>
data_source native_connected_socket_impl<Protocol>::source() {
    return data_source(std::make_unique<native_data_source_impl>(_conn));
}

template <typename Protocol>
data_sink native_connected_socket_impl<Protocol>::sink() {
    return data_sink(std::make_unique<native_data_sink_impl>(_conn));
}

template <typename Protocol>
void
native_connected_socket_impl<Protocol>::shutdown_input() {
    _conn->close_read();
}

template <typename Protocol>
void
native_connected_socket_impl<Protocol>::shutdown_output() {
    _conn->close_write();
}

template <typename Protocol>
void
native_connected_socket_impl<Protocol>::set_nodelay(bool nodelay) {
    // FIXME: implement
}

template <typename Protocol>
bool
native_connected_socket_impl<Protocol>::get_nodelay() const {
    // FIXME: implement
    return true;
}

template <typename Protocol>
void native_connected_socket_impl<Protocol>::set_keepalive(bool keepalive) {
    // FIXME: implement
    std::cerr << "Keepalive is not supported by native stack" << std::endl;
}
template <typename Protocol>
bool native_connected_socket_impl<Protocol>::get_keepalive() const {
    // FIXME: implement
    return false;
}

template <typename Protocol>
void native_connected_socket_impl<Protocol>::set_keepalive_parameters(const keepalive_params&) {
    // FIXME: implement
    std::cerr << "Keepalive parameters are not supported by native stack" << std::endl;
}

template <typename Protocol>
keepalive_params native_connected_socket_impl<Protocol>::get_keepalive_parameters() const {
    // FIXME: implement
    return tcp_keepalive_params {std::chrono::seconds(0), std::chrono::seconds(0), 0};
}

template<typename Protocol>
void native_connected_socket_impl<Protocol>::set_sockopt(int level, int optname, const void* data, size_t len) {
    throw std::runtime_error("Setting custom socket options is not supported for native stack");
}

template<typename Protocol>
int native_connected_socket_impl<Protocol>::get_sockopt(int level, int optname, void* data, size_t len) const {
    throw std::runtime_error("Getting custom socket options is not supported for native stack");
}

}

}
<commit_msg>net: expose hidden method from parent class<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  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.
 */
/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#pragma once

#include <seastar/net/stack.hh>
#include <iostream>
#include <seastar/net/inet_address.hh>

namespace seastar {

namespace net {

using namespace seastar;

template <typename Protocol>
class native_server_socket_impl;

template <typename Protocol>
class native_connected_socket_impl;

class native_network_stack;

// native_server_socket_impl
template <typename Protocol>
class native_server_socket_impl : public server_socket_impl {
    typename Protocol::listener _listener;
public:
    native_server_socket_impl(Protocol& proto, uint16_t port, listen_options opt);
    virtual future<accept_result> accept() override;
    virtual void abort_accept() override;
    virtual socket_address local_address() const override;
};

template <typename Protocol>
native_server_socket_impl<Protocol>::native_server_socket_impl(Protocol& proto, uint16_t port, listen_options opt)
    : _listener(proto.listen(port)) {
}

template <typename Protocol>
future<accept_result>
native_server_socket_impl<Protocol>::accept() {
    return _listener.accept().then([] (typename Protocol::connection conn) {
        // Save "conn" contents before call below function
        // "conn" is moved in 1st argument, and used in 2nd argument
        // It causes trouble on Arm which passes arguments from left to right
        auto ip = conn.foreign_ip().ip;
        auto port = conn.foreign_port();
        return make_ready_future<accept_result>(accept_result{
                connected_socket(std::make_unique<native_connected_socket_impl<Protocol>>(make_lw_shared(std::move(conn)))),
                make_ipv4_address(ip, port)});
    });
}

template <typename Protocol>
void
native_server_socket_impl<Protocol>::abort_accept() {
    _listener.abort_accept();
}

template <typename Protocol>
socket_address native_server_socket_impl<Protocol>::local_address() const {
    return socket_address(_listener.get_tcp().inet().inet().host_address(), _listener.port());
}

// native_connected_socket_impl
template <typename Protocol>
class native_connected_socket_impl : public connected_socket_impl {
    lw_shared_ptr<typename Protocol::connection> _conn;
    class native_data_source_impl;
    class native_data_sink_impl;
public:
    explicit native_connected_socket_impl(lw_shared_ptr<typename Protocol::connection> conn)
        : _conn(std::move(conn)) {}
    using connected_socket_impl::source;
    virtual data_source source() override;
    virtual data_sink sink() override;
    virtual void shutdown_input() override;
    virtual void shutdown_output() override;
    virtual void set_nodelay(bool nodelay) override;
    virtual bool get_nodelay() const override;
    void set_keepalive(bool keepalive) override;
    bool get_keepalive() const override;
    void set_keepalive_parameters(const keepalive_params&) override;
    keepalive_params get_keepalive_parameters() const override;
    int get_sockopt(int level, int optname, void* data, size_t len) const;
    void set_sockopt(int level, int optname, const void* data, size_t len);
};

template <typename Protocol>
class native_socket_impl final : public socket_impl {
    Protocol& _proto;
    lw_shared_ptr<typename Protocol::connection> _conn;
public:
    explicit native_socket_impl(Protocol& proto)
        : _proto(proto), _conn(nullptr) { }

    virtual future<connected_socket> connect(socket_address sa, socket_address local, transport proto = transport::TCP) override {
        //TODO: implement SCTP
        assert(proto == transport::TCP);

        // FIXME: local is ignored since native stack does not support multiple IPs yet
        assert(sa.as_posix_sockaddr().sa_family == AF_INET);

        _conn = make_lw_shared<typename Protocol::connection>(_proto.connect(sa));
        return _conn->connected().then([conn = _conn]() mutable {
            auto csi = std::make_unique<native_connected_socket_impl<Protocol>>(std::move(conn));
            return make_ready_future<connected_socket>(connected_socket(std::move(csi)));
        });
    }

    virtual void set_reuseaddr(bool reuseaddr) override {
        // FIXME: implement
        std::cerr << "Reuseaddr is not supported by native stack" << std::endl;
    }

    virtual bool get_reuseaddr() const override {
        // FIXME: implement
        return false;
    }

    virtual void shutdown() override {
        if (_conn) {
            _conn->shutdown_connect();
        }
    }
};

template <typename Protocol>
class native_connected_socket_impl<Protocol>::native_data_source_impl final
    : public data_source_impl {
    typedef typename Protocol::connection connection_type;
    lw_shared_ptr<connection_type> _conn;
    size_t _cur_frag = 0;
    bool _eof = false;
    packet _buf;
public:
    explicit native_data_source_impl(lw_shared_ptr<connection_type> conn)
        : _conn(std::move(conn)) {}
    virtual future<temporary_buffer<char>> get() override {
        if (_eof) {
            return make_ready_future<temporary_buffer<char>>(temporary_buffer<char>(0));
        }
        if (_cur_frag != _buf.nr_frags()) {
            auto& f = _buf.fragments()[_cur_frag++];
            return make_ready_future<temporary_buffer<char>>(
                    temporary_buffer<char>(f.base, f.size,
                            make_deleter(deleter(), [p = _buf.share()] () mutable {})));
        }
        return _conn->wait_for_data().then([this] {
            _buf = _conn->read();
            _cur_frag = 0;
            _eof = !_buf.len();
            return get();
        });
    }
    future<> close() override {
        _conn->close_write();
        return make_ready_future<>();
    }
};

template <typename Protocol>
class native_connected_socket_impl<Protocol>::native_data_sink_impl final
    : public data_sink_impl {
    typedef typename Protocol::connection connection_type;
    lw_shared_ptr<connection_type> _conn;
public:
    explicit native_data_sink_impl(lw_shared_ptr<connection_type> conn)
        : _conn(std::move(conn)) {}
    using data_sink_impl::put;
    virtual future<> put(packet p) override {
        return _conn->send(std::move(p));
    }
    virtual future<> close() override {
        _conn->close_write();
        return make_ready_future<>();
    }
};

template <typename Protocol>
data_source native_connected_socket_impl<Protocol>::source() {
    return data_source(std::make_unique<native_data_source_impl>(_conn));
}

template <typename Protocol>
data_sink native_connected_socket_impl<Protocol>::sink() {
    return data_sink(std::make_unique<native_data_sink_impl>(_conn));
}

template <typename Protocol>
void
native_connected_socket_impl<Protocol>::shutdown_input() {
    _conn->close_read();
}

template <typename Protocol>
void
native_connected_socket_impl<Protocol>::shutdown_output() {
    _conn->close_write();
}

template <typename Protocol>
void
native_connected_socket_impl<Protocol>::set_nodelay(bool nodelay) {
    // FIXME: implement
}

template <typename Protocol>
bool
native_connected_socket_impl<Protocol>::get_nodelay() const {
    // FIXME: implement
    return true;
}

template <typename Protocol>
void native_connected_socket_impl<Protocol>::set_keepalive(bool keepalive) {
    // FIXME: implement
    std::cerr << "Keepalive is not supported by native stack" << std::endl;
}
template <typename Protocol>
bool native_connected_socket_impl<Protocol>::get_keepalive() const {
    // FIXME: implement
    return false;
}

template <typename Protocol>
void native_connected_socket_impl<Protocol>::set_keepalive_parameters(const keepalive_params&) {
    // FIXME: implement
    std::cerr << "Keepalive parameters are not supported by native stack" << std::endl;
}

template <typename Protocol>
keepalive_params native_connected_socket_impl<Protocol>::get_keepalive_parameters() const {
    // FIXME: implement
    return tcp_keepalive_params {std::chrono::seconds(0), std::chrono::seconds(0), 0};
}

template<typename Protocol>
void native_connected_socket_impl<Protocol>::set_sockopt(int level, int optname, const void* data, size_t len) {
    throw std::runtime_error("Setting custom socket options is not supported for native stack");
}

template<typename Protocol>
int native_connected_socket_impl<Protocol>::get_sockopt(int level, int optname, void* data, size_t len) const {
    throw std::runtime_error("Getting custom socket options is not supported for native stack");
}

}

}
<|endoftext|>


<commit_before>
#include <configure/Application.hpp>

#include <boost/filesystem.hpp>

#include <fstream>
#include <vector>

namespace fs = boost::filesystem;

typedef configure::Application app_t;

BOOST_AUTO_TEST_CASE(invalid_args)
{
	std::vector<std::string> empty_args;
	BOOST_CHECK_THROW(configure::Application(0, nullptr), std::exception);
	BOOST_CHECK_THROW(configure::Application(-1, nullptr), std::exception);
	BOOST_CHECK_THROW(configure::Application(empty_args), std::exception);
}

struct Env
{
	fs::path _dir;
	fs::path _old_cwd;

	Env()
		: _dir{fs::temp_directory_path() / fs::unique_path()}
		, _old_cwd{fs::current_path()}
	{
		fs::create_directories(_dir);
		fs::current_path(_dir);
	}

	~Env()
	{
		fs::current_path(_old_cwd);
		fs::remove_all(_dir);
	}

	void add_project()
	{
		std::ofstream out{(_dir / "configure.lua").string()};
		out << "something";
		out.close();
	}

	fs::path const& dir() { return _dir; }
};

BOOST_AUTO_TEST_CASE(missing_project)
{
	Env env;
	BOOST_CHECK_THROW(app_t({"pif"}), std::exception);
}

BOOST_AUTO_TEST_CASE(no_build_dir)
{
	Env env;
	env.add_project();
	app_t app({"pif"});
	BOOST_CHECK_EQUAL(app.build_directories().size(), 0);
	BOOST_CHECK_EQUAL(app.project_directory(), env.dir());
}
<commit_msg>Prevent messed up macros with parenthesis.<commit_after>
#include <configure/Application.hpp>

#include <boost/filesystem.hpp>

#include <fstream>

namespace fs = boost::filesystem;

typedef configure::Application app_t;

BOOST_AUTO_TEST_CASE(invalid_args)
{
	BOOST_CHECK_THROW(configure::Application(0, nullptr), std::exception);
	BOOST_CHECK_THROW(configure::Application(-1, nullptr), std::exception);
	BOOST_CHECK_THROW(
		(configure::Application(std::vector<std::string>())),
		std::exception
	);
}

struct Env
{
	fs::path _dir;
	fs::path _old_cwd;

	Env()
		: _dir{fs::temp_directory_path() / fs::unique_path()}
		, _old_cwd{fs::current_path()}
	{
		fs::create_directories(_dir);
		fs::current_path(_dir);
	}

	~Env()
	{
		fs::current_path(_old_cwd);
		fs::remove_all(_dir);
	}

	void add_project()
	{
		std::ofstream out{(_dir / "configure.lua").string()};
		out << "something";
		out.close();
	}

	fs::path const& dir() { return _dir; }
};

BOOST_AUTO_TEST_CASE(missing_project)
{
	Env env;
	BOOST_CHECK_THROW(app_t({"pif"}), std::exception);
}

BOOST_AUTO_TEST_CASE(no_build_dir)
{
	Env env;
	env.add_project();
	app_t app({"pif"});
	BOOST_CHECK_EQUAL(app.build_directories().size(), 0);
	BOOST_CHECK_EQUAL(app.project_directory(), env.dir());
}
<|endoftext|>


<commit_before>#pragma once

#include<vector>

#include "nifty/tools/runtime_check.hxx"
#include "nifty/graph/optimization/multicut/multicut_base.hxx"
#include "nifty/graph/optimization/multicut/multicut_factory.hxx"
#include "nifty/graph/optimization/multicut/multicut_greedy_additive.hxx"
#include "nifty/graph/optimization/multicut/multicut_kernighan_lin.hxx"
#include "nifty/ufd/ufd.hxx"

// LP_MP includes
#include "visitors/standard_visitor.hxx"
#include "solvers/multicut/multicut.h"

namespace nifty{
namespace graph{

    template<class OBJECTIVE>
    class MulticutMp : public MulticutBase<OBJECTIVE>
    {
    public:

        typedef OBJECTIVE Objective;
        typedef MulticutBase<OBJECTIVE> Base;
        typedef typename Base::VisitorBase VisitorBase;
        typedef typename Base::VisitorProxy VisitorProxy;
        typedef typename Base::EdgeLabels EdgeLabels;
        typedef typename Base::NodeLabels NodeLabels;
        typedef typename Objective::Graph Graph;

        // factory for the lp_mp primal rounder
        typedef MulticutFactoryBase<Objective> McFactoryBase;

    public:

        struct NiftyRounder {

            typedef Graph GraphType;

            NiftyRounder(std::shared_ptr<McFactoryBase> factory,
                    const bool greedyWarmstart)
                : factory_(factory), greedyWarmstart_(greedyWarmstart)
            {}

            // TODO do we have to call by value here due to using async or could we also use a call by refernce?
            // TODO need to change between between edge and node labelings -> could be done more efficient ?!
            std::vector<char> operator()(GraphType g, std::vector<double> edgeValues) {

                std::vector<char> labeling(g.numberOfEdges(), 0);
                if(g.numberOfEdges() > 0) {

                    Objective obj(g);

                    auto & objWeights = obj.weights();
                    for(auto eId = 0; eId < edgeValues.size(); ++eId) {
                        objWeights[eId] = edgeValues[eId];
                    }

                    NodeLabels nodeLabels(g.numberOfNodes());
                    // TODO is there a bug in here ?!?
                    if(greedyWarmstart_) {
                        MulticutGreedyAdditive<Objective> greedy(obj);
                        greedy.optimize(nodeLabels, nullptr);
                    }

                    auto solverPtr = factory_->createRawPtr(obj);
                    std::cout << "compute multicut primal with " << (greedyWarmstart_ ? "GAEC + " : "") << solverPtr->name()  << std::endl;
                    solverPtr->optimize(nodeLabels, nullptr);
                    delete solverPtr;

                    // node labeling to edge labeling
                    for(auto eId = 0; eId < g.numberOfEdges(); ++eId) {
                        const auto & uv = g.uv(eId);
                        labeling[eId] = nodeLabels[uv.first] != nodeLabels[uv.second];
                    }

                }
                return labeling;

            }

            // TODO add factory name here
            static std::string name() {
                return "NiftyRounder";
            }

        private:
            std::shared_ptr<McFactoryBase> factory_;
            bool greedyWarmstart_;
        };

        //typedef LP_MP::KlRounder Rounder;
        typedef NiftyRounder Rounder;

        // TODO with or without odd wheel ?
        //typedef LP_MP::FMC_MULTICUT<LP_MP::MessageSendingType::SRMP,NiftyRounder> FMC;
        typedef LP_MP::FMC_ODD_WHEEL_MULTICUT<LP_MP::MessageSendingType::SRMP,Rounder> FMC;

        typedef LP_MP::Solver<FMC,LP_MP::LP,LP_MP::StandardTighteningVisitor,Rounder> SolverBase;
        typedef LP_MP::ProblemConstructorRoundingSolver<SolverBase> SolverType;

        // FIXME verbose deosn't have any effect right now
        struct Settings{
            // multicut factory for the primal rounder used in lp_mp
            std::shared_ptr<McFactoryBase> mcFactory;
            bool greedyWarmstart{false};
            // settings for the lp_mp solver
            size_t numberOfIterations{1000};
            int verbose{0};
            size_t primalComputationInterval{100};
            std::string standardReparametrization{"anisotropic"};
            std::string roundingReparametrization{"damped_uniform"};
            std::string tightenReparametrization{"damped_uniform"};
            bool tighten{true};
            size_t tightenInterval{100};
            size_t tightenIteration{10};
            double tightenSlope{0.02};
            double tightenConstraintsPercentage{0.1};
            double minDualImprovement{0.};
            size_t minDualImprovementInterval{0};
            size_t timeout{0};
            size_t numberOfThreads{1};
        };

        virtual ~MulticutMp(){
            delete mpSolver_;
        }

        MulticutMp(const Objective & objective, const Settings & settings = Settings());

        virtual void optimize(NodeLabels & nodeLabels, VisitorBase * visitor);

        virtual const Objective & objective() const {return objective_;}
        virtual const NodeLabels & currentBestNodeLabels() {return *currentBest_;}

        virtual std::string name() const {
            return std::string("MulticutMp");
        }

        // TODO do we need this, what does it do?
        // reset ?!
        //virtual void weightsChanged(){
        //}

    private:

        void initializeMp();
        void nodeLabeling();
        std::vector<std::string> toOptionsVector() const;

        const Objective & objective_;
        const Graph & graph_;

        Settings settings_;
        NodeLabels * currentBest_;
        size_t numberOfOptRuns_;
        SolverType * mpSolver_;
        ufd::Ufd<uint64_t> ufd_;
    };

    template<class OBJECTIVE>
    MulticutMp<OBJECTIVE>::
    MulticutMp(
        const Objective & objective,
        const Settings & settings
    )
    :   objective_(objective),
        graph_(objective.graph()),
        settings_(settings),
        currentBest_(nullptr),
        mpSolver_(nullptr),
        ufd_(graph_.numberOfNodes())
    {
        // if we don't have a mc-factory, we use the LP_MP default rounder
        if(!bool(settings_.mcFactory)) {
            typedef MulticutKernighanLin<Objective> DefaultSolver;
            typedef MulticutFactory<DefaultSolver> DefaultFactory;
            settings_.mcFactory = std::make_shared<DefaultFactory>();
        }
        mpSolver_ = new SolverType(
                toOptionsVector()
                ,NiftyRounder(settings_.mcFactory, settings_.greedyWarmstart)
            );
        this->initializeMp();
    }

    template<class OBJECTIVE>
    void MulticutMp<OBJECTIVE>::
    initializeMp() {

        if(graph_.numberOfEdges()!= 0 ){

            auto & constructor = (*mpSolver_).template GetProblemConstructor<0>();
            const auto & weights = objective_.weights();

            for(auto e : graph_.edges()){
                const auto & uv = graph_.uv(e);
                constructor.AddUnaryFactor(uv.first, uv.second, weights[e]);
            }
        }
    }

    // returns options in correct format for the LP_MP solver
    // TODO would be bettter to have a decent interface for LP_MP and then
    // get rid of this
    template<class OBJECTIVE>
    std::vector<std::string> MulticutMp<OBJECTIVE>::
    toOptionsVector() const {

        std::vector<std::string> options = {
          "multicut_mp",
          "-i", " ", // empty input file
          "--primalComputationInterval", std::to_string(settings_.primalComputationInterval),
          "--standardReparametrization", settings_.standardReparametrization,
          "--roundingReparametrization", settings_.roundingReparametrization,
          "--tightenReparametrization",  settings_.tightenReparametrization,
          "--tightenInterval",           std::to_string(settings_.tightenInterval),
          "--tightenIteration",          std::to_string(settings_.tightenIteration),
          "--tightenSlope",              std::to_string(settings_.tightenSlope),
          "--tightenConstraintsPercentage", std::to_string(settings_.tightenConstraintsPercentage),
          "--maxIter", std::to_string(settings_.numberOfIterations),
          #ifdef LP_MP_PARALLEL
          "--numLpThreads", std::to_string(settings_.numberOfThreads)
          #endif
        };
        if(settings_.tighten)
            options.push_back("--tighten");
        if(settings_.minDualImprovement > 0) {
            options.push_back("--minDualImprovement");
            options.push_back(std::to_string(settings_.minDualImprovement));
        }
        if(settings_.minDualImprovementInterval > 0) {
            options.push_back("--minDualImprovementInterval");
            options.push_back(std::to_string(settings_.minDualImprovementInterval));
        }
        if(settings_.timeout > 0) {
            options.push_back("--timeout");
            options.push_back(std::to_string(settings_.timeout));
        }

        return options;
    }

    // TODO maybe this can be done more efficient
    // (if we only call it once, this should be fine, but if we need
    // to call this more often for some reason, this might get expensive)
    template<class OBJECTIVE>
    void MulticutMp<OBJECTIVE>::
    nodeLabeling() {

        ufd_.reset();
        auto & constructor = (*mpSolver_).template GetProblemConstructor<0>();
        for(auto e : graph_.edges()){
            const auto & uv = graph_.uv(e);
            const bool cut = constructor.get_edge_label(uv.first, uv.second);
            if(!cut){
                ufd_.merge(uv.first, uv.second);
            }
        }
        ufd_.elementLabeling(currentBest_->begin());
    }

    template<class OBJECTIVE>
    void MulticutMp<OBJECTIVE>::
    optimize(
        NodeLabels & nodeLabels,  VisitorBase * visitor
    ){

        //VisitorProxy visitorProxy(visitor);
        currentBest_ = &nodeLabels;

        // TODO for now the visitor is doing nothing, but we should implement one, that is
        // compatible with lp_mp visitor
        //visitorProxy.begin(this);

        if(graph_.numberOfEdges()>0){
            mpSolver_->Solve();
            nodeLabeling();
        }
        //visitorProxy.end(this);
    }

} // namespace nifty::graph
} // namespace nifty
<commit_msg>different default rounder<commit_after>#pragma once

#include<vector>

#include "nifty/tools/runtime_check.hxx"
#include "nifty/graph/optimization/multicut/multicut_base.hxx"
#include "nifty/graph/optimization/multicut/multicut_factory.hxx"
//#include "nifty/graph/optimization/multicut/multicut_greedy_additive.hxx"
//#include "nifty/graph/optimization/multicut/multicut_kernighan_lin.hxx"
#include "nifty/graph/optimization/multicut/multicut_andres.hxx"
#include "nifty/ufd/ufd.hxx"

// LP_MP includes
#include "visitors/standard_visitor.hxx"
#include "solvers/multicut/multicut.h"

namespace nifty{
namespace graph{

    template<class OBJECTIVE>
    class MulticutMp : public MulticutBase<OBJECTIVE>
    {
    public:

        typedef OBJECTIVE Objective;
        typedef MulticutBase<OBJECTIVE> Base;
        typedef typename Base::VisitorBase VisitorBase;
        typedef typename Base::VisitorProxy VisitorProxy;
        typedef typename Base::EdgeLabels EdgeLabels;
        typedef typename Base::NodeLabels NodeLabels;
        typedef typename Objective::Graph Graph;

        // factory for the lp_mp primal rounder
        typedef MulticutFactoryBase<Objective> McFactoryBase;

    public:

        struct NiftyRounder {

            typedef Graph GraphType;

            NiftyRounder(std::shared_ptr<McFactoryBase> factory,
                    const bool greedyWarmstart)
                : factory_(factory), greedyWarmstart_(greedyWarmstart)
            {}

            // TODO do we have to call by value here due to using async or could we also use a call by refernce?
            // TODO need to change between between edge and node labelings -> could be done more efficient ?!
            std::vector<char> operator()(GraphType g, std::vector<double> edgeValues) {

                std::vector<char> labeling(g.numberOfEdges(), 0);
                if(g.numberOfEdges() > 0) {

                    Objective obj(g);

                    auto & objWeights = obj.weights();
                    for(auto eId = 0; eId < edgeValues.size(); ++eId) {
                        objWeights[eId] = edgeValues[eId];
                    }

                    NodeLabels nodeLabels(g.numberOfNodes());
                    // TODO is there a bug in here ?!?
                    if(greedyWarmstart_) {
                        MulticutGreedyAdditive<Objective> greedy(obj);
                        greedy.optimize(nodeLabels, nullptr);
                    }

                    auto solverPtr = factory_->createRawPtr(obj);
                    std::cout << "compute multicut primal with " << (greedyWarmstart_ ? "GAEC + " : "") << solverPtr->name()  << std::endl;
                    solverPtr->optimize(nodeLabels, nullptr);
                    delete solverPtr;

                    // node labeling to edge labeling
                    for(auto eId = 0; eId < g.numberOfEdges(); ++eId) {
                        const auto & uv = g.uv(eId);
                        labeling[eId] = nodeLabels[uv.first] != nodeLabels[uv.second];
                    }

                }
                return labeling;

            }

            // TODO add factory name here
            static std::string name() {
                return "NiftyRounder";
            }

        private:
            std::shared_ptr<McFactoryBase> factory_;
            bool greedyWarmstart_;
        };

        //typedef LP_MP::KlRounder Rounder;
        typedef NiftyRounder Rounder;

        // TODO with or without odd wheel ?
        //typedef LP_MP::FMC_MULTICUT<LP_MP::MessageSendingType::SRMP,NiftyRounder> FMC;
        typedef LP_MP::FMC_ODD_WHEEL_MULTICUT<LP_MP::MessageSendingType::SRMP,Rounder> FMC;

        typedef LP_MP::Solver<FMC,LP_MP::LP,LP_MP::StandardTighteningVisitor,Rounder> SolverBase;
        typedef LP_MP::ProblemConstructorRoundingSolver<SolverBase> SolverType;

        // FIXME verbose deosn't have any effect right now
        struct Settings{
            // multicut factory for the primal rounder used in lp_mp
            std::shared_ptr<McFactoryBase> mcFactory;
            bool greedyWarmstart{false};
            // settings for the lp_mp solver
            size_t numberOfIterations{1000};
            int verbose{0};
            size_t primalComputationInterval{100};
            std::string standardReparametrization{"anisotropic"};
            std::string roundingReparametrization{"damped_uniform"};
            std::string tightenReparametrization{"damped_uniform"};
            bool tighten{true};
            size_t tightenInterval{100};
            size_t tightenIteration{10};
            double tightenSlope{0.02};
            double tightenConstraintsPercentage{0.1};
            double minDualImprovement{0.};
            size_t minDualImprovementInterval{0};
            size_t timeout{0};
            size_t numberOfThreads{1};
        };

        virtual ~MulticutMp(){
            delete mpSolver_;
        }

        MulticutMp(const Objective & objective, const Settings & settings = Settings());

        virtual void optimize(NodeLabels & nodeLabels, VisitorBase * visitor);

        virtual const Objective & objective() const {return objective_;}
        virtual const NodeLabels & currentBestNodeLabels() {return *currentBest_;}

        virtual std::string name() const {
            return std::string("MulticutMp");
        }

        // TODO do we need this, what does it do?
        // reset ?!
        //virtual void weightsChanged(){
        //}

    private:

        void initializeMp();
        void nodeLabeling();
        std::vector<std::string> toOptionsVector() const;

        const Objective & objective_;
        const Graph & graph_;

        Settings settings_;
        NodeLabels * currentBest_;
        size_t numberOfOptRuns_;
        SolverType * mpSolver_;
        ufd::Ufd<uint64_t> ufd_;
    };

    template<class OBJECTIVE>
    MulticutMp<OBJECTIVE>::
    MulticutMp(
        const Objective & objective,
        const Settings & settings
    )
    :   objective_(objective),
        graph_(objective.graph()),
        settings_(settings),
        currentBest_(nullptr),
        mpSolver_(nullptr),
        ufd_(graph_.numberOfNodes())
    {
        // if we don't have a mc-factory, we use the LP_MP default rounder
        if(!bool(settings_.mcFactory)) {
            typedef MulticutAndresKernighanLin<Objective> DefaultSolver;
            typedef MulticutFactory<DefaultSolver> DefaultFactory;
            settings_.mcFactory = std::make_shared<DefaultFactory>();
        }
        mpSolver_ = new SolverType(
                toOptionsVector()
                ,NiftyRounder(settings_.mcFactory, settings_.greedyWarmstart)
            );
        this->initializeMp();
    }

    template<class OBJECTIVE>
    void MulticutMp<OBJECTIVE>::
    initializeMp() {

        if(graph_.numberOfEdges()!= 0 ){

            auto & constructor = (*mpSolver_).template GetProblemConstructor<0>();
            const auto & weights = objective_.weights();

            for(auto e : graph_.edges()){
                const auto & uv = graph_.uv(e);
                constructor.AddUnaryFactor(uv.first, uv.second, weights[e]);
            }
        }
    }

    // returns options in correct format for the LP_MP solver
    // TODO would be bettter to have a decent interface for LP_MP and then
    // get rid of this
    template<class OBJECTIVE>
    std::vector<std::string> MulticutMp<OBJECTIVE>::
    toOptionsVector() const {

        std::vector<std::string> options = {
          "multicut_mp",
          "-i", " ", // empty input file
          "--primalComputationInterval", std::to_string(settings_.primalComputationInterval),
          "--standardReparametrization", settings_.standardReparametrization,
          "--roundingReparametrization", settings_.roundingReparametrization,
          "--tightenReparametrization",  settings_.tightenReparametrization,
          "--tightenInterval",           std::to_string(settings_.tightenInterval),
          "--tightenIteration",          std::to_string(settings_.tightenIteration),
          "--tightenSlope",              std::to_string(settings_.tightenSlope),
          "--tightenConstraintsPercentage", std::to_string(settings_.tightenConstraintsPercentage),
          "--maxIter", std::to_string(settings_.numberOfIterations),
          #ifdef LP_MP_PARALLEL
          "--numLpThreads", std::to_string(settings_.numberOfThreads)
          #endif
        };
        if(settings_.tighten)
            options.push_back("--tighten");
        if(settings_.minDualImprovement > 0) {
            options.push_back("--minDualImprovement");
            options.push_back(std::to_string(settings_.minDualImprovement));
        }
        if(settings_.minDualImprovementInterval > 0) {
            options.push_back("--minDualImprovementInterval");
            options.push_back(std::to_string(settings_.minDualImprovementInterval));
        }
        if(settings_.timeout > 0) {
            options.push_back("--timeout");
            options.push_back(std::to_string(settings_.timeout));
        }

        return options;
    }

    // TODO maybe this can be done more efficient
    // (if we only call it once, this should be fine, but if we need
    // to call this more often for some reason, this might get expensive)
    template<class OBJECTIVE>
    void MulticutMp<OBJECTIVE>::
    nodeLabeling() {

        ufd_.reset();
        auto & constructor = (*mpSolver_).template GetProblemConstructor<0>();
        for(auto e : graph_.edges()){
            const auto & uv = graph_.uv(e);
            const bool cut = constructor.get_edge_label(uv.first, uv.second);
            if(!cut){
                ufd_.merge(uv.first, uv.second);
            }
        }
        ufd_.elementLabeling(currentBest_->begin());
    }

    template<class OBJECTIVE>
    void MulticutMp<OBJECTIVE>::
    optimize(
        NodeLabels & nodeLabels,  VisitorBase * visitor
    ){

        //VisitorProxy visitorProxy(visitor);
        currentBest_ = &nodeLabels;

        // TODO for now the visitor is doing nothing, but we should implement one, that is
        // compatible with lp_mp visitor
        //visitorProxy.begin(this);

        if(graph_.numberOfEdges()>0){
            mpSolver_->Solve();
            nodeLabeling();
        }
        //visitorProxy.end(this);
    }

} // namespace nifty::graph
} // namespace nifty
<|endoftext|>


<commit_before>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * 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 <vector>
#include <iostream>
#include <sstream>

#include <zorba/zorba.h>
#include <inmemorystore/inmemorystore.h>

using namespace zorba;

void* query_thread_1(void *param);
void* query_thread_2(void *param);
void* query_thread_3(void *param);
void* query_thread_4(void *param);

#define NR_THREADS  20

struct data {
  Zorba*  lZorba;
  Item    lItem;
} dataObj;

static  XQuery_t    lQuery;
std::string make_absolute_file_name(const char *target_file_name, const char *this_file_name);

#ifdef ZORBA_HAVE_PTHREAD_H

/*
Simple cloning test
*/
bool
multithread_example_1(Zorba* aZorba)
{
  unsigned int  i;
  pthread_t     pt[NR_THREADS];

  try {
    lQuery = aZorba->compileQuery("1+1");

    for(i=0; i<NR_THREADS; i++)
    {
      pthread_create(&pt[i], NULL, query_thread_1, (void*)i);
    }

    //wait for threads to finish
    for(i=0;i<NR_THREADS;i++)
    {
      void  *thread_result;
      pthread_join(pt[i], &thread_result);
    }

    lQuery = NULL;

    return true;
  }
  catch (ZorbaException &e) {
    std::cerr << "some exception " << e << std::endl;
    return false;
  }
}

/*
Create multiple threads that compile and execute a query
*/
bool
multithread_example_2(Zorba* aZorba)
{
  unsigned int  i;
  pthread_t     pt[NR_THREADS];

  try {
    for(i=0; i<NR_THREADS; i++)
    {
      pthread_create(&pt[i], NULL, query_thread_2, (void*)aZorba);
    }

    //wait for threads to finish
    for(i=0;i<NR_THREADS;i++)
    {
      void  *thread_result;
      pthread_join(pt[i], &thread_result);
    }

    return true;
  }
  catch (ZorbaException &e) {
    std::cerr << "some exception " << e << std::endl;
    return false;
  }
}

/*
Create separate queries that are working with the same document loaded in store.
*/
bool
multithread_example_3(Zorba* aZorba)
{
  unsigned int  i;
  pthread_t     pt[NR_THREADS];

  try {
    std::stringstream lInStream("<books><book>Book 1</book><book>Book 2</book><book>Book 3</book></books>");

    Item aItem = aZorba->getXmlDataManager()->loadDocument("books.xml", lInStream);

    dataObj.lZorba = aZorba;
    dataObj.lItem = aItem;

    for(i=0; i<NR_THREADS; i++)
    {
      pthread_create(&pt[i], NULL, query_thread_3, (void*)(&dataObj));
    }

    for(i=0;i<NR_THREADS;i++)
    {
      void  *thread_result;
      pthread_join(pt[i], &thread_result);
    }

    return true;
  }
  catch (ZorbaException &e) {
    std::cerr << "some exception " << e << std::endl;
    return false;
  }
}

/*
Load a big document in store and query it from diffrent threads.
*/
bool
multithread_example_4(Zorba* aZorba)
{
  unsigned int  i;
  pthread_t     pt[NR_THREADS];

  try {
    Item aItem = aZorba->getXmlDataManager()->loadDocument(make_absolute_file_name("XQTSCatalog.xml", __FILE__));

    dataObj.lZorba = aZorba;
    dataObj.lItem = aItem;

    for(i=0; i<NR_THREADS; i++)
    {
      pthread_create(&pt[i], NULL, query_thread_4, (void*)(&dataObj));
    }

    for(i=0;i<NR_THREADS;i++)
    {
      void  *thread_result;
      pthread_join(pt[i], &thread_result);
    }

    return true;
  }
  catch (ZorbaException &e) {
    std::cerr << "some exception " << e << std::endl;
    return false;
  }
}

int
multithread(int argc, char* argv[])
{
  store::SimpleStore* lStore = inmemorystore::InMemoryStore::getInstance();
  Zorba*              lZorba = Zorba::getInstance(lStore);
  bool                res = false;

  std::cout << std::endl  << "executing multithread test 1 : ";
  res = multithread_example_1(lZorba);
  if (!res) {
    std::cout << "Failed" << std::endl;
    lZorba->shutdown();
    inmemorystore::InMemoryStore::shutdown(lStore);
    return 1;
  }
  else std::cout << "Passed" << std::endl;

  std::cout << std::endl  << "executing multithread test 2 : ";
  res = multithread_example_2(lZorba);
  if (!res) {
    std::cout << "Failed" << std::endl;
    lZorba->shutdown();
    inmemorystore::InMemoryStore::shutdown(lStore);
    return 1;
  }
  else std::cout << "Passed" << std::endl;

  std::cout << std::endl  << "executing multithread test 3 : ";
  res = multithread_example_3(lZorba);
  if (!res) {
    std::cout << "Failed" << std::endl;
    lZorba->shutdown();
    inmemorystore::InMemoryStore::shutdown(lStore);
    return 1;
  }
  else std::cout << "Passed" << std::endl;

  std::cout << std::endl  << "executing multithread test 4 : ";
  res = multithread_example_4(lZorba);
  if (!res) {
    std::cout << "Failed" << std::endl;
    lZorba->shutdown();
    inmemorystore::InMemoryStore::shutdown(lStore);
    return 1;
  }
  else std::cout << "Passed" << std::endl;

  lZorba->shutdown();
  inmemorystore::InMemoryStore::shutdown(lStore);
  return 0;
}

void* query_thread_1(void *param)
{
  XQuery_t        xquery_clone;

  xquery_clone = lQuery->clone();
  if(xquery_clone == NULL)
  {
    std::cout << "cannot clone xquery object" << std::endl;
    return (void*)1;
  }

  std::ostringstream os;
  os << xquery_clone << std::endl;

  xquery_clone->close();

  return (void*)0;
}

void* query_thread_2(void *param)
{
  XQuery_t    query;

  query = ((Zorba*)param)->compileQuery("2+2");

  std::ostringstream os;
  os << query << std::endl;

  query->close();

  return (void*)0;
}

void* query_thread_3(void *param)
{
  data* var = (data*)param;

  XQuery_t lQuery = var->lZorba->compileQuery("declare variable $var external; doc('books.xml')//book");

  DynamicContext* lCtx = lQuery->getDynamicContext();

  lCtx->setVariable("var", var->lItem);

  std::ostringstream os;
  os << lQuery << std::endl;

  return (void*)0;
}

void* query_thread_4(void *param)
{
  data* var = (data*)param;

  XQuery_t aQuery = var->lZorba->compileQuery(".//citation-spec");

  DynamicContext* lCtx = aQuery->getDynamicContext();

  lCtx->setContextItem(var->lItem);

  std::ostringstream os;
  os << aQuery << std::endl;

  aQuery->close();

  return (void*)0;
}

std::string make_absolute_file_name(const char *target_file_name, const char *this_file_name)
{
  std::string             str_result;
  std::string::size_type  pos;

  str_result = this_file_name;
  pos = str_result.rfind('/');
  if(pos == std::string::npos)
    pos = str_result.rfind('\\');
  if(pos == std::string::npos)
    return target_file_name;
  str_result.erase(pos+1);
  str_result += target_file_name;
//   std::cout << "make_absolute_file_name -> " << str_result << std::endl;
  return str_result;
}
#endif
<commit_msg>Fixed test no. 4.<commit_after>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * 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 <vector>
#include <iostream>
#include <sstream>

#include <zorba/zorba.h>
#include <inmemorystore/inmemorystore.h>

using namespace zorba;

void* query_thread_1(void *param);
void* query_thread_2(void *param);
void* query_thread_3(void *param);
void* query_thread_4(void *param);

#define NR_THREADS  20

struct data {
  Zorba*  lZorba;
  Item    lItem;
} dataObj;

static  XQuery_t    lQuery;
std::string make_absolute_file_name(const char *target_file_name, const char *this_file_name);

#ifdef ZORBA_HAVE_PTHREAD_H

/*
Simple cloning test
*/
bool
multithread_example_1(Zorba* aZorba)
{
  unsigned int  i;
  pthread_t     pt[NR_THREADS];

  try {
    lQuery = aZorba->compileQuery("1+1");

    for(i=0; i<NR_THREADS; i++)
    {
      pthread_create(&pt[i], NULL, query_thread_1, (void*)i);
    }

    //wait for threads to finish
    for(i=0;i<NR_THREADS;i++)
    {
      void  *thread_result;
      pthread_join(pt[i], &thread_result);
    }

    lQuery = NULL;

    return true;
  }
  catch (ZorbaException &e) {
    std::cerr << "some exception " << e << std::endl;
    return false;
  }
}

/*
Create multiple threads that compile and execute a query
*/
bool
multithread_example_2(Zorba* aZorba)
{
  unsigned int  i;
  pthread_t     pt[NR_THREADS];

  try {
    for(i=0; i<NR_THREADS; i++)
    {
      pthread_create(&pt[i], NULL, query_thread_2, (void*)aZorba);
    }

    //wait for threads to finish
    for(i=0;i<NR_THREADS;i++)
    {
      void  *thread_result;
      pthread_join(pt[i], &thread_result);
    }

    return true;
  }
  catch (ZorbaException &e) {
    std::cerr << "some exception " << e << std::endl;
    return false;
  }
}

/*
Create separate queries that are working with the same document loaded in store.
*/
bool
multithread_example_3(Zorba* aZorba)
{
  unsigned int  i;
  pthread_t     pt[NR_THREADS];

  try {
    std::stringstream lInStream("<books><book>Book 1</book><book>Book 2</book><book>Book 3</book></books>");

    Item aItem = aZorba->getXmlDataManager()->loadDocument("books.xml", lInStream);

    dataObj.lZorba = aZorba;
    dataObj.lItem = aItem;

    for(i=0; i<NR_THREADS; i++)
    {
      pthread_create(&pt[i], NULL, query_thread_3, (void*)(&dataObj));
    }

    for(i=0;i<NR_THREADS;i++)
    {
      void  *thread_result;
      pthread_join(pt[i], &thread_result);
    }

    return true;
  }
  catch (ZorbaException &e) {
    std::cerr << "some exception " << e << std::endl;
    return false;
  }
}

/*
Load a big document in store and query it from diffrent threads.
*/
bool
multithread_example_4(Zorba* aZorba)
{
  unsigned int  i;
  pthread_t     pt[NR_THREADS];

  try {
    Item aItem = aZorba->getXmlDataManager()->loadDocument(make_absolute_file_name("XQTSCatalog.xml", __FILE__));

    dataObj.lZorba = aZorba;
    dataObj.lItem = aItem;

    for(i=0; i<NR_THREADS; i++)
    {
      pthread_create(&pt[i], NULL, query_thread_4, (void*)(&dataObj));
    }

    for(i=0;i<NR_THREADS;i++)
    {
      void  *thread_result;
      pthread_join(pt[i], &thread_result);
    }

    dataObj.lItem = NULL;

    return true;
  }
  catch (ZorbaException &e) {
    std::cerr << "some exception " << e << std::endl;
    return false;
  }
}

int
multithread(int argc, char* argv[])
{
  store::SimpleStore* lStore = inmemorystore::InMemoryStore::getInstance();
  Zorba*              lZorba = Zorba::getInstance(lStore);
  bool                res = false;

  std::cout << std::endl  << "executing multithread test 1 : ";
  res = multithread_example_1(lZorba);
  if (!res) {
    std::cout << "Failed" << std::endl;
    lZorba->shutdown();
    inmemorystore::InMemoryStore::shutdown(lStore);
    return 1;
  }
  else std::cout << "Passed" << std::endl;

  std::cout << std::endl  << "executing multithread test 2 : ";
  res = multithread_example_2(lZorba);
  if (!res) {
    std::cout << "Failed" << std::endl;
    lZorba->shutdown();
    inmemorystore::InMemoryStore::shutdown(lStore);
    return 1;
  }
  else std::cout << "Passed" << std::endl;

  std::cout << std::endl  << "executing multithread test 3 : ";
  res = multithread_example_3(lZorba);
  if (!res) {
    std::cout << "Failed" << std::endl;
    lZorba->shutdown();
    inmemorystore::InMemoryStore::shutdown(lStore);
    return 1;
  }
  else std::cout << "Passed" << std::endl;

  std::cout << std::endl  << "executing multithread test 4 : ";
  res = multithread_example_4(lZorba);
  if (!res) {
    std::cout << "Failed" << std::endl;
    lZorba->shutdown();
    inmemorystore::InMemoryStore::shutdown(lStore);
    return 1;
  }
  else std::cout << "Passed" << std::endl;

  lZorba->shutdown();
  inmemorystore::InMemoryStore::shutdown(lStore);
  return 0;
}

void* query_thread_1(void *param)
{
  XQuery_t        xquery_clone;

  xquery_clone = lQuery->clone();
  if(xquery_clone == NULL)
  {
    std::cout << "cannot clone xquery object" << std::endl;
    return (void*)1;
  }

  std::ostringstream os;
  os << xquery_clone << std::endl;

  xquery_clone->close();

  return (void*)0;
}

void* query_thread_2(void *param)
{
  XQuery_t    query;

  query = ((Zorba*)param)->compileQuery("2+2");

  std::ostringstream os;
  os << query << std::endl;

  query->close();

  return (void*)0;
}

void* query_thread_3(void *param)
{
  data* var = (data*)param;

  XQuery_t lQuery = var->lZorba->compileQuery("declare variable $var external; doc('books.xml')//book");

  DynamicContext* lCtx = lQuery->getDynamicContext();

  lCtx->setVariable("var", var->lItem);

  std::ostringstream os;
  os << lQuery << std::endl;

  return (void*)0;
}

void* query_thread_4(void *param)
{
  data* var = (data*)param;

  XQuery_t aQuery = var->lZorba->compileQuery(".//citation-spec");

  DynamicContext* lCtx = aQuery->getDynamicContext();

  lCtx->setContextItem(var->lItem);

  std::ostringstream os;
  os << aQuery << std::endl;

  aQuery->close();

  return (void*)0;
}

std::string make_absolute_file_name(const char *target_file_name, const char *this_file_name)
{
  std::string             str_result;
  std::string::size_type  pos;

  str_result = this_file_name;
  pos = str_result.rfind('/');
  if(pos == std::string::npos)
    pos = str_result.rfind('\\');
  if(pos == std::string::npos)
    return target_file_name;
  str_result.erase(pos+1);
  str_result += target_file_name;
//   std::cout << "make_absolute_file_name -> " << str_result << std::endl;
  return str_result;
}
#endif
<|endoftext|>


<commit_before>//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Axel Naumann <axel@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "ClingPragmas.h"

#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/Transaction.h"
#include "cling/Utils/Output.h"
#include "cling/Utils/Paths.h"

#include "clang/AST/ASTContext.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/Token.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/ParseDiagnostic.h"

#include <cstdlib>

using namespace cling;
using namespace clang;

namespace {
  class ClingPragmaHandler: public PragmaHandler {
    Interpreter& m_Interp;

    struct SkipToEOD {
      Preprocessor& m_PP;
      Token& m_Tok;
      SkipToEOD(Preprocessor& PParg, Token& Tok):
        m_PP(PParg), m_Tok(Tok) {
      }
      ~SkipToEOD() {
        // Can't use Preprocessor::DiscardUntilEndOfDirective, as we may
        // already be on an eod token
        while (!m_Tok.isOneOf(tok::eod, tok::eof))
          m_PP.LexUnexpandedToken(m_Tok);
      }
    };

    enum {
      kLoadFile,
      kAddLibrary,
      kAddInclude,
      // Put all commands that expand environment variables above this
      kExpandEnvCommands,

      // Put all commands that only take string literals above this
      kArgumentsAreLiterals,

      kOptimize,
      kInvalidCommand,
    };

    bool GetNextLiteral(Preprocessor& PP, Token& Tok, std::string& Literal,
                        unsigned Cmd, const char* firstTime = nullptr) const {
      Literal.clear();

      PP.Lex(Tok);
      if (Tok.isLiteral()) {
        if (clang::tok::isStringLiteral(Tok.getKind())) {
          SmallVector<Token, 1> StrToks(1, Tok);
          StringLiteralParser LitParse(StrToks, PP);
          if (!LitParse.hadError)
            Literal = LitParse.GetString();
        } else {
          llvm::SmallString<64> Buffer;
          Literal = PP.getSpelling(Tok, Buffer).str();
        }
      }
      else if (Tok.is(tok::comma))
        return GetNextLiteral(PP, Tok, Literal, Cmd);
      else if (firstTime) {
        if (Tok.is(tok::l_paren)) {
          if (Cmd < kArgumentsAreLiterals) {
            if (!PP.LexStringLiteral(Tok, Literal, firstTime,
                                     false /*allowMacroExpansion*/)) {
              // already diagnosed.
              return false;
            }
          } else {
            PP.Lex(Tok);
            llvm::SmallString<64> Buffer;
            Literal = PP.getSpelling(Tok, Buffer).str();
          }
        }
      }

      if (Literal.empty())
        return false;

      if (Cmd < kExpandEnvCommands)
        utils::ExpandEnvVars(Literal);

      return true;
    }

    void ReportCommandErr(Preprocessor& PP, const Token& Tok) {
      PP.Diag(Tok.getLocation(), diag::err_expected)
        << "load, add_library_path, or add_include_path";
    }

    int GetCommand(const StringRef CommandStr) {
      if (CommandStr == "load")
        return kLoadFile;
      else if (CommandStr == "add_library_path")
        return kAddLibrary;
      else if (CommandStr == "add_include_path")
        return kAddInclude;
      else if (CommandStr == "optimize")
        return kOptimize;
      return kInvalidCommand;
    }

    void LoadCommand(Preprocessor& PP, Token& Tok, std::string Literal) {
      // No need to load libraries when not executing anything.
      if (m_Interp.isInSyntaxOnlyMode())
        return;

      // Need to parse them all until the end to handle the possible
      // #include statements that will be generated
      struct LibraryFileInfo {
        std::string FileName;
        SourceLocation StartLoc;
      };
      std::vector<LibraryFileInfo> FileInfos;
      FileInfos.push_back({std::move(Literal), Tok.getLocation()});
      while (GetNextLiteral(PP, Tok, Literal, kLoadFile))
        FileInfos.push_back({std::move(Literal), Tok.getLocation()});

      clang::Parser& P = m_Interp.getParser();
      Parser::ParserCurTokRestoreRAII savedCurToken(P);
      // After we have saved the token reset the current one to something
      // which is safe (semi colon usually means empty decl)
      Token& CurTok = const_cast<Token&>(P.getCurToken());
      CurTok.setKind(tok::semi);

      Preprocessor::CleanupAndRestoreCacheRAII cleanupRAII(PP);
      // We can't PushDeclContext, because we go up and the routine that
      // pops the DeclContext assumes that we drill down always.
      // We have to be on the global context. At that point we are in a
      // wrapper function so the parent context must be the global.
      TranslationUnitDecl* TU =
      m_Interp.getCI()->getASTContext().getTranslationUnitDecl();
      Sema::ContextAndScopeRAII pushedDCAndS(m_Interp.getSema(),
                                            TU, m_Interp.getSema().TUScope);
      Interpreter::PushTransactionRAII pushedT(&m_Interp);

      for (const LibraryFileInfo& FI : FileInfos) {
        // FIXME: Consider the case where the library static init section has
        // a call to interpreter parsing header file. It will suffer the same
        // issue as if we included the file within the pragma.
        if (m_Interp.loadLibrary(FI.FileName, true) != Interpreter::kSuccess) {
          const clang::DirectoryLookup *CurDir = nullptr;
          if (PP.getHeaderSearchInfo().LookupFile(FI.FileName, FI.StartLoc,
              /*isAngled*/ false, /*fromDir*/ nullptr, /*CurDir*/ CurDir, /*Includers*/ {},
              /*SearchPath*/ nullptr, /*RelativePath*/ nullptr, /*RequestingModule*/ nullptr,
              /*suggestedModule*/ nullptr, /*IsMapped*/ nullptr,
              /*IsFrameworkFound*/ nullptr, /*SkipCache*/ true, /*BuildSystemModule*/ false,
              /*OpenFile*/ false, /*CacheFailures*/ false)) {
            PP.Diag(FI.StartLoc, diag::err_expected)
              << FI.FileName + " to be a library, but it is not. If this is a source file, use `#include \"" + FI.FileName + "\"`";
          } else {
            PP.Diag(FI.StartLoc, diag::err_pp_file_not_found)
              << FI.FileName;
          }
          return;
        }
      }
    }

    void OptimizeCommand(const char* Str) {
      char* ConvEnd = nullptr;
      int OptLevel = std::strtol(Str, &ConvEnd, 10 /*base*/);
      if (!ConvEnd || ConvEnd == Str) {
        cling::errs() << "cling::PHOptLevel: "
          "missing or non-numerical optimization level.\n" ;
        return;
      }
      auto T = const_cast<Transaction*>(m_Interp.getCurrentTransaction());
      assert(T && "Parsing code without transaction!");
      // The topmost Transaction drives the jitting.
      T = T->getTopmostParent();
      CompilationOptions& CO = T->getCompilationOpts();
      if (CO.OptLevel != m_Interp.getDefaultOptLevel()) {
        // Another #pragma already changed the opt level, a conflict that
        // cannot be resolve here.  Mention and keep the lower one.
        cling::errs() << "cling::PHOptLevel: "
          "conflicting `#pragma cling optimize` directives: "
          "was already set to " << CO.OptLevel << '\n';
        if (CO.OptLevel > OptLevel) {
          CO.OptLevel = OptLevel;
          cling::errs() << "Setting to lower value of " << OptLevel << '\n';
        } else {
          cling::errs() << "Ignoring higher value of " << OptLevel << '\n';
        }
      } else
        CO.OptLevel = OptLevel;
  }

  public:
    ClingPragmaHandler(Interpreter& interp):
      PragmaHandler("cling"), m_Interp(interp) {}

    void HandlePragma(Preprocessor& PP,
                      PragmaIntroducer /*Introducer*/,
                      Token& /*FirstToken*/) override {

      Token Tok;
      PP.Lex(Tok);
      SkipToEOD OnExit(PP, Tok);

      // #pragma cling(load, "A")
      if (Tok.is(tok::l_paren))
        PP.Lex(Tok);

      if (Tok.isNot(tok::identifier)) {
        ReportCommandErr(PP, Tok);
        return;
      }

      const StringRef CommandStr = Tok.getIdentifierInfo()->getName();
      const unsigned Command = GetCommand(CommandStr);
      assert(Command != kArgumentsAreLiterals && Command != kExpandEnvCommands);
      if (Command == kInvalidCommand) {
        ReportCommandErr(PP, Tok);
        return;
      }

      std::string Literal;
      if (!GetNextLiteral(PP, Tok, Literal, Command, CommandStr.data())) {
        PP.Diag(Tok.getLocation(), diag::err_expected_after)
          << CommandStr << "argument";
        return;
      }

      switch (Command) {
        case kLoadFile:
        return LoadCommand(PP, Tok, std::move(Literal));
        case kOptimize:
          return OptimizeCommand(Literal.c_str());

        default:
          do {
            if (Command == kAddLibrary)
              m_Interp.getOptions().LibSearchPath.push_back(std::move(Literal));
            else if (Command == kAddInclude)
              m_Interp.AddIncludePath(Literal);
          } while (GetNextLiteral(PP, Tok, Literal, Command));
          break;
      }
    }
  };
}

void cling::addClingPragmas(Interpreter& interp) {
  Preprocessor& PP = interp.getCI()->getPreprocessor();
  // PragmaNamespace / PP takes ownership of sub-handlers.
  PP.AddPragmaHandler(StringRef(), new ClingPragmaHandler(interp));
}
<commit_msg>Fix regression in #pragma cling add_library_path().<commit_after>//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Axel Naumann <axel@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "ClingPragmas.h"

#include "cling/Interpreter/DynamicLibraryManager.h"
#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/Transaction.h"
#include "cling/Utils/Output.h"
#include "cling/Utils/Paths.h"

#include "clang/AST/ASTContext.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/Token.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/ParseDiagnostic.h"

#include <cstdlib>

using namespace cling;
using namespace clang;

namespace {
  class ClingPragmaHandler: public PragmaHandler {
    Interpreter& m_Interp;

    struct SkipToEOD {
      Preprocessor& m_PP;
      Token& m_Tok;
      SkipToEOD(Preprocessor& PParg, Token& Tok):
        m_PP(PParg), m_Tok(Tok) {
      }
      ~SkipToEOD() {
        // Can't use Preprocessor::DiscardUntilEndOfDirective, as we may
        // already be on an eod token
        while (!m_Tok.isOneOf(tok::eod, tok::eof))
          m_PP.LexUnexpandedToken(m_Tok);
      }
    };

    enum {
      kLoadFile,
      kAddLibrary,
      kAddInclude,
      // Put all commands that expand environment variables above this
      kExpandEnvCommands,

      // Put all commands that only take string literals above this
      kArgumentsAreLiterals,

      kOptimize,
      kInvalidCommand,
    };

    bool GetNextLiteral(Preprocessor& PP, Token& Tok, std::string& Literal,
                        unsigned Cmd, const char* firstTime = nullptr) const {
      Literal.clear();

      PP.Lex(Tok);
      if (Tok.isLiteral()) {
        if (clang::tok::isStringLiteral(Tok.getKind())) {
          SmallVector<Token, 1> StrToks(1, Tok);
          StringLiteralParser LitParse(StrToks, PP);
          if (!LitParse.hadError)
            Literal = LitParse.GetString();
        } else {
          llvm::SmallString<64> Buffer;
          Literal = PP.getSpelling(Tok, Buffer).str();
        }
      }
      else if (Tok.is(tok::comma))
        return GetNextLiteral(PP, Tok, Literal, Cmd);
      else if (firstTime) {
        if (Tok.is(tok::l_paren)) {
          if (Cmd < kArgumentsAreLiterals) {
            if (!PP.LexStringLiteral(Tok, Literal, firstTime,
                                     false /*allowMacroExpansion*/)) {
              // already diagnosed.
              return false;
            }
          } else {
            PP.Lex(Tok);
            llvm::SmallString<64> Buffer;
            Literal = PP.getSpelling(Tok, Buffer).str();
          }
        }
      }

      if (Literal.empty())
        return false;

      if (Cmd < kExpandEnvCommands)
        utils::ExpandEnvVars(Literal);

      return true;
    }

    void ReportCommandErr(Preprocessor& PP, const Token& Tok) {
      PP.Diag(Tok.getLocation(), diag::err_expected)
        << "load, add_library_path, or add_include_path";
    }

    int GetCommand(const StringRef CommandStr) {
      if (CommandStr == "load")
        return kLoadFile;
      else if (CommandStr == "add_library_path")
        return kAddLibrary;
      else if (CommandStr == "add_include_path")
        return kAddInclude;
      else if (CommandStr == "optimize")
        return kOptimize;
      return kInvalidCommand;
    }

    void LoadCommand(Preprocessor& PP, Token& Tok, std::string Literal) {
      // No need to load libraries when not executing anything.
      if (m_Interp.isInSyntaxOnlyMode())
        return;

      // Need to parse them all until the end to handle the possible
      // #include statements that will be generated
      struct LibraryFileInfo {
        std::string FileName;
        SourceLocation StartLoc;
      };
      std::vector<LibraryFileInfo> FileInfos;
      FileInfos.push_back({std::move(Literal), Tok.getLocation()});
      while (GetNextLiteral(PP, Tok, Literal, kLoadFile))
        FileInfos.push_back({std::move(Literal), Tok.getLocation()});

      clang::Parser& P = m_Interp.getParser();
      Parser::ParserCurTokRestoreRAII savedCurToken(P);
      // After we have saved the token reset the current one to something
      // which is safe (semi colon usually means empty decl)
      Token& CurTok = const_cast<Token&>(P.getCurToken());
      CurTok.setKind(tok::semi);

      Preprocessor::CleanupAndRestoreCacheRAII cleanupRAII(PP);
      // We can't PushDeclContext, because we go up and the routine that
      // pops the DeclContext assumes that we drill down always.
      // We have to be on the global context. At that point we are in a
      // wrapper function so the parent context must be the global.
      TranslationUnitDecl* TU =
      m_Interp.getCI()->getASTContext().getTranslationUnitDecl();
      Sema::ContextAndScopeRAII pushedDCAndS(m_Interp.getSema(),
                                            TU, m_Interp.getSema().TUScope);
      Interpreter::PushTransactionRAII pushedT(&m_Interp);

      for (const LibraryFileInfo& FI : FileInfos) {
        // FIXME: Consider the case where the library static init section has
        // a call to interpreter parsing header file. It will suffer the same
        // issue as if we included the file within the pragma.
        if (m_Interp.loadLibrary(FI.FileName, true) != Interpreter::kSuccess) {
          const clang::DirectoryLookup *CurDir = nullptr;
          if (PP.getHeaderSearchInfo().LookupFile(FI.FileName, FI.StartLoc,
              /*isAngled*/ false, /*fromDir*/ nullptr, /*CurDir*/ CurDir, /*Includers*/ {},
              /*SearchPath*/ nullptr, /*RelativePath*/ nullptr, /*RequestingModule*/ nullptr,
              /*suggestedModule*/ nullptr, /*IsMapped*/ nullptr,
              /*IsFrameworkFound*/ nullptr, /*SkipCache*/ true, /*BuildSystemModule*/ false,
              /*OpenFile*/ false, /*CacheFailures*/ false)) {
            PP.Diag(FI.StartLoc, diag::err_expected)
              << FI.FileName + " to be a library, but it is not. If this is a source file, use `#include \"" + FI.FileName + "\"`";
          } else {
            PP.Diag(FI.StartLoc, diag::err_pp_file_not_found)
              << FI.FileName;
          }
          return;
        }
      }
    }

    void OptimizeCommand(const char* Str) {
      char* ConvEnd = nullptr;
      int OptLevel = std::strtol(Str, &ConvEnd, 10 /*base*/);
      if (!ConvEnd || ConvEnd == Str) {
        cling::errs() << "cling::PHOptLevel: "
          "missing or non-numerical optimization level.\n" ;
        return;
      }
      auto T = const_cast<Transaction*>(m_Interp.getCurrentTransaction());
      assert(T && "Parsing code without transaction!");
      // The topmost Transaction drives the jitting.
      T = T->getTopmostParent();
      CompilationOptions& CO = T->getCompilationOpts();
      if (CO.OptLevel != m_Interp.getDefaultOptLevel()) {
        // Another #pragma already changed the opt level, a conflict that
        // cannot be resolve here.  Mention and keep the lower one.
        cling::errs() << "cling::PHOptLevel: "
          "conflicting `#pragma cling optimize` directives: "
          "was already set to " << CO.OptLevel << '\n';
        if (CO.OptLevel > OptLevel) {
          CO.OptLevel = OptLevel;
          cling::errs() << "Setting to lower value of " << OptLevel << '\n';
        } else {
          cling::errs() << "Ignoring higher value of " << OptLevel << '\n';
        }
      } else
        CO.OptLevel = OptLevel;
  }

  public:
    ClingPragmaHandler(Interpreter& interp):
      PragmaHandler("cling"), m_Interp(interp) {}

    void HandlePragma(Preprocessor& PP,
                      PragmaIntroducer /*Introducer*/,
                      Token& /*FirstToken*/) override {

      Token Tok;
      PP.Lex(Tok);
      SkipToEOD OnExit(PP, Tok);

      // #pragma cling(load, "A")
      if (Tok.is(tok::l_paren))
        PP.Lex(Tok);

      if (Tok.isNot(tok::identifier)) {
        ReportCommandErr(PP, Tok);
        return;
      }

      const StringRef CommandStr = Tok.getIdentifierInfo()->getName();
      const unsigned Command = GetCommand(CommandStr);
      assert(Command != kArgumentsAreLiterals && Command != kExpandEnvCommands);
      if (Command == kInvalidCommand) {
        ReportCommandErr(PP, Tok);
        return;
      }

      std::string Literal;
      if (!GetNextLiteral(PP, Tok, Literal, Command, CommandStr.data())) {
        PP.Diag(Tok.getLocation(), diag::err_expected_after)
          << CommandStr << "argument";
        return;
      }

      switch (Command) {
        case kLoadFile:
        return LoadCommand(PP, Tok, std::move(Literal));
        case kOptimize:
          return OptimizeCommand(Literal.c_str());

        default:
          do {
            if (Command == kAddLibrary)
              m_Interp.getDynamicLibraryManager()->addSearchPath(std::move(Literal));
            else if (Command == kAddInclude)
              m_Interp.AddIncludePath(Literal);
          } while (GetNextLiteral(PP, Tok, Literal, Command));
          break;
      }
    }
  };
}

void cling::addClingPragmas(Interpreter& interp) {
  Preprocessor& PP = interp.getCI()->getPreprocessor();
  // PragmaNamespace / PP takes ownership of sub-handlers.
  PP.AddPragmaHandler(StringRef(), new ClingPragmaHandler(interp));
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Pierre Moulon.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef OPENMVG_SFM_DATA_HPP
#define OPENMVG_SFM_DATA_HPP

#include "openMVG/types.hpp"
#include "openMVG/sfm/sfm_view.hpp"
#include "openMVG/sfm/sfm_landmark.hpp"
#include "openMVG/geometry/pose3.hpp"
#include "openMVG/cameras/cameras.hpp"

namespace openMVG {
namespace sfm {

/// Define a collection of View
typedef Hash_Map<IndexT, std::shared_ptr<View> > Views;

/// Define a collection of Pose (indexed by View::id_pose)
typedef Hash_Map<IndexT, geometry::Pose3> Poses;

/// Define a collection of IntrinsicParameter (indexed by View::id_intrinsic)
typedef Hash_Map<IndexT, std::shared_ptr<cameras::IntrinsicBase> > Intrinsics;

/// Define a collection of landmarks are indexed by their TrackId
typedef Hash_Map<IndexT, Landmark> Landmarks;

/// Generic SfM data container
/// Store structure and camera properties:
struct SfM_Data
{
  /// Considered views
  Views views;
  /// Considered poses (indexed by view.id_pose)
  Poses poses;
  /// Considered camera intrinsics (indexed by view.id_cam)
  Intrinsics intrinsics;
  /// Structure (3D points with their 2D observations)
  Landmarks structure;

  /// Root Views path
  std::string s_root_path;

  //--
  // Accessors
  //--
  const Views & GetViews() const {return views;}
  const Poses & GetPoses() const {return poses;}
  const Intrinsics & GetIntrinsics() const {return intrinsics;}
  const Landmarks & GetLandmarks() const {return structure;}

  /// Check if the View have defined intrinsic and pose
  bool IsPoseAndIntrinsicDefined(const View * view) const
  {
    if (view == NULL) return false;
    return (
      view->id_intrinsic != UndefinedIndexT &&
      view->id_pose != UndefinedIndexT &&
      intrinsics.find(view->id_intrinsic) != intrinsics.end() &&
      poses.find(view->id_pose) != poses.end());
  }

  /// Get the pose associated to a view
  const geometry::Pose3 GetPoseOrDie(const View * view) const
  {
    return poses.at(view->id_pose);
  }
};

} // namespace sfm
} // namespace openMVG

#endif // OPENMVG_SFM_DATA_HPP
<commit_msg>Fix a typo error in comments.<commit_after>// Copyright (c) 2015 Pierre Moulon.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef OPENMVG_SFM_DATA_HPP
#define OPENMVG_SFM_DATA_HPP

#include "openMVG/types.hpp"
#include "openMVG/sfm/sfm_view.hpp"
#include "openMVG/sfm/sfm_landmark.hpp"
#include "openMVG/geometry/pose3.hpp"
#include "openMVG/cameras/cameras.hpp"

namespace openMVG {
namespace sfm {

/// Define a collection of View
typedef Hash_Map<IndexT, std::shared_ptr<View> > Views;

/// Define a collection of Pose (indexed by View::id_pose)
typedef Hash_Map<IndexT, geometry::Pose3> Poses;

/// Define a collection of IntrinsicParameter (indexed by View::id_intrinsic)
typedef Hash_Map<IndexT, std::shared_ptr<cameras::IntrinsicBase> > Intrinsics;

/// Define a collection of landmarks are indexed by their TrackId
typedef Hash_Map<IndexT, Landmark> Landmarks;

/// Generic SfM data container
/// Store structure and camera properties:
struct SfM_Data
{
  /// Considered views
  Views views;
  /// Considered poses (indexed by view.id_pose)
  Poses poses;
  /// Considered camera intrinsics (indexed by view.id_intrinsic)
  Intrinsics intrinsics;
  /// Structure (3D points with their 2D observations)
  Landmarks structure;

  /// Root Views path
  std::string s_root_path;

  //--
  // Accessors
  //--
  const Views & GetViews() const {return views;}
  const Poses & GetPoses() const {return poses;}
  const Intrinsics & GetIntrinsics() const {return intrinsics;}
  const Landmarks & GetLandmarks() const {return structure;}

  /// Check if the View have defined intrinsic and pose
  bool IsPoseAndIntrinsicDefined(const View * view) const
  {
    if (view == NULL) return false;
    return (
      view->id_intrinsic != UndefinedIndexT &&
      view->id_pose != UndefinedIndexT &&
      intrinsics.find(view->id_intrinsic) != intrinsics.end() &&
      poses.find(view->id_pose) != poses.end());
  }

  /// Get the pose associated to a view
  const geometry::Pose3 GetPoseOrDie(const View * view) const
  {
    return poses.at(view->id_pose);
  }
};

} // namespace sfm
} // namespace openMVG

#endif // OPENMVG_SFM_DATA_HPP
<|endoftext|>