<commit_before>// Copyright (c) 2015, Baidu.com, Inc. All Rights Reserved
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "master/workload_scheduler.h"

#include "glog/logging.h"
#include "master/tablet_manager.h"

DECLARE_double(tera_master_load_balance_size_ratio_trigger);
DECLARE_double(tera_master_load_balance_qps_ratio_trigger);
DECLARE_int32(tera_master_load_balance_qps_min_limit);

namespace tera {
namespace master {

class WorkloadGetter {
public:
    virtual int64_t operator() (const TabletNodePtr& tablet_node,
                                const std::string& table_name = "") const = 0;
    virtual int64_t operator() (const TabletPtr& tablet) const = 0;
    virtual ~WorkloadGetter() {}
};

class WorkloadComparator {
public:
    // Three-way comparison.  Returns value:
    //   < 0 iff "a" < "b",
    //   == 0 iff "a" == "b",
    //   > 0 iff "a" > "b"
    int Compare(const TabletNodePtr& a, const TabletNodePtr& b,
                const std::string& table_name) {
        if (!table_name.empty()) {
            uint64_t a_load = (*m_load_getter)(a, table_name);
            uint64_t b_load = (*m_load_getter)(b, table_name);
            if (a_load < b_load) {
                return -1;
            } else if (a_load > b_load) {
                return 1;
            }
        }

        uint64_t a_load = (*m_load_getter)(a);
        uint64_t b_load = (*m_load_getter)(b);
        if (a_load < b_load) {
            return -1;
        } else if (a_load > b_load) {
            return 1;
        } else if (m_next_comparator != NULL) {
            return m_next_comparator->Compare(a, b, table_name);
        } else {
            return 0;
        }
    }

    int Compare(const TabletPtr& a, const TabletPtr& b) {
        uint64_t a_load = (*m_load_getter)(a);
        uint64_t b_load = (*m_load_getter)(b);
        if (a_load < b_load) {
            return -1;
        } else if (a_load > b_load) {
            return 1;
        } else if (m_next_comparator != NULL) {
            return m_next_comparator->Compare(a, b);
        } else {
            return 0;
        }
    }

    WorkloadComparator(WorkloadGetter* load_getter,
                       bool owns_load_getter = false,
                       WorkloadComparator* next_comparator = NULL,
                       bool owns_next_comparator = false)
        : m_load_getter(load_getter),
          m_owns_load_getter(owns_load_getter),
          m_next_comparator(next_comparator),
          m_owns_next_comparator(owns_next_comparator) {
    }

    virtual ~WorkloadComparator() {
        if (m_owns_next_comparator) {
            delete m_next_comparator;
        }
        if (m_owns_load_getter) {
            delete m_load_getter;
        }
    }

private:
    WorkloadGetter* m_load_getter;
    bool m_owns_load_getter;
    WorkloadComparator* m_next_comparator;
    bool m_owns_next_comparator;
};

class WorkloadLess {
public:
    bool operator() (const TabletNodePtr& a, const TabletNodePtr& b) {
        return m_comparator->Compare(a, b, m_table_name) < 0;
    }
    bool operator() (const TabletPtr& a, const TabletPtr& b) {
        return m_comparator->Compare(a, b) < 0;
    }
    WorkloadLess(WorkloadComparator* comparator, const std::string& table_name = "")
        : m_comparator(comparator), m_table_name(table_name) {}
private:
    WorkloadComparator* m_comparator;
    std::string m_table_name;
};

class WorkloadGreater {
public:
    bool operator() (const TabletNodePtr& a, const TabletNodePtr& b) {
        return m_comparator->Compare(a, b, m_table_name) > 0;
    }
    bool operator() (const TabletPtr& a, const TabletPtr& b) {
        return m_comparator->Compare(a, b) > 0;
    }
    WorkloadGreater(WorkloadComparator* comparator, const std::string& table_name = "")
        : m_comparator(comparator), m_table_name(table_name) {}

private:
    WorkloadComparator* m_comparator;
    std::string m_table_name;
};

class SizeGetter : public WorkloadGetter {
public:
    virtual int64_t operator() (const TabletNodePtr& tabletnode,
                                const std::string& table_name = "") const {
        return tabletnode->GetSize(table_name);
    }
    virtual int64_t operator() (const TabletPtr& tablet) const {
        return tablet->GetDataSize();
    }
    virtual ~SizeGetter() {}
};

class SizeComparator : public WorkloadComparator {
public:
    SizeComparator() : WorkloadComparator(&m_size_getter) {}
private:
    SizeGetter m_size_getter;
};

class QPSGetter : public WorkloadGetter {
public:
    virtual int64_t operator() (const TabletNodePtr& tabletnode,
                                const std::string& table_name = "") const {
        return tabletnode->GetQps(table_name);
    }
    virtual int64_t operator() (const TabletPtr& tablet) const {
        return tablet->GetAverageCounter().read_rows();
    }
    virtual ~QPSGetter() {}
};

class QPSComparator : public WorkloadComparator {
public:
    QPSComparator() : WorkloadComparator(&m_qps_getter) {}
private:
    QPSGetter m_qps_getter;
};

/////////////////////////////////////////////////
//                SizeScheduler
/////////////////////////////////////////////////

bool SizeScheduler::FindBestNode(const std::vector<TabletNodePtr>& node_list,
                                 const std::string& table_name,
                                 size_t* best_index) {
    if (node_list.size() == 0) {
        return false;
    }

    SizeComparator comparator;
    *best_index = 0;
    for (size_t i = 1; i < node_list.size(); ++i) {
        int r = comparator.Compare(node_list[*best_index], node_list[i], table_name);
        if (r > 0) {
            *best_index = i;
        } else if (r < 0) {
            // do nothing
        } else if (node_list[*best_index]->GetAddr() <= m_last_choose_node
            && node_list[i]->GetAddr() > m_last_choose_node) {
            // round-robin
            *best_index = i;
        }
    }
    m_last_choose_node = node_list[*best_index]->GetAddr();
    VLOG(7) << "[size-sched] best node = " << m_last_choose_node;
    return true;
}

bool SizeScheduler::FindBestTablet(TabletNodePtr src_node, TabletNodePtr dst_node,
                                   const std::vector<TabletPtr>& tablet_list,
                                   const std::string& table_name,
                                   size_t* best_index) {
    VLOG(7) << "[size-sched] FindBestTablet() " << src_node->GetAddr()
            << " -> " << dst_node->GetAddr();

    SizeGetter size_getter;
    int64_t src_node_size = size_getter(src_node, table_name);
    int64_t dst_node_size = size_getter(dst_node, table_name);

    const double& size_ratio = FLAGS_tera_master_load_balance_size_ratio_trigger;
    if ((double)src_node_size < (double)dst_node_size * size_ratio) {
        VLOG(7) << "[size-sched] size ratio not reach threshold: " << src_node_size
                << " : " << dst_node_size;
        return false;
    }

    QPSGetter qps_getter;
    uint64_t src_node_qps = qps_getter(src_node, table_name);
    uint64_t dst_node_qps = qps_getter(dst_node, table_name);

    const double& qps_ratio = FLAGS_tera_master_load_balance_qps_ratio_trigger;
    if (dst_node_qps != 0
            && (double)src_node_qps * qps_ratio <= (double)dst_node_qps) {
        VLOG(7) << "[size-sched] revert qps ratio reach threshold: " << src_node_qps
                << " : " << dst_node_qps;
        return false;
    }

    int64_t ideal_move_size = (src_node_size - dst_node_size) / 2;
    VLOG(7) << "[size-sched] size = " << src_node_size << " : " << dst_node_size
            << " qps = " << src_node_qps << " : " << dst_node_qps
            << " ideal_move_size = " << ideal_move_size;

    int64_t best_tablet_index = -1;
    int64_t best_tablet_size = 0;
    int64_t best_tablet_qps = 0;
    for (size_t i = 0; i < tablet_list.size(); ++i) {
        TabletPtr tablet = tablet_list[i];
        int64_t size = size_getter(tablet);
        int64_t qps = qps_getter(tablet);
        if (size <= ideal_move_size
                && (dst_node_qps == 0 && qps == 0
                    || (src_node_qps - qps) * qps_ratio > (dst_node_qps + qps))
                && (best_tablet_index == -1 || size > best_tablet_size)) {
            best_tablet_index = i;
            best_tablet_size = size;
            best_tablet_qps = qps;
        }
    }
    if (best_tablet_index == -1) {
        return false;
    }
    *best_index = best_tablet_index;
    TabletPtr best_tablet = tablet_list[best_tablet_index];
    VLOG(7) << "[size-sched] best tablet = " << best_tablet->GetPath()
            << " size = " << best_tablet_size
            << " qps = " << best_tablet_qps;
    return true;
}

void SizeScheduler::AscendingSort(std::vector<TabletNodePtr>& node_list,
                                  const std::string& table_name) {
    SizeComparator comparator;
    WorkloadLess less(&comparator, table_name);
    std::sort(node_list.begin(), node_list.end(), less);
}

void SizeScheduler::DescendingSort(std::vector<TabletNodePtr>& node_list,
                                   const std::string& table_name) {
    SizeComparator comparator;
    WorkloadGreater greater(&comparator, table_name);
    std::sort(node_list.begin(), node_list.end(), greater);
}

/////////////////////////////////////////////////
//                QPSScheduler
/////////////////////////////////////////////////

bool QPSScheduler::FindBestNode(const std::vector<TabletNodePtr>& node_list,
                                const std::string& table_name,
                                size_t* best_index) {
    if (node_list.size() == 0) {
        return false;
    }

    QPSComparator comparator;
    *best_index = 0;
    for (size_t i = 1; i < node_list.size(); ++i) {
        int r = comparator.Compare(node_list[*best_index], node_list[i], table_name);
        if (r > 0) {
            *best_index = i;
        } else if (r < 0) {
            // do nothing
        } else if (node_list[*best_index]->GetAddr() <= m_last_choose_node
            && node_list[i]->GetAddr() > m_last_choose_node) {
            // round-robin
            *best_index = i;
        }
    }
    m_last_choose_node = node_list[*best_index]->GetAddr();
    VLOG(7) << "[QPS-sched] best node : " << m_last_choose_node;
    return true;
}

bool QPSScheduler::FindBestTablet(TabletNodePtr src_node, TabletNodePtr dst_node,
                                  const std::vector<TabletPtr>& tablet_list,
                                  const std::string& table_name,
                                  size_t* best_index) {
    VLOG(7) << "[QPS-sched] FindBestTablet() " << src_node->GetAddr()
            << " -> " << dst_node->GetAddr();

    SizeGetter size_getter;
    QPSGetter qps_getter;
    int64_t src_node_qps = qps_getter(src_node, table_name);
    if (src_node_qps < FLAGS_tera_master_load_balance_qps_min_limit) {
        VLOG(7) << "qps not reach min limit: " << src_node_qps;
        return false;
    }

    int64_t dst_node_qps = qps_getter(dst_node, table_name);
    const double& qps_ratio = FLAGS_tera_master_load_balance_qps_ratio_trigger;
    if ((double)src_node_qps < (double)dst_node_qps * qps_ratio) {
        VLOG(7) << "qps ratio not reach threshold: " << src_node_qps
                << " : " << dst_node_qps;
        return false;
    }

    int64_t ideal_move_qps = (src_node_qps - dst_node_qps) / 2;
    VLOG(7) << "[QPS-sched] qps = " << src_node_qps << " : " << dst_node_qps
            << " ideal_move_qps = " << ideal_move_qps;

    int64_t best_tablet_index = -1;
    int64_t best_tablet_size = 0;
    int64_t best_tablet_qps = 0;
    for (size_t i = 0; i < tablet_list.size(); ++i) {
        TabletPtr tablet = tablet_list[i];
        int64_t size = size_getter(tablet);
        int64_t qps = qps_getter(tablet);
        if (qps <= ideal_move_qps
                && (best_tablet_index == -1 || qps > best_tablet_qps)) {
            best_tablet_index = i;
            best_tablet_size = size;
            best_tablet_qps = qps;
        }
    }
    if (best_tablet_index == -1) {
        return false;
    }
    if (best_tablet_qps == 0) {
        VLOG(7) << "[QPS-sched] no need to move 0 QPS tablet";
        return false;
    }
    *best_index = best_tablet_index;
    TabletPtr best_tablet = tablet_list[best_tablet_index];
    VLOG(7) << "[QPS-sched] best tablet = " << best_tablet->GetPath()
            << " size = " << best_tablet_size
            << " qps = " << best_tablet_qps;
    return true;
}

void QPSScheduler::AscendingSort(std::vector<TabletNodePtr>& node_list,
                                 const std::string& table_name) {
    QPSComparator comparator;
    WorkloadLess less(&comparator, table_name);
    std::sort(node_list.begin(), node_list.end(), less);
}

void QPSScheduler::DescendingSort(std::vector<TabletNodePtr>& node_list,
                                  const std::string& table_name) {
    QPSComparator comparator;
    WorkloadGreater greater(&comparator, table_name);
    std::sort(node_list.begin(), node_list.end(), greater);
}

} // namespace master
} // namespace tera
<commit_msg>load balance<commit_after>// Copyright (c) 2015, Baidu.com, Inc. All Rights Reserved
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "master/workload_scheduler.h"

#include "glog/logging.h"
#include "master/tablet_manager.h"

DECLARE_double(tera_master_load_balance_size_ratio_trigger);
DECLARE_double(tera_master_load_balance_qps_ratio_trigger);
DECLARE_int32(tera_master_load_balance_qps_min_limit);

namespace tera {
namespace master {

class WorkloadGetter {
public:
    virtual int64_t operator() (const TabletNodePtr& tablet_node,
                                const std::string& table_name = "") const = 0;
    virtual int64_t operator() (const TabletPtr& tablet) const = 0;
    virtual ~WorkloadGetter() {}
};

class WorkloadComparator {
public:
    // Three-way comparison.  Returns value:
    //   < 0 iff "a" < "b",
    //   == 0 iff "a" == "b",
    //   > 0 iff "a" > "b"
    int Compare(const TabletNodePtr& a, const TabletNodePtr& b,
                const std::string& table_name) {
        if (!table_name.empty()) {
            uint64_t a_load = (*m_load_getter)(a, table_name);
            uint64_t b_load = (*m_load_getter)(b, table_name);
            if (a_load < b_load) {
                return -1;
            } else if (a_load > b_load) {
                return 1;
            }
        }

        uint64_t a_load = (*m_load_getter)(a);
        uint64_t b_load = (*m_load_getter)(b);
        if (a_load < b_load) {
            return -1;
        } else if (a_load > b_load) {
            return 1;
        } else if (m_next_comparator != NULL) {
            return m_next_comparator->Compare(a, b, table_name);
        } else {
            return 0;
        }
    }

    int Compare(const TabletPtr& a, const TabletPtr& b) {
        uint64_t a_load = (*m_load_getter)(a);
        uint64_t b_load = (*m_load_getter)(b);
        if (a_load < b_load) {
            return -1;
        } else if (a_load > b_load) {
            return 1;
        } else if (m_next_comparator != NULL) {
            return m_next_comparator->Compare(a, b);
        } else {
            return 0;
        }
    }

    WorkloadComparator(WorkloadGetter* load_getter,
                       bool owns_load_getter = false,
                       WorkloadComparator* next_comparator = NULL,
                       bool owns_next_comparator = false)
        : m_load_getter(load_getter),
          m_owns_load_getter(owns_load_getter),
          m_next_comparator(next_comparator),
          m_owns_next_comparator(owns_next_comparator) {
    }

    virtual ~WorkloadComparator() {
        if (m_owns_next_comparator) {
            delete m_next_comparator;
        }
        if (m_owns_load_getter) {
            delete m_load_getter;
        }
    }

private:
    WorkloadGetter* m_load_getter;
    bool m_owns_load_getter;
    WorkloadComparator* m_next_comparator;
    bool m_owns_next_comparator;
};

class WorkloadLess {
public:
    bool operator() (const TabletNodePtr& a, const TabletNodePtr& b) {
        return m_comparator->Compare(a, b, m_table_name) < 0;
    }
    bool operator() (const TabletPtr& a, const TabletPtr& b) {
        return m_comparator->Compare(a, b) < 0;
    }
    WorkloadLess(WorkloadComparator* comparator, const std::string& table_name = "")
        : m_comparator(comparator), m_table_name(table_name) {}
private:
    WorkloadComparator* m_comparator;
    std::string m_table_name;
};

class WorkloadGreater {
public:
    bool operator() (const TabletNodePtr& a, const TabletNodePtr& b) {
        return m_comparator->Compare(a, b, m_table_name) > 0;
    }
    bool operator() (const TabletPtr& a, const TabletPtr& b) {
        return m_comparator->Compare(a, b) > 0;
    }
    WorkloadGreater(WorkloadComparator* comparator, const std::string& table_name = "")
        : m_comparator(comparator), m_table_name(table_name) {}

private:
    WorkloadComparator* m_comparator;
    std::string m_table_name;
};

class SizeGetter : public WorkloadGetter {
public:
    virtual int64_t operator() (const TabletNodePtr& tabletnode,
                                const std::string& table_name = "") const {
        return tabletnode->GetSize(table_name);
    }
    virtual int64_t operator() (const TabletPtr& tablet) const {
        return tablet->GetDataSize();
    }
    virtual ~SizeGetter() {}
};

class SizeComparator : public WorkloadComparator {
public:
    SizeComparator() : WorkloadComparator(&m_size_getter) {}
private:
    SizeGetter m_size_getter;
};

class QPSGetter : public WorkloadGetter {
public:
    virtual int64_t operator() (const TabletNodePtr& tabletnode,
                                const std::string& table_name = "") const {
        return tabletnode->GetQps(table_name);
    }
    virtual int64_t operator() (const TabletPtr& tablet) const {
        return tablet->GetAverageCounter().read_rows();
    }
    virtual ~QPSGetter() {}
};

class QPSComparator : public WorkloadComparator {
public:
    QPSComparator() : WorkloadComparator(&m_qps_getter) {}
private:
    QPSGetter m_qps_getter;
};

/////////////////////////////////////////////////
//                SizeScheduler
/////////////////////////////////////////////////

bool SizeScheduler::FindBestNode(const std::vector<TabletNodePtr>& node_list,
                                 const std::string& table_name,
                                 size_t* best_index) {
    if (node_list.size() == 0) {
        return false;
    }

    SizeComparator comparator;
    *best_index = 0;
    for (size_t i = 1; i < node_list.size(); ++i) {
        int r = comparator.Compare(node_list[*best_index], node_list[i], table_name);
        if (r > 0) {
            *best_index = i;
        } else if (r < 0) {
            // do nothing
        } else if (node_list[*best_index]->GetAddr() <= m_last_choose_node
            && node_list[i]->GetAddr() > m_last_choose_node) {
            // round-robin
            *best_index = i;
        }
    }
    m_last_choose_node = node_list[*best_index]->GetAddr();
    VLOG(7) << "[size-sched] best node = " << m_last_choose_node;
    return true;
}

bool SizeScheduler::FindBestTablet(TabletNodePtr src_node, TabletNodePtr dst_node,
                                   const std::vector<TabletPtr>& tablet_list,
                                   const std::string& table_name,
                                   size_t* best_index) {
    VLOG(7) << "[size-sched] FindBestTablet() " << src_node->GetAddr()
            << " -> " << dst_node->GetAddr();

    SizeGetter size_getter;
    int64_t src_node_size = size_getter(src_node, table_name);
    int64_t dst_node_size = size_getter(dst_node, table_name);

    const double& size_ratio = FLAGS_tera_master_load_balance_size_ratio_trigger;
    if ((double)src_node_size < (double)dst_node_size * size_ratio) {
        VLOG(7) << "[size-sched] size ratio not reach threshold: " << src_node_size
                << " : " << dst_node_size;
        return false;
    }

    QPSGetter qps_getter;
    uint64_t src_node_qps = qps_getter(src_node, table_name);
    uint64_t dst_node_qps = qps_getter(dst_node, table_name);

    const double& qps_ratio = FLAGS_tera_master_load_balance_qps_ratio_trigger;
    if (dst_node_qps >= FLAGS_tera_master_load_balance_qps_min_limit
            && (double)src_node_qps * qps_ratio <= (double)dst_node_qps) {
        VLOG(7) << "[size-sched] revert qps ratio reach threshold: " << src_node_qps
                << " : " << dst_node_qps;
        return false;
    }

    int64_t ideal_move_size = (src_node_size - dst_node_size) / 2;
    VLOG(7) << "[size-sched] size = " << src_node_size << " : " << dst_node_size
            << " qps = " << src_node_qps << " : " << dst_node_qps
            << " ideal_move_size = " << ideal_move_size;

    int64_t best_tablet_index = -1;
    int64_t best_tablet_size = 0;
    int64_t best_tablet_qps = 0;
    for (size_t i = 0; i < tablet_list.size(); ++i) {
        TabletPtr tablet = tablet_list[i];
        int64_t size = size_getter(tablet);
        int64_t qps = qps_getter(tablet);
        if (size <= ideal_move_size
                && (dst_node_qps + qps < FLAGS_tera_master_load_balance_qps_min_limit
                    || (src_node_qps - qps) * qps_ratio > (dst_node_qps + qps))
                && (best_tablet_index == -1 || size > best_tablet_size)) {
            best_tablet_index = i;
            best_tablet_size = size;
            best_tablet_qps = qps;
        }
    }
    if (best_tablet_index == -1) {
        return false;
    }
    *best_index = best_tablet_index;
    TabletPtr best_tablet = tablet_list[best_tablet_index];
    VLOG(7) << "[size-sched] best tablet = " << best_tablet->GetPath()
            << " size = " << best_tablet_size
            << " qps = " << best_tablet_qps;
    return true;
}

void SizeScheduler::AscendingSort(std::vector<TabletNodePtr>& node_list,
                                  const std::string& table_name) {
    SizeComparator comparator;
    WorkloadLess less(&comparator, table_name);
    std::sort(node_list.begin(), node_list.end(), less);
}

void SizeScheduler::DescendingSort(std::vector<TabletNodePtr>& node_list,
                                   const std::string& table_name) {
    SizeComparator comparator;
    WorkloadGreater greater(&comparator, table_name);
    std::sort(node_list.begin(), node_list.end(), greater);
}

/////////////////////////////////////////////////
//                QPSScheduler
/////////////////////////////////////////////////

bool QPSScheduler::FindBestNode(const std::vector<TabletNodePtr>& node_list,
                                const std::string& table_name,
                                size_t* best_index) {
    if (node_list.size() == 0) {
        return false;
    }

    QPSComparator comparator;
    *best_index = 0;
    for (size_t i = 1; i < node_list.size(); ++i) {
        int r = comparator.Compare(node_list[*best_index], node_list[i], table_name);
        if (r > 0) {
            *best_index = i;
        } else if (r < 0) {
            // do nothing
        } else if (node_list[*best_index]->GetAddr() <= m_last_choose_node
            && node_list[i]->GetAddr() > m_last_choose_node) {
            // round-robin
            *best_index = i;
        }
    }
    m_last_choose_node = node_list[*best_index]->GetAddr();
    VLOG(7) << "[QPS-sched] best node : " << m_last_choose_node;
    return true;
}

bool QPSScheduler::FindBestTablet(TabletNodePtr src_node, TabletNodePtr dst_node,
                                  const std::vector<TabletPtr>& tablet_list,
                                  const std::string& table_name,
                                  size_t* best_index) {
    VLOG(7) << "[QPS-sched] FindBestTablet() " << src_node->GetAddr()
            << " -> " << dst_node->GetAddr();

    SizeGetter size_getter;
    QPSGetter qps_getter;
    int64_t src_node_qps = qps_getter(src_node, table_name);
    if (src_node_qps < FLAGS_tera_master_load_balance_qps_min_limit) {
        VLOG(7) << "qps not reach min limit: " << src_node_qps;
        return false;
    }

    int64_t dst_node_qps = qps_getter(dst_node, table_name);
    const double& qps_ratio = FLAGS_tera_master_load_balance_qps_ratio_trigger;
    if ((double)src_node_qps < (double)dst_node_qps * qps_ratio) {
        VLOG(7) << "qps ratio not reach threshold: " << src_node_qps
                << " : " << dst_node_qps;
        return false;
    }

    int64_t ideal_move_qps = (src_node_qps - dst_node_qps) / 2;
    VLOG(7) << "[QPS-sched] qps = " << src_node_qps << " : " << dst_node_qps
            << " ideal_move_qps = " << ideal_move_qps;

    int64_t best_tablet_index = -1;
    int64_t best_tablet_size = 0;
    int64_t best_tablet_qps = 0;
    for (size_t i = 0; i < tablet_list.size(); ++i) {
        TabletPtr tablet = tablet_list[i];
        int64_t size = size_getter(tablet);
        int64_t qps = qps_getter(tablet);
        if (qps <= ideal_move_qps
                && (best_tablet_index == -1 || qps > best_tablet_qps)) {
            best_tablet_index = i;
            best_tablet_size = size;
            best_tablet_qps = qps;
        }
    }
    if (best_tablet_index == -1) {
        return false;
    }
    if (best_tablet_qps == 0) {
        VLOG(7) << "[QPS-sched] no need to move 0 QPS tablet";
        return false;
    }
    *best_index = best_tablet_index;
    TabletPtr best_tablet = tablet_list[best_tablet_index];
    VLOG(7) << "[QPS-sched] best tablet = " << best_tablet->GetPath()
            << " size = " << best_tablet_size
            << " qps = " << best_tablet_qps;
    return true;
}

void QPSScheduler::AscendingSort(std::vector<TabletNodePtr>& node_list,
                                 const std::string& table_name) {
    QPSComparator comparator;
    WorkloadLess less(&comparator, table_name);
    std::sort(node_list.begin(), node_list.end(), less);
}

void QPSScheduler::DescendingSort(std::vector<TabletNodePtr>& node_list,
                                  const std::string& table_name) {
    QPSComparator comparator;
    WorkloadGreater greater(&comparator, table_name);
    std::sort(node_list.begin(), node_list.end(), greater);
}

} // namespace master
} // namespace tera
<|endoftext|>


<commit_before>/*!
  \copyright (c) RDO-Team, 2011
  \file      main.cpp
  \author      (lord.tiran@gmail.com)
  \date      26.10.2011
  \brief       RDO
  \indent    4T
*/

// ----------------------------------------------------------------------- INCLUDES
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
// ----------------------------------------------------------------------- SYNOPSIS
#include "utils/rdocommon.h"
#include "repository/rdorepository.h"
#include "simulator/service/rdosimwin.h"
#include "app/rdo_console/terminate_codes.h"
#include "app/rdo_console/controller_console_options.h"
#include "app/rdo_console/rdo_console_controller.h"
// --------------------------------------------------------------------------------

#define LOG_FILE_NAME "log.txt"

static ruint g_exitCode = TERMINATION_NORMAL;

int main(int argc, PTR(char) argv[])
{
	RDOControllerConsoleOptions options_controller(argc, argv);
	options_controller.parseOptions();

	tstring model_name;
	options_controller.getModelName(model_name);
	rbool model_exist = fs::exists(model_name);

	boost::filesystem::path path(model_name);
	tstring model_dir = path.parent_path().string();

	if (options_controller.helpQuery())
	{
		return TERMINATION_NORMAL;
	}
	else if (!model_exist && !options_controller.helpQuery())
	{
		std::cout << _T("Model does not exist") << std::endl;
		return TERMINATION_WITH_AN_ERROR_NO_MODEL;
	}

	// simulation

	RDOKernel::init();
	new rdo::service::simulation::RDOThreadSimulator();
	new rdo::repository::RDOThreadRepository();

	PTR(RDOStudioConsoleController) pAppController = new RDOStudioConsoleController();
	ASSERT(pAppController);

	rdo::repository::RDOThreadRepository::OpenFile data(model_name);
	pAppController->broadcastMessage(RDOThread::RT_STUDIO_MODEL_OPEN, &data);
	pAppController->broadcastMessage(RDOThread::RT_STUDIO_MODEL_BUILD      );

	bool simulationSuccessfully = false;

	bool buildError = pAppController->buildError();
	if (buildError)
	{
		StringList buildList;
		pAppController->getBuildLogList(buildList);

		tstring fileName(model_dir + "/" + LOG_FILE_NAME);
		boost::filesystem::remove(fileName);
		std::ofstream stream(fileName.c_str(), std::ios::out);

		stream.clear();
		if (stream.fail()) {
			return TERMINATION_WITH_APP_RUNTIME_ERROR;
		}
		size_t counter = 0;
		size_t size = buildList.size();
		for (StringList::const_iterator it = buildList.begin(); it != buildList.end(); ++it)
		{
			stream << it->c_str();
			if (counter < size - 1)
			{
				stream << std::endl;
			}
			++counter;
		}
		stream.close();

		std::cerr << _T("Build model error") << std::endl;
		g_exitCode = TERMINATION_WITH_AN_ERROR_PARSE_ERROR;
	}
	else
	{
		pAppController->broadcastMessage(RDOThread::RT_STUDIO_MODEL_RUN);

		while (!pAppController->finished())
		{
			kernel->idle();

			if (pAppController->runtimeError())
			{
				std::cout << _T("Run-time error") << std::endl;
				g_exitCode = TERMINATION_WITH_AN_ERROR_RUNTIME_ERROR;
			}
		}
		simulationSuccessfully = pAppController->simulationSuccessfully();

		RDOKernel::close();
	}
	if (simulationSuccessfully)
	{
		std::cout << _T("Simulation finished successfully") << std::endl;
		g_exitCode = TERMINATION_NORMAL;
	}
	else
	{
		std::cout << _T("Simulation completed with errors") << std::endl;
	}
	return g_exitCode;
}
<commit_msg> - updated rdo_console app : updated log build messages in file code<commit_after>/*!
  \copyright (c) RDO-Team, 2011
  \file      main.cpp
  \author      (lord.tiran@gmail.com)
  \date      26.10.2011
  \brief       RDO
  \indent    4T
*/

// ----------------------------------------------------------------------- INCLUDES
#include <boost/filesystem.hpp>
// ----------------------------------------------------------------------- SYNOPSIS
#include "utils/rdocommon.h"
#include "repository/rdorepository.h"
#include "simulator/service/rdosimwin.h"
#include "app/rdo_console/terminate_codes.h"
#include "app/rdo_console/controller_console_options.h"
#include "app/rdo_console/rdo_console_controller.h"
// --------------------------------------------------------------------------------

namespace fs = boost::filesystem;

const tstring LOG_FILE_NAME = _T("log.txt");

static ruint g_exitCode = TERMINATION_NORMAL;

int main(int argc, PTR(char) argv[])
{
	RDOControllerConsoleOptions options_controller(argc, argv);
	options_controller.parseOptions();

	tstring model_name;
	options_controller.getModelName(model_name);
	rbool model_exist = fs::exists(model_name);

	boost::filesystem::path path(model_name);
	tstring model_dir = path.parent_path().string();

	if (options_controller.helpQuery())
	{
		return TERMINATION_NORMAL;
	}
	else if (!model_exist && !options_controller.helpQuery())
	{
		std::cout << _T("Model does not exist") << std::endl;
		return TERMINATION_WITH_AN_ERROR_NO_MODEL;
	}

	// simulation

	RDOKernel::init();
	new rdo::service::simulation::RDOThreadSimulator();
	new rdo::repository::RDOThreadRepository();

	PTR(RDOStudioConsoleController) pAppController = new RDOStudioConsoleController();
	ASSERT(pAppController);

	rdo::repository::RDOThreadRepository::OpenFile data(model_name);
	pAppController->broadcastMessage(RDOThread::RT_STUDIO_MODEL_OPEN, &data);
	pAppController->broadcastMessage(RDOThread::RT_STUDIO_MODEL_BUILD      );

	bool simulationSuccessfully = false;

	bool buildError = pAppController->buildError();
	if (buildError)
	{
		StringList buildList;
		pAppController->getBuildLogList(buildList);

		tstring fileName(model_dir + "/" + LOG_FILE_NAME);
		boost::filesystem::remove(fileName);
		std::ofstream stream(fileName.c_str(), std::ios::out);

		stream.clear();
		if (stream.fail()) {
			return TERMINATION_WITH_APP_RUNTIME_ERROR;
		}
		for (StringList::const_iterator it = buildList.begin(); it != buildList.end(); ++it)
		{
			stream << it->c_str() << std::endl;
		}
		stream.close();

		std::cout << _T("Build model error") << std::endl;
		g_exitCode = TERMINATION_WITH_AN_ERROR_PARSE_ERROR;
	}
	else
	{
		pAppController->broadcastMessage(RDOThread::RT_STUDIO_MODEL_RUN);

		while (!pAppController->finished())
		{
			kernel->idle();

			if (pAppController->runtimeError())
			{
				std::cout << _T("Run-time error") << std::endl;
				g_exitCode = TERMINATION_WITH_AN_ERROR_RUNTIME_ERROR;
			}
		}
		simulationSuccessfully = pAppController->simulationSuccessfully();

		RDOKernel::close();
	}
	if (simulationSuccessfully)
	{
		std::cout << _T("Simulation finished successfully") << std::endl;
		g_exitCode = TERMINATION_NORMAL;
	}
	else
	{
		std::cout << _T("Simulation completed with errors") << std::endl;
	}
	return g_exitCode;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders 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.
 */

#ifndef __MEM_RUBY_SYSTEM_MACHINEID_HH__
#define __MEM_RUBY_SYSTEM_MACHINEID_HH__

#include <iostream>
#include <string>

#include "base/cprintf.hh"
#include "mem/protocol/MachineType.hh"

struct MachineID
{
    MachineType type;
    //! range: 0 ... number of this machine's components in system - 1
    uint32_t num;

    MachineType getType() const { return type; }
    uint32_t getNum() const { return num; }
};

inline std::string
MachineIDToString(MachineID machine)
{
    return csprintf("%s_%d", MachineType_to_string(machine.type), machine.num);
}

inline bool
operator==(const MachineID & obj1, const MachineID & obj2)
{
    return (obj1.type == obj2.type && obj1.num == obj2.num);
}

inline bool
operator!=(const MachineID & obj1, const MachineID & obj2)
{
    return (obj1.type != obj2.type || obj1.num != obj2.num);
}

// Output operator declaration
std::ostream& operator<<(std::ostream& out, const MachineID& obj);

inline std::ostream&
operator<<(std::ostream& out, const MachineID& obj)
{
    if ((obj.type < MachineType_NUM) && (obj.type >= MachineType_FIRST)) {
        out << MachineType_to_string(obj.type);
    } else {
        out << "NULL";
    }
    out << "-";
    out << obj.num;
    out << std::flush;
    return out;
}

#endif // __MEM_RUBY_SYSTEM_MACHINEID_HH__
<commit_msg>Ruby: Fix compilation errors on gcc 4.7 and clang 3.2<commit_after>/*
 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders 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.
 */

#ifndef __MEM_RUBY_SYSTEM_MACHINEID_HH__
#define __MEM_RUBY_SYSTEM_MACHINEID_HH__

#include <iostream>
#include <string>

#include "base/cprintf.hh"
#include "mem/protocol/MachineType.hh"

struct MachineID
{
    MachineType type;
    //! range: 0 ... number of this machine's components in system - 1
    NodeID num;

    MachineType getType() const { return type; }
    NodeID getNum() const { return num; }
};

inline std::string
MachineIDToString(MachineID machine)
{
    return csprintf("%s_%d", MachineType_to_string(machine.type), machine.num);
}

inline bool
operator==(const MachineID & obj1, const MachineID & obj2)
{
    return (obj1.type == obj2.type && obj1.num == obj2.num);
}

inline bool
operator!=(const MachineID & obj1, const MachineID & obj2)
{
    return (obj1.type != obj2.type || obj1.num != obj2.num);
}

// Output operator declaration
std::ostream& operator<<(std::ostream& out, const MachineID& obj);

inline std::ostream&
operator<<(std::ostream& out, const MachineID& obj)
{
    if ((obj.type < MachineType_NUM) && (obj.type >= MachineType_FIRST)) {
        out << MachineType_to_string(obj.type);
    } else {
        out << "NULL";
    }
    out << "-";
    out << obj.num;
    out << std::flush;
    return out;
}

#endif // __MEM_RUBY_SYSTEM_MACHINEID_HH__
<|endoftext|>


<commit_before>#include "mem/st/visitor/XmlDumper.hpp"

namespace mem { namespace st { namespace visitor {

void
XmlDumper::setup ()
{
   *_out << "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
}

bool
XmlDumper::visit (st::Symbol* sym)
{
   switch (sym->Kind())
   {
      case st::MetaKind::ARG:
         visitArgument(st::cast<st::Arg>(sym));
         break;

      case st::MetaKind::ARRAY_TYPE:
         visitArrayType(st::cast<st::ArrayType>(sym));
         break;

      case st::MetaKind::CLASS_TYPE:
         visitClass(st::cast<st::Class>(sym));
         break;

      case st::MetaKind::ENUM_TYPE:
         visitEnumType(st::cast<st::EnumType>(sym));
         break;

      case st::MetaKind::INT_CONSTANT:
         visitIntConstant(st::cast<st::IntConstant>(sym));
         break;

      case st::MetaKind::FIELD:
         visitField(st::cast<st::Field>(sym));
         break;

      case st::MetaKind::FUNCTION:
         visitFunction(st::cast<st::Func>(sym));
         break;

      case st::MetaKind::INT_TYPE:
         visitIntType(st::cast<st::IntType>(sym));
         break;

      case st::MetaKind::NAMESPACE:
         visitNamespace(st::cast<st::Namespace>(sym));
         break;

      case st::MetaKind::POINTER_TYPE:
         visitPointerType(st::cast<st::PointerType>(sym));
         break;

      case st::MetaKind::PRIMITIVE_TYPE:
         visitPrimitiveType(st::cast<st::PrimitiveType>(sym));
         break;

      case st::MetaKind::TUPLE_TYPE:
         visitTupleType(st::cast<st::TupleType>(sym));
         break;

      case st::MetaKind::VAR:
         visitVar(st::cast<st::Var>(sym));
         break;

      default:
         visitUnknown(sym);
   }

   return false;
}

void
XmlDumper::visitChildren (st::Symbol* sym)
{
   st::Symbol::SymbolCollectionIterator i;
   for (i=sym->Children().begin(); i != sym->Children().end(); ++i)
   {
      this->visit(i->second);
   }
}

bool
XmlDumper::visitArgument (st::Arg* s)
{
   *_out << "<Argument name=\"" + s->Name() + "\"";
   if (s->Type() != NULL)
   {
      *_out << " type=\"" + s->Type()->gQualifiedName() + "\"";
   }
   *_out << " />\n";

   return true;
}

bool
XmlDumper::visitArrayType (st::ArrayType* s)
{
   *_out << "<ArrayType name=\"" + s->Name() + "\"";
   if (s->ItemType() != NULL)
   {
      *_out << " base-type=\"" + s->ItemType()->gQualifiedName() + "\"";
   }
   if (s->hasLength())
   {
      *_out << " size=\"" << s->ArrayLength() << "\"";
   }
   *_out << " byte-size=\"" << s->ByteSize() << "\"";
   *_out << " />\n";

   return true;
}

bool
XmlDumper::visitEnumType (st::EnumType* e)
{
   *_out << "<EnumType name=\"" + e->Name() + "\"";
   *_out << " byte-size=\"" << e->ByteSize() << "\"";
   *_out << ">\n";
   this->visitChildren(e);
   *_out << "</EnumType>";

   return true;
}

bool
XmlDumper::visitClass (st::Class* cls_sym)
{
   *_out << "<ClassType name=\"" + cls_sym->Name() + "\"";
   if (cls_sym->ParentClass() != NULL)
   {
      *_out << " parent-class=\"" + cls_sym->ParentClass()->gQualifiedName() + "\"";
   }
   if (cls_sym->DefaultCtor() != NULL)
   {
      *_out << " default-ctor=\"" << cls_sym->DefaultCtor()->gQualifiedName() << "\"";
   }
   *_out << " absolute-field-count=\"" << cls_sym->getAbsoluteFieldCount() << "\"";
   *_out << " byte-size=\"" << cls_sym->ByteSize() << "\"";
   *_out << ">\n";
   this->visitChildren(cls_sym);
   *_out << "</ClassType>";

   return true;
}

bool
XmlDumper::visitField (st::Field* s)
{
   *_out << "<Field name=\"" + s->Name() + "\"";
   if (s->Type() != NULL)
   {
      *_out << " type=\"" + s->Type()->gQualifiedName() + "\"";
   }
   *_out << " />\n";

   return true;
}

bool
XmlDumper::visitFunction (st::Func* func_sym)
{
   *_out << "<Function name=\"" + func_sym->Name() + "\"";
   if (func_sym->ReturnType() != NULL)
   {
      *_out << " return-type=\"" + func_sym->ReturnType()->gQualifiedName() + "\"";
   }
   if (func_sym->Type() != NULL)
   {
      *_out << " type=\"" + func_sym->Type()->gQualifiedName() + "\"";
   }
   if (func_sym->IsVirtual())
   {
      *_out << " virtual=\"true\"";
   }
   *_out << ">\n";
   visitChildren(func_sym);
   *_out << "</Function>";

   return true;
}
bool
XmlDumper::visitIntConstant (st::IntConstant* s)
{
   *_out << "<IntConstant name=\"" << s->Name() << "\"";
   *_out << " byte-size=\"" << s->ByteSize() << "\"";
   *_out << " signed=\"" << (s->IsSigned() ? "true" : "false") << "\"";
   *_out << " />\n";
   return true;
}

bool
XmlDumper::visitIntType (st::IntType* s)
{
   *_out << "<IntType name=\"" + s->Name() + "\"";
   *_out << " byte-size=\"" << s->ByteSize() << "\"";
   *_out << " />\n";

   return true;
}

bool
XmlDumper::visitNamespace (st::Namespace* ns_sym)
{
   *_out << "<Namespace name=\"" << ns_sym->Name() << "\">\n";
   visitChildren(ns_sym);
   *_out << "</Namespace>";

   return true;
}

bool
XmlDumper::visitPointerType (st::PointerType* s)
{
   *_out << "<PointerType name=\"" + s->Name() + "\"";
   if (s->PointedType() != NULL)
   {
      *_out << " base-type=\"" + s->PointedType()->gQualifiedName() + "\"";
   }
   *_out << " byte-size=\"" << s->ByteSize() << "\"";
   *_out << " />\n";

   return true;
}

bool
XmlDumper::visitPrimitiveType (st::PrimitiveType* s)
{
   *_out << "<PrimitiveType name=\"" + s->Name() + "\"";
   *_out << " byte-size=\"" << s->ByteSize() << "\"";
   *_out << " />\n";

   return true;
}

bool
XmlDumper::visitTupleType (st::TupleType* s)
{
   *_out << "<TupleType name=\"" + s->Name() + "\"";
   *_out << " byte-size=\"" << s->ByteSize() << "\"";
   if (s->hasChildren())
   {
      *_out << ">\n";
      visitChildren(s);
      *_out << "</TupleType>\n";
   }
   else
   {
      *_out << " />\n";
   }

   return true;
}

bool
XmlDumper::visitVar (st::Var* var_sym)
{
   *_out << "<Variable name=\"" + var_sym->Name() + "\"";
   if (var_sym->Type() != NULL)
   {
      *_out << " type=\"" + var_sym->Type()->gQualifiedName() + "\"";
   }
   *_out << " constant=\"" << (var_sym->IsConstant() ? "true" : "false") << "\"";
   *_out << " global=\"" << (var_sym->IsGlobal() ? "true" : "false") << "\"";
   if (var_sym->ConstantValue() != NULL)
   {
      *_out << " constant-value=\"" << var_sym->ConstantValue()->gQualifiedName() << "\"";
   }
   *_out << " />\n";

   return true;
}

bool
XmlDumper::visitUnknown (st::Symbol* sym)
{
   *_out << "<Unknown name=\"" + sym->Name() + "\">\n";
   visitChildren(sym);
   *_out << "</Unknown>";

   return true;
}

} } }
<commit_msg>Dump enum parent type in ST XML dump<commit_after>#include "mem/st/visitor/XmlDumper.hpp"

namespace mem { namespace st { namespace visitor {

void
XmlDumper::setup ()
{
   *_out << "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
}

bool
XmlDumper::visit (st::Symbol* sym)
{
   switch (sym->Kind())
   {
      case st::MetaKind::ARG:
         visitArgument(st::cast<st::Arg>(sym));
         break;

      case st::MetaKind::ARRAY_TYPE:
         visitArrayType(st::cast<st::ArrayType>(sym));
         break;

      case st::MetaKind::CLASS_TYPE:
         visitClass(st::cast<st::Class>(sym));
         break;

      case st::MetaKind::ENUM_TYPE:
         visitEnumType(st::cast<st::EnumType>(sym));
         break;

      case st::MetaKind::INT_CONSTANT:
         visitIntConstant(st::cast<st::IntConstant>(sym));
         break;

      case st::MetaKind::FIELD:
         visitField(st::cast<st::Field>(sym));
         break;

      case st::MetaKind::FUNCTION:
         visitFunction(st::cast<st::Func>(sym));
         break;

      case st::MetaKind::INT_TYPE:
         visitIntType(st::cast<st::IntType>(sym));
         break;

      case st::MetaKind::NAMESPACE:
         visitNamespace(st::cast<st::Namespace>(sym));
         break;

      case st::MetaKind::POINTER_TYPE:
         visitPointerType(st::cast<st::PointerType>(sym));
         break;

      case st::MetaKind::PRIMITIVE_TYPE:
         visitPrimitiveType(st::cast<st::PrimitiveType>(sym));
         break;

      case st::MetaKind::TUPLE_TYPE:
         visitTupleType(st::cast<st::TupleType>(sym));
         break;

      case st::MetaKind::VAR:
         visitVar(st::cast<st::Var>(sym));
         break;

      default:
         visitUnknown(sym);
   }

   return false;
}

void
XmlDumper::visitChildren (st::Symbol* sym)
{
   st::Symbol::SymbolCollectionIterator i;
   for (i=sym->Children().begin(); i != sym->Children().end(); ++i)
   {
      this->visit(i->second);
   }
}

bool
XmlDumper::visitArgument (st::Arg* s)
{
   *_out << "<Argument name=\"" + s->Name() + "\"";
   if (s->Type() != NULL)
   {
      *_out << " type=\"" + s->Type()->gQualifiedName() + "\"";
   }
   *_out << " />\n";

   return true;
}

bool
XmlDumper::visitArrayType (st::ArrayType* s)
{
   *_out << "<ArrayType name=\"" + s->Name() + "\"";
   if (s->ItemType() != NULL)
   {
      *_out << " base-type=\"" + s->ItemType()->gQualifiedName() + "\"";
   }
   if (s->hasLength())
   {
      *_out << " size=\"" << s->ArrayLength() << "\"";
   }
   *_out << " byte-size=\"" << s->ByteSize() << "\"";
   *_out << " />\n";

   return true;
}

bool
XmlDumper::visitEnumType (st::EnumType* e)
{
   *_out << "<EnumType name=\"" + e->Name() + "\"";
   *_out << " byte-size=\"" << e->ByteSize() << "\"";
   if (e->ParentType() != NULL)
   {
      *_out << " parent-type=\"" + e->ParentType()->gQualifiedName() + "\"";
   }
   *_out << ">\n";
   this->visitChildren(e);
   *_out << "</EnumType>";

   return true;
}

bool
XmlDumper::visitClass (st::Class* cls_sym)
{
   *_out << "<ClassType name=\"" + cls_sym->Name() + "\"";
   if (cls_sym->ParentClass() != NULL)
   {
      *_out << " parent-class=\"" + cls_sym->ParentClass()->gQualifiedName() + "\"";
   }
   if (cls_sym->DefaultCtor() != NULL)
   {
      *_out << " default-ctor=\"" << cls_sym->DefaultCtor()->gQualifiedName() << "\"";
   }
   *_out << " absolute-field-count=\"" << cls_sym->getAbsoluteFieldCount() << "\"";
   *_out << " byte-size=\"" << cls_sym->ByteSize() << "\"";
   *_out << ">\n";
   this->visitChildren(cls_sym);
   *_out << "</ClassType>";

   return true;
}

bool
XmlDumper::visitField (st::Field* s)
{
   *_out << "<Field name=\"" + s->Name() + "\"";
   if (s->Type() != NULL)
   {
      *_out << " type=\"" + s->Type()->gQualifiedName() + "\"";
   }
   *_out << " />\n";

   return true;
}

bool
XmlDumper::visitFunction (st::Func* func_sym)
{
   *_out << "<Function name=\"" + func_sym->Name() + "\"";
   if (func_sym->ReturnType() != NULL)
   {
      *_out << " return-type=\"" + func_sym->ReturnType()->gQualifiedName() + "\"";
   }
   if (func_sym->Type() != NULL)
   {
      *_out << " type=\"" + func_sym->Type()->gQualifiedName() + "\"";
   }
   if (func_sym->IsVirtual())
   {
      *_out << " virtual=\"true\"";
   }
   *_out << ">\n";
   visitChildren(func_sym);
   *_out << "</Function>";

   return true;
}
bool
XmlDumper::visitIntConstant (st::IntConstant* s)
{
   *_out << "<IntConstant name=\"" << s->Name() << "\"";
   *_out << " byte-size=\"" << s->ByteSize() << "\"";
   *_out << " signed=\"" << (s->IsSigned() ? "true" : "false") << "\"";
   *_out << " />\n";
   return true;
}

bool
XmlDumper::visitIntType (st::IntType* s)
{
   *_out << "<IntType name=\"" + s->Name() + "\"";
   *_out << " byte-size=\"" << s->ByteSize() << "\"";
   *_out << " />\n";

   return true;
}

bool
XmlDumper::visitNamespace (st::Namespace* ns_sym)
{
   *_out << "<Namespace name=\"" << ns_sym->Name() << "\">\n";
   visitChildren(ns_sym);
   *_out << "</Namespace>";

   return true;
}

bool
XmlDumper::visitPointerType (st::PointerType* s)
{
   *_out << "<PointerType name=\"" + s->Name() + "\"";
   if (s->PointedType() != NULL)
   {
      *_out << " base-type=\"" + s->PointedType()->gQualifiedName() + "\"";
   }
   *_out << " byte-size=\"" << s->ByteSize() << "\"";
   *_out << " />\n";

   return true;
}

bool
XmlDumper::visitPrimitiveType (st::PrimitiveType* s)
{
   *_out << "<PrimitiveType name=\"" + s->Name() + "\"";
   *_out << " byte-size=\"" << s->ByteSize() << "\"";
   *_out << " />\n";

   return true;
}

bool
XmlDumper::visitTupleType (st::TupleType* s)
{
   *_out << "<TupleType name=\"" + s->Name() + "\"";
   *_out << " byte-size=\"" << s->ByteSize() << "\"";
   if (s->hasChildren())
   {
      *_out << ">\n";
      visitChildren(s);
      *_out << "</TupleType>\n";
   }
   else
   {
      *_out << " />\n";
   }

   return true;
}

bool
XmlDumper::visitVar (st::Var* var_sym)
{
   *_out << "<Variable name=\"" + var_sym->Name() + "\"";
   if (var_sym->Type() != NULL)
   {
      *_out << " type=\"" + var_sym->Type()->gQualifiedName() + "\"";
   }
   *_out << " constant=\"" << (var_sym->IsConstant() ? "true" : "false") << "\"";
   *_out << " global=\"" << (var_sym->IsGlobal() ? "true" : "false") << "\"";
   if (var_sym->ConstantValue() != NULL)
   {
      *_out << " constant-value=\"" << var_sym->ConstantValue()->gQualifiedName() << "\"";
   }
   *_out << " />\n";

   return true;
}

bool
XmlDumper::visitUnknown (st::Symbol* sym)
{
   *_out << "<Unknown name=\"" + sym->Name() + "\">\n";
   visitChildren(sym);
   *_out << "</Unknown>";

   return true;
}

} } }
<|endoftext|>


<commit_before>/*
 Copyright (c) 2016, Ford Motor Company
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:

 Redistributions of source code must retain the above copyright notice, this
 list of conditions and the following disclaimer.

 Redistributions in binary form must reproduce the above copyright notice,
 this list of conditions and the following
 disclaimer in the documentation and/or other materials provided with the
 distribution.

 Neither the name of the Ford Motor Company 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 HOLDER OR CONTRIBUTORS BE
 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
 */

#include <cstring>
#include <cstdio>
#include <string>
#include "application_manager/commands/mobile/on_system_request_notification.h"
#include "interfaces/MOBILE_API.h"
#include "utils/file_system.h"
#include "application_manager/application_manager_impl.h"
#include "application_manager/policies/policy_handler.h"

namespace application_manager {

namespace commands {

namespace mobile {

OnSystemRequestNotification::OnSystemRequestNotification(
    const MessageSharedPtr& message)
    : CommandNotificationImpl(message) {}

OnSystemRequestNotification::~OnSystemRequestNotification() {}

void OnSystemRequestNotification::Run() {
  LOG4CXX_AUTO_TRACE(logger_);
  using namespace application_manager;
  using namespace mobile_apis;

  ApplicationSharedPtr app =
      ApplicationManagerImpl::instance()->application(connection_key());

  if (!app.valid()) {
    LOG4CXX_ERROR(logger_,
                  "Application with connection key " << connection_key()
                                                     << " is not registered.");
    return;
  }

  RequestType::eType request_type = static_cast<RequestType::eType>(
      (*message_)[strings::msg_params][strings::request_type].asInt());

  if (!policy::PolicyHandler::instance()->IsRequestTypeAllowed(
        app->mobile_app_id(), request_type)) {
    LOG4CXX_WARN(logger_,
                 "Request type " << request_type
                                 << " is not allowed by policies");
    return;
  }

  if (RequestType::PROPRIETARY == request_type) {
/* According to requirements:
   "If the requestType = PROPRIETARY, add to mobile API fileType = JSON
    If the requestType = HTTP, add to mobile API fileType = BINARY"
   Also in Genivi SDL we don't save the PT to file - we put it directly in
   binary_data */

#ifdef EXTENDED_POLICY
    const std::string filename =
        (*message_)[strings::msg_params][strings::file_name].asString();

    BinaryMessage binary_data;
    file_system::ReadBinaryFile(filename, binary_data);
    AddHeader(binary_data);
    (*message_)[strings::params][strings::binary_data] = binary_data;
#endif
    (*message_)[strings::msg_params][strings::file_type] = FileType::JSON;
  } else if (RequestType::HTTP == request_type) {
    (*message_)[strings::msg_params][strings::file_type] = FileType::BINARY;
  }

  SendNotification();
}

#ifdef EXTENDED_POLICY
void OnSystemRequestNotification::AddHeader(BinaryMessage& message) const {
  LOG4CXX_AUTO_TRACE(logger_);
  const int timeout = policy::PolicyHandler::instance()->TimeoutExchange();

  char size_str[24];

  if (0 > sprintf(size_str, "%lu", message.size())) {
    memset(size_str, 0, sizeof(size_str));
  }

  char timeout_str[24];
  if (0 > sprintf(timeout_str, "%d", timeout)) {
    memset(timeout_str, 0, sizeof(timeout_str));
  }

  const std::string header =

  "{"
     " \"HTTPRequest\": {"
          "\"headers\": {"
              "\"ContentType\": \"application/json\","
              "\"ConnectTimeout\": " + std::string(timeout_str) + ","
              "\"DoOutput\": true,"
              "\"DoInput\": true,"
              "\"UseCaches\": false,"
              "\"RequestMethod\": \"POST\","
              "\"ReadTimeout\":" + std::string(timeout_str) + ","
              "\"InstanceFollowRedirects\": false,"
              "\"charset\": \"utf-8\","
              "\"Content_Length\": " + std::string(size_str) +
          "},"
          "\"body\": \"" + std::string(message.begin(), message.end()) + "\""
      "}"
  "}";

  message.clear();
  message.assign(header.begin(), header.end());

  LOG4CXX_DEBUG(
      logger_, "Header added: " << std::string(message.begin(), message.end()));
}
#endif

}  //namespace mobile

}  // namespace commands

}  // namespace application_manager
<commit_msg>Fixes build warning for 32-bit Ubuntu<commit_after>/*
 Copyright (c) 2016, Ford Motor Company
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:

 Redistributions of source code must retain the above copyright notice, this
 list of conditions and the following disclaimer.

 Redistributions in binary form must reproduce the above copyright notice,
 this list of conditions and the following
 disclaimer in the documentation and/or other materials provided with the
 distribution.

 Neither the name of the Ford Motor Company 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 HOLDER OR CONTRIBUTORS BE
 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
 */

#include <cstring>
#include <cstdio>
#include <string>
#include "application_manager/commands/mobile/on_system_request_notification.h"
#include "interfaces/MOBILE_API.h"
#include "utils/file_system.h"
#include "application_manager/application_manager_impl.h"
#include "application_manager/policies/policy_handler.h"

namespace application_manager {

namespace commands {

namespace mobile {

OnSystemRequestNotification::OnSystemRequestNotification(
    const MessageSharedPtr& message)
    : CommandNotificationImpl(message) {}

OnSystemRequestNotification::~OnSystemRequestNotification() {}

void OnSystemRequestNotification::Run() {
  LOG4CXX_AUTO_TRACE(logger_);
  using namespace application_manager;
  using namespace mobile_apis;

  ApplicationSharedPtr app =
      ApplicationManagerImpl::instance()->application(connection_key());

  if (!app.valid()) {
    LOG4CXX_ERROR(logger_,
                  "Application with connection key " << connection_key()
                                                     << " is not registered.");
    return;
  }

  RequestType::eType request_type = static_cast<RequestType::eType>(
      (*message_)[strings::msg_params][strings::request_type].asInt());

  if (!policy::PolicyHandler::instance()->IsRequestTypeAllowed(
        app->mobile_app_id(), request_type)) {
    LOG4CXX_WARN(logger_,
                 "Request type " << request_type
                                 << " is not allowed by policies");
    return;
  }

  if (RequestType::PROPRIETARY == request_type) {
/* According to requirements:
   "If the requestType = PROPRIETARY, add to mobile API fileType = JSON
    If the requestType = HTTP, add to mobile API fileType = BINARY"
   Also in Genivi SDL we don't save the PT to file - we put it directly in
   binary_data */

#ifdef EXTENDED_POLICY
    const std::string filename =
        (*message_)[strings::msg_params][strings::file_name].asString();

    BinaryMessage binary_data;
    file_system::ReadBinaryFile(filename, binary_data);
    AddHeader(binary_data);
    (*message_)[strings::params][strings::binary_data] = binary_data;
#endif
    (*message_)[strings::msg_params][strings::file_type] = FileType::JSON;
  } else if (RequestType::HTTP == request_type) {
    (*message_)[strings::msg_params][strings::file_type] = FileType::BINARY;
  }

  SendNotification();
}

#ifdef EXTENDED_POLICY
void OnSystemRequestNotification::AddHeader(BinaryMessage& message) const {
  LOG4CXX_AUTO_TRACE(logger_);
  const int timeout = policy::PolicyHandler::instance()->TimeoutExchange();

  char size_str[24];

  if (0 > sprintf(size_str, "%zu", static_cast<size_t>(message.size()))) {
    memset(size_str, 0, sizeof(size_str));
  }

  char timeout_str[24];
  if (0 > sprintf(timeout_str, "%d", timeout)) {
    memset(timeout_str, 0, sizeof(timeout_str));
  }

  const std::string header =

  "{"
     " \"HTTPRequest\": {"
          "\"headers\": {"
              "\"ContentType\": \"application/json\","
              "\"ConnectTimeout\": " + std::string(timeout_str) + ","
              "\"DoOutput\": true,"
              "\"DoInput\": true,"
              "\"UseCaches\": false,"
              "\"RequestMethod\": \"POST\","
              "\"ReadTimeout\":" + std::string(timeout_str) + ","
              "\"InstanceFollowRedirects\": false,"
              "\"charset\": \"utf-8\","
              "\"Content_Length\": " + std::string(size_str) +
          "},"
          "\"body\": \"" + std::string(message.begin(), message.end()) + "\""
      "}"
  "}";

  message.clear();
  message.assign(header.begin(), header.end());

  LOG4CXX_DEBUG(
      logger_, "Header added: " << std::string(message.begin(), message.end()));
}
#endif

}  //namespace mobile

}  // namespace commands

}  // namespace application_manager
<|endoftext|>


<commit_before>/**
 * @file llupdaterservice.cpp
 *
 * $LicenseInfo:firstyear=2010&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include "linden_common.h"
#include <boost/format.hpp>
#include "llhttpclient.h"
#include "llupdatechecker.h"

class LLUpdateChecker::Implementation:
	public LLHTTPClient::Responder
{
public:

	Implementation(Client & client);
	~Implementation();
	void check(std::string const & host, std::string channel, std::string version);

	// Responder:
	virtual void completed(U32 status,
						   const std::string & reason,
						   const LLSD& content);
	virtual void error(U32 status, const std::string & reason);

private:
	std::string buildUrl(std::string const & host, std::string channel, std::string version);

	Client & mClient;
	LLHTTPClient mHttpClient;
	bool mInProgress;
	LLHTTPClient::ResponderPtr mMe;
	std::string mVersion;

	LOG_CLASS(LLUpdateChecker::Implementation);
};

// LLUpdateChecker
//-----------------------------------------------------------------------------

LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client):
	mImplementation(new LLUpdateChecker::Implementation(client))
{
	; // No op.
}

void LLUpdateChecker::check(std::string const & host, std::string channel, std::string version)
{
	mImplementation->check(host, channel, version);
}

// LLUpdateChecker::Implementation
//-----------------------------------------------------------------------------

LLUpdateChecker::Implementation::Implementation(LLUpdateChecker::Client & client):
	mClient(client),
	mInProgress(false),
	mMe(this)
{
	; // No op.
}

LLUpdateChecker::Implementation::~Implementation()
{
	mMe.reset(0);
}

void LLUpdateChecker::Implementation::check(std::string const & host, std::string channel, std::string version)
{
	// llassert(!mInProgress);

	mInProgress = true;
	mVersion = version;
	std::string checkUrl = buildUrl(host, channel, version);
	LL_INFOS("UpdateCheck") << "checking for updates at " << checkUrl << llendl;
	mHttpClient.get(checkUrl, mMe);
}

void LLUpdateChecker::Implementation::completed(U32 status,
							  const std::string & reason,
							  const LLSD & content)
{
	mInProgress = false;

	if(status != 200) {
		LL_WARNS("UpdateCheck") << "html error " << status << " (" << reason << ")" << llendl;
		mClient.error(reason);
	} else if(!content["valid"].asBoolean()) {
		LL_INFOS("UpdateCheck") << "version invalid" << llendl;
		mClient.requiredUpdate(content["latest_version"].asString());
	} else if(content["latest_version"].asString() != mVersion) {
		LL_INFOS("UpdateCheck") << "newer version " << content["latest_version"].asString() << " available" << llendl;
		mClient.optionalUpdate(content["latest_version"].asString());
	} else {
		LL_INFOS("UpdateCheck") << "up to date" << llendl;
		mClient.upToDate();
	}
}

void LLUpdateChecker::Implementation::error(U32 status, const std::string & reason)
{
	mInProgress = false;
	LL_WARNS("UpdateCheck") << "update check failed; " << reason << llendl;
}

std::string LLUpdateChecker::Implementation::buildUrl(std::string const & host, std::string channel, std::string version)
{
	static boost::format urlFormat("%s/version/%s/%s");
	urlFormat % host % channel % version;
	return urlFormat.str();
}

<commit_msg>fix quoting of url in version check.<commit_after>/**
 * @file llupdaterservice.cpp
 *
 * $LicenseInfo:firstyear=2010&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include "linden_common.h"
#include <boost/format.hpp>
#include "llhttpclient.h"
#include "llsd.h"
#include "llupdatechecker.h"
#include "lluri.h"

class LLUpdateChecker::Implementation:
	public LLHTTPClient::Responder
{
public:

	Implementation(Client & client);
	~Implementation();
	void check(std::string const & host, std::string channel, std::string version);

	// Responder:
	virtual void completed(U32 status,
						   const std::string & reason,
						   const LLSD& content);
	virtual void error(U32 status, const std::string & reason);

private:
	std::string buildUrl(std::string const & host, std::string channel, std::string version);

	Client & mClient;
	LLHTTPClient mHttpClient;
	bool mInProgress;
	LLHTTPClient::ResponderPtr mMe;
	std::string mVersion;

	LOG_CLASS(LLUpdateChecker::Implementation);
};

// LLUpdateChecker
//-----------------------------------------------------------------------------

LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client):
	mImplementation(new LLUpdateChecker::Implementation(client))
{
	; // No op.
}

void LLUpdateChecker::check(std::string const & host, std::string channel, std::string version)
{
	mImplementation->check(host, channel, version);
}

// LLUpdateChecker::Implementation
//-----------------------------------------------------------------------------

LLUpdateChecker::Implementation::Implementation(LLUpdateChecker::Client & client):
	mClient(client),
	mInProgress(false),
	mMe(this)
{
	; // No op.
}

LLUpdateChecker::Implementation::~Implementation()
{
	mMe.reset(0);
}

void LLUpdateChecker::Implementation::check(std::string const & host, std::string channel, std::string version)
{
	// llassert(!mInProgress);

	mInProgress = true;
	mVersion = version;
	std::string checkUrl = buildUrl(host, channel, version);
	LL_INFOS("UpdateCheck") << "checking for updates at " << checkUrl << llendl;
	mHttpClient.get(checkUrl, mMe);
}

void LLUpdateChecker::Implementation::completed(U32 status,
							  const std::string & reason,
							  const LLSD & content)
{
	mInProgress = false;

	if(status != 200) {
		LL_WARNS("UpdateCheck") << "html error " << status << " (" << reason << ")" << llendl;
		mClient.error(reason);
	} else if(!content["valid"].asBoolean()) {
		LL_INFOS("UpdateCheck") << "version invalid" << llendl;
		mClient.requiredUpdate(content["latest_version"].asString());
	} else if(content["latest_version"].asString() != mVersion) {
		LL_INFOS("UpdateCheck") << "newer version " << content["latest_version"].asString() << " available" << llendl;
		mClient.optionalUpdate(content["latest_version"].asString());
	} else {
		LL_INFOS("UpdateCheck") << "up to date" << llendl;
		mClient.upToDate();
	}
}

void LLUpdateChecker::Implementation::error(U32 status, const std::string & reason)
{
	mInProgress = false;
	LL_WARNS("UpdateCheck") << "update check failed; " << reason << llendl;
}

std::string LLUpdateChecker::Implementation::buildUrl(std::string const & host, std::string channel, std::string version)
{
	LLSD path;
	path.append("version");
	path.append(channel);
	path.append(version);
	return LLURI::buildHTTP(host, path).asString();
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015 New Designs Unlimited, LLC
 * Opensource Automated License Plate Recognition [http://www.openalpr.com]
 *
 * This file is part of OpenAlpr.
 *
 * OpenAlpr is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License
 * version 3 as published by the Free Software Foundation
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/calib3d/calib3d.hpp>

#include "support/filesystem.h"
#include "../tclap/CmdLine.h"
#include "prewarp.h"

#include <sstream>

using namespace std;
using namespace cv;

const int INSTRUCTIONS_HEIGHT = 32;

bool panning;
bool left_clicking;
Point left_click_start;
Point left_click_cur;

Point lastPos;

float w;
float h;
float panX = 0;
float panY = 0;
float rotationx = 0;
float rotationy = 0;
float rotationz = 0;
float stretchX = 1.0;
float dist = 1.0;

Mat imgOriginal;
Mat curWarpedImage;

alpr::Config config("us");

const string WINDOW_NAME = "Adjust OpenALPR Perspective";

string get_config()
{
  stringstream output;
  output << "planar," << std::fixed;
  output << w << "," << h << ",";
  output << rotationx << "," << rotationy << "," << rotationz << ",";
  output << stretchX << "," << dist << ",";
  output << panX << "," << panY;

  return output.str();
}

void drawImage(Mat img)
{

  config.prewarp = get_config();
  alpr::PreWarp prewarp(&config);

  if (!left_clicking)
  {
    curWarpedImage = prewarp.warpImage(img);
  }

  Mat imgWithInstructions(curWarpedImage.rows + INSTRUCTIONS_HEIGHT, curWarpedImage.cols, curWarpedImage.type());

  curWarpedImage.copyTo(imgWithInstructions(Rect(0, INSTRUCTIONS_HEIGHT, curWarpedImage.cols, curWarpedImage.rows)));

  if (left_clicking)
  {
    Point start = left_click_start;
    Point end = left_click_cur;
    start.y += INSTRUCTIONS_HEIGHT;
    end.y += INSTRUCTIONS_HEIGHT;
    rectangle(imgWithInstructions, start, end, Scalar(255,0,255), 2);
  }

  rectangle(imgWithInstructions, Point(0,0), Point(curWarpedImage.cols, INSTRUCTIONS_HEIGHT), Scalar(255,255,255), -1);

  putText(imgWithInstructions, "Press 'o' to output config to console.",
          Point(5,25), FONT_HERSHEY_DUPLEX, 1.0, Scalar(0,0,0));

  imshow(WINDOW_NAME, imgWithInstructions);

}

void mouse_callback(int event, int x, int y, int flags, void* userdata)
{
  y = y - INSTRUCTIONS_HEIGHT;
  if (y < 0)
    return;

  if (event == EVENT_RBUTTONDOWN)
  {
    lastPos.x = x;
    lastPos.y = y;
    panning = true;
  }
  if (event == EVENT_RBUTTONUP)
  {
    panning = false;
    drawImage(imgOriginal);
  }
  if (event == EVENT_MOUSEMOVE && panning)
  {
    int xdiff = x - lastPos.x;
    int ydiff = y - lastPos.y;
    panX -= xdiff;
    panY -= ydiff;

    lastPos.x = x;
    lastPos.y = y;

    // Reduce the computation by only doing it every 3rd pixel
    if (x % 3 == 0 && y % 3 == 0)
    {
      drawImage(imgOriginal);
    }
  }

  if (event == EVENT_LBUTTONDOWN)
  {
    left_click_start.x = x;
    left_click_start.y = y;
    left_clicking = true;
  }
  if (event == EVENT_LBUTTONUP)
  {
    left_clicking = false;
    drawImage(imgOriginal);
  }
  if (event == EVENT_MOUSEMOVE && left_clicking)
  {
    left_click_cur.x = x;

    float IDEAL_PLATE_RATIO = config.charWidthMM / config.charHeightMM;
    float curWidth = left_click_cur.x - left_click_start.x;

    left_click_cur.y = left_click_start.y + (IDEAL_PLATE_RATIO * curWidth);

    // Reduce the computation by only doing it every 3rd pixel
    if (x % 2 == 0 || y % 2 == 0)
    {
      drawImage(imgOriginal);
    }
  }

}

void ZChange(int pos, void* userdata)
{

  rotationz = -((float)pos - 100) / 100.0;

  drawImage(imgOriginal);
}

void XChange(int pos, void* userdata)
{

  rotationx = -((float)pos - 100) / 20000.0;

  drawImage(imgOriginal);
}

void YChange(int pos, void* userdata)
{
  rotationy = ((float)pos - 100) / 20000.0;

  drawImage(imgOriginal);
}

void DistChange(int pos, void* userdata)
{
  dist = 1.0 - ((float)pos - 100) / 200.0;

  drawImage(imgOriginal);
}

void StretchChange(int pos, void* userdata)
{
  stretchX = 1.0 + ((float)pos - 100) / -200.0;

  drawImage(imgOriginal);
}

int value;
void create_window()
{
  namedWindow(WINDOW_NAME, CV_WINDOW_AUTOSIZE | CV_WINDOW_KEEPRATIO | CV_GUI_EXPANDED);

  value = 100;
  panX = 0;
  panY = 0;

  XChange(100, NULL);
  YChange(100, NULL);
  ZChange(100, NULL);
  DistChange(100, NULL);

    createTrackbar( "X", WINDOW_NAME, &value, 200,  XChange);
    createTrackbar( "Y", WINDOW_NAME, &value, 200,  YChange);
    createTrackbar( "Z", WINDOW_NAME, &value, 200,  ZChange);
    createTrackbar( "W", WINDOW_NAME, &value, 200,  StretchChange);
    createTrackbar( "D", WINDOW_NAME, &value, 200,  DistChange);

  setMouseCallback(WINDOW_NAME, mouse_callback, NULL);

}

/*
 *
 */
int main(int argc, char** argv) {

  string filename;
  string country;
  string config_path;
  string translate_config;
  int max_width;
  int max_height;

  TCLAP::CmdLine cmd("OpenAlpr Perspective Utility", ' ', "0.1");

  TCLAP::UnlabeledValueArg<std::string>  fileArg( "image_file", "Image containing license plates", true, "", "image_file_path"  );

  TCLAP::ValueArg<std::string> countryCodeArg("c","country","Country code to identify (either us for USA or eu for Europe).  Default=us",false, "us" ,"country_code");

  TCLAP::ValueArg<std::string> configFileArg("","config","Path to the openalpr.conf file",false, "" ,"config_file");

  TCLAP::ValueArg<std::string> translateTestArg("t","test","Test an image using the provided translation config",false, "" ,"prewarp config");

  TCLAP::ValueArg<int> maxWidthArg("w", "maxwidth", "Max Width used for displaying image in this utility.  Default=1280",false, 1280 ,"max width");
  TCLAP::ValueArg<int> maxHeightArg("", "maxheight", "Max Height used for displaying image in this utility.  Default=1024",false, 1024 ,"max height");

  try
  {
    cmd.add( configFileArg );
    cmd.add( fileArg );
    cmd.add( countryCodeArg );
    cmd.add( translateTestArg );
    cmd.add( maxWidthArg );
    cmd.add( maxHeightArg );

    if (cmd.parse( argc, argv ) == false)
    {
      // Error occured while parsing.  Exit now.
      return 1;
    }

    filename = fileArg.getValue();
    country = countryCodeArg.getValue();
    config_path = configFileArg.getValue();
    translate_config = translateTestArg.getValue();
    max_width = maxWidthArg.getValue();
    max_height = maxHeightArg.getValue();

  }
  catch (TCLAP::ArgException &e)    // catch any exceptions
  {
    std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl;
    return 1;
  }

  if (!alpr::fileExists(filename.c_str()))
  {
    cerr << "Could not find image file: " << filename << endl;
  }

  config = alpr::Config(country);

  panning = false;
  left_clicking = false;

  imgOriginal = imread(filename);

  if (imgOriginal.cols > max_width)
  {
    float aspect = max_width / ((float)imgOriginal.cols);
    float y = ((float)imgOriginal.rows) * aspect;

    resize(imgOriginal, imgOriginal, Size((int) max_width, (int) y));
  }
  if (imgOriginal.rows > max_height)
  {
    float aspect = max_height / ((float)imgOriginal.rows);
    float x = ((float)imgOriginal.cols) * aspect;

    resize(imgOriginal, imgOriginal, Size((int) x, (int) max_height));
  }

  w = imgOriginal.cols;
  h = imgOriginal.rows;

  create_window();

  if (translate_config != "")
  {
    int first_comma = translate_config.find(",");

    string name = translate_config.substr(0, first_comma);
    stringstream ss(translate_config.substr(first_comma + 1, translate_config.length()));

    ss >> w;
    ss.ignore();
    ss >> h;
    ss.ignore();
    ss >> rotationx;
    ss.ignore();  // Ignore comma
    ss >> rotationy;
    ss.ignore();  // Ignore comma
    ss >> rotationz;
    ss.ignore();  // Ignore comma
    ss >> stretchX;
    ss.ignore();  // Ignore comma
    ss >> dist;
    ss.ignore();  // Ignore comma
    ss >> panX;
    ss.ignore();  // Ignore comma
    ss >> panY;

  }

  float width_ratio = w / ((float)imgOriginal.cols);
  float height_ratio = h / ((float)imgOriginal.rows);
  w = imgOriginal.cols;
  h = imgOriginal.rows;
  rotationx *=width_ratio;
  rotationy *=width_ratio;
  panX /= width_ratio;
  panY /= height_ratio;

  drawImage(imgOriginal);

  while (true)
  {

    char c = waitKey(15);

    if (c == 'o')
    {
      cout << "prewarp = " << get_config() << endl;

    }
  }

  cvDestroyAllWindows();

  return 0;
}

<commit_msg>Fixed incorrect aspect ratio for plate overlay in calibrate utility<commit_after>/*
 * Copyright (c) 2015 New Designs Unlimited, LLC
 * Opensource Automated License Plate Recognition [http://www.openalpr.com]
 *
 * This file is part of OpenAlpr.
 *
 * OpenAlpr is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License
 * version 3 as published by the Free Software Foundation
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/calib3d/calib3d.hpp>

#include "support/filesystem.h"
#include "../tclap/CmdLine.h"
#include "prewarp.h"

#include <sstream>

using namespace std;
using namespace cv;

const int INSTRUCTIONS_HEIGHT = 32;

bool panning;
bool left_clicking;
Point left_click_start;
Point left_click_cur;

Point lastPos;

float w;
float h;
float panX = 0;
float panY = 0;
float rotationx = 0;
float rotationy = 0;
float rotationz = 0;
float stretchX = 1.0;
float dist = 1.0;

Mat imgOriginal;
Mat curWarpedImage;

alpr::Config config("us");

const string WINDOW_NAME = "Adjust OpenALPR Perspective";

string get_config()
{
  stringstream output;
  output << "planar," << std::fixed;
  output << w << "," << h << ",";
  output << rotationx << "," << rotationy << "," << rotationz << ",";
  output << stretchX << "," << dist << ",";
  output << panX << "," << panY;

  return output.str();
}

void drawImage(Mat img)
{

  config.prewarp = get_config();
  alpr::PreWarp prewarp(&config);

  if (!left_clicking)
  {
    curWarpedImage = prewarp.warpImage(img);
  }

  Mat imgWithInstructions(curWarpedImage.rows + INSTRUCTIONS_HEIGHT, curWarpedImage.cols, curWarpedImage.type());

  curWarpedImage.copyTo(imgWithInstructions(Rect(0, INSTRUCTIONS_HEIGHT, curWarpedImage.cols, curWarpedImage.rows)));

  if (left_clicking)
  {
    Point start = left_click_start;
    Point end = left_click_cur;
    start.y += INSTRUCTIONS_HEIGHT;
    end.y += INSTRUCTIONS_HEIGHT;
    rectangle(imgWithInstructions, start, end, Scalar(255,0,255), 2);
  }

  rectangle(imgWithInstructions, Point(0,0), Point(curWarpedImage.cols, INSTRUCTIONS_HEIGHT), Scalar(255,255,255), -1);

  putText(imgWithInstructions, "Press 'o' to output config to console.",
          Point(5,25), FONT_HERSHEY_DUPLEX, 1.0, Scalar(0,0,0));

  imshow(WINDOW_NAME, imgWithInstructions);

}

void mouse_callback(int event, int x, int y, int flags, void* userdata)
{
  y = y - INSTRUCTIONS_HEIGHT;
  if (y < 0)
    return;

  if (event == EVENT_RBUTTONDOWN)
  {
    lastPos.x = x;
    lastPos.y = y;
    panning = true;
  }
  if (event == EVENT_RBUTTONUP)
  {
    panning = false;
    drawImage(imgOriginal);
  }
  if (event == EVENT_MOUSEMOVE && panning)
  {
    int xdiff = x - lastPos.x;
    int ydiff = y - lastPos.y;
    panX -= xdiff;
    panY -= ydiff;

    lastPos.x = x;
    lastPos.y = y;

    // Reduce the computation by only doing it every 3rd pixel
    if (x % 3 == 0 && y % 3 == 0)
    {
      drawImage(imgOriginal);
    }
  }

  if (event == EVENT_LBUTTONDOWN)
  {
    left_click_start.x = x;
    left_click_start.y = y;
    left_clicking = true;
  }
  if (event == EVENT_LBUTTONUP)
  {
    left_clicking = false;
    drawImage(imgOriginal);
  }
  if (event == EVENT_MOUSEMOVE && left_clicking)
  {
    left_click_cur.x = x;

    float IDEAL_PLATE_RATIO = config.plateWidthMM / config.plateHeightMM;
    float curWidth = left_click_cur.x - left_click_start.x;

    left_click_cur.y = left_click_start.y + (curWidth / IDEAL_PLATE_RATIO );

    // Reduce the computation by only doing it every 3rd pixel
    if (x % 2 == 0 || y % 2 == 0)
    {
      drawImage(imgOriginal);
    }
  }

}

void ZChange(int pos, void* userdata)
{

  rotationz = -((float)pos - 100) / 100.0;

  drawImage(imgOriginal);
}

void XChange(int pos, void* userdata)
{

  rotationx = -((float)pos - 100) / 20000.0;

  drawImage(imgOriginal);
}

void YChange(int pos, void* userdata)
{
  rotationy = ((float)pos - 100) / 20000.0;

  drawImage(imgOriginal);
}

void DistChange(int pos, void* userdata)
{
  dist = 1.0 - ((float)pos - 100) / 200.0;

  drawImage(imgOriginal);
}

void StretchChange(int pos, void* userdata)
{
  stretchX = 1.0 + ((float)pos - 100) / -200.0;

  drawImage(imgOriginal);
}

int value;
void create_window()
{
  namedWindow(WINDOW_NAME, CV_WINDOW_AUTOSIZE | CV_WINDOW_KEEPRATIO | CV_GUI_EXPANDED);

  value = 100;
  panX = 0;
  panY = 0;

  XChange(100, NULL);
  YChange(100, NULL);
  ZChange(100, NULL);
  DistChange(100, NULL);

    createTrackbar( "X", WINDOW_NAME, &value, 200,  XChange);
    createTrackbar( "Y", WINDOW_NAME, &value, 200,  YChange);
    createTrackbar( "Z", WINDOW_NAME, &value, 200,  ZChange);
    createTrackbar( "W", WINDOW_NAME, &value, 200,  StretchChange);
    createTrackbar( "D", WINDOW_NAME, &value, 200,  DistChange);

  setMouseCallback(WINDOW_NAME, mouse_callback, NULL);

}

/*
 *
 */
int main(int argc, char** argv) {

  string filename;
  string country;
  string config_path;
  string translate_config;
  int max_width;
  int max_height;

  TCLAP::CmdLine cmd("OpenAlpr Perspective Utility", ' ', "0.1");

  TCLAP::UnlabeledValueArg<std::string>  fileArg( "image_file", "Image containing license plates", true, "", "image_file_path"  );

  TCLAP::ValueArg<std::string> countryCodeArg("c","country","Country code to identify (either us for USA or eu for Europe).  Default=us",false, "us" ,"country_code");

  TCLAP::ValueArg<std::string> configFileArg("","config","Path to the openalpr.conf file",false, "" ,"config_file");

  TCLAP::ValueArg<std::string> translateTestArg("t","test","Test an image using the provided translation config",false, "" ,"prewarp config");

  TCLAP::ValueArg<int> maxWidthArg("w", "maxwidth", "Max Width used for displaying image in this utility.  Default=1280",false, 1280 ,"max width");
  TCLAP::ValueArg<int> maxHeightArg("", "maxheight", "Max Height used for displaying image in this utility.  Default=1024",false, 1024 ,"max height");

  try
  {
    cmd.add( configFileArg );
    cmd.add( fileArg );
    cmd.add( countryCodeArg );
    cmd.add( translateTestArg );
    cmd.add( maxWidthArg );
    cmd.add( maxHeightArg );

    if (cmd.parse( argc, argv ) == false)
    {
      // Error occured while parsing.  Exit now.
      return 1;
    }

    filename = fileArg.getValue();
    country = countryCodeArg.getValue();
    config_path = configFileArg.getValue();
    translate_config = translateTestArg.getValue();
    max_width = maxWidthArg.getValue();
    max_height = maxHeightArg.getValue();

  }
  catch (TCLAP::ArgException &e)    // catch any exceptions
  {
    std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl;
    return 1;
  }

  if (!alpr::fileExists(filename.c_str()))
  {
    cerr << "Could not find image file: " << filename << endl;
  }

  config = alpr::Config(country);

  panning = false;
  left_clicking = false;

  imgOriginal = imread(filename);

  if (imgOriginal.cols > max_width)
  {
    float aspect = max_width / ((float)imgOriginal.cols);
    float y = ((float)imgOriginal.rows) * aspect;

    resize(imgOriginal, imgOriginal, Size((int) max_width, (int) y));
  }
  if (imgOriginal.rows > max_height)
  {
    float aspect = max_height / ((float)imgOriginal.rows);
    float x = ((float)imgOriginal.cols) * aspect;

    resize(imgOriginal, imgOriginal, Size((int) x, (int) max_height));
  }

  w = imgOriginal.cols;
  h = imgOriginal.rows;

  create_window();

  if (translate_config != "")
  {
    int first_comma = translate_config.find(",");

    string name = translate_config.substr(0, first_comma);
    stringstream ss(translate_config.substr(first_comma + 1, translate_config.length()));

    ss >> w;
    ss.ignore();
    ss >> h;
    ss.ignore();
    ss >> rotationx;
    ss.ignore();  // Ignore comma
    ss >> rotationy;
    ss.ignore();  // Ignore comma
    ss >> rotationz;
    ss.ignore();  // Ignore comma
    ss >> stretchX;
    ss.ignore();  // Ignore comma
    ss >> dist;
    ss.ignore();  // Ignore comma
    ss >> panX;
    ss.ignore();  // Ignore comma
    ss >> panY;

  }

  float width_ratio = w / ((float)imgOriginal.cols);
  float height_ratio = h / ((float)imgOriginal.rows);
  w = imgOriginal.cols;
  h = imgOriginal.rows;
  rotationx *=width_ratio;
  rotationy *=width_ratio;
  panX /= width_ratio;
  panY /= height_ratio;

  drawImage(imgOriginal);

  while (true)
  {

    char c = waitKey(15);

    if (c == 'o')
    {
      cout << "prewarp = " << get_config() << endl;

    }
  }

  cvDestroyAllWindows();

  return 0;
}

<|endoftext|>