<commit_before>/*
 * Copyright 2014 Cloudius Systems
 */

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

#include "database.hh"
#include "core/app-template.hh"
#include "core/distributed.hh"
#include "thrift/server.hh"
#include "transport/server.hh"
#include "http/httpd.hh"
#include "api/api.hh"
#include "db/config.hh"
#include "service/storage_service.hh"
#include "service/migration_manager.hh"
#include "streaming/stream_session.hh"
#include "db/system_keyspace.hh"
#include "db/batchlog_manager.hh"
#include "db/commitlog/commitlog.hh"
#include "db/commitlog/commitlog_replayer.hh"
#include "utils/runtime.hh"
#include "utils/file_lock.hh"
#include "dns.hh"
#include "log.hh"
#include "debug.hh"
#include "init.hh"
#include "release.hh"
#include <cstdio>

logging::logger startlog("init");

namespace bpo = boost::program_options;

static future<>
read_config(bpo::variables_map& opts, db::config& cfg) {
    sstring file;

    if (opts.count("options-file") > 0) {
        file = opts["options-file"].as<sstring>();
    } else {
        sstring confdir;
        auto* cd = std::getenv("SCYLLA_CONF");
        if (cd != nullptr) {
            confdir = cd;
        } else {
            auto* p = std::getenv("SCYLLA_HOME");
            if (p != nullptr) {
                confdir = sstring(p) + "/";
            }
            confdir += "conf";
        }
        file = confdir + "/scylla.yaml";
    }
    return cfg.read_from_file(file).handle_exception([file](auto ep) {
        startlog.error("Could not read configuration file {}: {}", file, ep);
        return make_exception_future<>(ep);
    });
}

static void do_help_loggers() {
    print("Available loggers:\n");
    for (auto&& name : logging::logger_registry().get_all_logger_names()) {
        print("    %s\n", name);
    }
}

static logging::log_level to_loglevel(sstring level) {
    try {
        return boost::lexical_cast<logging::log_level>(std::string(level));
    } catch(boost::bad_lexical_cast e) {
        throw std::runtime_error("Unknown log level '" + level + "'");
    }
}

static void apply_logger_settings(sstring default_level, db::config::string_map levels,
        bool log_to_stdout, bool log_to_syslog) {
    logging::logger_registry().set_all_loggers_level(to_loglevel(default_level));
    for (auto&& kv: levels) {
        auto&& k = kv.first;
        auto&& v = kv.second;
        try {
            logging::logger_registry().set_logger_level(k, to_loglevel(v));
        } catch(std::out_of_range e) {
            throw std::runtime_error("Unknown logger '" + k + "'. Use --help-loggers to list available loggers.");
        }
    }
    logging::logger::set_stdout_enabled(log_to_stdout);
    logging::logger::set_syslog_enabled(log_to_syslog);
}

class directories {
public:
    future<> touch_and_lock(sstring path) {
        return recursive_touch_directory(path).then_wrapped([this, path] (future<> f) {
            try {
                f.get();
                return utils::file_lock::acquire(path + "/.lock").then([this](utils::file_lock lock) {
                   _locks.emplace_back(std::move(lock));
                }).handle_exception([path](auto ep) {
                    // only do this because "normal" unhandled exception exit in seastar
                    // _drops_ system_error message ("what()") and thus does not quite deliver
                    // the relevant info to the user
                    try {
                        std::rethrow_exception(ep);
                    } catch (std::exception& e) {
                        startlog.error("Could not initialize {}: {}", path, e.what());
                        throw;
                    } catch (...) {
                        throw;
                    }
                });
            } catch (std::system_error& e) {
                startlog.error("Directory '{}' not found. Tried to created it but failed: {}", path, e.what());
                throw;
            }
        });
    }
    template<typename _Iter>
    future<> touch_and_lock(_Iter i, _Iter e) {
        return parallel_for_each(i, e, [this](sstring path) {
           return touch_and_lock(std::move(path));
        });
    }
    template<typename _Range>
    future<> touch_and_lock(_Range&& r) {
        return touch_and_lock(std::begin(r), std::end(r));
    }
private:
    std::vector<utils::file_lock>
        _locks;
};

int main(int ac, char** av) {
    runtime::init_uptime();
    std::setvbuf(stdout, nullptr, _IOLBF, 1000);
    app_template app;
    auto opt_add = app.add_options();

    auto cfg = make_lw_shared<db::config>();
    bool help_loggers = false;
    cfg->add_options(opt_add)
        // TODO : default, always read?
        ("options-file", bpo::value<sstring>(), "configuration file (i.e. <SCYLLA_HOME>/conf/scylla.yaml)")
        ("help-loggers", bpo::bool_switch(&help_loggers), "print a list of logger names and exit")
        ;

    distributed<database> db;
    debug::db = &db;
    distributed<cql3::query_processor> qp;
    auto& proxy = service::get_storage_proxy();
    auto& mm = service::get_migration_manager();
    api::http_context ctx(db, proxy);
    directories dirs;

    return app.run_deprecated(ac, av, [&] {
        if (help_loggers) {
            do_help_loggers();
            engine().exit(1);
            return make_ready_future<>();
        }
        print("Scylla version %s starting ...\n", scylla_version());
        auto&& opts = app.configuration();

        // Do this first once set log applied from command line so for example config
        // parse can get right log level.
        apply_logger_settings(cfg->default_log_level(), cfg->logger_log_level(),
                cfg->log_to_stdout(), cfg->log_to_syslog());

        return read_config(opts, *cfg).then([&cfg, &db, &qp, &proxy, &mm, &ctx, &opts, &dirs]() {
            apply_logger_settings(cfg->default_log_level(), cfg->logger_log_level(),
                    cfg->log_to_stdout(), cfg->log_to_syslog());
            dht::set_global_partitioner(cfg->partitioner());
            auto start_thrift = cfg->start_rpc();
            uint16_t thrift_port = cfg->rpc_port();
            uint16_t cql_port = cfg->native_transport_port();
            uint16_t api_port = cfg->api_port();
            ctx.api_dir = cfg->api_ui_dir();
            ctx.api_doc = cfg->api_doc_dir();
            sstring cluster_name = cfg->cluster_name();
            sstring listen_address = cfg->listen_address();
            sstring rpc_address = cfg->rpc_address();
            sstring api_address = cfg->api_address() != "" ? cfg->api_address() : rpc_address;
            auto seed_provider= cfg->seed_provider();
            using namespace locator;
            return i_endpoint_snitch::create_snitch(cfg->endpoint_snitch()).then([] {
                // #293 - do not stop anything
                // engine().at_exit([] { return i_endpoint_snitch::stop_snitch(); });
            }).then([&db] {
                return init_storage_service(db);
            }).then([&db, cfg] {
                return db.start(std::move(*cfg)).then([&db] {
                    engine().at_exit([&db] {

                        // #293 - do not stop anything - not even db (for real)
                        //return db.stop();
                        // call stop on each db instance, but leave the shareded<database> pointers alive.
                        return db.invoke_on_all([](auto& db) {
                            return db.stop();
                        }).then([] {
                            ::_exit(3);
                        });
                    });
                });
            }).then([listen_address, seed_provider, cluster_name] {
                return init_ms_fd_gossiper(listen_address, seed_provider, cluster_name);
            }).then([&db] {
                return streaming::stream_session::init_streaming_service(db);
            }).then([&proxy, &db] {
                return proxy.start(std::ref(db)).then([&proxy] {
                    // #293 - do not stop anything
                    // engine().at_exit([&proxy] { return proxy.stop(); });
                });
            }).then([&mm] {
                return mm.start().then([&mm] {
                    // #293 - do not stop anything
                    // engine().at_exit([&mm] { return mm.stop(); });
                });
            }).then([&db, &proxy, &qp] {
                return qp.start(std::ref(proxy), std::ref(db)).then([&qp] {
                    // #293 - do not stop anything
                    // engine().at_exit([&qp] { return qp.stop(); });
                });
            }).then([&qp] {
                return db::get_batchlog_manager().start(std::ref(qp)).then([] {
                    // #293 - do not stop anything
                    // engine().at_exit([] { return db::get_batchlog_manager().stop(); });
                });
            }).then([&db, &dirs] {
                return dirs.touch_and_lock(db.local().get_config().data_file_directories());
            }).then([&db, &dirs] {
                return dirs.touch_and_lock(db.local().get_config().commitlog_directory());
            }).then([&db] {
                return db.invoke_on_all([] (database& db) {
                    return db.init_system_keyspace();
                });
            }).then([&db, &proxy] {
                return db.invoke_on_all([&proxy] (database& db) {
                    return db.load_sstables(proxy);
                });
            }).then([&db, &qp] {
                return db::system_keyspace::setup(db, qp);
            }).then([&db, &qp] {
                auto cl = db.local().commitlog();
                if (cl == nullptr) {
                    return make_ready_future<>();
                }
                return cl->list_existing_segments().then([&db, &qp](auto paths) {
                    if (paths.empty()) {
                        return make_ready_future<>();
                    }
                    return db::commitlog_replayer::create_replayer(qp).then([paths](auto rp) {
                        return do_with(std::move(rp), [paths = std::move(paths)](auto& rp) {
                            return rp.recover(paths);
                        });
                    }).then([&db] {
                        return db.invoke_on_all([] (database& db) {
                            return db.flush_all_memtables();
                        });
                    }).then([paths] {
                        for (auto& path : paths) {
                            ::unlink(path.c_str());
                        }
                    });
                });
            }).then([] {
                auto& ss = service::get_local_storage_service();
                return ss.init_server();
            }).then([rpc_address] {
                return dns::gethostbyname(rpc_address);
            }).then([&db, &proxy, &qp, rpc_address, cql_port, thrift_port, start_thrift] (dns::hostent e) {
                auto ip = e.addresses[0].in.s_addr;
                auto cserver = new distributed<transport::cql_server>;
                cserver->start(std::ref(proxy), std::ref(qp)).then([server = std::move(cserver), cql_port, rpc_address, ip] () mutable {
                    // #293 - do not stop anything
                    //engine().at_exit([server] {
                    //    return server->stop();
                    //});
                    server->invoke_on_all(&transport::cql_server::listen, ipv4_addr{ip, cql_port});
                }).then([rpc_address, cql_port] {
                    print("Starting listening for CQL clients on %s:%s...\n", rpc_address, cql_port);
                });
                if (start_thrift) {
                    auto tserver = new distributed<thrift_server>;
                    tserver->start(std::ref(db)).then([server = std::move(tserver), thrift_port, rpc_address, ip] () mutable {
                        // #293 - do not stop anything
                        //engine().at_exit([server] {
                        //    return server->stop();
                        //});
                        server->invoke_on_all(&thrift_server::listen, ipv4_addr{ip, thrift_port});
                    }).then([rpc_address, thrift_port] {
                        print("Thrift server listening on %s:%s ...\n", rpc_address, thrift_port);
                    });
                }
            }).then([api_address] {
                return dns::gethostbyname(api_address);
            }).then([&db, api_address, api_port, &ctx] (dns::hostent e){
                auto ip = e.addresses[0].in.s_addr;
                ctx.http_server.start().then([api_address, api_port, ip, &ctx] {
                    return set_server(ctx);
                }).then([api_address, api_port, ip, &ctx] {
                    ctx.http_server.listen(ipv4_addr{ip, api_port});
                }).then([api_address, api_port] {
                    print("Seastar HTTP server listening on %s:%s ...\n", api_address, api_port);
                });
            });
        }).or_terminate();
    });
}

namespace debug {

seastar::sharded<database>* db;

}
<commit_msg>warn users on 100 % CPU usage<commit_after>/*
 * Copyright 2014 Cloudius Systems
 */

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

#include "database.hh"
#include "core/app-template.hh"
#include "core/distributed.hh"
#include "thrift/server.hh"
#include "transport/server.hh"
#include "http/httpd.hh"
#include "api/api.hh"
#include "db/config.hh"
#include "service/storage_service.hh"
#include "service/migration_manager.hh"
#include "streaming/stream_session.hh"
#include "db/system_keyspace.hh"
#include "db/batchlog_manager.hh"
#include "db/commitlog/commitlog.hh"
#include "db/commitlog/commitlog_replayer.hh"
#include "utils/runtime.hh"
#include "utils/file_lock.hh"
#include "dns.hh"
#include "log.hh"
#include "debug.hh"
#include "init.hh"
#include "release.hh"
#include <cstdio>

logging::logger startlog("init");

namespace bpo = boost::program_options;

static future<>
read_config(bpo::variables_map& opts, db::config& cfg) {
    sstring file;

    if (opts.count("options-file") > 0) {
        file = opts["options-file"].as<sstring>();
    } else {
        sstring confdir;
        auto* cd = std::getenv("SCYLLA_CONF");
        if (cd != nullptr) {
            confdir = cd;
        } else {
            auto* p = std::getenv("SCYLLA_HOME");
            if (p != nullptr) {
                confdir = sstring(p) + "/";
            }
            confdir += "conf";
        }
        file = confdir + "/scylla.yaml";
    }
    return cfg.read_from_file(file).handle_exception([file](auto ep) {
        startlog.error("Could not read configuration file {}: {}", file, ep);
        return make_exception_future<>(ep);
    });
}

static void do_help_loggers() {
    print("Available loggers:\n");
    for (auto&& name : logging::logger_registry().get_all_logger_names()) {
        print("    %s\n", name);
    }
}

static logging::log_level to_loglevel(sstring level) {
    try {
        return boost::lexical_cast<logging::log_level>(std::string(level));
    } catch(boost::bad_lexical_cast e) {
        throw std::runtime_error("Unknown log level '" + level + "'");
    }
}

static void apply_logger_settings(sstring default_level, db::config::string_map levels,
        bool log_to_stdout, bool log_to_syslog) {
    logging::logger_registry().set_all_loggers_level(to_loglevel(default_level));
    for (auto&& kv: levels) {
        auto&& k = kv.first;
        auto&& v = kv.second;
        try {
            logging::logger_registry().set_logger_level(k, to_loglevel(v));
        } catch(std::out_of_range e) {
            throw std::runtime_error("Unknown logger '" + k + "'. Use --help-loggers to list available loggers.");
        }
    }
    logging::logger::set_stdout_enabled(log_to_stdout);
    logging::logger::set_syslog_enabled(log_to_syslog);
}

class directories {
public:
    future<> touch_and_lock(sstring path) {
        return recursive_touch_directory(path).then_wrapped([this, path] (future<> f) {
            try {
                f.get();
                return utils::file_lock::acquire(path + "/.lock").then([this](utils::file_lock lock) {
                   _locks.emplace_back(std::move(lock));
                }).handle_exception([path](auto ep) {
                    // only do this because "normal" unhandled exception exit in seastar
                    // _drops_ system_error message ("what()") and thus does not quite deliver
                    // the relevant info to the user
                    try {
                        std::rethrow_exception(ep);
                    } catch (std::exception& e) {
                        startlog.error("Could not initialize {}: {}", path, e.what());
                        throw;
                    } catch (...) {
                        throw;
                    }
                });
            } catch (std::system_error& e) {
                startlog.error("Directory '{}' not found. Tried to created it but failed: {}", path, e.what());
                throw;
            }
        });
    }
    template<typename _Iter>
    future<> touch_and_lock(_Iter i, _Iter e) {
        return parallel_for_each(i, e, [this](sstring path) {
           return touch_and_lock(std::move(path));
        });
    }
    template<typename _Range>
    future<> touch_and_lock(_Range&& r) {
        return touch_and_lock(std::begin(r), std::end(r));
    }
private:
    std::vector<utils::file_lock>
        _locks;
};

int main(int ac, char** av) {
    runtime::init_uptime();
    std::setvbuf(stdout, nullptr, _IOLBF, 1000);
    app_template app;
    auto opt_add = app.add_options();

    auto cfg = make_lw_shared<db::config>();
    bool help_loggers = false;
    cfg->add_options(opt_add)
        // TODO : default, always read?
        ("options-file", bpo::value<sstring>(), "configuration file (i.e. <SCYLLA_HOME>/conf/scylla.yaml)")
        ("help-loggers", bpo::bool_switch(&help_loggers), "print a list of logger names and exit")
        ;

    distributed<database> db;
    debug::db = &db;
    distributed<cql3::query_processor> qp;
    auto& proxy = service::get_storage_proxy();
    auto& mm = service::get_migration_manager();
    api::http_context ctx(db, proxy);
    directories dirs;

    return app.run_deprecated(ac, av, [&] {
        if (help_loggers) {
            do_help_loggers();
            engine().exit(1);
            return make_ready_future<>();
        }
        print("Scylla version %s starting ...\n", scylla_version());
        auto&& opts = app.configuration();

        // Do this first once set log applied from command line so for example config
        // parse can get right log level.
        apply_logger_settings(cfg->default_log_level(), cfg->logger_log_level(),
                cfg->log_to_stdout(), cfg->log_to_syslog());

        return read_config(opts, *cfg).then([&cfg, &db, &qp, &proxy, &mm, &ctx, &opts, &dirs]() {
            apply_logger_settings(cfg->default_log_level(), cfg->logger_log_level(),
                    cfg->log_to_stdout(), cfg->log_to_syslog());
            dht::set_global_partitioner(cfg->partitioner());
            auto start_thrift = cfg->start_rpc();
            uint16_t thrift_port = cfg->rpc_port();
            uint16_t cql_port = cfg->native_transport_port();
            uint16_t api_port = cfg->api_port();
            ctx.api_dir = cfg->api_ui_dir();
            ctx.api_doc = cfg->api_doc_dir();
            sstring cluster_name = cfg->cluster_name();
            sstring listen_address = cfg->listen_address();
            sstring rpc_address = cfg->rpc_address();
            sstring api_address = cfg->api_address() != "" ? cfg->api_address() : rpc_address;
            auto seed_provider= cfg->seed_provider();
            using namespace locator;
            return i_endpoint_snitch::create_snitch(cfg->endpoint_snitch()).then([] {
                // #293 - do not stop anything
                // engine().at_exit([] { return i_endpoint_snitch::stop_snitch(); });
            }).then([&db] {
                return init_storage_service(db);
            }).then([&db, cfg] {
                return db.start(std::move(*cfg)).then([&db] {
                    engine().at_exit([&db] {

                        // #293 - do not stop anything - not even db (for real)
                        //return db.stop();
                        // call stop on each db instance, but leave the shareded<database> pointers alive.
                        return db.invoke_on_all([](auto& db) {
                            return db.stop();
                        }).then([] {
                            ::_exit(3);
                        });
                    });
                });
            }).then([listen_address, seed_provider, cluster_name] {
                return init_ms_fd_gossiper(listen_address, seed_provider, cluster_name);
            }).then([&db] {
                return streaming::stream_session::init_streaming_service(db);
            }).then([&proxy, &db] {
                return proxy.start(std::ref(db)).then([&proxy] {
                    // #293 - do not stop anything
                    // engine().at_exit([&proxy] { return proxy.stop(); });
                });
            }).then([&mm] {
                return mm.start().then([&mm] {
                    // #293 - do not stop anything
                    // engine().at_exit([&mm] { return mm.stop(); });
                });
            }).then([&db, &proxy, &qp] {
                return qp.start(std::ref(proxy), std::ref(db)).then([&qp] {
                    // #293 - do not stop anything
                    // engine().at_exit([&qp] { return qp.stop(); });
                });
            }).then([&qp] {
                return db::get_batchlog_manager().start(std::ref(qp)).then([] {
                    // #293 - do not stop anything
                    // engine().at_exit([] { return db::get_batchlog_manager().stop(); });
                });
            }).then([&db, &dirs] {
                return dirs.touch_and_lock(db.local().get_config().data_file_directories());
            }).then([&db, &dirs] {
                return dirs.touch_and_lock(db.local().get_config().commitlog_directory());
            }).then([&db] {
                return db.invoke_on_all([] (database& db) {
                    return db.init_system_keyspace();
                });
            }).then([&db, &proxy] {
                return db.invoke_on_all([&proxy] (database& db) {
                    return db.load_sstables(proxy);
                });
            }).then([&db, &qp] {
                return db::system_keyspace::setup(db, qp);
            }).then([&db, &qp] {
                auto cl = db.local().commitlog();
                if (cl == nullptr) {
                    return make_ready_future<>();
                }
                return cl->list_existing_segments().then([&db, &qp](auto paths) {
                    if (paths.empty()) {
                        return make_ready_future<>();
                    }
                    return db::commitlog_replayer::create_replayer(qp).then([paths](auto rp) {
                        return do_with(std::move(rp), [paths = std::move(paths)](auto& rp) {
                            return rp.recover(paths);
                        });
                    }).then([&db] {
                        return db.invoke_on_all([] (database& db) {
                            return db.flush_all_memtables();
                        });
                    }).then([paths] {
                        for (auto& path : paths) {
                            ::unlink(path.c_str());
                        }
                    });
                });
            }).then([] {
                auto& ss = service::get_local_storage_service();
                return ss.init_server();
            }).then([rpc_address] {
                return dns::gethostbyname(rpc_address);
            }).then([&db, &proxy, &qp, rpc_address, cql_port, thrift_port, start_thrift] (dns::hostent e) {
                auto ip = e.addresses[0].in.s_addr;
                auto cserver = new distributed<transport::cql_server>;
                cserver->start(std::ref(proxy), std::ref(qp)).then([server = std::move(cserver), cql_port, rpc_address, ip] () mutable {
                    // #293 - do not stop anything
                    //engine().at_exit([server] {
                    //    return server->stop();
                    //});
                    server->invoke_on_all(&transport::cql_server::listen, ipv4_addr{ip, cql_port});
                }).then([rpc_address, cql_port] {
                    print("Starting listening for CQL clients on %s:%s...\n", rpc_address, cql_port);
                });
                if (start_thrift) {
                    auto tserver = new distributed<thrift_server>;
                    tserver->start(std::ref(db)).then([server = std::move(tserver), thrift_port, rpc_address, ip] () mutable {
                        // #293 - do not stop anything
                        //engine().at_exit([server] {
                        //    return server->stop();
                        //});
                        server->invoke_on_all(&thrift_server::listen, ipv4_addr{ip, thrift_port});
                    }).then([rpc_address, thrift_port] {
                        print("Thrift server listening on %s:%s ...\n", rpc_address, thrift_port);
                    });
                }
            }).then([api_address] {
                return dns::gethostbyname(api_address);
            }).then([&db, api_address, api_port, &ctx] (dns::hostent e){
                auto ip = e.addresses[0].in.s_addr;
                ctx.http_server.start().then([api_address, api_port, ip, &ctx] {
                    return set_server(ctx);
                }).then([api_address, api_port, ip, &ctx] {
                    ctx.http_server.listen(ipv4_addr{ip, api_port});
                }).then([api_address, api_port] {
                    print("Seastar HTTP server listening on %s:%s ...\n", api_address, api_port);
                });
            }).then([] {
                startlog.warn("Polling mode enabled. ScyllaDB will use 100% of all your CPUs.\nSee https://github.com/scylladb/scylla/issues/417 for a more detailed explanation");
            });
        }).or_terminate();
    });
}

namespace debug {

seastar::sharded<database>* db;

}
<|endoftext|>


<commit_before>//===-- main.cpp ------------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include <iostream>
#include <stdio.h>

int main(int argc, char const *argv[])
{
    getchar();
    printf("Set a breakpoint here.\n");
    return 0;
}

<commit_msg>Fix breakpoint_set_restart test for Windows<commit_after>//===-- main.cpp ------------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include <chrono>
#include <stdio.h>
#include <thread>

int main(int argc, char const *argv[])
{
    static bool done = false;
    while (!done)
    {
      std::this_thread::sleep_for(std::chrono::milliseconds{100});
    }
    printf("Set a breakpoint here.\n");
    return 0;
}

<|endoftext|>


<commit_before>#ifndef __PARSE_TOOL_HPP__
#define __PARSE_TOOL_HPP__

#include <functional>
using namespace std;

// data type: Maybe
template<typename T>
struct Maybe{
private:
    bool const nil;
    T const val;
public:
    using data_type = T;
    constexpr Maybe(): nil(true) {}
    constexpr Maybe(T const & val): val(val), nil(false) {}
    bool Nil() const { return this->nil; }
    T Val() const { if (this->nil) { throw val; } else { return val; } }
    constexpr operator bool () const { return this->nil == false; }
};
template<typename T>
constexpr Maybe<T> const Just(T const & val) {
    return Maybe<T>(val);
}
template<typename T>
constexpr Maybe<T> const Nothing() {
    return Maybe<T>();
}
template<typename T>
constexpr T const FromJust(Maybe<T> const & wrapper) {
    return wrapper.Val();
}

/**
 * The result representation of a parser. `Success` and `Failure` are used to construct Value object, while
 * `Aggregate` is used to accmulate two Value object into one.
 */
template<typename V>
struct ValueT {
    bool const status;
    pair<int, int> loc;
    int len;
    V const actual;
    string expected;
    bool strict;

    string to_string(int n) const { return ::to_string(n); }
    string to_string(char c) const { return string(1, c); }
    string to_string(string s) const { return s; }
    string to_string(vector<char> vec) const { string ans = "vector char: "; for (char c: vec) { ans.push_back(c); ans.push_back(','); } return ans; }
    string to_string(vector<string> vec) const { string ans = "vector string: "; for (string s: vec) { ans += s + ","; } return ans; }

    string name() const {
        return "stream @ " + ::to_string(loc.first) + ":" + ::to_string(loc.second)
            + ", " + (status ? "true" : "false") + ", length: " + ::to_string(len) + "\n"
            + "    actual:   " + to_string(actual) + "\n"
            + "    expected: " + to_string(expected) + "\n";
    }

    ValueT<V>(bool status, pair<int, int> loc, int len, V const & actual, string const & expected, bool const & strict = false)
        : status(status), loc(loc), len(len), actual(actual), expected(expected), strict(strict) {}

    static ValueT<V> Success(pair<int, int> loc, int len, V const & actual, string const & expected, bool const & strict = false) {
        return ValueT<V>(true, loc, len, actual, expected, strict);
    }

    static ValueT<V> Failure(pair<int, int> loc, int len, V const & actual, string const & expected, bool const & strict = false) {
        return ValueT<V>(false, loc, len, actual, expected, strict);
    }
};

struct ParseError: public exception {
    string const sname, message;
    pair<int, int> const loc;
    ParseError(string const & sname, string const & message, pair<int, int> const loc): exception(), sname(sname), message(message), loc(loc) {}
    const char *what() const noexcept { return (sname + ": " + message).c_str(); }
};

/**
 * Parser model, wraps a function parse a Value object from a stream at specified position.
 */
template<typename P, typename = typename P::parser_type>
struct ParsecT {
private:
    P const parser;
public:
    using V = typename P::parser_type;
    constexpr ParsecT(P const & parser): parser(parser) {}
    string name() const { return "ParsecT"; }
    ValueT<V> parse(input_t *text) const {
        pair<int, int> loc = make_pair(1, 1);
        tuple<int, V, string> res;
        try { // try exception throwed during operating the stream object.
            res = parser(text);
        } catch (std::exception & e) {
            cout << string("!!!Exception: ") + string(e.what()) << endl;
            res = make_tuple(-1, V(), "!!!Exception: " + string(e.what()));
        } catch (...) {
            cout << string("!!!Exception: ") + "unknown exception." << endl;
        }
        text = text->next(std::get<0>(res)); // move ahead offset.
        if (!text->empty()) {
            // cout << "NOT COMSUME ALL TOKEN IN THE INPUT STREAM!" << endl;
            // cout << "    in stream: " << (*text) << endl;
        }
        return ValueT<V>(std::get<0>(res) != -1, loc, std::get<0>(res), std::get<1>(res), std::get<2>(res), text->empty());
    }
    ValueT<V> operator () (input_t *text) const {
        return this->parse(text);
    }
};

template<typename T>
class parser_t {
private:
    pair<int, int> loc;
    string const desc;
    function<pair<int, T>(input_t *)> fn;
public:
    using parser_type = T;
    parser_t(string const desc): desc(desc) {}
    parser_t(string const desc, function<pair<int, T>(input_t *)> fn): desc(desc), fn(fn) {}
    ~parser_t() {}
    void setfn(function<pair<int, T>(input_t *)> const & fn) {
        this->fn = fn;
    }
    tuple<int, parser_type const, string const> operator () (input_t *text) const {
        auto res = this->fn(text);
        return make_tuple(res.first, res.second, this->name());
    }
    string const name() const { return this->desc; }
};

#endif /* __PARSE_TOOL_HPP__ */
<commit_msg>Fix a bug.<commit_after>#ifndef __PARSE_TOOL_HPP__
#define __PARSE_TOOL_HPP__

#include <vector>
#include <functional>
using namespace std;

// data type: Maybe
template<typename T>
struct Maybe{
private:
    bool const nil;
    T const val;
public:
    using data_type = T;
    constexpr Maybe(): nil(true) {}
    constexpr Maybe(T const & val): val(val), nil(false) {}
    bool Nil() const { return this->nil; }
    T Val() const { if (this->nil) { throw val; } else { return val; } }
    constexpr operator bool () const { return this->nil == false; }
};
template<typename T>
constexpr Maybe<T> const Just(T const & val) {
    return Maybe<T>(val);
}
template<typename T>
constexpr Maybe<T> const Nothing() {
    return Maybe<T>();
}
template<typename T>
constexpr T const FromJust(Maybe<T> const & wrapper) {
    return wrapper.Val();
}

/**
 * The result representation of a parser. `Success` and `Failure` are used to construct Value object, while
 * `Aggregate` is used to accmulate two Value object into one.
 */
template<typename V>
struct ValueT {
    bool const status;
    pair<int, int> loc;
    int len;
    V const actual;
    string expected;
    bool strict;

    string to_string(int n) const { return ::to_string(n); }
    string to_string(char c) const { return string(1, c); }
    string to_string(string s) const { return s; }
    string to_string(vector<char> vec) const { string ans = "vector char: "; for (char c: vec) { ans.push_back(c); ans.push_back(','); } return ans; }
    string to_string(vector<string> vec) const { string ans = "vector string: "; for (string s: vec) { ans += s + ","; } return ans; }

    string name() const {
        return "stream @ " + ::to_string(loc.first) + ":" + ::to_string(loc.second)
            + ", " + (status ? "true" : "false") + ", length: " + ::to_string(len) + "\n"
            + "    actual:   " + to_string(actual) + "\n"
            + "    expected: " + to_string(expected) + "\n";
    }

    ValueT<V>(bool status, pair<int, int> loc, int len, V const & actual, string const & expected, bool const & strict = false)
        : status(status), loc(loc), len(len), actual(actual), expected(expected), strict(strict) {}

    static ValueT<V> Success(pair<int, int> loc, int len, V const & actual, string const & expected, bool const & strict = false) {
        return ValueT<V>(true, loc, len, actual, expected, strict);
    }

    static ValueT<V> Failure(pair<int, int> loc, int len, V const & actual, string const & expected, bool const & strict = false) {
        return ValueT<V>(false, loc, len, actual, expected, strict);
    }
};

struct ParseError: public exception {
    string const sname, message;
    pair<int, int> const loc;
    ParseError(string const & sname, string const & message, pair<int, int> const loc): exception(), sname(sname), message(message), loc(loc) {}
    const char *what() const noexcept { return (sname + ": " + message).c_str(); }
};

/**
 * Parser model, wraps a function parse a Value object from a stream at specified position.
 */
template<typename P, typename = typename P::parser_type>
struct ParsecT {
private:
    P const parser;
public:
    using V = typename P::parser_type;
    constexpr ParsecT(P const & parser): parser(parser) {}
    string name() const { return "ParsecT"; }
    ValueT<V> parse(input_t *text) const {
        pair<int, int> loc = make_pair(1, 1);
        tuple<int, V, string> res;
        try { // try exception throwed during operating the stream object.
            res = parser(text);
        } catch (std::exception & e) {
            cout << string("!!!Exception: ") + string(e.what()) << endl;
            res = make_tuple(-1, V(), "!!!Exception: " + string(e.what()));
        } catch (...) {
            cout << string("!!!Exception: ") + "unknown exception." << endl;
        }
        text = text->next(std::get<0>(res)); // move ahead offset.
        if (!text->empty()) {
            // cout << "NOT COMSUME ALL TOKEN IN THE INPUT STREAM!" << endl;
            // cout << "    in stream: " << (*text) << endl;
        }
        return ValueT<V>(std::get<0>(res) != -1, loc, std::get<0>(res), std::get<1>(res), std::get<2>(res), text->empty());
    }
    ValueT<V> operator () (input_t *text) const {
        return this->parse(text);
    }
};

template<typename T>
class parser_t {
private:
    pair<int, int> loc;
    string const desc;
    function<pair<int, T>(input_t *)> fn;
public:
    using parser_type = T;
    parser_t(string const desc): desc(desc) {}
    parser_t(string const desc, function<pair<int, T>(input_t *)> fn): desc(desc), fn(fn) {}
    ~parser_t() {}
    void setfn(function<pair<int, T>(input_t *)> const & fn) {
        this->fn = fn;
    }
    tuple<int, parser_type const, string const> operator () (input_t *text) const {
        auto res = this->fn(text);
        return make_tuple(res.first, res.second, this->name());
    }
    string const name() const { return this->desc; }
};

#endif /* __PARSE_TOOL_HPP__ */
<|endoftext|>


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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
#include <berryIStructuredSelection.h>

// Qmitk
#include "QmitkStochasticFiberTrackingView.h"
#include "QmitkStdMultiWidget.h"

// Qt
#include <QMessageBox>

// MITK
#include <mitkImageToItk.h>
#include <mitkFiberBundleX.h>

// VTK
#include <vtkPolyData.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkSmartPointer.h>
#include <vtkPolyLine.h>
#include <vtkCellData.h>

const std::string QmitkStochasticFiberTrackingView::VIEW_ID = "org.mitk.views.stochasticfibertracking";
const std::string id_DataManager = "org.mitk.views.datamanager";
using namespace berry;

QmitkStochasticFiberTrackingView::QmitkStochasticFiberTrackingView()
    : QmitkFunctionality()
    , m_Controls( 0 )
    , m_MultiWidget( NULL )
    , m_SeedRoi( NULL )
    , m_DiffusionImage( NULL )
{
}

// Destructor
QmitkStochasticFiberTrackingView::~QmitkStochasticFiberTrackingView()
{

}

void QmitkStochasticFiberTrackingView::CreateQtPartControl( QWidget *parent )
{
    if ( !m_Controls )
    {
        // create GUI widgets from the Qt Designer's .ui file
        m_Controls = new Ui::QmitkStochasticFiberTrackingViewControls;
        m_Controls->setupUi( parent );

        connect( m_Controls->commandLinkButton, SIGNAL(clicked()), this, SLOT(DoFiberTracking()) );
        connect( m_Controls->m_SeedsPerVoxelSlider, SIGNAL(valueChanged(int)), this, SLOT(OnSeedsPerVoxelChanged(int)) );
        connect( m_Controls->m_MaxCacheSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(OnMaxCacheSizeChanged(int)) );
        connect( m_Controls->m_MaxTractLengthSlider, SIGNAL(valueChanged(int)), this, SLOT(OnMaxTractLengthChanged(int)) );
    }
}

void QmitkStochasticFiberTrackingView::OnSeedsPerVoxelChanged(int value)
{
    m_Controls->m_SeedsPerVoxelLabel->setText(QString("Seeds per Voxel: ")+QString::number(value));
}

void QmitkStochasticFiberTrackingView::OnMaxTractLengthChanged(int value)
{
    m_Controls->m_MaxTractLengthLabel->setText(QString("Max. Tract Length: ")+QString::number(value));
}

void QmitkStochasticFiberTrackingView::OnMaxCacheSizeChanged(int value)
{
    m_Controls->m_MaxCacheSizeLabel->setText(QString("Max. Cache Size: ")+QString::number(value)+"GB");
}

void QmitkStochasticFiberTrackingView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget)
{
    m_MultiWidget = &stdMultiWidget;
}

void QmitkStochasticFiberTrackingView::StdMultiWidgetNotAvailable()
{
    m_MultiWidget = NULL;
}

void QmitkStochasticFiberTrackingView::OnSelectionChanged( std::vector<mitk::DataNode*> nodes )
{
    m_DiffusionImageNode = NULL;
    m_DiffusionImage = NULL;
    m_SeedRoi = NULL;
    m_Controls->m_DiffusionImageLabel->setText("mandatory");
    m_Controls->m_RoiImageLabel->setText("mandatory");

    for( std::vector<mitk::DataNode*>::iterator it = nodes.begin(); it != nodes.end(); ++it )
    {
        mitk::DataNode::Pointer node = *it;

        if( node.IsNotNull() && dynamic_cast<mitk::Image*>(node->GetData()) )
        {
            if( dynamic_cast<mitk::DiffusionImage<short>*>(node->GetData()) )
            {
                m_DiffusionImageNode = node;
                m_DiffusionImage = dynamic_cast<mitk::DiffusionImage<short>*>(node->GetData());
                m_Controls->m_DiffusionImageLabel->setText(node->GetName().c_str());
            }
            else
            {
                bool isBinary = false;
                node->GetPropertyValue<bool>("binary", isBinary);
                if (isBinary)
                {
                    m_SeedRoi = dynamic_cast<mitk::Image*>(node->GetData());
                    m_Controls->m_RoiImageLabel->setText(node->GetName().c_str());
                }
            }
        }
    }

    if(m_DiffusionImage.IsNotNull() && m_SeedRoi.IsNotNull())
    {
        m_Controls->m_InputData->setTitle("Input Data");
        m_Controls->commandLinkButton->setEnabled(true);
    }
    else
    {
        m_Controls->m_InputData->setTitle("Please Select Input Data");
        m_Controls->commandLinkButton->setEnabled(false);
    }
}

void QmitkStochasticFiberTrackingView::DoFiberTracking()
{
    typedef itk::VectorImage< short int, 3 >    DWIVectorImageType;
    typedef itk::Image< float, 3 >              FloatImageType;
    typedef itk::Image< unsigned int, 3 >       CImageType;
    typedef itk::StochasticTractographyFilter< DWIVectorImageType, FloatImageType, CImageType > TrackingFilterType;
    typedef itk::DTITubeSpatialObject<3>        DTITubeType;
    typedef itk::DTITubeSpatialObjectPoint<3>   DTITubePointType;
    typedef itk::SceneSpatialObject<3>          SceneSpatialObjectType;

    /* get Gradients/Direction of dwi */
    itk::VectorContainer< unsigned int, vnl_vector_fixed<double,3> >::Pointer Pdir = m_DiffusionImage->GetDirections();

    /* bValueContainer, Container includes b-values according to corresponding gradient-direction*/
    TrackingFilterType::bValueContainerType::Pointer vecCont = TrackingFilterType::bValueContainerType::New();

    /* for each gradient set b-Value; for 0-gradient set b-value eq. 0 */
    for ( int i=0; i<(int)Pdir->size(); ++i)
    {
        vnl_vector_fixed<double,3> valsGrad = Pdir->at(i);
        if (valsGrad.get(0) == 0 && valsGrad.get(1) == 0 && valsGrad.get(2) == 0)
        {  //set 0-Gradient to bValue 0
            vecCont->InsertElement(i,0);
        }else{
            vecCont->InsertElement(i,m_DiffusionImage->GetB_Value());
        }
    }

    /* define measurement frame (identity-matrix 3x3) */
    TrackingFilterType::MeasurementFrameType measurement_frame = m_DiffusionImage->GetMeasurementFrame();

    /* generate white matterImage (dummy?)*/
    FloatImageType::Pointer wmImage = FloatImageType::New();
    wmImage->SetSpacing( m_DiffusionImage->GetVectorImage()->GetSpacing() );
    wmImage->SetOrigin( m_DiffusionImage->GetVectorImage()->GetOrigin() );
    wmImage->SetDirection( m_DiffusionImage->GetVectorImage()->GetDirection() );
    wmImage->SetLargestPossibleRegion( m_DiffusionImage->GetVectorImage()->GetLargestPossibleRegion() );
    wmImage->SetBufferedRegion( wmImage->GetLargestPossibleRegion() );
    wmImage->SetRequestedRegion( wmImage->GetLargestPossibleRegion() );
    wmImage->Allocate();

    itk::ImageRegionIterator<FloatImageType> ot(wmImage, wmImage->GetLargestPossibleRegion() );
    while (!ot.IsAtEnd())
    {
        ot.Set(1);
        ++ot;
    }

    /* init TractographyFilter */
    TrackingFilterType::Pointer trackingFilter = TrackingFilterType::New();
    trackingFilter->SetInput(m_DiffusionImage->GetVectorImage().GetPointer());
    trackingFilter->SetbValues(vecCont);
    trackingFilter->SetGradients(Pdir);
    trackingFilter->SetMeasurementFrame(measurement_frame);
    trackingFilter->SetWhiteMatterProbabilityImage(wmImage);
    trackingFilter->SetTotalTracts(m_Controls->m_SeedsPerVoxelSlider->value());
    trackingFilter->SetMaxLikelihoodCacheSize(m_Controls->m_MaxCacheSizeSlider->value()*1000);
    trackingFilter->SetMaxTractLength(m_Controls->m_MaxTractLengthSlider->value());

    //itk::Image< char, 3 >
    mitk::ImageToItk< itk::Image< unsigned char, 3 > >::Pointer binaryImageToItk1 = mitk::ImageToItk< itk::Image< unsigned char, 3 > >::New();
    binaryImageToItk1->SetInput( m_SeedRoi );
    binaryImageToItk1->Update();

    vtkSmartPointer<vtkPoints> vPoints = vtkSmartPointer<vtkPoints>::New();
    vtkSmartPointer<vtkCellArray> vCellArray = vtkSmartPointer<vtkCellArray>::New();

    itk::ImageRegionConstIterator< BinaryImageType > it(binaryImageToItk1->GetOutput(), binaryImageToItk1->GetOutput()->GetRequestedRegion());
    it.GoToBegin();
    mitk::Geometry3D* geom = m_DiffusionImage->GetGeometry();

    while(!it.IsAtEnd())
    {
        itk::ImageConstIterator<BinaryImageType>::PixelType tmpPxValue = it.Get();

        if(tmpPxValue != 0){
            mitk::Point3D point;
            itk::ImageRegionConstIterator< BinaryImageType >::IndexType seedIdx = it.GetIndex();
            trackingFilter->SetSeedIndex(seedIdx);
            trackingFilter->Update();

            /* get results from Filter */
            /* write each single tract into member container */
            TrackingFilterType::TractContainerType::Pointer container_tmp = trackingFilter->GetOutputTractContainer();
            TrackingFilterType::TractContainerType::Iterator elIt = container_tmp->Begin();
            TrackingFilterType::TractContainerType::Iterator end = container_tmp->End();
            bool addTract = true;

            while( elIt != end ){
                TrackingFilterType::TractContainerType::Element tract = elIt.Value();
                TrackingFilterType::TractContainerType::Element::ObjectType::VertexListType::ConstPointer vertexlist = tract->GetVertexList();

                vtkSmartPointer<vtkPolyLine> vPolyLine = vtkSmartPointer<vtkPolyLine>::New();
                for( int j=0; j<(int)vertexlist->Size(); j++)
                {
                    TrackingFilterType::TractContainerType::Element::ObjectType::VertexListType::Element vertex = vertexlist->GetElement(j);
                    mitk::Point3D index;
                    index[0] = (float)vertex[0];
                    index[1] = (float)vertex[1];
                    index[2] = (float)vertex[2];

                    if (geom->IsIndexInside(index))
                    {
                        geom->IndexToWorld(index, point);
                        vtkIdType id = vPoints->InsertNextPoint(point.GetDataPointer());
                        vPolyLine->GetPointIds()->InsertNextId(id);
                    }
                    else
                    {
                        addTract = false;
                        break;
                    }
                }

                if (addTract)
                    vCellArray->InsertNextCell(vPolyLine);

                ++elIt;
            }
        }
        ++it;
    }

    vtkSmartPointer<vtkPolyData> fiberPolyData = vtkSmartPointer<vtkPolyData>::New();
    fiberPolyData->SetPoints(vPoints);
    fiberPolyData->SetLines(vCellArray);

    mitk::FiberBundleX::Pointer fib = mitk::FiberBundleX::New(fiberPolyData);
    mitk::DataNode::Pointer fbNode = mitk::DataNode::New();
    fbNode->SetData(fib);
    QString name("FiberBundle_");
    name += m_DiffusionImageNode->GetName().c_str();
    name += "_Probabilistic";
    fbNode->SetName(name.toStdString());
    fbNode->SetVisibility(true);
    GetDataStorage()->Add(fbNode, m_DiffusionImageNode);
}

<commit_msg>Usage of itkStochasticTractographyFilter changed, so SetInput is now SetPrimaryInput.<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
#include <berryIStructuredSelection.h>

// Qmitk
#include "QmitkStochasticFiberTrackingView.h"
#include "QmitkStdMultiWidget.h"

// Qt
#include <QMessageBox>

// MITK
#include <mitkImageToItk.h>
#include <mitkFiberBundleX.h>

// VTK
#include <vtkPolyData.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkSmartPointer.h>
#include <vtkPolyLine.h>
#include <vtkCellData.h>

const std::string QmitkStochasticFiberTrackingView::VIEW_ID = "org.mitk.views.stochasticfibertracking";
const std::string id_DataManager = "org.mitk.views.datamanager";
using namespace berry;

QmitkStochasticFiberTrackingView::QmitkStochasticFiberTrackingView()
    : QmitkFunctionality()
    , m_Controls( 0 )
    , m_MultiWidget( NULL )
    , m_SeedRoi( NULL )
    , m_DiffusionImage( NULL )
{
}

// Destructor
QmitkStochasticFiberTrackingView::~QmitkStochasticFiberTrackingView()
{

}

void QmitkStochasticFiberTrackingView::CreateQtPartControl( QWidget *parent )
{
    if ( !m_Controls )
    {
        // create GUI widgets from the Qt Designer's .ui file
        m_Controls = new Ui::QmitkStochasticFiberTrackingViewControls;
        m_Controls->setupUi( parent );

        connect( m_Controls->commandLinkButton, SIGNAL(clicked()), this, SLOT(DoFiberTracking()) );
        connect( m_Controls->m_SeedsPerVoxelSlider, SIGNAL(valueChanged(int)), this, SLOT(OnSeedsPerVoxelChanged(int)) );
        connect( m_Controls->m_MaxCacheSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(OnMaxCacheSizeChanged(int)) );
        connect( m_Controls->m_MaxTractLengthSlider, SIGNAL(valueChanged(int)), this, SLOT(OnMaxTractLengthChanged(int)) );
    }
}

void QmitkStochasticFiberTrackingView::OnSeedsPerVoxelChanged(int value)
{
    m_Controls->m_SeedsPerVoxelLabel->setText(QString("Seeds per Voxel: ")+QString::number(value));
}

void QmitkStochasticFiberTrackingView::OnMaxTractLengthChanged(int value)
{
    m_Controls->m_MaxTractLengthLabel->setText(QString("Max. Tract Length: ")+QString::number(value));
}

void QmitkStochasticFiberTrackingView::OnMaxCacheSizeChanged(int value)
{
    m_Controls->m_MaxCacheSizeLabel->setText(QString("Max. Cache Size: ")+QString::number(value)+"GB");
}

void QmitkStochasticFiberTrackingView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget)
{
    m_MultiWidget = &stdMultiWidget;
}

void QmitkStochasticFiberTrackingView::StdMultiWidgetNotAvailable()
{
    m_MultiWidget = NULL;
}

void QmitkStochasticFiberTrackingView::OnSelectionChanged( std::vector<mitk::DataNode*> nodes )
{
    m_DiffusionImageNode = NULL;
    m_DiffusionImage = NULL;
    m_SeedRoi = NULL;
    m_Controls->m_DiffusionImageLabel->setText("mandatory");
    m_Controls->m_RoiImageLabel->setText("mandatory");

    for( std::vector<mitk::DataNode*>::iterator it = nodes.begin(); it != nodes.end(); ++it )
    {
        mitk::DataNode::Pointer node = *it;

        if( node.IsNotNull() && dynamic_cast<mitk::Image*>(node->GetData()) )
        {
            if( dynamic_cast<mitk::DiffusionImage<short>*>(node->GetData()) )
            {
                m_DiffusionImageNode = node;
                m_DiffusionImage = dynamic_cast<mitk::DiffusionImage<short>*>(node->GetData());
                m_Controls->m_DiffusionImageLabel->setText(node->GetName().c_str());
            }
            else
            {
                bool isBinary = false;
                node->GetPropertyValue<bool>("binary", isBinary);
                if (isBinary)
                {
                    m_SeedRoi = dynamic_cast<mitk::Image*>(node->GetData());
                    m_Controls->m_RoiImageLabel->setText(node->GetName().c_str());
                }
            }
        }
    }

    if(m_DiffusionImage.IsNotNull() && m_SeedRoi.IsNotNull())
    {
        m_Controls->m_InputData->setTitle("Input Data");
        m_Controls->commandLinkButton->setEnabled(true);
    }
    else
    {
        m_Controls->m_InputData->setTitle("Please Select Input Data");
        m_Controls->commandLinkButton->setEnabled(false);
    }
}

void QmitkStochasticFiberTrackingView::DoFiberTracking()
{
    typedef itk::VectorImage< short int, 3 >    DWIVectorImageType;
    typedef itk::Image< float, 3 >              FloatImageType;
    typedef itk::Image< unsigned int, 3 >       CImageType;
    typedef itk::StochasticTractographyFilter< DWIVectorImageType, FloatImageType, CImageType > TrackingFilterType;
    typedef itk::DTITubeSpatialObject<3>        DTITubeType;
    typedef itk::DTITubeSpatialObjectPoint<3>   DTITubePointType;
    typedef itk::SceneSpatialObject<3>          SceneSpatialObjectType;

    /* get Gradients/Direction of dwi */
    itk::VectorContainer< unsigned int, vnl_vector_fixed<double,3> >::Pointer Pdir = m_DiffusionImage->GetDirections();

    /* bValueContainer, Container includes b-values according to corresponding gradient-direction*/
    TrackingFilterType::bValueContainerType::Pointer vecCont = TrackingFilterType::bValueContainerType::New();

    /* for each gradient set b-Value; for 0-gradient set b-value eq. 0 */
    for ( int i=0; i<(int)Pdir->size(); ++i)
    {
        vnl_vector_fixed<double,3> valsGrad = Pdir->at(i);
        if (valsGrad.get(0) == 0 && valsGrad.get(1) == 0 && valsGrad.get(2) == 0)
        {  //set 0-Gradient to bValue 0
            vecCont->InsertElement(i,0);
        }else{
            vecCont->InsertElement(i,m_DiffusionImage->GetB_Value());
        }
    }

    /* define measurement frame (identity-matrix 3x3) */
    TrackingFilterType::MeasurementFrameType measurement_frame = m_DiffusionImage->GetMeasurementFrame();

    /* generate white matterImage (dummy?)*/
    FloatImageType::Pointer wmImage = FloatImageType::New();
    wmImage->SetSpacing( m_DiffusionImage->GetVectorImage()->GetSpacing() );
    wmImage->SetOrigin( m_DiffusionImage->GetVectorImage()->GetOrigin() );
    wmImage->SetDirection( m_DiffusionImage->GetVectorImage()->GetDirection() );
    wmImage->SetLargestPossibleRegion( m_DiffusionImage->GetVectorImage()->GetLargestPossibleRegion() );
    wmImage->SetBufferedRegion( wmImage->GetLargestPossibleRegion() );
    wmImage->SetRequestedRegion( wmImage->GetLargestPossibleRegion() );
    wmImage->Allocate();

    itk::ImageRegionIterator<FloatImageType> ot(wmImage, wmImage->GetLargestPossibleRegion() );
    while (!ot.IsAtEnd())
    {
        ot.Set(1);
        ++ot;
    }

    /* init TractographyFilter */
    TrackingFilterType::Pointer trackingFilter = TrackingFilterType::New();
    trackingFilter->SetPrimaryInput(m_DiffusionImage->GetVectorImage().GetPointer());
    trackingFilter->SetbValues(vecCont);
    trackingFilter->SetGradients(Pdir);
    trackingFilter->SetMeasurementFrame(measurement_frame);
    trackingFilter->SetWhiteMatterProbabilityImage(wmImage);
    trackingFilter->SetTotalTracts(m_Controls->m_SeedsPerVoxelSlider->value());
    trackingFilter->SetMaxLikelihoodCacheSize(m_Controls->m_MaxCacheSizeSlider->value()*1000);
    trackingFilter->SetMaxTractLength(m_Controls->m_MaxTractLengthSlider->value());

    //itk::Image< char, 3 >
    mitk::ImageToItk< itk::Image< unsigned char, 3 > >::Pointer binaryImageToItk1 = mitk::ImageToItk< itk::Image< unsigned char, 3 > >::New();
    binaryImageToItk1->SetInput( m_SeedRoi );
    binaryImageToItk1->Update();

    vtkSmartPointer<vtkPoints> vPoints = vtkSmartPointer<vtkPoints>::New();
    vtkSmartPointer<vtkCellArray> vCellArray = vtkSmartPointer<vtkCellArray>::New();

    itk::ImageRegionConstIterator< BinaryImageType > it(binaryImageToItk1->GetOutput(), binaryImageToItk1->GetOutput()->GetRequestedRegion());
    it.GoToBegin();
    mitk::Geometry3D* geom = m_DiffusionImage->GetGeometry();

    while(!it.IsAtEnd())
    {
        itk::ImageConstIterator<BinaryImageType>::PixelType tmpPxValue = it.Get();

        if(tmpPxValue != 0){
            mitk::Point3D point;
            itk::ImageRegionConstIterator< BinaryImageType >::IndexType seedIdx = it.GetIndex();
            trackingFilter->SetSeedIndex(seedIdx);
            trackingFilter->Update();

            /* get results from Filter */
            /* write each single tract into member container */
            TrackingFilterType::TractContainerType::Pointer container_tmp = trackingFilter->GetOutputTractContainer();
            TrackingFilterType::TractContainerType::Iterator elIt = container_tmp->Begin();
            TrackingFilterType::TractContainerType::Iterator end = container_tmp->End();
            bool addTract = true;

            while( elIt != end ){
                TrackingFilterType::TractContainerType::Element tract = elIt.Value();
                TrackingFilterType::TractContainerType::Element::ObjectType::VertexListType::ConstPointer vertexlist = tract->GetVertexList();

                vtkSmartPointer<vtkPolyLine> vPolyLine = vtkSmartPointer<vtkPolyLine>::New();
                for( int j=0; j<(int)vertexlist->Size(); j++)
                {
                    TrackingFilterType::TractContainerType::Element::ObjectType::VertexListType::Element vertex = vertexlist->GetElement(j);
                    mitk::Point3D index;
                    index[0] = (float)vertex[0];
                    index[1] = (float)vertex[1];
                    index[2] = (float)vertex[2];

                    if (geom->IsIndexInside(index))
                    {
                        geom->IndexToWorld(index, point);
                        vtkIdType id = vPoints->InsertNextPoint(point.GetDataPointer());
                        vPolyLine->GetPointIds()->InsertNextId(id);
                    }
                    else
                    {
                        addTract = false;
                        break;
                    }
                }

                if (addTract)
                    vCellArray->InsertNextCell(vPolyLine);

                ++elIt;
            }
        }
        ++it;
    }

    vtkSmartPointer<vtkPolyData> fiberPolyData = vtkSmartPointer<vtkPolyData>::New();
    fiberPolyData->SetPoints(vPoints);
    fiberPolyData->SetLines(vCellArray);

    mitk::FiberBundleX::Pointer fib = mitk::FiberBundleX::New(fiberPolyData);
    mitk::DataNode::Pointer fbNode = mitk::DataNode::New();
    fbNode->SetData(fib);
    QString name("FiberBundle_");
    name += m_DiffusionImageNode->GetName().c_str();
    name += "_Probabilistic";
    fbNode->SetName(name.toStdString());
    fbNode->SetVisibility(true);
    GetDataStorage()->Add(fbNode, m_DiffusionImageNode);
}

<|endoftext|>


<commit_before>// Harshad Kasture, Jason Miller, Chris Celio, Charles Gruenwald,
// Nathan Beckmann, George Kurian, David Wentzlaff, James Psota
// 10.12.08
//
// Carbon Computer Simulator
//
// This simulator models future multi-core computers with thousands of cores.
// It runs on today's x86 multicores and will scale as more and more cores
// and better inter-core communications mechanisms become available.
// The simulator provides a platform for research in processor architecture,
// compilers, network interconnect topologies, and some OS.
//
// The simulator runs on top of Intel's Pin dynamic binary instrumention engine.
// Application code in the absence of instrumentation runs more or less
// natively and is thus high performance. When instrumentation is used, models
// can be hot-swapped or dynamically enabled and disabled as desired so that
// performance tracks the level of simulation detail needed.

#include <iostream>
#include <assert.h>
#include <set>
#include <sys/syscall.h>
#include <unistd.h>

#include "pin.H"
#include "log.h"
#include "routine_replace.h"

// FIXME: This list could probably be trimmed down a lot.
#include "simulator.h"
#include "core_manager.h"
#include "config.h"
#include "core.h"
#include "syscall_model.h"
#include "thread_manager.h"
#include "config_file.hpp"
#include "handle_args.h"
#include "thread_start.h"
#include "pin_config.h"
#include "log.h"
#include "vm_manager.h"
#include "instruction_modeling.h"
#include "progress_trace.h"
#include "clock_skew_minimization.h"

#include "redirect_memory.h"
#include "handle_syscalls.h"
#include "opcodes.h"
#include <typeinfo>

// lite directories
#include "lite/routine_replace.h"
#include "lite/memory_modeling.h"

// ---------------------------------------------------------------
// FIXME:
// There should be a better place to keep these globals
// -- a PinSimulator class or smthg
bool done_app_initialization = false;
config::ConfigFile *cfg;

// clone stuff
extern int *parent_tidptr;
#ifdef TARGET_IA32
extern struct user_desc *newtls;
#endif
extern int *child_tidptr;

extern PIN_LOCK clone_memory_update_lock;
// ---------------------------------------------------------------

map <ADDRINT, string> rtn_map;
PIN_LOCK rtn_map_lock;

void printRtn (ADDRINT rtn_addr, bool enter)
{
   GetLock (&rtn_map_lock, 1);
   map<ADDRINT, string>::iterator it = rtn_map.find (rtn_addr);

   string point = enter ? "Enter" : "Exit";
   if (it != rtn_map.end())
   {
      LOG_PRINT ("Stack trace : %s %s", point.c_str(), (it->second).c_str());
   }
   else
   {
      LOG_PRINT ("Stack trace : %s UNKNOWN", point.c_str());
   }

   ReleaseLock (&rtn_map_lock);
}

VOID printInsInfo(CONTEXT* ctxt)
{
   __attribute(__unused__) ADDRINT reg_inst_ptr = PIN_GetContextReg(ctxt, REG_INST_PTR);
   __attribute(__unused__) ADDRINT reg_stack_ptr = PIN_GetContextReg(ctxt, REG_STACK_PTR);

   LOG_PRINT("eip = %#llx, esp = %#llx", reg_inst_ptr, reg_stack_ptr);
}

void initializeSyscallModeling ()
{
   InitLock (&clone_memory_update_lock);
}

void routineCallback(RTN rtn, void *v)
{
   string rtn_name = RTN_Name(rtn);

   replaceUserAPIFunction(rtn, rtn_name);

   // ---------------------------------------------------------------

   std::string module = Log::getSingleton()->getModule(__FILE__);
   if (Log::getSingleton()->isEnabled(module.c_str()) &&
       Sim()->getCfg()->getBool("log/stack_trace",false))
   {
      RTN_Open (rtn);

      ADDRINT rtn_addr = RTN_Address (rtn);

      GetLock (&rtn_map_lock, 1);

      rtn_map.insert (make_pair (rtn_addr, rtn_name));

      ReleaseLock (&rtn_map_lock);

      RTN_InsertCall (rtn, IPOINT_BEFORE,
                      AFUNPTR (printRtn),
                      IARG_ADDRINT, rtn_addr,
                      IARG_BOOL, true,
                      IARG_END);

      RTN_InsertCall (rtn, IPOINT_AFTER,
                      AFUNPTR (printRtn),
                      IARG_ADDRINT, rtn_addr,
                      IARG_BOOL, false,
                      IARG_END);

      RTN_Close (rtn);
   }

   // ---------------------------------------------------------------

   if (rtn_name == "CarbonSpawnThreadSpawner")
   {
      RTN_Open (rtn);

      RTN_InsertCall (rtn, IPOINT_BEFORE,
            AFUNPTR (setupCarbonSpawnThreadSpawnerStack),
            IARG_CONTEXT,
            IARG_END);

      RTN_Close (rtn);
   }

   else if (rtn_name == "CarbonThreadSpawner")
   {
      RTN_Open (rtn);

      RTN_InsertCall (rtn, IPOINT_BEFORE,
            AFUNPTR (setupCarbonThreadSpawnerStack),
            IARG_CONTEXT,
            IARG_END);

      RTN_Close(rtn);
   }
}

void showInstructionInfo(INS ins)
{
   if (Sim()->getCoreManager()->getCurrentCore()->getId() != 0)
      return;
   printf("\t");
   if (INS_IsMemoryRead(ins) || INS_IsMemoryWrite(ins))
      printf("* ");
   else
      printf("  ");
//   printf("%d - %s ", INS_Category(ins), CATEGORY_StringShort(INS_Category(ins)).c_str());
   printf("%x - %s ", INS_Opcode(ins), OPCODE_StringShort(INS_Opcode(ins)).c_str());
   printf(" %s ", INS_Disassemble(ins).c_str());
   printf("\n");
}

VOID instructionCallback (INS ins, void *v)
{
   // Debugging Functions
   // showInstructionInfo(ins);
   if (Log::getSingleton()->isLoggingEnabled())
   {
      INS_InsertCall(ins, IPOINT_BEFORE,
            AFUNPTR(printInsInfo),
            IARG_CALL_ORDER, CALL_ORDER_FIRST,
            IARG_CONTEXT,
            IARG_END);
   }

   // Core Performance Modeling
   if (Config::getSingleton()->getEnablePerformanceModeling())
      addInstructionModeling(ins);

   // Progress Trace
   addProgressTrace(ins);
   // Clock Skew Minimization
   addPeriodicSync(ins);

   if (Sim()->getConfig()->getSimulationMode() == Config::FULL)
   {
      // Special handling for futex syscall because of internal Pin lock
      if (INS_IsSyscall(ins))
      {
         INS_InsertCall(ins, IPOINT_BEFORE,
               AFUNPTR(handleFutexSyscall),
               IARG_CONTEXT,
               IARG_END);
      }

      // Emulate(/Rewrite) String, Stack and Memory Operations
      if (rewriteStringOp (ins));
      else if (rewriteStackOp (ins));
      else rewriteMemOp (ins);
   }
   else // Sim()->getConfig()->getSimulationMode() == Config::LITE
   {
      // Instrument Memory Operations
      lite::addMemoryModeling(ins);
   }
}

// syscall model wrappers

void SyscallEntry(THREADID threadIndex, CONTEXT *ctxt, SYSCALL_STANDARD std, void *v)
{
   syscallEnterRunModel (ctxt, std);
}

void SyscallExit(THREADID threadIndex, CONTEXT *ctxt, SYSCALL_STANDARD std, void *v)
{
   syscallExitRunModel (ctxt, std);
}

void ApplicationStart()
{
}

void ApplicationExit(int, void*)
{
   LOG_PRINT("Application exit.");
   Simulator::release();
   shutdownProgressTrace();
   delete cfg;
}

VOID threadStartCallback(THREADID threadIndex, CONTEXT *ctxt, INT32 flags, VOID *v)
{
   threadStartProgressTrace();

   // Conditions under which we must initialize a core
   // 1) (!done_app_initialization) && (curr_process_num == 0)
   // 2) (done_app_initialization) && (!thread_spawner)

   if (! done_app_initialization)
   {
      UInt32 curr_process_num = Sim()->getConfig()->getCurrentProcessNum();

      if (Sim()->getConfig()->getSimulationMode() == Config::LITE)
      {
         LOG_ASSERT_ERROR(curr_process_num == 0, "Lite mode can only be run with 1 process");
         Sim()->getCoreManager()->initializeThread(0);
      }
      else // Sim()->getConfig()->getSimulationMode() == Config::FULL
      {
         ADDRINT reg_esp = PIN_GetContextReg(ctxt, REG_STACK_PTR);
         allocateStackSpace();

         if (curr_process_num == 0)
         {
            Sim()->getCoreManager()->initializeThread(0);

            ADDRINT reg_eip = PIN_GetContextReg(ctxt, REG_INST_PTR);
            // 1) Copying over Static Data
            // Get the image first
            PIN_LockClient();
            IMG img = IMG_FindByAddress(reg_eip);
            PIN_UnlockClient();

            LOG_PRINT("Process: 0, Start Copying Static Data");
            copyStaticData(img);
            LOG_PRINT("Process: 0, Finished Copying Static Data");

            // 2) Copying over initial stack data
            LOG_PRINT("Process: 0, Start Copying Initial Stack Data");
            copyInitialStackData(reg_esp, 0);
            LOG_PRINT("Process: 0, Finished Copying Initial Stack Data");
         }
         else
         {
            core_id_t core_id = Sim()->getConfig()->getCurrentThreadSpawnerCoreNum();
            Sim()->getCoreManager()->initializeThread(core_id);

            Core *core = Sim()->getCoreManager()->getCurrentCore();

            // main thread clock is not affected by start-up time of other processes
            core->getNetwork()->netRecv (0, SYSTEM_INITIALIZATION_NOTIFY);

            LOG_PRINT("Process: %i, Start Copying Initial Stack Data");
            copyInitialStackData(reg_esp, core_id);
            LOG_PRINT("Process: %i, Finished Copying Initial Stack Data");
         }

         // Set the current ESP accordingly
         PIN_SetContextReg(ctxt, REG_STACK_PTR, reg_esp);
      }

      // All the real initialization is done in
      // replacement_start at the moment
      done_app_initialization = true;
   }
   else
   {
      // This is NOT the main thread
      // 'application' thread or 'thread spawner'

      if (Sim()->getConfig()->getSimulationMode() == Config::LITE)
      {
         ThreadSpawnRequest req;
         Sim()->getThreadManager()->getThreadToSpawn(&req);
         Sim()->getThreadManager()->dequeueThreadSpawnReq(&req);

         LOG_ASSERT_ERROR(req.core_id < SInt32(Config::getSingleton()->getApplicationCores()),
               "req.core_id(%i), num application cores(%u)", req.core_id, Config::getSingleton()->getApplicationCores());
         Sim()->getThreadManager()->onThreadStart(&req);
      }
      else // Sim()->getConfig()->getSimulationMode() == Config::FULL
      {
         ADDRINT reg_esp = PIN_GetContextReg(ctxt, REG_STACK_PTR);
         core_id_t core_id = PinConfig::getSingleton()->getCoreIDFromStackPtr(reg_esp);

         LOG_ASSERT_ERROR(core_id != -1, "All application threads and thread spawner are cores now");

         if (core_id == Sim()->getConfig()->getCurrentThreadSpawnerCoreNum())
         {
            // 'Thread Spawner' thread
            Sim()->getCoreManager()->initializeThread(core_id);
         }
         else
         {
            // 'Application' thread
            ThreadSpawnRequest* req = Sim()->getThreadManager()->getThreadSpawnReq();

            LOG_ASSERT_ERROR (req != NULL, "ThreadSpawnRequest is NULL !!");

            // This is an application thread
            LOG_ASSERT_ERROR(core_id == req->core_id, "Got 2 different core_ids: req->core_id = %i, core_id = %i", req->core_id, core_id);

            Sim()->getThreadManager()->onThreadStart(req);
         }

#ifdef TARGET_IA32
         // Restore the clone syscall arguments
         PIN_SetContextReg (ctxt, REG_GDX, (ADDRINT) parent_tidptr);
         PIN_SetContextReg (ctxt, REG_GSI, (ADDRINT) newtls);
         PIN_SetContextReg (ctxt, REG_GDI, (ADDRINT) child_tidptr);
#endif

#ifdef TARGET_X86_64
         // Restore the clone syscall arguments
         PIN_SetContextReg (ctxt, REG_GDX, (ADDRINT) parent_tidptr);
         PIN_SetContextReg (ctxt, LEVEL_BASE::REG_R10, (ADDRINT) child_tidptr);
#endif

         __attribute(__unused__) Core *core = Sim()->getCoreManager()->getCurrentCore();
         LOG_ASSERT_ERROR(core, "core(NULL)");

         // Wait to make sure that the spawner has written stuff back to memory
         // FIXME: What is this for(?) This seems arbitrary
         GetLock (&clone_memory_update_lock, 2);
         ReleaseLock (&clone_memory_update_lock);
      }
   }
}

VOID threadFiniCallback(THREADID threadIndex, const CONTEXT *ctxt, INT32 flags, VOID *v)
{
   Sim()->getThreadManager()->onThreadExit();
}

int main(int argc, char *argv[])
{
   // ---------------------------------------------------------------
   // FIXME:
   InitLock (&rtn_map_lock);
   // ---------------------------------------------------------------

   // Global initialization
   PIN_InitSymbols();
   PIN_Init(argc,argv);

   string_vec args;

   // Set the default config path if it isn't
   // overwritten on the command line.
   std::string config_path = "carbon_sim.cfg";

   parse_args(args, config_path, argc, argv);

   cfg = new config::ConfigFile();
   cfg->load(config_path);

   handle_args(args, *cfg);

   Simulator::setConfig(cfg);

   Simulator::allocate();
   Sim()->start();

   if (Sim()->getConfig()->getSimulationMode() == Config::FULL)
      PinConfig::allocate();

   // Instrumentation
   LOG_PRINT("Start of instrumentation.");

   if (Sim()->getConfig()->getSimulationMode() == Config::FULL)
      RTN_AddInstrumentFunction(routineCallback, 0);
   else // Sim()->getConfig()->getSimulationMode() == Config::LITE
      RTN_AddInstrumentFunction(lite::routineCallback, 0);

   PIN_AddThreadStartFunction (threadStartCallback, 0);
   PIN_AddThreadFiniFunction (threadFiniCallback, 0);

   if ((cfg->getBool("general/enable_syscall_modeling")) && \
         (Sim()->getConfig()->getSimulationMode() == Config::FULL))
   {
      initializeSyscallModeling();

      PIN_AddSyscallEntryFunction(SyscallEntry, 0);
      PIN_AddSyscallExitFunction(SyscallExit, 0);
      PIN_AddContextChangeFunction(contextChange, NULL);
   }

   INS_AddInstrumentFunction(instructionCallback, 0);

   initProgressTrace();

   PIN_AddFiniFunction(ApplicationExit, 0);

   // Just in case ... might not be strictly necessary
   Transport::getSingleton()->barrier();

   // Never returns
   LOG_PRINT("Running program...");
   PIN_StartProgram();

   return 0;
}
<commit_msg>[pin_sim] Some changes to pin/pin_sim.cc<commit_after>// Harshad Kasture, Jason Miller, Chris Celio, Charles Gruenwald,
// Nathan Beckmann, George Kurian, David Wentzlaff, James Psota
// 10.12.08
//
// Carbon Computer Simulator
//
// This simulator models future multi-core computers with thousands of cores.
// It runs on today's x86 multicores and will scale as more and more cores
// and better inter-core communications mechanisms become available.
// The simulator provides a platform for research in processor architecture,
// compilers, network interconnect topologies, and some OS.
//
// The simulator runs on top of Intel's Pin dynamic binary instrumention engine.
// Application code in the absence of instrumentation runs more or less
// natively and is thus high performance. When instrumentation is used, models
// can be hot-swapped or dynamically enabled and disabled as desired so that
// performance tracks the level of simulation detail needed.

#include <iostream>
#include <assert.h>
#include <set>
#include <sys/syscall.h>
#include <unistd.h>

#include "pin.H"
#include "log.h"
#include "routine_replace.h"

// FIXME: This list could probably be trimmed down a lot.
#include "simulator.h"
#include "core_manager.h"
#include "config.h"
#include "core.h"
#include "syscall_model.h"
#include "thread_manager.h"
#include "config_file.hpp"
#include "handle_args.h"
#include "thread_start.h"
#include "pin_config.h"
#include "log.h"
#include "vm_manager.h"
#include "instruction_modeling.h"
#include "progress_trace.h"
#include "clock_skew_minimization.h"

#include "redirect_memory.h"
#include "handle_syscalls.h"
#include "opcodes.h"
#include <typeinfo>

// lite directories
#include "lite/routine_replace.h"
#include "lite/memory_modeling.h"

// ---------------------------------------------------------------
// FIXME:
// There should be a better place to keep these globals
// -- a PinSimulator class or smthg
bool done_app_initialization = false;
config::ConfigFile *cfg;

// clone stuff
extern int *parent_tidptr;
#ifdef TARGET_IA32
extern struct user_desc *newtls;
#endif
extern int *child_tidptr;

extern PIN_LOCK clone_memory_update_lock;
// ---------------------------------------------------------------

map <ADDRINT, string> rtn_map;
PIN_LOCK rtn_map_lock;

void printRtn (ADDRINT rtn_addr, bool enter)
{
   GetLock (&rtn_map_lock, 1);
   map<ADDRINT, string>::iterator it = rtn_map.find (rtn_addr);

   string point = enter ? "Enter" : "Exit";
   if (it != rtn_map.end())
   {
      LOG_PRINT ("Stack trace : %s %s", point.c_str(), (it->second).c_str());
   }
   else
   {
      LOG_PRINT ("Stack trace : %s UNKNOWN", point.c_str());
   }

   ReleaseLock (&rtn_map_lock);
}

VOID printInsInfo(CONTEXT* ctxt)
{
   __attribute(__unused__) ADDRINT reg_inst_ptr = PIN_GetContextReg(ctxt, REG_INST_PTR);
   __attribute(__unused__) ADDRINT reg_stack_ptr = PIN_GetContextReg(ctxt, REG_STACK_PTR);

   LOG_PRINT("eip = %#llx, esp = %#llx", reg_inst_ptr, reg_stack_ptr);
}

void initializeSyscallModeling ()
{
   InitLock (&clone_memory_update_lock);
}

void routineCallback(RTN rtn, void *v)
{
   string rtn_name = RTN_Name(rtn);

   replaceUserAPIFunction(rtn, rtn_name);

   // ---------------------------------------------------------------

   std::string module = Log::getSingleton()->getModule(__FILE__);
   if (Log::getSingleton()->isEnabled(module.c_str()) &&
       Sim()->getCfg()->getBool("log/stack_trace",false))
   {
      RTN_Open (rtn);

      ADDRINT rtn_addr = RTN_Address (rtn);

      GetLock (&rtn_map_lock, 1);

      rtn_map.insert (make_pair (rtn_addr, rtn_name));

      ReleaseLock (&rtn_map_lock);

      RTN_InsertCall (rtn, IPOINT_BEFORE,
                      AFUNPTR (printRtn),
                      IARG_ADDRINT, rtn_addr,
                      IARG_BOOL, true,
                      IARG_END);

      RTN_InsertCall (rtn, IPOINT_AFTER,
                      AFUNPTR (printRtn),
                      IARG_ADDRINT, rtn_addr,
                      IARG_BOOL, false,
                      IARG_END);

      RTN_Close (rtn);
   }

   // ---------------------------------------------------------------

   if (rtn_name == "CarbonSpawnThreadSpawner")
   {
      RTN_Open (rtn);

      RTN_InsertCall (rtn, IPOINT_BEFORE,
            AFUNPTR (setupCarbonSpawnThreadSpawnerStack),
            IARG_CONTEXT,
            IARG_END);

      RTN_Close (rtn);
   }

   else if (rtn_name == "CarbonThreadSpawner")
   {
      RTN_Open (rtn);

      RTN_InsertCall (rtn, IPOINT_BEFORE,
            AFUNPTR (setupCarbonThreadSpawnerStack),
            IARG_CONTEXT,
            IARG_END);

      RTN_Close(rtn);
   }
}

void showInstructionInfo(INS ins)
{
   if (Sim()->getCoreManager()->getCurrentCore()->getId() != 0)
      return;
   printf("\t");
   if (INS_IsMemoryRead(ins) || INS_IsMemoryWrite(ins))
      printf("* ");
   else
      printf("  ");
//   printf("%d - %s ", INS_Category(ins), CATEGORY_StringShort(INS_Category(ins)).c_str());
   printf("%x - %s ", INS_Opcode(ins), OPCODE_StringShort(INS_Opcode(ins)).c_str());
   printf(" %s ", INS_Disassemble(ins).c_str());
   printf("\n");
}

VOID instructionCallback (INS ins, void *v)
{
   // Debugging Functions
   // showInstructionInfo(ins);
   if (Log::getSingleton()->isLoggingEnabled())
   {
      INS_InsertCall(ins, IPOINT_BEFORE,
            AFUNPTR(printInsInfo),
            IARG_CALL_ORDER, CALL_ORDER_FIRST,
            IARG_CONTEXT,
            IARG_END);
   }

   // Core Performance Modeling
   if (Config::getSingleton()->getEnablePerformanceModeling())
      addInstructionModeling(ins);

   // Progress Trace
   addProgressTrace(ins);
   // Clock Skew Minimization
   addPeriodicSync(ins);

   if (Sim()->getConfig()->getSimulationMode() == Config::FULL)
   {
      // Special handling for futex syscall because of internal Pin lock
      if (INS_IsSyscall(ins))
      {
         INS_InsertCall(ins, IPOINT_BEFORE,
               AFUNPTR(handleFutexSyscall),
               IARG_CONTEXT,
               IARG_END);
      }

      // Emulate(/Rewrite) String, Stack and Memory Operations
      if (rewriteStringOp (ins));
      else if (rewriteStackOp (ins));
      else rewriteMemOp (ins);
   }
   else // Sim()->getConfig()->getSimulationMode() == Config::LITE
   {
      // Instrument Memory Operations
      lite::addMemoryModeling(ins);
   }
}

// syscall model wrappers

void SyscallEntry(THREADID threadIndex, CONTEXT *ctxt, SYSCALL_STANDARD std, void *v)
{
   syscallEnterRunModel (ctxt, std);
}

void SyscallExit(THREADID threadIndex, CONTEXT *ctxt, SYSCALL_STANDARD std, void *v)
{
   syscallExitRunModel (ctxt, std);
}

void ApplicationStart()
{
}

void ApplicationExit(int, void*)
{
   LOG_PRINT("Application exit.");
   Simulator::release();
   shutdownProgressTrace();
   delete cfg;
}

VOID threadStartCallback(THREADID threadIndex, CONTEXT *ctxt, INT32 flags, VOID *v)
{
   threadStartProgressTrace();

   // Conditions under which we must initialize a core
   // 1) (!done_app_initialization) && (curr_process_num == 0)
   // 2) (done_app_initialization) && (!thread_spawner)

   if (! done_app_initialization)
   {
      UInt32 curr_process_num = Sim()->getConfig()->getCurrentProcessNum();

      if (Sim()->getConfig()->getSimulationMode() == Config::LITE)
      {
         LOG_ASSERT_ERROR(curr_process_num == 0, "Lite mode can only be run with 1 process");
         Sim()->getCoreManager()->initializeThread(0);
      }
      else // Sim()->getConfig()->getSimulationMode() == Config::FULL
      {
         ADDRINT reg_esp = PIN_GetContextReg(ctxt, REG_STACK_PTR);
         allocateStackSpace();

         if (curr_process_num == 0)
         {
            Sim()->getCoreManager()->initializeThread(0);

            ADDRINT reg_eip = PIN_GetContextReg(ctxt, REG_INST_PTR);
            // 1) Copying over Static Data
            // Get the image first
            PIN_LockClient();
            IMG img = IMG_FindByAddress(reg_eip);
            PIN_UnlockClient();

            LOG_PRINT("Process: 0, Start Copying Static Data");
            copyStaticData(img);
            LOG_PRINT("Process: 0, Finished Copying Static Data");

            // 2) Copying over initial stack data
            LOG_PRINT("Process: 0, Start Copying Initial Stack Data");
            copyInitialStackData(reg_esp, 0);
            LOG_PRINT("Process: 0, Finished Copying Initial Stack Data");
         }
         else
         {
            core_id_t core_id = Sim()->getConfig()->getCurrentThreadSpawnerCoreNum();
            Sim()->getCoreManager()->initializeThread(core_id);

            Core *core = Sim()->getCoreManager()->getCurrentCore();

            // main thread clock is not affected by start-up time of other processes
            core->getNetwork()->netRecv (0, SYSTEM_INITIALIZATION_NOTIFY);

            LOG_PRINT("Process: %i, Start Copying Initial Stack Data");
            copyInitialStackData(reg_esp, core_id);
            LOG_PRINT("Process: %i, Finished Copying Initial Stack Data");
         }

         // Set the current ESP accordingly
         PIN_SetContextReg(ctxt, REG_STACK_PTR, reg_esp);
      }

      // All the real initialization is done in
      // replacement_start at the moment
      done_app_initialization = true;
   }
   else
   {
      // This is NOT the main thread
      // 'application' thread or 'thread spawner'

      if (Sim()->getConfig()->getSimulationMode() == Config::LITE)
      {
         ThreadSpawnRequest req;
         Sim()->getThreadManager()->getThreadToSpawn(&req);
         Sim()->getThreadManager()->dequeueThreadSpawnReq(&req);

         LOG_ASSERT_ERROR(req.core_id < SInt32(Config::getSingleton()->getApplicationCores()),
               "req.core_id(%i), num application cores(%u)", req.core_id, Config::getSingleton()->getApplicationCores());
         Sim()->getThreadManager()->onThreadStart(&req);
      }
      else // Sim()->getConfig()->getSimulationMode() == Config::FULL
      {
         ADDRINT reg_esp = PIN_GetContextReg(ctxt, REG_STACK_PTR);
         core_id_t core_id = PinConfig::getSingleton()->getCoreIDFromStackPtr(reg_esp);

         LOG_ASSERT_ERROR(core_id != -1, "All application threads and thread spawner are cores now");

         if (core_id == Sim()->getConfig()->getCurrentThreadSpawnerCoreNum())
         {
            // 'Thread Spawner' thread
            Sim()->getCoreManager()->initializeThread(core_id);
         }
         else
         {
            // 'Application' thread
            ThreadSpawnRequest* req = Sim()->getThreadManager()->getThreadSpawnReq();

            LOG_ASSERT_ERROR (req != NULL, "ThreadSpawnRequest is NULL !!");

            // This is an application thread
            LOG_ASSERT_ERROR(core_id == req->core_id, "Got 2 different core_ids: req->core_id = %i, core_id = %i", req->core_id, core_id);

            Sim()->getThreadManager()->onThreadStart(req);
         }

#ifdef TARGET_IA32
         // Restore the clone syscall arguments
         PIN_SetContextReg (ctxt, REG_GDX, (ADDRINT) parent_tidptr);
         PIN_SetContextReg (ctxt, REG_GSI, (ADDRINT) newtls);
         PIN_SetContextReg (ctxt, REG_GDI, (ADDRINT) child_tidptr);
#endif

#ifdef TARGET_X86_64
         // Restore the clone syscall arguments
         PIN_SetContextReg (ctxt, REG_GDX, (ADDRINT) parent_tidptr);
         PIN_SetContextReg (ctxt, LEVEL_BASE::REG_R10, (ADDRINT) child_tidptr);
#endif

         __attribute(__unused__) Core *core = Sim()->getCoreManager()->getCurrentCore();
         LOG_ASSERT_ERROR(core, "core(NULL)");

         // Copy over thread stack data
         // copySpawnedThreadStackData(reg_esp);

         // Wait to make sure that the spawner has written stuff back to memory
         // FIXME: What is this for(?) This seems arbitrary
         GetLock (&clone_memory_update_lock, 2);
         ReleaseLock (&clone_memory_update_lock);
      }
   }
}

VOID threadFiniCallback(THREADID threadIndex, const CONTEXT *ctxt, INT32 flags, VOID *v)
{
   Sim()->getThreadManager()->onThreadExit();
}

int main(int argc, char *argv[])
{
   // ---------------------------------------------------------------
   // FIXME:
   InitLock (&rtn_map_lock);
   // ---------------------------------------------------------------

   // Global initialization
   PIN_InitSymbols();
   PIN_Init(argc,argv);

   string_vec args;

   // Set the default config path if it isn't
   // overwritten on the command line.
   std::string config_path = "carbon_sim.cfg";

   parse_args(args, config_path, argc, argv);

   cfg = new config::ConfigFile();
   cfg->load(config_path);

   handle_args(args, *cfg);

   Simulator::setConfig(cfg);

   Simulator::allocate();
   Sim()->start();

   if (Sim()->getConfig()->getSimulationMode() == Config::FULL)
      PinConfig::allocate();

   // Instrumentation
   LOG_PRINT("Start of instrumentation.");

   if (Sim()->getConfig()->getSimulationMode() == Config::FULL)
      RTN_AddInstrumentFunction(routineCallback, 0);
   else // Sim()->getConfig()->getSimulationMode() == Config::LITE
      RTN_AddInstrumentFunction(lite::routineCallback, 0);

   PIN_AddThreadStartFunction (threadStartCallback, 0);
   PIN_AddThreadFiniFunction (threadFiniCallback, 0);

   if ((cfg->getBool("general/enable_syscall_modeling")) && \
         (Sim()->getConfig()->getSimulationMode() == Config::FULL))
   {
      initializeSyscallModeling();

      PIN_AddSyscallEntryFunction(SyscallEntry, 0);
      PIN_AddSyscallExitFunction(SyscallExit, 0);
      PIN_AddContextChangeFunction(contextChange, NULL);
   }

   INS_AddInstrumentFunction(instructionCallback, 0);

   initProgressTrace();

   PIN_AddFiniFunction(ApplicationExit, 0);

   // Just in case ... might not be strictly necessary
   Transport::getSingleton()->barrier();

   // Never returns
   LOG_PRINT("Running program...");
   PIN_StartProgram();

   return 0;
}
<|endoftext|>


<commit_before>#ifndef __PML_FACTOR__
#define __PML_FACTOR__

#include <vector>

#include "prime.hpp"

inline uint64_t gdc(uint64_t a, uint64_t b)
{
    if (a < b)
        return gdc(b, a);

    uint64_t mod;
    while (b != 0)
    {
        mod = a % b;
        a = b;
        b = mod;
    }
    return a;
}

inline uint64_t lcm(uint64_t a, uint64_t b)
{
    if (a == 0 && b == 0)
        return 0;

    uint64_t num = a * b;
    return num / gdc(a, b);
}

inline uint64_t rho_f(uint64_t val)
{
    if (val == 0)
        return 1;

    uint64_t x_fixed = 2;
    uint64_t x = 2;
    uint64_t cycles = 2;
    uint64_t factor = 1;

    while (factor == 1)
    {
        for (unsigned i = 0; i < cycles && factor <= 1; i++)
        {
            x = (x * x + 1) % val;
            factor = gdc(x - x_fixed, val);
        }

        cycles *= 2;
        x_fixed = x;
    }

    return factor;
}

inline std::vector<uint64_t> rho(uint64_t val)
{
    std::vector<uint64_t> factors;

    if (val == 0)
        return factors;

    const uint64_t MAX_REDUCE = 100000;
    std::vector<uint64_t> primes;

    uint64_t fac;
    std::vector<uint64_t> tmp_factor;
    while (val != 1)
    {
        fac = rho_f(val);
        if (fac != 1) {
            if (fac < MAX_REDUCE) {
                if (primes.size() == 0)
                    primes = prime_sieve(MAX_REDUCE);
                tmp_factor = factorize(fac, primes);
            } else {
                if (fac == val)
                    tmp_factor = {fac};
                else
                    factors.push_back(fac);
            }
            factors.insert(factors.begin(), tmp_factor.begin(),
                                            tmp_factor.end());
            val /= fac;
        } else {
            break;
        }
    }

    return factors;
}

inline std::vector<uint64_t> quick_factorize(uint64_t val)
{
    std::vector<uint64_t> factors;
    if (val == 0)
        return factors;

    while ((val & 0x01) == 0)
    {
        val >>= 1;
        factors.push_back(2);
    }

    std::vector<uint64_t> other_factors = rho(val);
    factors.insert(factors.end(), other_factors.begin(),
                                  other_factors.end());

    uint64_t mul = 1;
    for (uint64_t u : factors)
        mul *= u;

    if (mul != val) {
        other_factors = factorize(val / mul);
        factors.insert(factors.end(), other_factors.begin(),
                                      other_factors.end());
    }

    std::sort(factors.begin(), factors.end());

    return factors;
}

#endif
<commit_msg>improved speed of rho function<commit_after>#ifndef __PML_FACTOR__
#define __PML_FACTOR__

#include <vector>

#include "prime.hpp"

inline uint64_t gdc(uint64_t a, uint64_t b)
{
    if (a < b)
        return gdc(b, a);

    uint64_t mod;
    while (b != 0)
    {
        mod = a % b;
        a = b;
        b = mod;
    }
    return a;
}

inline uint64_t lcm(uint64_t a, uint64_t b)
{
    if (a == 0 && b == 0)
        return 0;

    uint64_t num = a * b;
    return num / gdc(a, b);
}

inline uint64_t rho_f(uint64_t val)
{
    if (val == 0)
        return 1;

    uint64_t x_fixed = 2;
    uint64_t x = 2;
    uint64_t cycles = 2;
    uint64_t factor = 1;

    while (factor == 1)
    {
        for (unsigned i = 0; i < cycles && factor <= 1; i++)
        {
            x = (x * x + 1) % val;
            factor = gdc(x - x_fixed, val);
        }

        cycles *= 2;
        x_fixed = x;
    }

    return factor;
}

inline std::vector<uint64_t> rho(uint64_t val)
{
    std::vector<uint64_t> factors;

    if (val == 0)
        return factors;

    uint64_t fac;
    std::vector<uint64_t> tmp_factor;
    while (val != 1)
    {
        fac = rho_f(val);
        if (fac != 1) {
            if (fac == val)
                tmp_factor = {fac};
            else
                factors.push_back(fac);
            factors.insert(factors.begin(), tmp_factor.begin(),
                                            tmp_factor.end());
            val /= fac;
        } else {
            break;
        }
    }

    return factors;
}

inline std::vector<uint64_t> quick_factorize(uint64_t val)
{
    std::vector<uint64_t> factors;
    if (val == 0)
        return factors;

    while ((val & 0x01) == 0)
    {
        val >>= 1;
        factors.push_back(2);
    }

    std::vector<uint64_t> other_factors = rho(val);
    factors.insert(factors.end(), other_factors.begin(),
                                  other_factors.end());

    uint64_t mul = 1;
    for (uint64_t u : factors)
        mul *= u;

    if (mul != val) {
        other_factors = factorize(val / mul);
        factors.insert(factors.end(), other_factors.begin(),
                                      other_factors.end());
    }

    std::sort(factors.begin(), factors.end());

    return factors;
}

#endif
<|endoftext|>