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

#define LCB_NO_DEPR_CXX_CTORS

#include "config.h"
#include <sys/types.h>
#include <libcouchbase/couchbase.h>
#include <libcouchbase/api3.h>
#include <libcouchbase/n1ql.h>
#include <libcouchbase/vbucket.h>
#include <iostream>
#include <list>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cerrno>
#include <fstream>
#include <algorithm> // random_shuffle
#include <stdexcept>
#include <sstream>
#ifndef WIN32
#include <pthread.h>
#include <unistd.h> // isatty()
#endif
#include "common/options.h"
#include "common/histogram.h"

using namespace cbc;
using namespace cliopts;
using std::vector;
using std::string;
using std::cerr;
using std::endl;

#ifndef _WIN32
static bool use_ansi_codes = true;
#else
static bool use_ansi_codes = false;
#endif

static void do_or_die(lcb_error_t rc)
{
    if (rc != LCB_SUCCESS) {
        std::stringstream ss;
        ss << "[" << std::hex << rc << "] " << lcb_strerror(NULL, rc);
        throw std::runtime_error(ss.str());
    }
}

class Metrics {
public:
    Metrics()
    : n_rows(0), n_queries(0), n_errors(0), last_update(time(NULL)), hg(NULL)
    {
        #ifndef _WIN32
        if (pthread_mutex_init(&m_lock, NULL) != 0) {
            abort();
        }
        #endif
        start_time = last_update;
    }

    size_t nerrors() { return n_errors; }

    void update_row(size_t n = 1) { n_rows += n; update_display(); }
    void update_done(size_t n = 1) { n_queries += n; update_display(); }
    void update_error(size_t n = 1) { n_errors += n; update_display(); }

    void update_timings(lcb_U64 duration) {
        if (hg != NULL) {
            hg->record(duration);
        }
    }

#ifndef _WIN32
    bool is_tty() const { return isatty(STDOUT_FILENO); }
    void lock() { pthread_mutex_lock(&m_lock); }
    void unlock() { pthread_mutex_unlock(&m_lock); }
#else
    void lock(){}
    void unlock(){}
    bool is_tty() const { return false; }
#endif
    void prepare_screen()
    {
        if (is_tty() && use_ansi_codes) {
            printf("\n\n\n");
        }
    }

    void prepare_timings()
    {
        if (hg == NULL) {
            hg = new Histogram();
            hg->installStandalone(stdout);
        }
    }

private:
    void update_display()
    {
        time_t now = time(NULL);
        time_t duration = now - last_update;

        if (!duration) {
            return;
        }

        last_update = now;

        const char *prefix;
        const char *final_suffix;

        // Only use "ticker" style updates if we're a TTY and we have no
        // following timings.
        if (use_ansi_codes && is_tty() && hg == NULL) {
            // Move up 3 cursors
            printf("\x1B[2A");
            prefix = "\x1B[K";
            final_suffix = "\r";
        } else {
            // Determine the total number of time
            unsigned total_duration = now - start_time;
            printf("\n"); // Clear line..
            printf("+%us\n", total_duration);
            prefix = "";
            final_suffix = "\n";
        }

        printf("%sQUERIES/SEC: %lu\n", prefix, (unsigned long)(n_queries / duration));
        printf("%sROWS/SEC:    %lu\n", prefix, (unsigned long)(n_rows / duration));
        printf("%sERRORS:      %lu%s", prefix, (unsigned long)n_errors, final_suffix);

        if (hg != NULL) {
            hg->write();
        }
        fflush(stdout);

        n_queries = 0;
        n_rows = 0;
    }

    size_t n_rows;
    size_t n_queries;
    size_t n_errors;
    time_t last_update;
    time_t start_time;
    cbc::Histogram *hg;
#ifndef _WIN32
    pthread_mutex_t m_lock;
#endif
};

Metrics GlobalMetrics;

class Configuration
{
public:
    Configuration() : o_file("queryfile"), o_threads("num-threads"), o_errlog("error-log"), m_errlog(NULL) {
        o_file.mandatory(true);
        o_file.description(
            "Path to a file containing all the queries to execute. "
            "Each line should contain the full query body");
        o_file.abbrev('f');

        o_threads.description("Number of threads to run");
        o_threads.abbrev('t');
        o_threads.setDefault(1);

        o_errlog.description(
            "Path to a file containing failed queries");
        o_errlog.abbrev('e');
        o_errlog.setDefault("");
    }

    ~Configuration() {
        if (m_errlog != NULL) {
            delete m_errlog;
            m_errlog = NULL;
        }
    }
    void addToParser(Parser& parser)
    {
        parser.addOption(o_file);
        parser.addOption(o_threads);
        parser.addOption(o_errlog);
        m_params.addToParser(parser);
    }

    void processOptions()
    {
        std::ifstream ifs(o_file.const_result().c_str());
        if (!ifs.is_open()) {
            int ec_save = errno;
            string errstr(o_file.const_result());
            errstr += ": ";
            errstr += strerror(ec_save);
            throw std::runtime_error(errstr);
        }

        string curline;
        while (std::getline(ifs, curline).good() && !ifs.eof()) {
            if (!curline.empty()) {
                m_queries.push_back(curline);
            }
        }
        if (m_params.useTimings()) {
            GlobalMetrics.prepare_timings();
        }

        if (o_errlog.passed()) {
            m_errlog = new std::ofstream(o_errlog.const_result().c_str());
            if (!m_errlog->is_open()) {
                int ec_save = errno;
                string errstr(o_file.const_result());
                errstr += ": ";
                errstr += strerror(ec_save);
                throw std::runtime_error(errstr);
            }
        }
    }

    void set_cropts(lcb_create_st &opts) { m_params.fillCropts(opts); }
    const vector<string>& queries() const { return m_queries; }
    size_t nthreads() { return o_threads.result(); }
    std::ofstream* errlog() { return m_errlog; }

private:
    vector<string> m_queries;
    StringOption o_file;
    UIntOption o_threads;
    ConnParams m_params;
    StringOption o_errlog;
    std::ofstream *m_errlog;
};

extern "C" { static void n1qlcb(lcb_t, int, const lcb_RESPN1QL *resp); }
extern "C" { static void* pthrfunc(void*); }

class ThreadContext;
struct QueryContext {
    lcb_U64 begin;
    bool received; // whether any row was received
    ThreadContext *ctx; // Parent

    QueryContext(ThreadContext *tctx)
    : begin(lcb_nstime()), received(false), ctx(tctx) {}
};

class ThreadContext {
public:
    void run()
    {
        while (!m_cancelled) {
            vector<string>::const_iterator ii = m_queries.begin();
            for (; ii != m_queries.end(); ++ii) {
                run_one_query(*ii);
            }
        }
    }

#ifndef _WIN32
    void start()
    {
        assert(m_thr == NULL);
        m_thr = new pthread_t;
        int rc = pthread_create(m_thr, NULL, pthrfunc, this);
        if (rc != 0) {
            throw std::runtime_error(strerror(rc));
        }
    }

    void join()
    {
        assert(m_thr != NULL);
        void *arg = NULL;
        pthread_join(*m_thr, &arg);
    }

    ~ThreadContext()
    {
        if (m_thr != NULL) {
            join();
            delete m_thr;
            m_thr = NULL;
        }
    }
#else
    void start() { run(); }
    void join() {}
#endif

    void handle_response(const lcb_RESPN1QL *resp, QueryContext *ctx)
    {
        if (!ctx->received) {
            lcb_U64 duration = lcb_nstime() - ctx->begin;
            m_metrics->lock();
            m_metrics->update_timings(duration);
            m_metrics->unlock();

            ctx->received = true;
        }

        if (resp->rflags & LCB_RESP_F_FINAL) {
            if (resp->rc != LCB_SUCCESS) {
                if (m_errlog != NULL) {
                    std::stringstream ss;
                    ss.write(m_cmd.query, m_cmd.nquery);
                    ss << endl;
                    ss.write(resp->row, resp->nrow);
                    log_error(resp->rc, ss.str().c_str(), ss.str().size());
                } else {
                    log_error(resp->rc, NULL, 0);
                }
            }
        } else {
            last_nrow++;
        }
    }

    ThreadContext(lcb_t instance, const vector<string>& initial_queries, std::ofstream *errlog)
    : m_instance(instance), last_nerr(0), last_nrow(0),
      m_metrics(&GlobalMetrics), m_cancelled(false), m_thr(NULL),
      m_errlog(errlog)
    {
        memset(&m_cmd, 0, sizeof m_cmd);
        m_cmd.content_type = "application/json";
        m_cmd.callback = n1qlcb;

        // Shuffle the list
        m_queries = initial_queries;
        std::random_shuffle(m_queries.begin(), m_queries.end());
    }

private:

    void log_error(lcb_error_t err, const char* info, size_t ninfo)
    {
        size_t erridx;
        m_metrics->lock();
        m_metrics->update_error();
        erridx = m_metrics->nerrors();
        m_metrics->unlock();

        if (m_errlog != NULL) {
            std::stringstream ss;
            ss << "[" << erridx << "] 0x" << std::hex << err << ", "
               << lcb_strerror(NULL, err) << endl;
            if (ninfo) {
                ss.write(info, ninfo);
                ss << endl;
            }
            *m_errlog << ss.str();
            m_errlog->flush();
        }
    }

    void run_one_query(const string& txt)
    {
        // Reset counters
        last_nrow = 0;
        last_nerr = 0;

        m_cmd.query = txt.c_str();
        m_cmd.nquery = txt.size();

        // Set up our context
        QueryContext qctx(this);

        lcb_error_t rc = lcb_n1ql_query(m_instance, &qctx, &m_cmd);
        if (rc != LCB_SUCCESS) {
            log_error(rc, txt.c_str(), txt.size());
        } else {
            lcb_wait(m_instance);
            m_metrics->lock();
            m_metrics->update_row(last_nrow);
            m_metrics->update_done(1);
            m_metrics->unlock();
        }
    }

    lcb_t m_instance;
    vector<string> m_queries;
    size_t last_nerr;
    size_t last_nrow;
    lcb_CMDN1QL m_cmd;
    Metrics *m_metrics;
    volatile bool m_cancelled;
    #ifndef _WIN32
    pthread_t *m_thr;
    #else
    void *m_thr;
    #endif
    std::ofstream *m_errlog;
};

static void n1qlcb(lcb_t, int, const lcb_RESPN1QL *resp)
{
    QueryContext *qctx = reinterpret_cast<QueryContext*>(resp->cookie);
    qctx->ctx->handle_response(resp, qctx);
}

static void* pthrfunc(void *arg)
{
    reinterpret_cast<ThreadContext*>(arg)->run();
    return NULL;
}

static bool
instance_has_n1ql(lcb_t instance) {
    // Check that the instance supports N1QL
    lcbvb_CONFIG *vbc;
    do_or_die(lcb_cntl(instance, LCB_CNTL_GET, LCB_CNTL_VBCONFIG, &vbc));

    int sslmode = 0;
    lcbvb_SVCMODE svcmode = LCBVB_SVCMODE_PLAIN;

    do_or_die(lcb_cntl(instance, LCB_CNTL_GET, LCB_CNTL_SSL_MODE, &sslmode));

    if (sslmode & LCB_SSL_ENABLED) {
        svcmode = LCBVB_SVCMODE_SSL;
    }

    int hix = lcbvb_get_randhost(vbc, LCBVB_SVCTYPE_N1QL, svcmode);
    return hix > -1;
}

static void real_main(int argc, char **argv) {
    Configuration config;
    Parser parser;
    config.addToParser(parser);
    parser.parse(argc, argv);

    vector<ThreadContext*> threads;
    vector<lcb_t> instances;

    lcb_create_st cropts = { 0 };
    config.set_cropts(cropts);
    config.processOptions();

    for (size_t ii = 0; ii < config.nthreads(); ii++) {
        lcb_t instance;
        do_or_die(lcb_create(&instance, &cropts));
        do_or_die(lcb_connect(instance));
        lcb_wait(instance);
        do_or_die(lcb_get_bootstrap_status(instance));

        if (ii == 0 && !instance_has_n1ql(instance)) {
            throw std::runtime_error("Cluster does not support N1QL!");
        }

        ThreadContext* cx = new ThreadContext(instance, config.queries(), config.errlog());
        threads.push_back(cx);
        instances.push_back(instance);
    }

    GlobalMetrics.prepare_screen();

    for (size_t ii = 0; ii < threads.size(); ++ii) {
        threads[ii]->start();
    }
    for (size_t ii = 0; ii < threads.size(); ++ii) {
        threads[ii]->join();
    }
    for (size_t ii = 0; ii < instances.size(); ++ii) {
        lcb_destroy(instances[ii]);
    }
}

int main(int argc, char **argv)
{
    try {
        real_main(argc, argv);
        return 0;
    } catch (std::exception& exc) {
        cerr << exc.what() << endl;
        exit(EXIT_FAILURE);
    }
}
<commit_msg>CCBC-908: cbc-n1qlback: report number of loaded queries<commit_after>/*
 *     Copyright 2015 Couchbase, Inc.
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

#define LCB_NO_DEPR_CXX_CTORS

#include "config.h"
#include <sys/types.h>
#include <libcouchbase/couchbase.h>
#include <libcouchbase/api3.h>
#include <libcouchbase/n1ql.h>
#include <libcouchbase/vbucket.h>
#include <iostream>
#include <list>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cerrno>
#include <fstream>
#include <algorithm> // random_shuffle
#include <stdexcept>
#include <sstream>
#ifndef WIN32
#include <pthread.h>
#include <unistd.h> // isatty()
#endif
#include "common/options.h"
#include "common/histogram.h"

using namespace cbc;
using namespace cliopts;
using std::vector;
using std::string;
using std::cerr;
using std::endl;

#ifndef _WIN32
static bool use_ansi_codes = true;
#else
static bool use_ansi_codes = false;
#endif

static void do_or_die(lcb_error_t rc)
{
    if (rc != LCB_SUCCESS) {
        std::stringstream ss;
        ss << "[" << std::hex << rc << "] " << lcb_strerror(NULL, rc);
        throw std::runtime_error(ss.str());
    }
}

class Metrics {
public:
    Metrics()
    : n_rows(0), n_queries(0), n_errors(0), last_update(time(NULL)), hg(NULL)
    {
        #ifndef _WIN32
        if (pthread_mutex_init(&m_lock, NULL) != 0) {
            abort();
        }
        #endif
        start_time = last_update;
    }

    size_t nerrors() { return n_errors; }

    void update_row(size_t n = 1) { n_rows += n; update_display(); }
    void update_done(size_t n = 1) { n_queries += n; update_display(); }
    void update_error(size_t n = 1) { n_errors += n; update_display(); }

    void update_timings(lcb_U64 duration) {
        if (hg != NULL) {
            hg->record(duration);
        }
    }

#ifndef _WIN32
    bool is_tty() const { return isatty(STDOUT_FILENO); }
    void lock() { pthread_mutex_lock(&m_lock); }
    void unlock() { pthread_mutex_unlock(&m_lock); }
#else
    void lock(){}
    void unlock(){}
    bool is_tty() const { return false; }
#endif
    void prepare_screen()
    {
        if (is_tty() && use_ansi_codes) {
            printf("\n\n\n");
        }
    }

    void prepare_timings()
    {
        if (hg == NULL) {
            hg = new Histogram();
            hg->installStandalone(stdout);
        }
    }

private:
    void update_display()
    {
        time_t now = time(NULL);
        time_t duration = now - last_update;

        if (!duration) {
            return;
        }

        last_update = now;

        const char *prefix;
        const char *final_suffix;

        // Only use "ticker" style updates if we're a TTY and we have no
        // following timings.
        if (use_ansi_codes && is_tty() && hg == NULL) {
            // Move up 3 cursors
            printf("\x1B[2A");
            prefix = "\x1B[K";
            final_suffix = "\r";
        } else {
            // Determine the total number of time
            unsigned total_duration = now - start_time;
            printf("\n"); // Clear line..
            printf("+%us\n", total_duration);
            prefix = "";
            final_suffix = "\n";
        }

        printf("%sQUERIES/SEC: %lu\n", prefix, (unsigned long)(n_queries / duration));
        printf("%sROWS/SEC:    %lu\n", prefix, (unsigned long)(n_rows / duration));
        printf("%sERRORS:      %lu%s", prefix, (unsigned long)n_errors, final_suffix);

        if (hg != NULL) {
            hg->write();
        }
        fflush(stdout);

        n_queries = 0;
        n_rows = 0;
    }

    size_t n_rows;
    size_t n_queries;
    size_t n_errors;
    time_t last_update;
    time_t start_time;
    cbc::Histogram *hg;
#ifndef _WIN32
    pthread_mutex_t m_lock;
#endif
};

Metrics GlobalMetrics;

class Configuration
{
public:
    Configuration() : o_file("queryfile"), o_threads("num-threads"), o_errlog("error-log"), m_errlog(NULL) {
        o_file.mandatory(true);
        o_file.description(
            "Path to a file containing all the queries to execute. "
            "Each line should contain the full query body");
        o_file.abbrev('f');

        o_threads.description("Number of threads to run");
        o_threads.abbrev('t');
        o_threads.setDefault(1);

        o_errlog.description(
            "Path to a file containing failed queries");
        o_errlog.abbrev('e');
        o_errlog.setDefault("");
    }

    ~Configuration() {
        if (m_errlog != NULL) {
            delete m_errlog;
            m_errlog = NULL;
        }
    }
    void addToParser(Parser& parser)
    {
        parser.addOption(o_file);
        parser.addOption(o_threads);
        parser.addOption(o_errlog);
        m_params.addToParser(parser);
    }

    void processOptions()
    {
        std::ifstream ifs(o_file.const_result().c_str());
        if (!ifs.is_open()) {
            int ec_save = errno;
            string errstr(o_file.const_result());
            errstr += ": ";
            errstr += strerror(ec_save);
            throw std::runtime_error(errstr);
        }

        string curline;
        while (std::getline(ifs, curline).good() && !ifs.eof()) {
            if (!curline.empty()) {
                m_queries.push_back(curline);
            }
        }
        std::cerr << "Loaded " << m_queries.size() << " queries "
                  << "from \"" << o_file.const_result() << "\"" << std::endl;
        if (m_params.useTimings()) {
            GlobalMetrics.prepare_timings();
        }

        if (o_errlog.passed()) {
            m_errlog = new std::ofstream(o_errlog.const_result().c_str());
            if (!m_errlog->is_open()) {
                int ec_save = errno;
                string errstr(o_file.const_result());
                errstr += ": ";
                errstr += strerror(ec_save);
                throw std::runtime_error(errstr);
            }
        }
    }

    void set_cropts(lcb_create_st &opts) { m_params.fillCropts(opts); }
    const vector<string>& queries() const { return m_queries; }
    size_t nthreads() { return o_threads.result(); }
    std::ofstream* errlog() { return m_errlog; }

private:
    vector<string> m_queries;
    StringOption o_file;
    UIntOption o_threads;
    ConnParams m_params;
    StringOption o_errlog;
    std::ofstream *m_errlog;
};

extern "C" { static void n1qlcb(lcb_t, int, const lcb_RESPN1QL *resp); }
extern "C" { static void* pthrfunc(void*); }

class ThreadContext;
struct QueryContext {
    lcb_U64 begin;
    bool received; // whether any row was received
    ThreadContext *ctx; // Parent

    QueryContext(ThreadContext *tctx)
    : begin(lcb_nstime()), received(false), ctx(tctx) {}
};

class ThreadContext {
public:
    void run()
    {
        while (!m_cancelled) {
            vector<string>::const_iterator ii = m_queries.begin();
            for (; ii != m_queries.end(); ++ii) {
                run_one_query(*ii);
            }
        }
    }

#ifndef _WIN32
    void start()
    {
        assert(m_thr == NULL);
        m_thr = new pthread_t;
        int rc = pthread_create(m_thr, NULL, pthrfunc, this);
        if (rc != 0) {
            throw std::runtime_error(strerror(rc));
        }
    }

    void join()
    {
        assert(m_thr != NULL);
        void *arg = NULL;
        pthread_join(*m_thr, &arg);
    }

    ~ThreadContext()
    {
        if (m_thr != NULL) {
            join();
            delete m_thr;
            m_thr = NULL;
        }
    }
#else
    void start() { run(); }
    void join() {}
#endif

    void handle_response(const lcb_RESPN1QL *resp, QueryContext *ctx)
    {
        if (!ctx->received) {
            lcb_U64 duration = lcb_nstime() - ctx->begin;
            m_metrics->lock();
            m_metrics->update_timings(duration);
            m_metrics->unlock();

            ctx->received = true;
        }

        if (resp->rflags & LCB_RESP_F_FINAL) {
            if (resp->rc != LCB_SUCCESS) {
                if (m_errlog != NULL) {
                    std::stringstream ss;
                    ss.write(m_cmd.query, m_cmd.nquery);
                    ss << endl;
                    ss.write(resp->row, resp->nrow);
                    log_error(resp->rc, ss.str().c_str(), ss.str().size());
                } else {
                    log_error(resp->rc, NULL, 0);
                }
            }
        } else {
            last_nrow++;
        }
    }

    ThreadContext(lcb_t instance, const vector<string>& initial_queries, std::ofstream *errlog)
    : m_instance(instance), last_nerr(0), last_nrow(0),
      m_metrics(&GlobalMetrics), m_cancelled(false), m_thr(NULL),
      m_errlog(errlog)
    {
        memset(&m_cmd, 0, sizeof m_cmd);
        m_cmd.content_type = "application/json";
        m_cmd.callback = n1qlcb;

        // Shuffle the list
        m_queries = initial_queries;
        std::random_shuffle(m_queries.begin(), m_queries.end());
    }

private:

    void log_error(lcb_error_t err, const char* info, size_t ninfo)
    {
        size_t erridx;
        m_metrics->lock();
        m_metrics->update_error();
        erridx = m_metrics->nerrors();
        m_metrics->unlock();

        if (m_errlog != NULL) {
            std::stringstream ss;
            ss << "[" << erridx << "] 0x" << std::hex << err << ", "
               << lcb_strerror(NULL, err) << endl;
            if (ninfo) {
                ss.write(info, ninfo);
                ss << endl;
            }
            *m_errlog << ss.str();
            m_errlog->flush();
        }
    }

    void run_one_query(const string& txt)
    {
        // Reset counters
        last_nrow = 0;
        last_nerr = 0;

        m_cmd.query = txt.c_str();
        m_cmd.nquery = txt.size();

        // Set up our context
        QueryContext qctx(this);

        lcb_error_t rc = lcb_n1ql_query(m_instance, &qctx, &m_cmd);
        if (rc != LCB_SUCCESS) {
            log_error(rc, txt.c_str(), txt.size());
        } else {
            lcb_wait(m_instance);
            m_metrics->lock();
            m_metrics->update_row(last_nrow);
            m_metrics->update_done(1);
            m_metrics->unlock();
        }
    }

    lcb_t m_instance;
    vector<string> m_queries;
    size_t last_nerr;
    size_t last_nrow;
    lcb_CMDN1QL m_cmd;
    Metrics *m_metrics;
    volatile bool m_cancelled;
    #ifndef _WIN32
    pthread_t *m_thr;
    #else
    void *m_thr;
    #endif
    std::ofstream *m_errlog;
};

static void n1qlcb(lcb_t, int, const lcb_RESPN1QL *resp)
{
    QueryContext *qctx = reinterpret_cast<QueryContext*>(resp->cookie);
    qctx->ctx->handle_response(resp, qctx);
}

static void* pthrfunc(void *arg)
{
    reinterpret_cast<ThreadContext*>(arg)->run();
    return NULL;
}

static bool
instance_has_n1ql(lcb_t instance) {
    // Check that the instance supports N1QL
    lcbvb_CONFIG *vbc;
    do_or_die(lcb_cntl(instance, LCB_CNTL_GET, LCB_CNTL_VBCONFIG, &vbc));

    int sslmode = 0;
    lcbvb_SVCMODE svcmode = LCBVB_SVCMODE_PLAIN;

    do_or_die(lcb_cntl(instance, LCB_CNTL_GET, LCB_CNTL_SSL_MODE, &sslmode));

    if (sslmode & LCB_SSL_ENABLED) {
        svcmode = LCBVB_SVCMODE_SSL;
    }

    int hix = lcbvb_get_randhost(vbc, LCBVB_SVCTYPE_N1QL, svcmode);
    return hix > -1;
}

static void real_main(int argc, char **argv) {
    Configuration config;
    Parser parser;
    config.addToParser(parser);
    parser.parse(argc, argv);

    vector<ThreadContext*> threads;
    vector<lcb_t> instances;

    lcb_create_st cropts = { 0 };
    config.set_cropts(cropts);
    config.processOptions();

    for (size_t ii = 0; ii < config.nthreads(); ii++) {
        lcb_t instance;
        do_or_die(lcb_create(&instance, &cropts));
        do_or_die(lcb_connect(instance));
        lcb_wait(instance);
        do_or_die(lcb_get_bootstrap_status(instance));

        if (ii == 0 && !instance_has_n1ql(instance)) {
            throw std::runtime_error("Cluster does not support N1QL!");
        }

        ThreadContext* cx = new ThreadContext(instance, config.queries(), config.errlog());
        threads.push_back(cx);
        instances.push_back(instance);
    }

    GlobalMetrics.prepare_screen();

    for (size_t ii = 0; ii < threads.size(); ++ii) {
        threads[ii]->start();
    }
    for (size_t ii = 0; ii < threads.size(); ++ii) {
        threads[ii]->join();
    }
    for (size_t ii = 0; ii < instances.size(); ++ii) {
        lcb_destroy(instances[ii]);
    }
}

int main(int argc, char **argv)
{
    try {
        real_main(argc, argv);
        return 0;
    } catch (std::exception& exc) {
        cerr << exc.what() << endl;
        exit(EXIT_FAILURE);
    }
}
<|endoftext|>


<commit_before>int main() {
  return 0;
}
<commit_msg>Add license header to no_op.cc.<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

// No-op main() to provide a dummy executable target.
int main() {
  return 0;
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
// LLVM 'GCCAS' UTILITY
//
//  This utility is designed to be used by the GCC frontend for creating
// bytecode files from it's intermediate llvm assembly.  The requirements for
// this utility are thus slightly different than that of the standard as util.
//
//===----------------------------------------------------------------------===//

#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Assembly/Parser.h"
#include "llvm/Transforms/CleanupGCCOutput.h"
#include "llvm/Transforms/LevelChange.h"
#include "llvm/Transforms/ConstantMerge.h"
#include "llvm/Transforms/ChangeAllocations.h"
#include "llvm/Transforms/Scalar/ConstantProp.h"
#include "llvm/Transforms/Scalar/DCE.h"
#include "llvm/Transforms/Scalar/GCSE.h"
#include "llvm/Transforms/Scalar/IndVarSimplify.h"
#include "llvm/Transforms/Scalar/InstructionCombining.h"
#include "llvm/Transforms/Scalar/PromoteMemoryToRegister.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "Support/CommandLine.h"
#include "Support/Signals.h"
#include <memory>
#include <fstream>

cl::String InputFilename ("", "Parse <arg> file, compile to bytecode",
                          cl::Required, "");
cl::String OutputFilename("o", "Override output filename", cl::NoFlags, "");
cl::Flag   StopAtLevelRaise("stopraise", "Stop optimization before level raise",
                            cl::Hidden);

int main(int argc, char **argv) {
  cl::ParseCommandLineOptions(argc, argv, " llvm .s -> .o assembler for GCC\n");

  std::auto_ptr<Module> M;
  try {
    // Parse the file now...
    M.reset(ParseAssemblyFile(InputFilename));
  } catch (const ParseException &E) {
    cerr << E.getMessage() << endl;
    return 1;
  }

  if (M.get() == 0) {
    cerr << "assembly didn't read correctly.\n";
    return 1;
  }

  if (OutputFilename == "") {   // Didn't specify an output filename?
    std::string IFN = InputFilename;
    int Len = IFN.length();
    if (IFN[Len-2] == '.' && IFN[Len-1] == 's') {   // Source ends in .s?
      OutputFilename = std::string(IFN.begin(), IFN.end()-2);
    } else {
      OutputFilename = IFN;   // Append a .o to it
    }
    OutputFilename += ".o";
  }

  std::ofstream Out(OutputFilename.c_str(), ios::out);
  if (!Out.good()) {
    cerr << "Error opening " << OutputFilename << "!\n";
    return 1;
  }

  // Make sure that the Out file gets unlink'd from the disk if we get a SIGINT
  RemoveFileOnSignal(OutputFilename);

  // In addition to just parsing the input from GCC, we also want to spiff it up
  // a little bit.  Do this now.
  //
  PassManager Passes;
  Passes.add(createFunctionResolvingPass());      // Resolve (...) functions
  Passes.add(createConstantMergePass());          // Merge dup global constants
  Passes.add(createDeadInstEliminationPass());    // Remove Dead code/vars
  Passes.add(createRaiseAllocationsPass());       // call %malloc -> malloc inst
  Passes.add(createCleanupGCCOutputPass());       // Fix gccisms
  Passes.add(createIndVarSimplifyPass());         // Simplify indvars
  if (!StopAtLevelRaise) {
    Passes.add(createRaisePointerReferencesPass()); // Eliminate casts
    Passes.add(createPromoteMemoryToRegister());    // Promote alloca's to regs
    Passes.add(createInstructionCombiningPass());   // Combine silly seq's
    Passes.add(createSCCPPass());                   // Constant prop with SCCP
    Passes.add(createGCSEPass());                   // Remove common subexprs
    Passes.add(createDeadCodeEliminationPass());    // Remove Dead code/vars
  }
  Passes.add(new WriteBytecodePass(&Out));        // Write bytecode to file...

  // Run our queue of passes all at once now, efficiently.
  Passes.run(M.get());
  return 0;
}

<commit_msg>Instruction Combination can create a ton of trivially dead instructions.  Remove them with an DIE pass before more expensive optimizations are run.<commit_after>//===----------------------------------------------------------------------===//
// LLVM 'GCCAS' UTILITY
//
//  This utility is designed to be used by the GCC frontend for creating
// bytecode files from it's intermediate llvm assembly.  The requirements for
// this utility are thus slightly different than that of the standard as util.
//
//===----------------------------------------------------------------------===//

#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Assembly/Parser.h"
#include "llvm/Transforms/CleanupGCCOutput.h"
#include "llvm/Transforms/LevelChange.h"
#include "llvm/Transforms/ConstantMerge.h"
#include "llvm/Transforms/ChangeAllocations.h"
#include "llvm/Transforms/Scalar/ConstantProp.h"
#include "llvm/Transforms/Scalar/DCE.h"
#include "llvm/Transforms/Scalar/GCSE.h"
#include "llvm/Transforms/Scalar/IndVarSimplify.h"
#include "llvm/Transforms/Scalar/InstructionCombining.h"
#include "llvm/Transforms/Scalar/PromoteMemoryToRegister.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "Support/CommandLine.h"
#include "Support/Signals.h"
#include <memory>
#include <fstream>

cl::String InputFilename ("", "Parse <arg> file, compile to bytecode",
                          cl::Required, "");
cl::String OutputFilename("o", "Override output filename", cl::NoFlags, "");
cl::Flag   StopAtLevelRaise("stopraise", "Stop optimization before level raise",
                            cl::Hidden);

int main(int argc, char **argv) {
  cl::ParseCommandLineOptions(argc, argv, " llvm .s -> .o assembler for GCC\n");

  std::auto_ptr<Module> M;
  try {
    // Parse the file now...
    M.reset(ParseAssemblyFile(InputFilename));
  } catch (const ParseException &E) {
    cerr << E.getMessage() << endl;
    return 1;
  }

  if (M.get() == 0) {
    cerr << "assembly didn't read correctly.\n";
    return 1;
  }

  if (OutputFilename == "") {   // Didn't specify an output filename?
    std::string IFN = InputFilename;
    int Len = IFN.length();
    if (IFN[Len-2] == '.' && IFN[Len-1] == 's') {   // Source ends in .s?
      OutputFilename = std::string(IFN.begin(), IFN.end()-2);
    } else {
      OutputFilename = IFN;   // Append a .o to it
    }
    OutputFilename += ".o";
  }

  std::ofstream Out(OutputFilename.c_str(), ios::out);
  if (!Out.good()) {
    cerr << "Error opening " << OutputFilename << "!\n";
    return 1;
  }

  // Make sure that the Out file gets unlink'd from the disk if we get a SIGINT
  RemoveFileOnSignal(OutputFilename);

  // In addition to just parsing the input from GCC, we also want to spiff it up
  // a little bit.  Do this now.
  //
  PassManager Passes;
  Passes.add(createFunctionResolvingPass());      // Resolve (...) functions
  Passes.add(createConstantMergePass());          // Merge dup global constants
  Passes.add(createDeadInstEliminationPass());    // Remove Dead code/vars
  Passes.add(createRaiseAllocationsPass());       // call %malloc -> malloc inst
  Passes.add(createCleanupGCCOutputPass());       // Fix gccisms
  Passes.add(createIndVarSimplifyPass());         // Simplify indvars
  if (!StopAtLevelRaise) {
    Passes.add(createRaisePointerReferencesPass()); // Eliminate casts
    Passes.add(createPromoteMemoryToRegister());    // Promote alloca's to regs
    Passes.add(createInstructionCombiningPass());   // Combine silly seq's
    Passes.add(createDeadInstEliminationPass());    // Kill InstCombine remnants
    Passes.add(createSCCPPass());                   // Constant prop with SCCP
    Passes.add(createGCSEPass());                   // Remove common subexprs
    Passes.add(createDeadCodeEliminationPass());    // Remove Dead code/vars
  }
  Passes.add(new WriteBytecodePass(&Out));        // Write bytecode to file...

  // Run our queue of passes all at once now, efficiently.
  Passes.run(M.get());
  return 0;
}

<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
// LLVM 'GCCAS' UTILITY
//
//  This utility is designed to be used by the GCC frontend for creating
// bytecode files from it's intermediate llvm assembly.  The requirements for
// this utility are thus slightly different than that of the standard as util.
//
//===----------------------------------------------------------------------===//

#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Assembly/Parser.h"
#include "llvm/Transforms/RaisePointerReferences.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Analysis/LoadValueNumbering.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "llvm/Target/TargetData.h"
#include "Support/CommandLine.h"
#include "Support/Signals.h"
#include <memory>
#include <fstream>

namespace {
  // FIXME: This should eventually be parameterized...
  TargetData TD("gccas target");

  cl::opt<std::string>
  InputFilename(cl::Positional,cl::desc("<input llvm assembly>"),cl::init("-"));

  cl::opt<std::string>
  OutputFilename("o", cl::desc("Override output filename"),
                 cl::value_desc("filename"));

  cl::opt<int>
  RunNPasses("stopAfterNPasses",
             cl::desc("Only run the first N passes of gccas"), cl::Hidden,
             cl::value_desc("# passes"));

  cl::opt<bool>
  Verify("verify", cl::desc("Verify each pass result"));
}

static inline void addPass(PassManager &PM, Pass *P) {
  static int NumPassesCreated = 0;

  // If we haven't already created the number of passes that was requested...
  if (RunNPasses == 0 || RunNPasses > NumPassesCreated) {
    // Add the pass to the pass manager...
    PM.add(P);

    // If we are verifying all of the intermediate steps, add the verifier...
    if (Verify) PM.add(createVerifierPass());

    // Keep track of how many passes we made for -stopAfterNPasses
    ++NumPassesCreated;
  } else {
    delete P;             // We don't want this pass to run, just delete it now
  }
}

void AddConfiguredTransformationPasses(PassManager &PM) {
  if (Verify) PM.add(createVerifierPass());

  addPass(PM, createFunctionResolvingPass());    // Resolve (...) functions
  addPass(PM, createGlobalDCEPass());            // Kill unused uinit g-vars
  addPass(PM, createDeadTypeEliminationPass());  // Eliminate dead types
  addPass(PM, createConstantMergePass());        // Merge dup global constants
  addPass(PM, createVerifierPass());             // Verify that input is correct
  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
  addPass(PM, createDeadInstEliminationPass());  // Remove Dead code/vars
  addPass(PM, createRaiseAllocationsPass());     // call %malloc -> malloc inst
  addPass(PM, createIndVarSimplifyPass());       // Simplify indvars
  addPass(PM, createRaisePointerReferencesPass(TD));// Recover type information
  addPass(PM, createInstructionCombiningPass()); // Combine silly seq's
  addPass(PM, createPromoteMemoryToRegister());  // Promote alloca's to regs
  addPass(PM, createReassociatePass());          // Reassociate expressions
  //addPass(PM, createCorrelatedExpressionEliminationPass());// Kill corr branches
  addPass(PM, createInstructionCombiningPass()); // Combine silly seq's
  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
  addPass(PM, createLICMPass());                 // Hoist loop invariants
  addPass(PM, createLoadValueNumberingPass());   // GVN for load instructions
  addPass(PM, createGCSEPass());                 // Remove common subexprs
  addPass(PM, createSCCPPass());                 // Constant prop with SCCP

  // Run instcombine after redundancy elimination to exploit opportunities
  // opened up by them.
  addPass(PM, createInstructionCombiningPass());
  addPass(PM, createAggressiveDCEPass());        // SSA based 'Agressive DCE'
  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
}

int main(int argc, char **argv) {
  cl::ParseCommandLineOptions(argc, argv, " llvm .s -> .o assembler for GCC\n");

  std::auto_ptr<Module> M;
  try {
    // Parse the file now...
    M.reset(ParseAssemblyFile(InputFilename));
  } catch (const ParseException &E) {
    std::cerr << argv[0] << ": " << E.getMessage() << "\n";
    return 1;
  }

  if (M.get() == 0) {
    std::cerr << argv[0] << ": assembly didn't read correctly.\n";
    return 1;
  }

  std::ostream *Out = 0;
  if (OutputFilename == "") {   // Didn't specify an output filename?
    if (InputFilename == "-") {
      OutputFilename = "-";
    } else {
      std::string IFN = InputFilename;
      int Len = IFN.length();
      if (IFN[Len-2] == '.' && IFN[Len-1] == 's') {   // Source ends in .s?
        OutputFilename = std::string(IFN.begin(), IFN.end()-2);
      } else {
        OutputFilename = IFN;   // Append a .o to it
      }
      OutputFilename += ".o";
    }
  }

  if (OutputFilename == "-")
    Out = &std::cout;
  else {
    Out = new std::ofstream(OutputFilename.c_str(), std::ios::out);

    // Make sure that the Out file gets unlink'd from the disk if we get a
    // signal
    RemoveFileOnSignal(OutputFilename);
  }

  if (!Out->good()) {
    std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
    return 1;
  }

  // In addition to just parsing the input from GCC, we also want to spiff it up
  // a little bit.  Do this now.
  //
  PassManager Passes;

  // Add all of the transformation passes to the pass manager to do the cleanup
  // and optimization of the GCC output.
  //
  AddConfiguredTransformationPasses(Passes);

  // Write bytecode to file...
  Passes.add(new WriteBytecodePass(Out));

  // Run our queue of passes all at once now, efficiently.
  Passes.run(*M.get());

  if (Out != &std::cout) delete Out;
  return 0;
}
<commit_msg>LevelRaise now gets target data from passmanager<commit_after>//===----------------------------------------------------------------------===//
// LLVM 'GCCAS' UTILITY
//
//  This utility is designed to be used by the GCC frontend for creating
// bytecode files from it's intermediate llvm assembly.  The requirements for
// this utility are thus slightly different than that of the standard as util.
//
//===----------------------------------------------------------------------===//

#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Assembly/Parser.h"
#include "llvm/Transforms/RaisePointerReferences.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Analysis/LoadValueNumbering.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "llvm/Target/TargetData.h"
#include "Support/CommandLine.h"
#include "Support/Signals.h"
#include <memory>
#include <fstream>

namespace {
  cl::opt<std::string>
  InputFilename(cl::Positional,cl::desc("<input llvm assembly>"),cl::init("-"));

  cl::opt<std::string>
  OutputFilename("o", cl::desc("Override output filename"),
                 cl::value_desc("filename"));

  cl::opt<int>
  RunNPasses("stopAfterNPasses",
             cl::desc("Only run the first N passes of gccas"), cl::Hidden,
             cl::value_desc("# passes"));

  cl::opt<bool>
  Verify("verify", cl::desc("Verify each pass result"));
}

static inline void addPass(PassManager &PM, Pass *P) {
  static int NumPassesCreated = 0;

  // If we haven't already created the number of passes that was requested...
  if (RunNPasses == 0 || RunNPasses > NumPassesCreated) {
    // Add the pass to the pass manager...
    PM.add(P);

    // If we are verifying all of the intermediate steps, add the verifier...
    if (Verify) PM.add(createVerifierPass());

    // Keep track of how many passes we made for -stopAfterNPasses
    ++NumPassesCreated;
  } else {
    delete P;             // We don't want this pass to run, just delete it now
  }
}

void AddConfiguredTransformationPasses(PassManager &PM) {
  if (Verify) PM.add(createVerifierPass());

  addPass(PM, createFunctionResolvingPass());    // Resolve (...) functions
  addPass(PM, createGlobalDCEPass());            // Kill unused uinit g-vars
  addPass(PM, createDeadTypeEliminationPass());  // Eliminate dead types
  addPass(PM, createConstantMergePass());        // Merge dup global constants
  addPass(PM, createVerifierPass());             // Verify that input is correct
  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
  addPass(PM, createDeadInstEliminationPass());  // Remove Dead code/vars
  addPass(PM, createRaiseAllocationsPass());     // call %malloc -> malloc inst
  addPass(PM, createIndVarSimplifyPass());       // Simplify indvars
  addPass(PM, createRaisePointerReferencesPass());// Recover type information
  addPass(PM, createInstructionCombiningPass()); // Combine silly seq's
  addPass(PM, createPromoteMemoryToRegister());  // Promote alloca's to regs
  addPass(PM, createReassociatePass());          // Reassociate expressions
  //addPass(PM, createCorrelatedExpressionEliminationPass());// Kill corr branches
  addPass(PM, createInstructionCombiningPass()); // Combine silly seq's
  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
  addPass(PM, createLICMPass());                 // Hoist loop invariants
  addPass(PM, createLoadValueNumberingPass());   // GVN for load instructions
  addPass(PM, createGCSEPass());                 // Remove common subexprs
  addPass(PM, createSCCPPass());                 // Constant prop with SCCP

  // Run instcombine after redundancy elimination to exploit opportunities
  // opened up by them.
  addPass(PM, createInstructionCombiningPass());
  addPass(PM, createAggressiveDCEPass());        // SSA based 'Agressive DCE'
  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
}

int main(int argc, char **argv) {
  cl::ParseCommandLineOptions(argc, argv, " llvm .s -> .o assembler for GCC\n");

  // FIXME: This should eventually be parameterized...
  TargetData TD("gccas target");

  std::auto_ptr<Module> M;
  try {
    // Parse the file now...
    M.reset(ParseAssemblyFile(InputFilename));
  } catch (const ParseException &E) {
    std::cerr << argv[0] << ": " << E.getMessage() << "\n";
    return 1;
  }

  if (M.get() == 0) {
    std::cerr << argv[0] << ": assembly didn't read correctly.\n";
    return 1;
  }

  std::ostream *Out = 0;
  if (OutputFilename == "") {   // Didn't specify an output filename?
    if (InputFilename == "-") {
      OutputFilename = "-";
    } else {
      std::string IFN = InputFilename;
      int Len = IFN.length();
      if (IFN[Len-2] == '.' && IFN[Len-1] == 's') {   // Source ends in .s?
        OutputFilename = std::string(IFN.begin(), IFN.end()-2);
      } else {
        OutputFilename = IFN;   // Append a .o to it
      }
      OutputFilename += ".o";
    }
  }

  if (OutputFilename == "-")
    Out = &std::cout;
  else {
    Out = new std::ofstream(OutputFilename.c_str(), std::ios::out);

    // Make sure that the Out file gets unlink'd from the disk if we get a
    // signal
    RemoveFileOnSignal(OutputFilename);
  }

  if (!Out->good()) {
    std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
    return 1;
  }

  // In addition to just parsing the input from GCC, we also want to spiff it up
  // a little bit.  Do this now.
  //
  PassManager Passes;

  // Add all of the transformation passes to the pass manager to do the cleanup
  // and optimization of the GCC output.
  //
  AddConfiguredTransformationPasses(Passes);

  // Write bytecode to file...
  Passes.add(new WriteBytecodePass(Out));

  // Run our queue of passes all at once now, efficiently.
  Passes.run(*M.get());

  if (Out != &std::cout) delete Out;
  return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015 Cryptonomex, Inc., and contributors.
 *
 * The MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#pragma once

#include <graphene/chain/protocol/base.hpp>
#include <graphene/chain/protocol/types.hpp>

namespace graphene { namespace chain {
   /**
    * @ingroup operations
    * @brief Generate an deflation
    *
    * This operation is used to generate a deflation
    */
    struct deflation_operation : public base_operation {
        struct fee_parameters_type {uint64_t fee = 0; };

        deflation_operation() {}

        account_id_type issuer;
        uint32_t rate;
        asset fee;                          //this is virtual operation, no fee is charged

        account_id_type fee_payer() const {
            return GRAPHENE_TEMP_ACCOUNT;
        }

        void validate() const;

        /// This is a virtual operation; there is no fee
        share_type      calculate_fee(const fee_parameters_type& k)const { return 0; }
    };

   /**
    * @ingroup operations
    * @brief Generate an accout deflation
    *
    * This operation is used to generate a deflation for a specified account
    */
    struct account_deflation_operation : public base_operation {
        struct fee_parameters_type {uint64_t fee = 0; };

        account_deflation_operation() {}

        deflation_id_type deflation_id;
        account_id_type owner;
        asset fee;                          //this is virtual operation, no fee is charged

        share_type amount;  // only for history detail

        account_id_type fee_payer() const {
            return GRAPHENE_TEMP_ACCOUNT;
        }

        void validate() const;

        /// This is a virtual operation; there is no fee
        share_type      calculate_fee(const fee_parameters_type& k)const { return 0; }
    };

}} // graphene::chain

FC_REFLECT( graphene::chain::deflation_operation::fee_parameters_type, (fee) )

FC_REFLECT( graphene::chain::deflation_operation, (issuer)(rate)(fee) )

FC_REFLECT( graphene::chain::account_deflation_operation::fee_parameters_type, (fee) )

FC_REFLECT( graphene::chain::account_deflation_operation, (deflation_id)(owner)(fee)(amount) )<commit_msg>deflation<commit_after>/*
 * Copyright (c) 2015 Cryptonomex, Inc., and contributors.
 *
 * The MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#pragma once

#include <graphene/chain/protocol/base.hpp>
#include <graphene/chain/protocol/types.hpp>

namespace graphene { namespace chain {
   /**
    * @ingroup operations
    * @brief Generate an deflation
    *
    * This operation is used to generate a deflation
    */
    struct deflation_operation : public base_operation {
        struct fee_parameters_type {uint64_t fee = 0; };

        deflation_operation() {}

        asset fee;                          //this is virtual operation, no fee is charged
        account_id_type issuer;
        uint32_t rate;

        account_id_type fee_payer() const {
            return issuer;
        }

        void validate() const;

        /// This is a virtual operation; there is no fee
        share_type      calculate_fee(const fee_parameters_type& k)const { return 0; }
    };

   /**
    * @ingroup operations
    * @brief Generate an accout deflation
    *
    * This operation is used to generate a deflation for a specified account
    */
    struct account_deflation_operation : public base_operation {
        struct fee_parameters_type {uint64_t fee = 0; };

        account_deflation_operation() {}

        asset fee;                          //this is virtual operation, no fee is charged
        deflation_id_type deflation_id;
        account_id_type owner;

        share_type amount;  // only for history detail

        account_id_type fee_payer() const {
            return GRAPHENE_TEMP_ACCOUNT;
        }

        void validate() const;

        /// This is a virtual operation; there is no fee
        share_type      calculate_fee(const fee_parameters_type& k)const { return 0; }
    };

}} // graphene::chain

FC_REFLECT( graphene::chain::deflation_operation::fee_parameters_type, (fee) )

FC_REFLECT( graphene::chain::deflation_operation, (fee)(issuer)(rate) )

FC_REFLECT( graphene::chain::account_deflation_operation::fee_parameters_type, (fee) )

FC_REFLECT( graphene::chain::account_deflation_operation, (fee)(deflation_id)(owner)(amount) )<|endoftext|>


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

/**
 * @file MulticopterLandDetector.cpp
 *
 * @author Johan Jansen <jnsn.johan@gmail.com>
 * @author Morten Lysgaard <morten@lysgaard.no>
 * @author Julian Oes <julian@oes.ch>
 */

#include <cmath>
#include <drivers/drv_hrt.h>
#include <mathlib/mathlib.h>

#include "MulticopterLandDetector.h"

namespace land_detector
{

MulticopterLandDetector::MulticopterLandDetector() : LandDetector(),
	_paramHandle(),
	_params(),
	_vehicleLocalPositionSub(-1),
	_actuatorsSub(-1),
	_armingSub(-1),
	_attitudeSub(-1),
	_manualSub(-1),
	_ctrl_state_sub(-1),
	_vehicle_control_mode_sub(-1),
	_vehicleLocalPosition{},
	_actuators{},
	_arming{},
	_vehicleAttitude{},
	_manual{},
	_ctrl_state{},
	_control_mode{},
	_min_trust_start(0),
	_arming_time(0)
{
	_paramHandle.maxRotation = param_find("LNDMC_ROT_MAX");
	_paramHandle.maxVelocity = param_find("LNDMC_XY_VEL_MAX");
	_paramHandle.maxClimbRate = param_find("LNDMC_Z_VEL_MAX");
	_paramHandle.minThrottle = param_find("MPC_THR_MIN");
	_paramHandle.minManThrottle = param_find("MPC_MANTHR_MIN");
	_paramHandle.freefall_acc_threshold = param_find("LNDMC_FFALL_THR");
	_paramHandle.freefall_trigger_time = param_find("LNDMC_FFALL_TTRI");
}

void MulticopterLandDetector::_initialize_topics()
{
	// subscribe to position, attitude, arming and velocity changes
	_vehicleLocalPositionSub = orb_subscribe(ORB_ID(vehicle_local_position));
	_attitudeSub = orb_subscribe(ORB_ID(vehicle_attitude));
	_actuatorsSub = orb_subscribe(ORB_ID(actuator_controls_0));
	_armingSub = orb_subscribe(ORB_ID(actuator_armed));
	_parameterSub = orb_subscribe(ORB_ID(parameter_update));
	_manualSub = orb_subscribe(ORB_ID(manual_control_setpoint));
	_ctrl_state_sub = orb_subscribe(ORB_ID(control_state));
	_vehicle_control_mode_sub = orb_subscribe(ORB_ID(vehicle_control_mode));
}

void MulticopterLandDetector::_update_topics()
{
	_orb_update(ORB_ID(vehicle_local_position), _vehicleLocalPositionSub, &_vehicleLocalPosition);
	_orb_update(ORB_ID(vehicle_attitude), _attitudeSub, &_vehicleAttitude);
	_orb_update(ORB_ID(actuator_controls_0), _actuatorsSub, &_actuators);
	_orb_update(ORB_ID(actuator_armed), _armingSub, &_arming);
	_orb_update(ORB_ID(manual_control_setpoint), _manualSub, &_manual);
	_orb_update(ORB_ID(control_state), _ctrl_state_sub, &_ctrl_state);
	_orb_update(ORB_ID(vehicle_control_mode), _vehicle_control_mode_sub, &_control_mode);
}

void MulticopterLandDetector::_update_params()
{
	param_get(_paramHandle.maxClimbRate, &_params.maxClimbRate);
	param_get(_paramHandle.maxVelocity, &_params.maxVelocity);
	param_get(_paramHandle.maxRotation, &_params.maxRotation_rad_s);
	_params.maxRotation_rad_s = math::radians(_params.maxRotation_rad_s);
	param_get(_paramHandle.minThrottle, &_params.minThrottle);
	param_get(_paramHandle.minManThrottle, &_params.minManThrottle);
	param_get(_paramHandle.freefall_acc_threshold, &_params.freefall_acc_threshold);
	param_get(_paramHandle.freefall_trigger_time, &_params.freefall_trigger_time);
	_freefall_hysteresis.set_hysteresis_time_from(false, 1e6f * _params.freefall_trigger_time);
}

bool MulticopterLandDetector::_get_freefall_state()
{
	if (_params.freefall_acc_threshold < 0.1f
	    || _params.freefall_acc_threshold > 10.0f) {	//if parameter is set to zero or invalid, disable free-fall detection.
		return false;
	}

	if (_ctrl_state.timestamp == 0) {
		// _ctrl_state is not valid yet, we have to assume we're not falling.
		return false;
	}

	float acc_norm = _ctrl_state.x_acc * _ctrl_state.x_acc
			 + _ctrl_state.y_acc * _ctrl_state.y_acc
			 + _ctrl_state.z_acc * _ctrl_state.z_acc;
	acc_norm = sqrtf(acc_norm);	//norm of specific force. Should be close to 9.8 m/s^2 when landed.

	return (acc_norm < _params.freefall_acc_threshold);	//true if we are currently falling
}

bool MulticopterLandDetector::_get_landed_state()
{
	// Time base for this function
	const uint64_t now = hrt_absolute_time();

	float sys_min_throttle = (_params.minThrottle + 0.01f);

	// Determine the system min throttle based on flight mode
	if (!_control_mode.flag_control_altitude_enabled) {
		sys_min_throttle = (_params.minManThrottle + 0.01f);
	}

	// Check if thrust output is less than the minimum auto throttle param.
	bool minimalThrust = (_actuators.control[3] <= sys_min_throttle);

	if (minimalThrust && _min_trust_start == 0) {
		_min_trust_start = now;

	} else if (!minimalThrust) {
		_min_trust_start = 0;
	}

	// only trigger flight conditions if we are armed
	if (!_arming.armed) {
		_arming_time = 0;

		return true;

	} else if (_arming_time == 0) {
		_arming_time = now;
	}

	const bool manual_control_present = _control_mode.flag_control_manual_enabled && _manual.timestamp > 0;

	// If we control manually and are still landed, we want to stay idle until the pilot rises the throttle
	if (_state == LandDetectionState::LANDED && manual_control_present && _manual.z < get_takeoff_throttle()) {
		return true;
	}

	// If in manual flight mode never report landed if the user has more than idle throttle
	// Check if user commands throttle and if so, report not landed based on
	// the user intent to take off (even if the system might physically still have
	// ground contact at this point).
	if (manual_control_present && _manual.z > 0.15f) {
		return false;
	}

	// Return status based on armed state and throttle if no position lock is available.
	if (_vehicleLocalPosition.timestamp == 0 ||
	    hrt_elapsed_time(&_vehicleLocalPosition.timestamp) > 500000 ||
	    !_vehicleLocalPosition.xy_valid ||
	    !_vehicleLocalPosition.z_valid) {

		// The system has minimum trust set (manual or in failsafe)
		// if this persists for 8 seconds AND the drone is not
		// falling consider it to be landed. This should even sustain
		// quite acrobatic flight.
		if ((_min_trust_start > 0) &&
		    (hrt_elapsed_time(&_min_trust_start) > 8000000)) {

			return true;

		} else {
			return false;
		}
	}

	float armThresholdFactor = 1.0f;

	// Widen acceptance thresholds for landed state right after arming
	// so that motor spool-up and other effects do not trigger false negatives.
	if (hrt_elapsed_time(&_arming_time) < LAND_DETECTOR_ARM_PHASE_TIME_US) {
		armThresholdFactor = 2.5f;
	}

	// Check if we are moving vertically - this might see a spike after arming due to
	// throttle-up vibration. If accelerating fast the throttle thresholds will still give
	// an accurate in-air indication.
	bool verticalMovement = fabsf(_vehicleLocalPosition.vz) > _params.maxClimbRate * armThresholdFactor;

	// Check if we are moving horizontally.
	bool horizontalMovement = sqrtf(_vehicleLocalPosition.vx * _vehicleLocalPosition.vx
					+ _vehicleLocalPosition.vy * _vehicleLocalPosition.vy) > _params.maxVelocity;

	// Next look if all rotation angles are not moving.
	float maxRotationScaled = _params.maxRotation_rad_s * armThresholdFactor;

	bool rotating = (fabsf(_vehicleAttitude.rollspeed)  > maxRotationScaled) ||
			(fabsf(_vehicleAttitude.pitchspeed) > maxRotationScaled) ||
			(fabsf(_vehicleAttitude.yawspeed) > maxRotationScaled);

	if (verticalMovement || rotating || !minimalThrust || horizontalMovement) {
		// Sensed movement or thottle high, so reset the land detector.
		return false;
	}

	return true;
}

float MulticopterLandDetector::get_takeoff_throttle()
{
	/* Position mode */
	if (_control_mode.flag_control_manual_enabled && _control_mode.flag_control_position_enabled) {
		/* Should be above 0.5 because below that we do not gain altitude and won't take off.
		 * Also it should be quite high such that we don't accidentally take off when using
		 * a spring loaded throttle and have a useful vertical speed to start with. */
		return 0.75f;
	}

	/* Manual/attitude mode */
	if (_control_mode.flag_control_manual_enabled && _control_mode.flag_control_attitude_enabled) {
		/* Should be quite low and certainly below hover throttle because pilot controls throttle manually. */
		return 0.15f;
	}

	/* As default for example in acro mode we do not want to stay landed. */
	return 0.0f;
}

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

/**
 * @file MulticopterLandDetector.cpp
 *
 * @author Johan Jansen <jnsn.johan@gmail.com>
 * @author Morten Lysgaard <morten@lysgaard.no>
 * @author Julian Oes <julian@oes.ch>
 */

#include <cmath>
#include <drivers/drv_hrt.h>
#include <mathlib/mathlib.h>

#include "MulticopterLandDetector.h"

namespace land_detector
{

MulticopterLandDetector::MulticopterLandDetector() : LandDetector(),
	_paramHandle(),
	_params(),
	_vehicleLocalPositionSub(-1),
	_actuatorsSub(-1),
	_armingSub(-1),
	_attitudeSub(-1),
	_manualSub(-1),
	_ctrl_state_sub(-1),
	_vehicle_control_mode_sub(-1),
	_vehicleLocalPosition{},
	_actuators{},
	_arming{},
	_vehicleAttitude{},
	_manual{},
	_ctrl_state{},
	_control_mode{},
	_min_trust_start(0),
	_arming_time(0)
{
	_paramHandle.maxRotation = param_find("LNDMC_ROT_MAX");
	_paramHandle.maxVelocity = param_find("LNDMC_XY_VEL_MAX");
	_paramHandle.maxClimbRate = param_find("LNDMC_Z_VEL_MAX");
	_paramHandle.minThrottle = param_find("MPC_THR_MIN");
	_paramHandle.minManThrottle = param_find("MPC_MANTHR_MIN");
	_paramHandle.freefall_acc_threshold = param_find("LNDMC_FFALL_THR");
	_paramHandle.freefall_trigger_time = param_find("LNDMC_FFALL_TTRI");
}

void MulticopterLandDetector::_initialize_topics()
{
	// subscribe to position, attitude, arming and velocity changes
	_vehicleLocalPositionSub = orb_subscribe(ORB_ID(vehicle_local_position));
	_attitudeSub = orb_subscribe(ORB_ID(vehicle_attitude));
	_actuatorsSub = orb_subscribe(ORB_ID(actuator_controls_0));
	_armingSub = orb_subscribe(ORB_ID(actuator_armed));
	_parameterSub = orb_subscribe(ORB_ID(parameter_update));
	_manualSub = orb_subscribe(ORB_ID(manual_control_setpoint));
	_ctrl_state_sub = orb_subscribe(ORB_ID(control_state));
	_vehicle_control_mode_sub = orb_subscribe(ORB_ID(vehicle_control_mode));
}

void MulticopterLandDetector::_update_topics()
{
	_orb_update(ORB_ID(vehicle_local_position), _vehicleLocalPositionSub, &_vehicleLocalPosition);
	_orb_update(ORB_ID(vehicle_attitude), _attitudeSub, &_vehicleAttitude);
	_orb_update(ORB_ID(actuator_controls_0), _actuatorsSub, &_actuators);
	_orb_update(ORB_ID(actuator_armed), _armingSub, &_arming);
	_orb_update(ORB_ID(manual_control_setpoint), _manualSub, &_manual);
	_orb_update(ORB_ID(control_state), _ctrl_state_sub, &_ctrl_state);
	_orb_update(ORB_ID(vehicle_control_mode), _vehicle_control_mode_sub, &_control_mode);
}

void MulticopterLandDetector::_update_params()
{
	param_get(_paramHandle.maxClimbRate, &_params.maxClimbRate);
	param_get(_paramHandle.maxVelocity, &_params.maxVelocity);
	param_get(_paramHandle.maxRotation, &_params.maxRotation_rad_s);
	_params.maxRotation_rad_s = math::radians(_params.maxRotation_rad_s);
	param_get(_paramHandle.minThrottle, &_params.minThrottle);
	param_get(_paramHandle.minManThrottle, &_params.minManThrottle);
	param_get(_paramHandle.freefall_acc_threshold, &_params.freefall_acc_threshold);
	param_get(_paramHandle.freefall_trigger_time, &_params.freefall_trigger_time);
	_freefall_hysteresis.set_hysteresis_time_from(false, 1e6f * _params.freefall_trigger_time);
}

bool MulticopterLandDetector::_get_freefall_state()
{
	if (_params.freefall_acc_threshold < 0.1f
	    || _params.freefall_acc_threshold > 10.0f) {	//if parameter is set to zero or invalid, disable free-fall detection.
		return false;
	}

	if (_ctrl_state.timestamp == 0) {
		// _ctrl_state is not valid yet, we have to assume we're not falling.
		return false;
	}

	float acc_norm = _ctrl_state.x_acc * _ctrl_state.x_acc
			 + _ctrl_state.y_acc * _ctrl_state.y_acc
			 + _ctrl_state.z_acc * _ctrl_state.z_acc;
	acc_norm = sqrtf(acc_norm);	//norm of specific force. Should be close to 9.8 m/s^2 when landed.

	return (acc_norm < _params.freefall_acc_threshold);	//true if we are currently falling
}

bool MulticopterLandDetector::_get_landed_state()
{
	// Time base for this function
	const uint64_t now = hrt_absolute_time();

	float sys_min_throttle = (_params.minThrottle + 0.2f);

	// Determine the system min throttle based on flight mode
	if (!_control_mode.flag_control_altitude_enabled) {
		sys_min_throttle = (_params.minManThrottle + 0.01f);
	}

	// Check if thrust output is less than the minimum auto throttle param.
	bool minimalThrust = (_actuators.control[3] <= sys_min_throttle);

	if (minimalThrust && _min_trust_start == 0) {
		_min_trust_start = now;

	} else if (!minimalThrust) {
		_min_trust_start = 0;
	}

	// only trigger flight conditions if we are armed
	if (!_arming.armed) {
		_arming_time = 0;

		return true;

	} else if (_arming_time == 0) {
		_arming_time = now;
	}

	const bool manual_control_present = _control_mode.flag_control_manual_enabled && _manual.timestamp > 0;

	// If we control manually and are still landed, we want to stay idle until the pilot rises the throttle
	if (_state == LandDetectionState::LANDED && manual_control_present && _manual.z < get_takeoff_throttle()) {
		return true;
	}

	// If in manual flight mode never report landed if the user has more than idle throttle
	// Check if user commands throttle and if so, report not landed based on
	// the user intent to take off (even if the system might physically still have
	// ground contact at this point).
	if (manual_control_present && _manual.z > 0.15f) {
		return false;
	}

	// Return status based on armed state and throttle if no position lock is available.
	if (_vehicleLocalPosition.timestamp == 0 ||
	    hrt_elapsed_time(&_vehicleLocalPosition.timestamp) > 500000 ||
	    !_vehicleLocalPosition.xy_valid ||
	    !_vehicleLocalPosition.z_valid) {

		// The system has minimum trust set (manual or in failsafe)
		// if this persists for 8 seconds AND the drone is not
		// falling consider it to be landed. This should even sustain
		// quite acrobatic flight.
		if ((_min_trust_start > 0) &&
		    (hrt_elapsed_time(&_min_trust_start) > 8000000)) {

			return true;

		} else {
			return false;
		}
	}

	float armThresholdFactor = 1.0f;

	// Widen acceptance thresholds for landed state right after arming
	// so that motor spool-up and other effects do not trigger false negatives.
	if (hrt_elapsed_time(&_arming_time) < LAND_DETECTOR_ARM_PHASE_TIME_US) {
		armThresholdFactor = 2.5f;
	}

	// Check if we are moving vertically - this might see a spike after arming due to
	// throttle-up vibration. If accelerating fast the throttle thresholds will still give
	// an accurate in-air indication.
	bool verticalMovement = fabsf(_vehicleLocalPosition.vz) > _params.maxClimbRate * armThresholdFactor;

	// Check if we are moving horizontally.
	bool horizontalMovement = sqrtf(_vehicleLocalPosition.vx * _vehicleLocalPosition.vx
					+ _vehicleLocalPosition.vy * _vehicleLocalPosition.vy) > _params.maxVelocity;

	// Next look if all rotation angles are not moving.
	float maxRotationScaled = _params.maxRotation_rad_s * armThresholdFactor;

	bool rotating = (fabsf(_vehicleAttitude.rollspeed)  > maxRotationScaled) ||
			(fabsf(_vehicleAttitude.pitchspeed) > maxRotationScaled) ||
			(fabsf(_vehicleAttitude.yawspeed) > maxRotationScaled);

	if (verticalMovement || rotating || !minimalThrust || horizontalMovement) {
		// Sensed movement or thottle high, so reset the land detector.
		return false;
	}

	return true;
}

float MulticopterLandDetector::get_takeoff_throttle()
{
	/* Position mode */
	if (_control_mode.flag_control_manual_enabled && _control_mode.flag_control_position_enabled) {
		/* Should be above 0.5 because below that we do not gain altitude and won't take off.
		 * Also it should be quite high such that we don't accidentally take off when using
		 * a spring loaded throttle and have a useful vertical speed to start with. */
		return 0.75f;
	}

	/* Manual/attitude mode */
	if (_control_mode.flag_control_manual_enabled && _control_mode.flag_control_attitude_enabled) {
		/* Should be quite low and certainly below hover throttle because pilot controls throttle manually. */
		return 0.15f;
	}

	/* As default for example in acro mode we do not want to stay landed. */
	return 0.0f;
}

}
<|endoftext|>


<commit_before>#include "core.hpp"

#include <ncurses.h>
#include <string>

#include "config.hpp"
#include "draw.hpp"
#include "todolist.hpp"

using std::string;

// ===================|
// internal variables |
// ===================|
TodoList *backup_;

// ===================|
// internal functions |
// ===================|

void backup(TodoList *list);
void restore(TodoList *&list);

//////////////////////////////////////////////
// initiate things such as the mouse listener
void Core::init()
{
    if (USE_MOUSE){
        mousemask(ALL_MOUSE_EVENTS, NULL);
    }
    backup_ = nullptr;
}

///////////////////////////////////////////
// cleanup everything and prepare to exit
void Core::stop()
{
    delete backup_;
}

//////////////////////////////////
// create and load the to-do list
TodoList* Core::list(string name)
{
    TodoList *list = new TodoList(name);
    list->load();
    return list;
}

//////////////////////////////////////////
// intercept keyboard input and act on it
// returns true if the program should exit
// and false if it should continue
bool Core::handleInput(int c, TodoList *&todoList, unsigned &position)
{
    std::string newTask;

    switch(c){
        case EXIT_KEY:
            return true;

        case TOGGLE_CHECK_KEY:
            if (todoList->size() != 0){
                todoList->at(position).toggleComplete();
            }
            break;

        case NEW_KEY:
            backup(todoList);
            newTask = Draw::getInput();
            if (!newTask.empty()){
                todoList->add(Task(newTask), position);
            }
            break;

        case EDIT_KEY:
            {
            backup(todoList);
            string base = todoList->at(position).raw();
            string editTask = Draw::getInput(base);
            if (!editTask.empty())
                todoList->at(position) = Task(editTask);
            break;
            }

        case REMOVE_KEY:
            backup(todoList);
            todoList->remove(position);
            if (todoList->size() != 0){
                if (position >= todoList->size()){
                    position = todoList->size() - 1;
                }
            }
            break;

        case UNDO_KEY:
            restore(todoList);
            break;

        case MOVE_UP_KEY:
            if (todoList->swap(position - 1)){
                --position;
                if (autoSave){
                    todoList->save();
                }
            }
            break;

        case MOVE_DOWN_KEY:
            if(todoList->swap(position)){
                ++position;
                if (autoSave){
                    todoList->save();
                }
            }
            break;

        case DIV_KEY:
            backup(todoList);
            newTask = Draw::getInput();
            if (!newTask.empty()){
                newTask ="[" + newTask + "]";
            }
            newTask = DIV_CODE + newTask;
            todoList->add(Task(newTask), position);
            break;

        case UP_KEY:
            if (position != 0){
                --position;
            }
            break;

        case DOWN_KEY:
	        if (todoList->size() != 0){
                ++position;
                if (position >= todoList->size()){
                    position = todoList->size() - 1;
                }
	        }
	        break;

        case SORT_KEY:
            backup(todoList);
            todoList->sort();
            if (autoSave){
                todoList->save();
            }
            break;

        case KEY_RESIZE:
            Draw::stop();
            Draw::init();
            break;

        case KEY_MOUSE:
            MEVENT event;
            if (getmouse(&event) == OK){
                if (event.bstate & BUTTON1_PRESSED){
                    Draw::mouse(event, todoList, position, false);
                } else if (event.bstate & BUTTON3_PRESSED){
                    Draw::mouse(event, todoList, position, true);
                } else if (event.bstate & BUTTON4_PRESSED){
                    if (position != 0){
                        --position;
                    }
                }
            } else {          // ncurses is weird and returns ERR
                ++position;   // on mouse wheel down events
                if (position >= todoList->size()){
                    position = todoList->size() - 1;
                }
            }
            break;
    }

    return false;
}

///////////////////
// backup todolist
void backup(TodoList *list)
{
    delete backup_;
    backup_ = new TodoList(list);
}

////////////////////////////////
// restore to-do list from backup
void restore(TodoList *&list)
{
    if (!backup_)
        return;
    delete list;
    list = new TodoList(backup_);
}
<commit_msg>fixed positioning of new items<commit_after>#include "core.hpp"

#include <ncurses.h>
#include <string>

#include "config.hpp"
#include "draw.hpp"
#include "todolist.hpp"

using std::string;

// ===================|
// internal variables |
// ===================|
TodoList *backup_;

// ===================|
// internal functions |
// ===================|

void backup(TodoList *list);
void restore(TodoList *&list);

//////////////////////////////////////////////
// initiate things such as the mouse listener
void Core::init()
{
    if (USE_MOUSE){
        mousemask(ALL_MOUSE_EVENTS, NULL);
    }
    backup_ = nullptr;
}

///////////////////////////////////////////
// cleanup everything and prepare to exit
void Core::stop()
{
    delete backup_;
}

//////////////////////////////////
// create and load the to-do list
TodoList* Core::list(string name)
{
    TodoList *list = new TodoList(name);
    list->load();
    return list;
}

//////////////////////////////////////////
// intercept keyboard input and act on it
// returns true if the program should exit
// and false if it should continue
bool Core::handleInput(int c, TodoList *&todoList, unsigned &position)
{
    std::string newTask;

    switch(c){
        case EXIT_KEY:
            return true;

        case TOGGLE_CHECK_KEY:
            if (todoList->size() != 0){
                todoList->at(position).toggleComplete();
            }
            break;

        case NEW_KEY:
            backup(todoList);
            newTask = Draw::getInput();
            if (!newTask.empty()){
                todoList->add(Task(newTask), position + 1);
            }
            break;

        case EDIT_KEY:
            {
            backup(todoList);
            string base = todoList->at(position).raw();
            string editTask = Draw::getInput(base);
            if (!editTask.empty())
                todoList->at(position) = Task(editTask);
            break;
            }

        case REMOVE_KEY:
            backup(todoList);
            todoList->remove(position);
            if (todoList->size() != 0){
                if (position >= todoList->size()){
                    position = todoList->size() - 1;
                }
            }
            break;

        case UNDO_KEY:
            restore(todoList);
            break;

        case MOVE_UP_KEY:
            if (todoList->swap(position - 1)){
                --position;
                if (autoSave){
                    todoList->save();
                }
            }
            break;

        case MOVE_DOWN_KEY:
            if(todoList->swap(position)){
                ++position;
                if (autoSave){
                    todoList->save();
                }
            }
            break;

        case DIV_KEY:
            backup(todoList);
            newTask = Draw::getInput();
            if (!newTask.empty()){
                newTask ="[" + newTask + "]";
            }
            newTask = DIV_CODE + newTask;
            todoList->add(Task(newTask), position + 1);
            break;

        case UP_KEY:
            if (position != 0){
                --position;
            }
            break;

        case DOWN_KEY:
	        if (todoList->size() != 0){
                ++position;
                if (position >= todoList->size()){
                    position = todoList->size() - 1;
                }
	        }
	        break;

        case SORT_KEY:
            backup(todoList);
            todoList->sort();
            if (autoSave){
                todoList->save();
            }
            break;

        case KEY_RESIZE:
            Draw::stop();
            Draw::init();
            break;

        case KEY_MOUSE:
            MEVENT event;
            if (getmouse(&event) == OK){
                if (event.bstate & BUTTON1_PRESSED){
                    Draw::mouse(event, todoList, position, false);
                } else if (event.bstate & BUTTON3_PRESSED){
                    Draw::mouse(event, todoList, position, true);
                } else if (event.bstate & BUTTON4_PRESSED){
                    if (position != 0){
                        --position;
                    }
                }
            } else {          // ncurses is weird and returns ERR
                ++position;   // on mouse wheel down events
                if (position >= todoList->size()){
                    position = todoList->size() - 1;
                }
            }
            break;
    }

    return false;
}

///////////////////
// backup todolist
void backup(TodoList *list)
{
    delete backup_;
    backup_ = new TodoList(list);
}

////////////////////////////////
// restore to-do list from backup
void restore(TodoList *&list)
{
    if (!backup_)
        return;
    delete list;
    list = new TodoList(backup_);
}
<|endoftext|>


<commit_before>/**
    @file
    @brief Hurwitz zeta function and polylogarithm.

    For implemenation, see

    Fredrik Johansson.

*/

#include <zeta.h>
#include <bernoulli.h>

#include <gsl/gsl_sf.h>
#include <gsl/gsl_math.h>
#include <complex>
#include <stdexcept>

cdouble S(double s, cdouble a, int N) {
  /**
      @returns \f$S\f$ part of zeta function
      @param s
      @param a
      @param N
  */
  cdouble sum = 0.;

  for (int k = 0; k <= N - 1; k += 1) {
    sum += pow(a + static_cast<cdouble>(k), -s);
  }

  return sum;
}

cdouble I(double s, cdouble a, int N) {
  /**
      @returns \f$I\f$ part of zeta function
      @param s
      @param a
      @param N
  */
  return pow(a + static_cast<cdouble>(N), 1. - s) / (s - 1.);
}

cdouble T(double s, cdouble a, int N, int M) {
  /**
      @returns \f$T\f$ part of zeta function
      @param s
      @param a
      @param N
      @param M
  */
  const cdouble d = a + static_cast<cdouble>(N);
  const cdouble factor = pow(d, -s);

  if (M > B_2n_fact_size) {
    #ifdef DEBUG
      printf("M = %d > B_2n_fact_size = %d. Using M = B_2n_fact_size\n",
        M, B_2n_fact_size);
    #endif

    #ifdef THROW
      throw std::invalid_argument("Bernoulli numbers out of bounds");
    #endif

    M = B_2n_fact_size;
  }

  cdouble sum = 0.;

  for (int k = 1; k <= M; k += 1) {
    sum += B_2n_fact[k] * gsl_sf_poch(s, 2. * k - 1.) / pow(d, 2 * k - 1);
  }

  return factor * (0.5 + sum);
}

cdouble hurwitz_zeta(double s, cdouble a, int N) {
  /**
      @returns Hurwitz zeta function, \f$\zeta_s(a)\f$
      @param s
      @param a
      @param N
  */
  if (N > B_2n_fact_size) {
    #ifdef DEBUG
      printf("N = %d > B_2n_fact_size = %d. Using N = B_2n_fact_size\n",
        N, B_2n_fact_size);
    #endif

    #ifdef THROW
      throw std::invalid_argument("Bernoulli numbers out of bounds");
    #endif

    N = B_2n_fact_size;
  }

  return S(s, a, N) + I(s, a, N) + T(s, a, N, N);
}

cdouble polylog(double s, cdouble a, int N) {
  /**
      @returns Polylogarithm function, \f$\textrm{Li}_s(a)\f$
      @param s
      @param a
      @param N
  */
  if (s > 1 && std::abs(a) <= 1) {
    cdouble term = a;
    cdouble sum = term;
    for (int i = 2; i <= N; i += 1) {
      const double x = (i - 1) / static_cast<double>(i);
      term *= a * gsl_pow_2(x) * sqrt(x);
      sum += term;
    }
    return sum;
  }

  const cdouble j(0., 1.);
  const cdouble factor = pow(0.5 * j * M_1_PI, 1. - s) * gsl_sf_gamma(1. - s);
  const cdouble arg = 0.5 * j * log(a) * M_1_PI;
  const cdouble zeta = - pow(j, 2. * s) * hurwitz_zeta(1. - s, arg, N) +
                       hurwitz_zeta(1. - s, 1. - arg, N);
  return factor * zeta;
}
<commit_msg>use pow for pow(double, double)<commit_after>/**
    @file
    @brief Hurwitz zeta function and polylogarithm.

    For implemenation, see

    Fredrik Johansson.

*/

#include <zeta.h>
#include <bernoulli.h>

#include <gsl/gsl_sf.h>
#include <complex>
#include <stdexcept>

cdouble S(double s, cdouble a, int N) {
  /**
      @returns \f$S\f$ part of zeta function
      @param s
      @param a
      @param N
  */
  cdouble sum = 0.;

  for (int k = 0; k <= N - 1; k += 1) {
    sum += pow(a + static_cast<cdouble>(k), -s);
  }

  return sum;
}

cdouble I(double s, cdouble a, int N) {
  /**
      @returns \f$I\f$ part of zeta function
      @param s
      @param a
      @param N
  */
  return pow(a + static_cast<cdouble>(N), 1. - s) / (s - 1.);
}

cdouble T(double s, cdouble a, int N, int M) {
  /**
      @returns \f$T\f$ part of zeta function
      @param s
      @param a
      @param N
      @param M
  */
  const cdouble d = a + static_cast<cdouble>(N);
  const cdouble factor = pow(d, -s);

  if (M > B_2n_fact_size) {
    #ifdef DEBUG
      printf("M = %d > B_2n_fact_size = %d. Using M = B_2n_fact_size\n",
        M, B_2n_fact_size);
    #endif

    #ifdef THROW
      throw std::invalid_argument("Bernoulli numbers out of bounds");
    #endif

    M = B_2n_fact_size;
  }

  cdouble sum = 0.;

  for (int k = 1; k <= M; k += 1) {
    sum += B_2n_fact[k] * gsl_sf_poch(s, 2. * k - 1.) / pow(d, 2 * k - 1);
  }

  return factor * (0.5 + sum);
}

cdouble hurwitz_zeta(double s, cdouble a, int N) {
  /**
      @returns Hurwitz zeta function, \f$\zeta_s(a)\f$
      @param s
      @param a
      @param N
  */
  if (N > B_2n_fact_size) {
    #ifdef DEBUG
      printf("N = %d > B_2n_fact_size = %d. Using N = B_2n_fact_size\n",
        N, B_2n_fact_size);
    #endif

    #ifdef THROW
      throw std::invalid_argument("Bernoulli numbers out of bounds");
    #endif

    N = B_2n_fact_size;
  }

  return S(s, a, N) + I(s, a, N) + T(s, a, N, N);
}

cdouble polylog(double s, cdouble a, int N) {
  /**
      @returns Polylogarithm function, \f$\textrm{Li}_s(a)\f$
      @param s
      @param a
      @param N
  */
  if (s > 1 && std::abs(a) <= 1) {
    cdouble term = a;
    cdouble sum = term;
    for (int i = 2; i <= N; i += 1) {
      const double x = (i - 1) / static_cast<double>(i);
      term *= a * pow(x, 2.5);
      sum += term;
    }
    return sum;
  }

  const cdouble j(0., 1.);
  const cdouble factor = pow(0.5 * j * M_1_PI, 1. - s) * gsl_sf_gamma(1. - s);
  const cdouble arg = 0.5 * j * log(a) * M_1_PI;
  const cdouble zeta = - pow(j, 2. * s) * hurwitz_zeta(1. - s, arg, N) +
                       hurwitz_zeta(1. - s, 1. - arg, N);
  return factor * zeta;
}
<|endoftext|>