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

#include "agent/resource_collector.h"

#include <errno.h>
#include <string.h>
#include <time.h>

#include <string>
#include <boost/lexical_cast.hpp>
#include "common/logging.h"

namespace galaxy {

#define SAFE_FREE(x) \
    do { \
        if (x != NULL) {\
            free(x); \
            x = NULL; \
        } \
    } while(0)

const std::string CGROUP_MOUNT_PATH = "/cgroups/";
const std::string CPUACT_SUBSYSTEM_PATH = "cpuacct";

static long SYS_TIMER_HZ = sysconf(_SC_CLK_TCK);
static long CPU_CORES = sysconf(_SC_NPROCESSORS_CONF);

// unit jiffies
struct ResourceStatistics {
    // cpu
    long cpu_user_time;
    long cpu_nice_time;
    long cpu_system_time;
    long cpu_idle_time;
    long cpu_iowait_time;
    long cpu_irq_time;
    long cpu_softirq_time;
    long cpu_stealstolen;
    long cpu_guest;

    long cpu_cores;
};

// unit jiffies
struct CgroupResourceStatistics {
    long cpu_user_time;
    long cpu_system_time;

    // cpu_cores from cfs_quota_usota_us
    double cpu_cores_limit;
};

// get cpu usage from /cgroups/cpuacct/xxxxx/cpuacct.stat
// get cpu limit cores from /cgroups/cpu/xxxxx/cpu.cfs_quota_usota_us and cpu.cfs_
static bool GetCgroupCpuUsage(
                const std::string& group_path,
                CgroupResourceStatistics* statistics);

// get total cpu usage from /proc/stat
static bool GetGlobalCpuUsage(ResourceStatistics* statistics);

static bool GetCgroupCpuCoresLimit(
        const std::string& group_path,
        CgroupResourceStatistics* statistics);

class CGroupResourceCollectorImpl {
public:
    CGroupResourceCollectorImpl() {}
    explicit CGroupResourceCollectorImpl(const std::string& cgroup_name)
        : cgroup_name_(cgroup_name),
          global_statistics_prev_(),
          global_statistics_cur_(),
          cgroup_statistics_prev_(),
          cgroup_statistics_cur_(),
          timestamp_prev_(0.0),
          timestamp_cur_(0.0),
          mutex_() {
    }

    virtual ~CGroupResourceCollectorImpl() {}

    virtual bool CollectStatistics();

    double GetCpuUsage();

    long GetMemoryUsage() {return 0;}
private:
    std::string cgroup_name_;
    // global resource statistics
    ResourceStatistics global_statistics_prev_;
    ResourceStatistics global_statistics_cur_;
    // cgroup resource statistics
    CgroupResourceStatistics cgroup_statistics_prev_;
    CgroupResourceStatistics cgroup_statistics_cur_;

    double timestamp_prev_;
    double timestamp_cur_;
    long collector_times_;
    common::Mutex mutex_;
};

double CGroupResourceCollectorImpl::GetCpuUsage() {
    const int MIN_COLLOECT_TIMES_NEED = 2;
    common::MutexLock lock(&mutex_);
    if (collector_times_ < MIN_COLLOECT_TIMES_NEED) {
        LOG(WARNING, "need try agin");
        return 0.0;
    }

    long global_cpu_before =
        global_statistics_prev_.cpu_user_time
        + global_statistics_prev_.cpu_nice_time
        + global_statistics_prev_.cpu_system_time
        + global_statistics_prev_.cpu_idle_time
        + global_statistics_prev_.cpu_iowait_time
        + global_statistics_prev_.cpu_irq_time
        + global_statistics_prev_.cpu_softirq_time
        + global_statistics_prev_.cpu_stealstolen
        + global_statistics_prev_.cpu_guest;

    long global_cpu_after =
        global_statistics_cur_.cpu_user_time
        + global_statistics_cur_.cpu_nice_time
        + global_statistics_cur_.cpu_system_time
        + global_statistics_cur_.cpu_idle_time
        + global_statistics_cur_.cpu_iowait_time
        + global_statistics_cur_.cpu_irq_time
        + global_statistics_cur_.cpu_softirq_time
        + global_statistics_cur_.cpu_stealstolen
        + global_statistics_cur_.cpu_guest;

    long cgroup_cpu_before = cgroup_statistics_prev_.cpu_user_time
        + cgroup_statistics_prev_.cpu_system_time;
    long cgroup_cpu_after = cgroup_statistics_cur_.cpu_user_time
        + cgroup_statistics_cur_.cpu_system_time;

    double radio = cgroup_statistics_cur_.cpu_cores_limit / global_statistics_cur_.cpu_cores;
    LOG(DEBUG, "radio = limit(%f) / cores(%ld)",
            cgroup_statistics_cur_.cpu_cores_limit,
            global_statistics_cur_.cpu_cores);

    double rs = (cgroup_cpu_after - cgroup_cpu_before) / (double)(global_cpu_after - global_cpu_before) ;
    rs /= radio;
    LOG(DEBUG, "p prev :%ld p post:%ld g pre:%ld g post:%ld radir:%f rs:%f",
            cgroup_cpu_before,
            cgroup_cpu_after,
            global_cpu_before,
            global_cpu_after,
            radio,
            rs);
    return rs;
}

bool CGroupResourceCollectorImpl::CollectStatistics() {
    common::MutexLock lock(&mutex_);
    global_statistics_prev_ = global_statistics_cur_;
    cgroup_statistics_prev_ = cgroup_statistics_cur_;
    timestamp_prev_ = timestamp_cur_;

    timestamp_cur_ = time(NULL);

    if (!GetCgroupCpuUsage(cgroup_name_,
                &cgroup_statistics_cur_)) {
        return false;
    }

    if (!GetGlobalCpuUsage(&global_statistics_cur_)) {
        return false;
    }

    if (!GetCgroupCpuCoresLimit(cgroup_name_,
                &cgroup_statistics_cur_)) {
        return false;
    }

    collector_times_ ++;
    return true;
}

// ----------- CGroupResourceCollector implement -----

CGroupResourceCollector::CGroupResourceCollector(
        const std::string& cgroup_name) : impl_(NULL) {
    impl_ = new CGroupResourceCollectorImpl(cgroup_name);
}

bool CGroupResourceCollector::CollectStatistics() {
    return impl_->CollectStatistics();
}

double CGroupResourceCollector::GetCpuUsage() {
    return impl_->GetCpuUsage();
}

long CGroupResourceCollector::GetMemoryUsage() {
    return impl_->GetMemoryUsage();
}

CGroupResourceCollector::~CGroupResourceCollector() {
    delete impl_;
}

// -----------  resource collector utils -------------

bool GetCgroupCpuUsage(
        const std::string& group_path,
        CgroupResourceStatistics* statistics) {
    if (statistics == NULL) {
        return false;
    }
    std::string path = CGROUP_MOUNT_PATH + "/"
        + CPUACT_SUBSYSTEM_PATH + "/" + group_path + "/cpuacct.stat";
    FILE* fin = fopen(path.c_str(), "r");
    if (fin == NULL) {
        LOG(WARNING, "open %s failed", path.c_str());
        return false;
    }

    ssize_t read;
    size_t len = 0;
    char* line = NULL;

    // read user time
    if ((read = getline(&line, &len, fin)) == -1) {
        LOG(WARNING, "read line failed err[%d: %s]",
                errno, strerror(errno));
        fclose(fin);
        return false;
    }

    char cpu_tmp_char[20];
    int item_size = sscanf(line, "%s %ld",
            cpu_tmp_char, &(statistics->cpu_user_time));
    SAFE_FREE(line);

    if (item_size != 2) {
        LOG(WARNING, "read from %s format err", path.c_str());
        fclose(fin);
        return false;
    }

    // read sys time
    if ((read = getline(&line, &len, fin)) == -1) {
        LOG(WARNING, "read line failed err[%d: %s]",
                errno, strerror(errno));
        fclose(fin);
        return false;
    }

    item_size = sscanf(line, "%s %ld",
            cpu_tmp_char, &(statistics->cpu_system_time));
    SAFE_FREE(line);

    if (item_size != 2) {
        LOG(WARNING, "read from %s format err", path.c_str());
        fclose(fin);
        return false;
    }

    fclose(fin);
    return true;
}

bool GetGlobalCpuUsage(ResourceStatistics* statistics) {
    if (statistics == NULL) {
        return false;
    }

    statistics->cpu_cores = CPU_CORES;
    std::string path = "/proc/stat";
    FILE* fin = fopen(path.c_str(), "r");
    if (fin == NULL) {
        LOG(WARNING, "open %s failed", path.c_str());
        return false;
    }

    ssize_t read;
    size_t len = 0;
    char* line = NULL;
    if ((read = getline(&line, &len, fin)) == -1) {
        LOG(WARNING, "read line failed err[%d: %s]",
                errno, strerror(errno));
        fclose(fin);
        return false;
    }
    fclose(fin);

    char cpu[5];
    int item_size = sscanf(line,
                           "%s %ld %ld %ld %ld %ld %ld %ld %ld %ld",
                           cpu,
                           &(statistics->cpu_user_time),
                           &(statistics->cpu_nice_time),
                           &(statistics->cpu_system_time),
                           &(statistics->cpu_idle_time),
                           &(statistics->cpu_iowait_time),
                           &(statistics->cpu_irq_time),
                           &(statistics->cpu_softirq_time),
                           &(statistics->cpu_stealstolen),
                           &(statistics->cpu_guest));

    SAFE_FREE(line);
    if (item_size != 10) {
        LOG(WARNING, "read from /proc/stat format err");
        return false;
    }
    return true;
}

bool GetCgroupCpuCoresLimit(
        const std::string& group_path,
        CgroupResourceStatistics* statistics) {
    std::string period_path = CGROUP_MOUNT_PATH
        + "/cpu/" + group_path + "/cpu.cfs_period_us";
    std::string quota_path = CGROUP_MOUNT_PATH
        + "/cpu/" + group_path + "/cpu.cfs_quota_us";

    FILE* fin = fopen(period_path.c_str(), "r");
    if (fin == NULL) {
        LOG(WARNING, "open %s failed", period_path.c_str());
        return false;
    }

    ssize_t read;
    size_t len = 0;
    char* line = NULL;

    if ((read = getline(&line, &len, fin)) == -1) {
        LOG(WARNING, "read line failed err[%d: %s]", errno, strerror(errno));
        fclose(fin);
        return false;
    }
    fclose(fin);

    long period_time = 0;
    int item_size = sscanf(line, "%ld", &period_time);
    SAFE_FREE(line);
    if (item_size != 1) {
        LOG(WARNING, "read from %s format err", period_path.c_str());
        return false;
    }

    fin = fopen(quota_path.c_str(), "r");
    if (fin == NULL) {
        LOG(WARNING, "open %s failed", quota_path.c_str());
        return false;
    }

    line = NULL;
    len = 0;
    if ((read = getline(&line, &len, fin)) == -1) {
        LOG(WARNING, "read line failed err[%d: %s]", errno, strerror(errno));
        fclose(fin);
        return false;
    }
    fclose(fin);

    long quota_value = 0;
    item_size = sscanf(line, "%ld", &quota_value);
    SAFE_FREE(line);
    if (item_size != 1) {
        LOG(WARNING, "read from %s format err", quota_path.c_str());
        return false;
    }
    LOG(DEBUG, "cpu cores limit : quota(%ld), period(%ld)",
            quota_value,
            period_time);
    statistics->cpu_cores_limit = quota_value * 1.0 / period_time;
    return true;
}

}   // ending namespace galaxy

/* vim: set ts=4 sw=4 sts=4 tw=100 */
<commit_msg>add memory collect<commit_after>// Copyright (c) 2015, Galaxy Authors. All Rights Reserved
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Author: yuanyi03@baidu.com

#include "agent/resource_collector.h"

#include <errno.h>
#include <string.h>
#include <time.h>

#include <string>
#include <boost/lexical_cast.hpp>
#include "common/logging.h"

namespace galaxy {

#define SAFE_FREE(x) \
    do { \
        if (x != NULL) {\
            free(x); \
            x = NULL; \
        } \
    } while(0)

const std::string CGROUP_MOUNT_PATH = "/cgroups/";
const std::string CPUACT_SUBSYSTEM_PATH = "cpuacct";

static long SYS_TIMER_HZ = sysconf(_SC_CLK_TCK);
static long CPU_CORES = sysconf(_SC_NPROCESSORS_CONF);

// unit jiffies
struct ResourceStatistics {
    // cpu
    long cpu_user_time;
    long cpu_nice_time;
    long cpu_system_time;
    long cpu_idle_time;
    long cpu_iowait_time;
    long cpu_irq_time;
    long cpu_softirq_time;
    long cpu_stealstolen;
    long cpu_guest;

    long cpu_cores;
};

// unit jiffies
struct CgroupResourceStatistics {
    long cpu_user_time;
    long cpu_system_time;

    // cpu_cores from cfs_quota_usota_us
    double cpu_cores_limit;

    long memory_rss_in_bytes;
};

// get cpu usage from /cgroups/cpuacct/xxxxx/cpuacct.stat
static bool GetCgroupCpuUsage(
                const std::string& group_path,
                CgroupResourceStatistics* statistics);

// get memory usage from /cgroups/memory/xxxxx/memory.stat
static bool GetCgroupMemoryUsage(
        const std::string& group_path,
        CgroupResourceStatistics* statistics);

// get total cpu usage from /proc/stat
static bool GetGlobalCpuUsage(ResourceStatistics* statistics);

// get cpu limit cores from /cgroups/cpu/xxxxx/cpu.cfs_quota_usota_us and cpu.cfs_
static bool GetCgroupCpuCoresLimit(
        const std::string& group_path,
        CgroupResourceStatistics* statistics);

class CGroupResourceCollectorImpl {
public:
    CGroupResourceCollectorImpl() {}
    explicit CGroupResourceCollectorImpl(const std::string& cgroup_name)
        : cgroup_name_(cgroup_name),
          global_statistics_prev_(),
          global_statistics_cur_(),
          cgroup_statistics_prev_(),
          cgroup_statistics_cur_(),
          timestamp_prev_(0.0),
          timestamp_cur_(0.0),
          mutex_() {
    }

    virtual ~CGroupResourceCollectorImpl() {}

    virtual bool CollectStatistics();

    double GetCpuUsage();

    long GetMemoryUsage() {
        return cgroup_statistics_cur_.memory_rss_in_bytes;
    }
private:
    std::string cgroup_name_;
    // global resource statistics
    ResourceStatistics global_statistics_prev_;
    ResourceStatistics global_statistics_cur_;
    // cgroup resource statistics
    CgroupResourceStatistics cgroup_statistics_prev_;
    CgroupResourceStatistics cgroup_statistics_cur_;

    double timestamp_prev_;
    double timestamp_cur_;
    long collector_times_;
    common::Mutex mutex_;
};

double CGroupResourceCollectorImpl::GetCpuUsage() {
    const int MIN_COLLOECT_TIMES_NEED = 2;
    common::MutexLock lock(&mutex_);
    if (collector_times_ < MIN_COLLOECT_TIMES_NEED) {
        LOG(WARNING, "need try agin");
        return 0.0;
    }

    long global_cpu_before =
        global_statistics_prev_.cpu_user_time
        + global_statistics_prev_.cpu_nice_time
        + global_statistics_prev_.cpu_system_time
        + global_statistics_prev_.cpu_idle_time
        + global_statistics_prev_.cpu_iowait_time
        + global_statistics_prev_.cpu_irq_time
        + global_statistics_prev_.cpu_softirq_time
        + global_statistics_prev_.cpu_stealstolen
        + global_statistics_prev_.cpu_guest;

    long global_cpu_after =
        global_statistics_cur_.cpu_user_time
        + global_statistics_cur_.cpu_nice_time
        + global_statistics_cur_.cpu_system_time
        + global_statistics_cur_.cpu_idle_time
        + global_statistics_cur_.cpu_iowait_time
        + global_statistics_cur_.cpu_irq_time
        + global_statistics_cur_.cpu_softirq_time
        + global_statistics_cur_.cpu_stealstolen
        + global_statistics_cur_.cpu_guest;

    long cgroup_cpu_before = cgroup_statistics_prev_.cpu_user_time
        + cgroup_statistics_prev_.cpu_system_time;
    long cgroup_cpu_after = cgroup_statistics_cur_.cpu_user_time
        + cgroup_statistics_cur_.cpu_system_time;

    double radio = cgroup_statistics_cur_.cpu_cores_limit / global_statistics_cur_.cpu_cores;
    LOG(DEBUG, "radio = limit(%f) / cores(%ld)",
            cgroup_statistics_cur_.cpu_cores_limit,
            global_statistics_cur_.cpu_cores);

    double rs = (cgroup_cpu_after - cgroup_cpu_before) / (double)(global_cpu_after - global_cpu_before) ;
    rs /= radio;
    LOG(DEBUG, "p prev :%ld p post:%ld g pre:%ld g post:%ld radir:%f rs:%f",
            cgroup_cpu_before,
            cgroup_cpu_after,
            global_cpu_before,
            global_cpu_after,
            radio,
            rs);
    return rs;
}

bool CGroupResourceCollectorImpl::CollectStatistics() {
    common::MutexLock lock(&mutex_);
    global_statistics_prev_ = global_statistics_cur_;
    cgroup_statistics_prev_ = cgroup_statistics_cur_;
    timestamp_prev_ = timestamp_cur_;

    timestamp_cur_ = time(NULL);

    if (!GetCgroupCpuUsage(cgroup_name_,
                &cgroup_statistics_cur_)) {
        return false;
    }

    if (!GetGlobalCpuUsage(&global_statistics_cur_)) {
        return false;
    }

    if (!GetCgroupCpuCoresLimit(cgroup_name_,
                &cgroup_statistics_cur_)) {
        return false;
    }

    if (!GetCgroupMemoryUsage(cgroup_name_,
                &cgroup_statistics_cur_)) {
        return false;
    }

    collector_times_ ++;
    return true;
}

// ----------- CGroupResourceCollector implement -----

CGroupResourceCollector::CGroupResourceCollector(
        const std::string& cgroup_name) : impl_(NULL) {
    impl_ = new CGroupResourceCollectorImpl(cgroup_name);
}

bool CGroupResourceCollector::CollectStatistics() {
    return impl_->CollectStatistics();
}

double CGroupResourceCollector::GetCpuUsage() {
    return impl_->GetCpuUsage();
}

long CGroupResourceCollector::GetMemoryUsage() {
    return impl_->GetMemoryUsage();
}

CGroupResourceCollector::~CGroupResourceCollector() {
    delete impl_;
}

// -----------  resource collector utils -------------

bool GetCgroupCpuUsage(
        const std::string& group_path,
        CgroupResourceStatistics* statistics) {
    if (statistics == NULL) {
        return false;
    }
    std::string path = CGROUP_MOUNT_PATH + "/"
        + CPUACT_SUBSYSTEM_PATH + "/" + group_path + "/cpuacct.stat";
    FILE* fin = fopen(path.c_str(), "r");
    if (fin == NULL) {
        LOG(WARNING, "open %s failed", path.c_str());
        return false;
    }

    ssize_t read;
    size_t len = 0;
    char* line = NULL;

    // read user time
    if ((read = getline(&line, &len, fin)) == -1) {
        LOG(WARNING, "read line failed err[%d: %s]",
                errno, strerror(errno));
        fclose(fin);
        return false;
    }

    char cpu_tmp_char[20];
    int item_size = sscanf(line, "%s %ld",
            cpu_tmp_char, &(statistics->cpu_user_time));
    SAFE_FREE(line);

    if (item_size != 2) {
        LOG(WARNING, "read from %s format err", path.c_str());
        fclose(fin);
        return false;
    }

    // read sys time
    if ((read = getline(&line, &len, fin)) == -1) {
        LOG(WARNING, "read line failed err[%d: %s]",
                errno, strerror(errno));
        fclose(fin);
        return false;
    }

    item_size = sscanf(line, "%s %ld",
            cpu_tmp_char, &(statistics->cpu_system_time));
    SAFE_FREE(line);

    if (item_size != 2) {
        LOG(WARNING, "read from %s format err", path.c_str());
        fclose(fin);
        return false;
    }

    fclose(fin);
    return true;
}

bool GetGlobalCpuUsage(ResourceStatistics* statistics) {
    if (statistics == NULL) {
        return false;
    }

    statistics->cpu_cores = CPU_CORES;
    std::string path = "/proc/stat";
    FILE* fin = fopen(path.c_str(), "r");
    if (fin == NULL) {
        LOG(WARNING, "open %s failed", path.c_str());
        return false;
    }

    ssize_t read;
    size_t len = 0;
    char* line = NULL;
    if ((read = getline(&line, &len, fin)) == -1) {
        LOG(WARNING, "read line failed err[%d: %s]",
                errno, strerror(errno));
        fclose(fin);
        return false;
    }
    fclose(fin);

    char cpu[5];
    int item_size = sscanf(line,
                           "%s %ld %ld %ld %ld %ld %ld %ld %ld %ld",
                           cpu,
                           &(statistics->cpu_user_time),
                           &(statistics->cpu_nice_time),
                           &(statistics->cpu_system_time),
                           &(statistics->cpu_idle_time),
                           &(statistics->cpu_iowait_time),
                           &(statistics->cpu_irq_time),
                           &(statistics->cpu_softirq_time),
                           &(statistics->cpu_stealstolen),
                           &(statistics->cpu_guest));

    SAFE_FREE(line);
    if (item_size != 10) {
        LOG(WARNING, "read from /proc/stat format err");
        return false;
    }
    return true;
}

bool GetCgroupCpuCoresLimit(
        const std::string& group_path,
        CgroupResourceStatistics* statistics) {
    std::string period_path = CGROUP_MOUNT_PATH
        + "/cpu/" + group_path + "/cpu.cfs_period_us";
    std::string quota_path = CGROUP_MOUNT_PATH
        + "/cpu/" + group_path + "/cpu.cfs_quota_us";

    FILE* fin = fopen(period_path.c_str(), "r");
    if (fin == NULL) {
        LOG(WARNING, "open %s failed", period_path.c_str());
        return false;
    }

    ssize_t read;
    size_t len = 0;
    char* line = NULL;

    if ((read = getline(&line, &len, fin)) == -1) {
        LOG(WARNING, "read line failed err[%d: %s]", errno, strerror(errno));
        fclose(fin);
        return false;
    }
    fclose(fin);

    long period_time = 0;
    int item_size = sscanf(line, "%ld", &period_time);
    SAFE_FREE(line);
    if (item_size != 1) {
        LOG(WARNING, "read from %s format err", period_path.c_str());
        return false;
    }

    fin = fopen(quota_path.c_str(), "r");
    if (fin == NULL) {
        LOG(WARNING, "open %s failed", quota_path.c_str());
        return false;
    }

    line = NULL;
    len = 0;
    if ((read = getline(&line, &len, fin)) == -1) {
        LOG(WARNING, "read line failed err[%d: %s]", errno, strerror(errno));
        fclose(fin);
        return false;
    }
    fclose(fin);

    long quota_value = 0;
    item_size = sscanf(line, "%ld", &quota_value);
    SAFE_FREE(line);
    if (item_size != 1) {
        LOG(WARNING, "read from %s format err", quota_path.c_str());
        return false;
    }
    LOG(DEBUG, "cpu cores limit : quota(%ld), period(%ld)",
            quota_value,
            period_time);
    statistics->cpu_cores_limit = quota_value * 1.0 / period_time;
    return true;
}

bool GetCgroupMemoryUsage(const std::string& group_path,
        CgroupResourceStatistics* statistics) {
    std::string memory_path = CGROUP_MOUNT_PATH
        + "/memory/" + group_path + "/memory.stat";
    FILE* fin = fopen(memory_path.c_str(), "r");
    if (fin == NULL) {
        LOG(WARNING, "open %s failed", memory_path.c_str());
        return false;
    }

    ssize_t read;
    char* line = NULL;
    size_t len = 0;

    // escape first line for cache usage
    if ((read = getline(&line, &len, fin)) == -1) {
        LOG(WARNING, "read line failed err[%d: %s]", errno, strerror(errno));
        return false;
    }

    fclose(fin);
    SAFE_FREE(line);
    if ((read = getline(&line, &len, fin)) == -1) {
        LOG(WARNING, "read line failed err[%d: %s]", errno, strerror(errno));
        return false;
    }

    int item_size = sscanf(line, "%ld", &(statistics->memory_rss_in_bytes));
    SAFE_FREE(line);
    if (item_size != 1) {
        LOG(WARNING, "read from %s format err", memory_path.c_str());
        return false;
    }
    return true;
}

}   // ending namespace galaxy

/* vim: set ts=4 sw=4 sts=4 tw=100 */
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2011 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.
 */

#include "system_wrappers/include/cpu_info.h"

#if defined(WEBRTC_WIN)
#include <windows.h>
#elif defined(WEBRTC_LINUX)
#include <unistd.h>
#endif
#if defined(WEBRTC_MAC)
#include <sys/sysctl.h>
#endif

#include "rtc_base/logging.h"

namespace internal {
static int DetectNumberOfCores() {
  // We fall back on assuming a single core in case of errors.
  int number_of_cores = 1;

#if defined(WEBRTC_WIN)
  SYSTEM_INFO si;
  GetNativeSystemInfo(&si);
  number_of_cores = static_cast<int>(si.dwNumberOfProcessors);
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)
  number_of_cores = static_cast<int>(sysconf(_SC_NPROCESSORS_ONLN));
#elif defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
  int name[] = {CTL_HW, HW_AVAILCPU};
  size_t size = sizeof(number_of_cores);
  if (0 != sysctl(name, 2, &number_of_cores, &size, NULL, 0)) {
    RTC_LOG(LS_ERROR) << "Failed to get number of cores";
    number_of_cores = 1;
  }
#else
  RTC_LOG(LS_ERROR) << "No function to get number of cores";
#endif

  RTC_LOG(LS_INFO) << "Available number of cores: " << number_of_cores;

  return number_of_cores;
}
}  // namespace internal

namespace webrtc {

uint32_t CpuInfo::DetectNumberOfCores() {
  // Statically cache the number of system cores available since if the process
  // is running in a sandbox, we may only be able to read the value once (before
  // the sandbox is initialized) and not thereafter.
  // For more information see crbug.com/176522.
  static uint32_t logical_cpus = 0;
  if (!logical_cpus)
    logical_cpus = static_cast<uint32_t>(internal::DetectNumberOfCores());
  return logical_cpus;
}

}  // namespace webrtc
<commit_msg>[Fuchsia] Implement detection of available cores.<commit_after>/*
 *  Copyright (c) 2011 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.
 */

#include "system_wrappers/include/cpu_info.h"

#if defined(WEBRTC_WIN)
#include <windows.h>
#elif defined(WEBRTC_LINUX)
#include <unistd.h>
#elif defined(WEBRTC_MAC)
#include <sys/sysctl.h>
#elif defined(WEBRTC_FUCHSIA)
#include <zircon/syscalls.h>
#endif

#include "rtc_base/logging.h"

namespace internal {
static int DetectNumberOfCores() {
  // We fall back on assuming a single core in case of errors.
  int number_of_cores = 1;

#if defined(WEBRTC_WIN)
  SYSTEM_INFO si;
  GetNativeSystemInfo(&si);
  number_of_cores = static_cast<int>(si.dwNumberOfProcessors);
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)
  number_of_cores = static_cast<int>(sysconf(_SC_NPROCESSORS_ONLN));
#elif defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
  int name[] = {CTL_HW, HW_AVAILCPU};
  size_t size = sizeof(number_of_cores);
  if (0 != sysctl(name, 2, &number_of_cores, &size, NULL, 0)) {
    RTC_LOG(LS_ERROR) << "Failed to get number of cores";
    number_of_cores = 1;
  }
#elif defined(WEBRTC_FUCHSIA)
  number_of_cores = zx_system_get_num_cpus();
#else
  RTC_LOG(LS_ERROR) << "No function to get number of cores";
#endif

  RTC_LOG(LS_INFO) << "Available number of cores: " << number_of_cores;

  return number_of_cores;
}
}  // namespace internal

namespace webrtc {

uint32_t CpuInfo::DetectNumberOfCores() {
  // Statically cache the number of system cores available since if the process
  // is running in a sandbox, we may only be able to read the value once (before
  // the sandbox is initialized) and not thereafter.
  // For more information see crbug.com/176522.
  static uint32_t logical_cpus = 0;
  if (!logical_cpus)
    logical_cpus = static_cast<uint32_t>(internal::DetectNumberOfCores());
  return logical_cpus;
}

}  // namespace webrtc
<|endoftext|>


<commit_before>// Copyright 2014-2017 Open Source Robotics Foundation, 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.

#include <set>
#include <map>
#include <string>

#include "rcutils/allocator.h"
#include "rcutils/logging_macros.h"
#include "rcutils/strdup.h"
#include "rmw/error_handling.h"
#include "rmw/names_and_types.h"
#include "rmw/get_service_names_and_types.h"
#include "rmw/types.h"
#include "rmw/convert_rcutils_ret_to_rmw_ret.h"
#include "rmw/impl/cpp/macros.hpp"

#include "identifier.hpp"
#include "types.hpp"
#include "demangle.hpp"

#define SAMPLE_PREFIX "/Sample_"
// The extern "C" here enforces that overloading is not used.
extern "C"
{
rmw_ret_t
rmw_get_service_names_and_types(
  const rmw_node_t * node,
  rcutils_allocator_t * allocator,
  rmw_names_and_types_t * service_names_and_types)
{
  if (!allocator) {
    RMW_SET_ERROR_MSG("allocator is null")
    return RMW_RET_INVALID_ARGUMENT;
  }
  if (!node) {
    RMW_SET_ERROR_MSG_ALLOC("null node handle", *allocator)
    return RMW_RET_INVALID_ARGUMENT;
  }
  RMW_CHECK_TYPE_IDENTIFIERS_MATCH(
    node handle,
    node->implementation_identifier, opensplice_cpp_identifier,
    return RMW_RET_ERROR)

  rmw_ret_t ret = rmw_names_and_types_check_zero(service_names_and_types);
  if (ret != RMW_RET_OK) {
    return ret;
  }
  auto node_info = static_cast<OpenSpliceStaticNodeInfo *>(node->data);
  if (!node_info) {
    RMW_SET_ERROR_MSG("node info handle is null");
  }
  if (!node_info->publisher_listener) {
    RMW_SET_ERROR_MSG("publisher listener handle is null");
    return RMW_RET_ERROR;
  }
  if (!node_info->publisher_listener) {
    RMW_SET_ERROR_MSG("publisher listener handle is null");
    return RMW_RET_ERROR;
  }
  if (!node_info->subscriber_listener) {
    RMW_SET_ERROR_MSG("subscriber listener handle is null");
    return RMW_RET_ERROR;
  }

  // combine publisher and subscriber information
  std::map<std::string, std::set<std::string>> services;
  node_info->publisher_listener->fill_service_names_and_types(services);
  node_info->subscriber_listener->fill_service_names_and_types(services);

  // Fill out service_names_and_types
  if (services.size()) {
    // Setup string array to store names
    rmw_ret_t rmw_ret =
      rmw_names_and_types_init(service_names_and_types, services.size(), allocator);
    if (rmw_ret != RMW_RET_OK) {
      return rmw_ret;
    }
    // Setup cleanup function, in case of failure below
    auto fail_cleanup = [&service_names_and_types]() {
        rmw_ret_t rmw_ret = rmw_names_and_types_fini(service_names_and_types);
        if (rmw_ret != RMW_RET_OK) {
          RCUTILS_LOG_ERROR("error during report of error: %s", rmw_get_error_string_safe())
        }
      };
    // For each service, store the name, initialize the string array for types, and store all types
    size_t index = 0;
    for (const auto & service_n_types : services) {
      // Duplicate and store the service_name
      char * service_name = rcutils_strdup(service_n_types.first.c_str(), *allocator);
      if (!service_name) {
        RMW_SET_ERROR_MSG_ALLOC("failed to allocate memory for service name", *allocator);
        fail_cleanup();
        return RMW_RET_BAD_ALLOC;
      }
      service_names_and_types->names.data[index] = service_name;
      // Setup storage for types
      {
        rcutils_ret_t rcutils_ret = rcutils_string_array_init(
          &service_names_and_types->types[index],
          service_n_types.second.size(),
          allocator);
        if (rcutils_ret != RCUTILS_RET_OK) {
          RMW_SET_ERROR_MSG(rcutils_get_error_string_safe())
          fail_cleanup();
          return rmw_convert_rcutils_ret_to_rmw_ret(rcutils_ret);
        }
      }
      // Duplicate and store each type for the service
      size_t type_index = 0;
      for (const auto & type : service_n_types.second) {
        size_t n = type.find(SAMPLE_PREFIX);
        if (std::string::npos == n) {
          char * error_msg = rcutils_format_string(
            *allocator,
            "failed to convert DDS type name to ROS service type name: '" SAMPLE_PREFIX
            "' not found in type: '%s'", type.c_str());
          RMW_SET_ERROR_MSG(error_msg)
          allocator->deallocate(error_msg, allocator->state);
          fail_cleanup();
          return RMW_RET_ERROR;
        }
        std::string stripped_type = type.substr(0, n + 1) + type.substr(n + strlen(SAMPLE_PREFIX));
        char * type_name = rcutils_strdup(stripped_type.c_str(), *allocator);
        if (!type_name) {
          RMW_SET_ERROR_MSG_ALLOC("failed to allocate memory for type name", *allocator)
          fail_cleanup();
          return RMW_RET_BAD_ALLOC;
        }
        service_names_and_types->types[index].data[type_index] = type_name;
        ++type_index;
      }  // for each type
      ++index;
    }  // for each service
  }
  return RMW_RET_OK;
}
}  // extern "C"
<commit_msg>Don't error if Sample_ prefix not found in service type (#240)<commit_after>// Copyright 2014-2017 Open Source Robotics Foundation, 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.

#include <set>
#include <map>
#include <string>

#include "rcutils/allocator.h"
#include "rcutils/logging_macros.h"
#include "rcutils/strdup.h"
#include "rmw/error_handling.h"
#include "rmw/names_and_types.h"
#include "rmw/get_service_names_and_types.h"
#include "rmw/types.h"
#include "rmw/convert_rcutils_ret_to_rmw_ret.h"
#include "rmw/impl/cpp/macros.hpp"

#include "identifier.hpp"
#include "types.hpp"
#include "demangle.hpp"

#define SAMPLE_PREFIX "/Sample_"
// The extern "C" here enforces that overloading is not used.
extern "C"
{
rmw_ret_t
rmw_get_service_names_and_types(
  const rmw_node_t * node,
  rcutils_allocator_t * allocator,
  rmw_names_and_types_t * service_names_and_types)
{
  if (!allocator) {
    RMW_SET_ERROR_MSG("allocator is null")
    return RMW_RET_INVALID_ARGUMENT;
  }
  if (!node) {
    RMW_SET_ERROR_MSG_ALLOC("null node handle", *allocator)
    return RMW_RET_INVALID_ARGUMENT;
  }
  RMW_CHECK_TYPE_IDENTIFIERS_MATCH(
    node handle,
    node->implementation_identifier, opensplice_cpp_identifier,
    return RMW_RET_ERROR)

  rmw_ret_t ret = rmw_names_and_types_check_zero(service_names_and_types);
  if (ret != RMW_RET_OK) {
    return ret;
  }
  auto node_info = static_cast<OpenSpliceStaticNodeInfo *>(node->data);
  if (!node_info) {
    RMW_SET_ERROR_MSG("node info handle is null");
  }
  if (!node_info->publisher_listener) {
    RMW_SET_ERROR_MSG("publisher listener handle is null");
    return RMW_RET_ERROR;
  }
  if (!node_info->publisher_listener) {
    RMW_SET_ERROR_MSG("publisher listener handle is null");
    return RMW_RET_ERROR;
  }
  if (!node_info->subscriber_listener) {
    RMW_SET_ERROR_MSG("subscriber listener handle is null");
    return RMW_RET_ERROR;
  }

  // combine publisher and subscriber information
  std::map<std::string, std::set<std::string>> services;
  node_info->publisher_listener->fill_service_names_and_types(services);
  node_info->subscriber_listener->fill_service_names_and_types(services);

  // Fill out service_names_and_types
  if (services.size()) {
    // Setup string array to store names
    rmw_ret_t rmw_ret =
      rmw_names_and_types_init(service_names_and_types, services.size(), allocator);
    if (rmw_ret != RMW_RET_OK) {
      return rmw_ret;
    }
    // Setup cleanup function, in case of failure below
    auto fail_cleanup = [&service_names_and_types]() {
        rmw_ret_t rmw_ret = rmw_names_and_types_fini(service_names_and_types);
        if (rmw_ret != RMW_RET_OK) {
          RCUTILS_LOG_ERROR("error during report of error: %s", rmw_get_error_string_safe())
        }
      };
    // For each service, store the name, initialize the string array for types, and store all types
    size_t index = 0;
    for (const auto & service_n_types : services) {
      // Duplicate and store the service_name
      char * service_name = rcutils_strdup(service_n_types.first.c_str(), *allocator);
      if (!service_name) {
        RMW_SET_ERROR_MSG_ALLOC("failed to allocate memory for service name", *allocator);
        fail_cleanup();
        return RMW_RET_BAD_ALLOC;
      }
      service_names_and_types->names.data[index] = service_name;
      // Setup storage for types
      {
        rcutils_ret_t rcutils_ret = rcutils_string_array_init(
          &service_names_and_types->types[index],
          service_n_types.second.size(),
          allocator);
        if (rcutils_ret != RCUTILS_RET_OK) {
          RMW_SET_ERROR_MSG(rcutils_get_error_string_safe())
          fail_cleanup();
          return rmw_convert_rcutils_ret_to_rmw_ret(rcutils_ret);
        }
      }
      // Duplicate and store each type for the service
      size_t type_index = 0;
      for (const auto & type : service_n_types.second) {
        // Strip the SAMPLE_PREFIX if it is found (e.g. from services using OpenSplice typesupport).
        // It may not be found if services are detected using other typesupports.
        size_t n = type.find(SAMPLE_PREFIX);
        std::string stripped_type = type;
        if (std::string::npos != n) {
          stripped_type = type.substr(0, n + 1) + type.substr(n + strlen(SAMPLE_PREFIX));
        }
        char * type_name = rcutils_strdup(stripped_type.c_str(), *allocator);
        if (!type_name) {
          RMW_SET_ERROR_MSG_ALLOC("failed to allocate memory for type name", *allocator)
          fail_cleanup();
          return RMW_RET_BAD_ALLOC;
        }
        service_names_and_types->types[index].data[type_index] = type_name;
        ++type_index;
      }  // for each type
      ++index;
    }  // for each service
  }
  return RMW_RET_OK;
}
}  // extern "C"
<|endoftext|>


<commit_before>//
// Created by ZhangMing on 02-26-17
//

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "function.h"
#include <QDebug>
#include <QUrl>
#include <QDesktopServices>
#include <QMessageBox>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_ServiceHub_triggered()
{
    const QUrl url("http://hub.hust.edu.cn/index.jsp");
    qDebug() << url.scheme();
    qDebug() << url.port();
    QDesktopServices::openUrl(url);
}

void MainWindow::on_ServiceHubEmail_triggered()
{
    const QUrl url("https://mail.hust.edu.cn/");
    qDebug() << url.scheme();
    qDebug() << url.port();
    QDesktopServices::openUrl(url);
}

void MainWindow::on_ServiceGithub_triggered()
{
    const QUrl url("https://github.com/");
    qDebug() << url.scheme();
    qDebug() << url.port();
    QDesktopServices::openUrl(url);
}

void MainWindow::on_FunCourseTree_triggered()
{
    CourseTree *p;
    QString queryname;
    if(BuildCourseTree() == false)
    {
        QMessageBox::information(this,"error","No File");
        return;
    }
    else
    {
        // Dialog
        if((p = QueryCourse(queryname)) == nullptr)
        {
            QMessageBox::information(this, "error", "No Such Course");
            return;
        }
        // Web Page
        DataVisualization(p);
    }
}
<commit_msg>add dialog with users on searching course, by zm, on 03-01-17<commit_after>//
// Created by ZhangMing on 02-26-17
//

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "function.h"
#include <QDebug>
#include <QUrl>
#include <QDesktopServices>
#include <QMessageBox>
#include <QInputDialog>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_ServiceHub_triggered()
{
    const QUrl url("http://hub.hust.edu.cn/index.jsp");
    qDebug() << url.scheme();
    qDebug() << url.port();
    QDesktopServices::openUrl(url);
}

void MainWindow::on_ServiceHubEmail_triggered()
{
    const QUrl url("https://mail.hust.edu.cn/");
    qDebug() << url.scheme();
    qDebug() << url.port();
    QDesktopServices::openUrl(url);
}

void MainWindow::on_ServiceGithub_triggered()
{
    const QUrl url("https://github.com/");
    qDebug() << url.scheme();
    qDebug() << url.port();
    QDesktopServices::openUrl(url);
}

void MainWindow::on_FunCourseTree_triggered()
{
    CourseTree *p;
    if(BuildCourseTree() == false)
    {
        QMessageBox::information(this,"error","No File");
        return;
    }
    else
    {
        bool ok;
        QString name = QInputDialog::getText(NULL,QObject::tr("查询"),QObject::tr("请输入正确课程名"),QLineEdit::Normal,QString(),&ok);
        if(!ok)// click cancle
            return;
        // click ok
        if(name.isEmpty())
        {
            QMessageBox::information(this,"error","输入为空");
            return;
        }
        else if((p = QueryCourse(name)) == nullptr)
        {
            QMessageBox::information(this,"error","查无此课程");
        }
        else
        {
            //Web Page,use p
        }
    }
}
<|endoftext|>


<commit_before>#include "apisurface.h"
#include "thumbnail.h"

#include <sstream>

#include <QDebug>
#include <QSysInfo>

#include "image/image.hpp"

ApiSurface::ApiSurface()
{
}

QSize ApiSurface::size() const
{
    return m_size;
}

void ApiSurface::setSize(const QSize &size)
{
    m_size = size;
}

struct ByteArrayBuf : public std::streambuf
{
    ByteArrayBuf(QByteArray & a)
    {
        setg(a.data(), a.data(), a.data() + a.size());
    }
};

void ApiSurface::contentsFromBase64(const QByteArray &base64)
{
    m_base64Data = base64;

    /*
     * We need to do the conversion to create the thumbnail
     */
    image::Image *image = imageFromBase64(base64);
    Q_ASSERT(image);
    QImage img = qimageFromRawImage(image);
    m_thumb = thumbnail(img);
    delete image;
}

QByteArray ApiSurface::base64Data() const
{
    return m_base64Data;
}

QImage ApiSurface::thumb() const
{
    return m_thumb;
}

int ApiSurface::depth() const
{
    return m_depth;
}

void ApiSurface::setDepth(int depth)
{
    m_depth = depth;
}

QString ApiSurface::formatName() const
{
    return m_formatName;
}

void ApiSurface::setFormatName(const QString &str)
{
    m_formatName = str;
}

ApiTexture::ApiTexture()
    : ApiSurface()
{
}

QString ApiTexture::label() const
{
    return m_label;
}

void ApiTexture::setLabel(const QString &str)
{
    m_label = str;
}

ApiFramebuffer::ApiFramebuffer()
    : ApiSurface()
{
}

QString ApiFramebuffer::type() const
{
    return m_type;
}

void ApiFramebuffer::setType(const QString &str)
{
    m_type = str;
}

image::Image *
ApiSurface::imageFromBase64(const QByteArray &base64)
{
    QByteArray dataArray = QByteArray::fromBase64(base64);
    image::Image *image;

    /*
     * Detect the PNG vs PFM images.
     */
    const char pngSignature[] = {(char)0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0};
    if (dataArray.startsWith(pngSignature)) {
        ByteArrayBuf buf(dataArray);
        std::istream istr(&buf);
        image = image::readPNG(istr);
    } else {
        image = image::readPNM(dataArray.data(), dataArray.size());
    }

    return image;
}

QImage
ApiSurface::qimageFromRawImage(const image::Image *image)
{
    QImage img;
    int width = image->width;
    int height = image->height;

    img = QImage(width, height, QImage::Format_ARGB32);

    const unsigned char *srcRow = image->start();
    for (int y = 0; y < height; ++y) {
        QRgb *dst = (QRgb *)img.scanLine(y);

        if (image->channelType == image::TYPE_UNORM8) {
            const unsigned char *src = srcRow;
            for (int x = 0; x < width; ++x) {
                unsigned char rgba[4];
                for (int c = 0; c < image->channels; ++c) {
                    rgba[c] = *src++;
                }
                if (image->channels == 1) {
                    // Use gray-scale instead of red
                    rgba[1] = rgba[0];
                    rgba[2] = rgba[0];
                }
                dst[x] = qRgba(rgba[0], rgba[1], rgba[2], rgba[3]);
            }
        } else {
            const float *src = (const float *)srcRow;
            for (int x = 0; x < width; ++x) {
                unsigned char rgba[4] = {0, 0, 0, 0xff};
                for (int c = 0; c < image->channels; ++c) {
                    float f = *src++;
                    unsigned char u;
                    if (f >= 1.0f) {
                        u = 255;
                    } else if (f <= 0.0f) {
                        u = 0;
                    } else {
                        u = f * 255 + 0.5;
                    }
                    rgba[c] = u;
                }
                if (image->channels == 1) {
                    // Use gray-scale instead of red
                    rgba[1] = rgba[0];
                    rgba[2] = rgba[0];
                }
                dst[x] = qRgba(rgba[0], rgba[1], rgba[2], rgba[3]);
            }
        }

        srcRow += image->stride();
    }

    return img;
}
<commit_msg>gui: make sure that the alpha channel is initialized<commit_after>#include "apisurface.h"
#include "thumbnail.h"

#include <sstream>

#include <QDebug>
#include <QSysInfo>

#include "image/image.hpp"

ApiSurface::ApiSurface()
{
}

QSize ApiSurface::size() const
{
    return m_size;
}

void ApiSurface::setSize(const QSize &size)
{
    m_size = size;
}

struct ByteArrayBuf : public std::streambuf
{
    ByteArrayBuf(QByteArray & a)
    {
        setg(a.data(), a.data(), a.data() + a.size());
    }
};

void ApiSurface::contentsFromBase64(const QByteArray &base64)
{
    m_base64Data = base64;

    /*
     * We need to do the conversion to create the thumbnail
     */
    image::Image *image = imageFromBase64(base64);
    Q_ASSERT(image);
    QImage img = qimageFromRawImage(image);
    m_thumb = thumbnail(img);
    delete image;
}

QByteArray ApiSurface::base64Data() const
{
    return m_base64Data;
}

QImage ApiSurface::thumb() const
{
    return m_thumb;
}

int ApiSurface::depth() const
{
    return m_depth;
}

void ApiSurface::setDepth(int depth)
{
    m_depth = depth;
}

QString ApiSurface::formatName() const
{
    return m_formatName;
}

void ApiSurface::setFormatName(const QString &str)
{
    m_formatName = str;
}

ApiTexture::ApiTexture()
    : ApiSurface()
{
}

QString ApiTexture::label() const
{
    return m_label;
}

void ApiTexture::setLabel(const QString &str)
{
    m_label = str;
}

ApiFramebuffer::ApiFramebuffer()
    : ApiSurface()
{
}

QString ApiFramebuffer::type() const
{
    return m_type;
}

void ApiFramebuffer::setType(const QString &str)
{
    m_type = str;
}

image::Image *
ApiSurface::imageFromBase64(const QByteArray &base64)
{
    QByteArray dataArray = QByteArray::fromBase64(base64);
    image::Image *image;

    /*
     * Detect the PNG vs PFM images.
     */
    const char pngSignature[] = {(char)0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0};
    if (dataArray.startsWith(pngSignature)) {
        ByteArrayBuf buf(dataArray);
        std::istream istr(&buf);
        image = image::readPNG(istr);
    } else {
        image = image::readPNM(dataArray.data(), dataArray.size());
    }

    return image;
}

QImage
ApiSurface::qimageFromRawImage(const image::Image *image)
{
    QImage img;
    int width = image->width;
    int height = image->height;

    img = QImage(width, height, QImage::Format_ARGB32);

    const unsigned char *srcRow = image->start();
    for (int y = 0; y < height; ++y) {
        QRgb *dst = (QRgb *)img.scanLine(y);

        if (image->channelType == image::TYPE_UNORM8) {
            const unsigned char *src = srcRow;
            for (int x = 0; x < width; ++x) {
                unsigned char rgba[4] = {0, 0, 0, 0xff};
                for (int c = 0; c < image->channels; ++c) {
                    rgba[c] = *src++;
                }
                if (image->channels == 1) {
                    // Use gray-scale instead of red
                    rgba[1] = rgba[0];
                    rgba[2] = rgba[0];
                }
                dst[x] = qRgba(rgba[0], rgba[1], rgba[2], rgba[3]);
            }
        } else {
            const float *src = (const float *)srcRow;
            for (int x = 0; x < width; ++x) {
                unsigned char rgba[4] = {0, 0, 0, 0xff};
                for (int c = 0; c < image->channels; ++c) {
                    float f = *src++;
                    unsigned char u;
                    if (f >= 1.0f) {
                        u = 255;
                    } else if (f <= 0.0f) {
                        u = 0;
                    } else {
                        u = f * 255 + 0.5;
                    }
                    rgba[c] = u;
                }
                if (image->channels == 1) {
                    // Use gray-scale instead of red
                    rgba[1] = rgba[0];
                    rgba[2] = rgba[0];
                }
                dst[x] = qRgba(rgba[0], rgba[1], rgba[2], rgba[3]);
            }
        }

        srcRow += image->stride();
    }

    return img;
}
<|endoftext|>


<commit_before>//===- ObjectTransformLayerTest.cpp - Unit tests for ObjectTransformLayer -===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/NullResolver.h"
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
#include "llvm/Object/ObjectFile.h"
#include "gtest/gtest.h"

using namespace llvm::orc;

namespace {

// Stand-in for RuntimeDyld::MemoryManager
typedef int MockMemoryManager;

// Stand-in for RuntimeDyld::SymbolResolver
typedef int MockSymbolResolver;

// stand-in for object::ObjectFile
typedef int MockObjectFile;

// stand-in for llvm::MemoryBuffer set
typedef int MockMemoryBufferSet;

// Mock transform that operates on unique pointers to object files, and
// allocates new object files rather than mutating the given ones.
struct AllocatingTransform {
  std::unique_ptr<MockObjectFile>
  operator()(std::unique_ptr<MockObjectFile> Obj) const {
    return llvm::make_unique<MockObjectFile>(*Obj + 1);
  }
};

// Mock base layer for verifying behavior of transform layer.
// Each method "T foo(args)" is accompanied by two auxiliary methods:
//  - "void expectFoo(args)", to be called before calling foo on the transform
//      layer; saves values of args, which mock layer foo then verifies against.
// - "void verifyFoo(T)", to be called after foo, which verifies that the
//      transform layer called the base layer and forwarded any return value.
class MockBaseLayer {
public:
  typedef int ObjSetHandleT;

  MockBaseLayer() : MockSymbol(nullptr) { resetExpectations(); }

  template <typename ObjSetT, typename MemoryManagerPtrT,
            typename SymbolResolverPtrT>
  ObjSetHandleT addObjectSet(ObjSetT Objects, MemoryManagerPtrT MemMgr,
                             SymbolResolverPtrT Resolver) {
    EXPECT_EQ(MockManager, *MemMgr) << "MM should pass through";
    EXPECT_EQ(MockResolver, *Resolver) << "Resolver should pass through";
    size_t I = 0;
    for (auto &ObjPtr : Objects) {
      EXPECT_EQ(MockObjects[I++] + 1, *ObjPtr) << "Transform should be applied";
    }
    EXPECT_EQ(MockObjects.size(), I) << "Number of objects should match";
    LastCalled = "addObjectSet";
    MockObjSetHandle = 111;
    return MockObjSetHandle;
  }
  template <typename ObjSetT>
  void expectAddObjectSet(ObjSetT &Objects, MockMemoryManager *MemMgr,
                          MockSymbolResolver *Resolver) {
    MockManager = *MemMgr;
    MockResolver = *Resolver;
    for (auto &ObjPtr : Objects) {
      MockObjects.push_back(*ObjPtr);
    }
  }
  void verifyAddObjectSet(ObjSetHandleT Returned) {
    EXPECT_EQ("addObjectSet", LastCalled);
    EXPECT_EQ(MockObjSetHandle, Returned) << "Return should pass through";
    resetExpectations();
  }

  void removeObjectSet(ObjSetHandleT H) {
    EXPECT_EQ(MockObjSetHandle, H);
    LastCalled = "removeObjectSet";
  }
  void expectRemoveObjectSet(ObjSetHandleT H) { MockObjSetHandle = H; }
  void verifyRemoveObjectSet() {
    EXPECT_EQ("removeObjectSet", LastCalled);
    resetExpectations();
  }

  JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
    EXPECT_EQ(MockName, Name) << "Name should pass through";
    EXPECT_EQ(MockBool, ExportedSymbolsOnly) << "Flag should pass through";
    LastCalled = "findSymbol";
    MockSymbol = JITSymbol(122, llvm::JITSymbolFlags::None);
    return MockSymbol;
  }
  void expectFindSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
    MockName = Name;
    MockBool = ExportedSymbolsOnly;
  }
  void verifyFindSymbol(llvm::orc::JITSymbol Returned) {
    EXPECT_EQ("findSymbol", LastCalled);
    EXPECT_EQ(MockSymbol.getAddress(), Returned.getAddress())
        << "Return should pass through";
    resetExpectations();
  }

  JITSymbol findSymbolIn(ObjSetHandleT H, const std::string &Name,
                         bool ExportedSymbolsOnly) {
    EXPECT_EQ(MockObjSetHandle, H) << "Handle should pass through";
    EXPECT_EQ(MockName, Name) << "Name should pass through";
    EXPECT_EQ(MockBool, ExportedSymbolsOnly) << "Flag should pass through";
    LastCalled = "findSymbolIn";
    MockSymbol = JITSymbol(122, llvm::JITSymbolFlags::None);
    return MockSymbol;
  }
  void expectFindSymbolIn(ObjSetHandleT H, const std::string &Name,
                          bool ExportedSymbolsOnly) {
    MockObjSetHandle = H;
    MockName = Name;
    MockBool = ExportedSymbolsOnly;
  }
  void verifyFindSymbolIn(llvm::orc::JITSymbol Returned) {
    EXPECT_EQ("findSymbolIn", LastCalled);
    EXPECT_EQ(MockSymbol.getAddress(), Returned.getAddress())
        << "Return should pass through";
    resetExpectations();
  }

  void emitAndFinalize(ObjSetHandleT H) {
    EXPECT_EQ(MockObjSetHandle, H) << "Handle should pass through";
    LastCalled = "emitAndFinalize";
  }
  void expectEmitAndFinalize(ObjSetHandleT H) { MockObjSetHandle = H; }
  void verifyEmitAndFinalize() {
    EXPECT_EQ("emitAndFinalize", LastCalled);
    resetExpectations();
  }

  void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
                         TargetAddress TargetAddr) {
    EXPECT_EQ(MockObjSetHandle, H);
    EXPECT_EQ(MockLocalAddress, LocalAddress);
    EXPECT_EQ(MockTargetAddress, TargetAddr);
    LastCalled = "mapSectionAddress";
  }
  void expectMapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
                               TargetAddress TargetAddr) {
    MockObjSetHandle = H;
    MockLocalAddress = LocalAddress;
    MockTargetAddress = TargetAddr;
  }
  void verifyMapSectionAddress() {
    EXPECT_EQ("mapSectionAddress", LastCalled);
    resetExpectations();
  }

private:
  // Backing fields for remembering parameter/return values
  std::string LastCalled;
  MockMemoryManager MockManager;
  MockSymbolResolver MockResolver;
  std::vector<MockObjectFile> MockObjects;
  ObjSetHandleT MockObjSetHandle;
  std::string MockName;
  bool MockBool;
  JITSymbol MockSymbol;
  const void *MockLocalAddress;
  TargetAddress MockTargetAddress;
  MockMemoryBufferSet MockBufferSet;

  // Clear remembered parameters between calls
  void resetExpectations() {
    LastCalled = "nothing";
    MockManager = 0;
    MockResolver = 0;
    MockObjects.clear();
    MockObjSetHandle = 0;
    MockName = "bogus";
    MockSymbol = JITSymbol(nullptr);
    MockLocalAddress = nullptr;
    MockTargetAddress = 0;
    MockBufferSet = 0;
  }
};

// Test each operation on ObjectTransformLayer.
TEST(ObjectTransformLayerTest, Main) {
  MockBaseLayer M;

  // Create one object transform layer using a transform (as a functor)
  // that allocates new objects, and deals in unique pointers.
  ObjectTransformLayer<MockBaseLayer, AllocatingTransform> T1(M);

  // Create a second object transform layer using a transform (as a lambda)
  // that mutates objects in place, and deals in naked pointers
  ObjectTransformLayer<MockBaseLayer,
                       std::function<MockObjectFile *(MockObjectFile *)>>
  T2(M, [](MockObjectFile *Obj) {
    ++(*Obj);
    return Obj;
  });

  // Instantiate some mock objects to use below
  MockObjectFile MockObject1 = 211;
  MockObjectFile MockObject2 = 222;
  MockMemoryManager MockManager = 233;
  MockSymbolResolver MockResolver = 244;

  // Test addObjectSet with T1 (allocating, unique pointers)
  std::vector<std::unique_ptr<MockObjectFile>> Objs1;
  Objs1.push_back(llvm::make_unique<MockObjectFile>(MockObject1));
  Objs1.push_back(llvm::make_unique<MockObjectFile>(MockObject2));
  auto MM = llvm::make_unique<MockMemoryManager>(MockManager);
  auto SR = llvm::make_unique<MockSymbolResolver>(MockResolver);
  M.expectAddObjectSet(Objs1, MM.get(), SR.get());
  auto H = T1.addObjectSet(std::move(Objs1), std::move(MM), std::move(SR));
  M.verifyAddObjectSet(H);

  // Test addObjectSet with T2 (mutating, naked pointers)
  llvm::SmallVector<MockObjectFile *, 2> Objs2Vec;
  Objs2Vec.push_back(&MockObject1);
  Objs2Vec.push_back(&MockObject2);
  llvm::MutableArrayRef<MockObjectFile *> Objs2(Objs2Vec);
  M.expectAddObjectSet(Objs2, &MockManager, &MockResolver);
  H = T2.addObjectSet(Objs2, &MockManager, &MockResolver);
  M.verifyAddObjectSet(H);
  EXPECT_EQ(212, MockObject1) << "Expected mutation";
  EXPECT_EQ(223, MockObject2) << "Expected mutation";

  // Test removeObjectSet
  M.expectRemoveObjectSet(H);
  T1.removeObjectSet(H);
  M.verifyRemoveObjectSet();

  // Test findSymbol
  std::string Name = "foo";
  bool ExportedOnly = true;
  M.expectFindSymbol(Name, ExportedOnly);
  JITSymbol Symbol = T2.findSymbol(Name, ExportedOnly);
  M.verifyFindSymbol(Symbol);

  // Test findSymbolIn
  Name = "bar";
  ExportedOnly = false;
  M.expectFindSymbolIn(H, Name, ExportedOnly);
  Symbol = T1.findSymbolIn(H, Name, ExportedOnly);
  M.verifyFindSymbolIn(Symbol);

  // Test emitAndFinalize
  M.expectEmitAndFinalize(H);
  T2.emitAndFinalize(H);
  M.verifyEmitAndFinalize();

  // Test mapSectionAddress
  char Buffer[24];
  TargetAddress MockAddress = 255;
  M.expectMapSectionAddress(H, Buffer, MockAddress);
  T1.mapSectionAddress(H, Buffer, MockAddress);
  M.verifyMapSectionAddress();

  // Verify transform getter (non-const)
  MockObjectFile Mutatee = 277;
  MockObjectFile *Out = T2.getTransform()(&Mutatee);
  EXPECT_EQ(&Mutatee, Out) << "Expected in-place transform";
  EXPECT_EQ(278, Mutatee) << "Expected incrementing transform";

  // Verify transform getter (const)
  auto OwnedObj = llvm::make_unique<MockObjectFile>(288);
  const auto &T1C = T1;
  OwnedObj = T1C.getTransform()(std::move(OwnedObj));
  EXPECT_EQ(289, *OwnedObj) << "Expected incrementing transform";

  volatile bool RunStaticChecks = false;
  if (RunStaticChecks) {
    // Make sure that ObjectTransformLayer implements the object layer concept
    // correctly by sandwitching one between an ObjectLinkingLayer and an
    // IRCompileLayer, verifying that it compiles if we have a call to the
    // IRComileLayer's addModuleSet that should call the transform layer's
    // addObjectSet, and also calling the other public transform layer methods
    // directly to make sure the methods they intend to forward to exist on
    // the ObjectLinkingLayer.

    // We'll need a concrete MemoryManager class.
    class NullManager : public llvm::RuntimeDyld::MemoryManager {
    public:
      uint8_t *allocateCodeSection(uintptr_t, unsigned, unsigned,
                                   llvm::StringRef) override {
        return nullptr;
      }
      uint8_t *allocateDataSection(uintptr_t, unsigned, unsigned,
                                   llvm::StringRef, bool) override {
        return nullptr;
      }
      void registerEHFrames(uint8_t *, uint64_t, size_t) override {}
      void deregisterEHFrames(uint8_t *, uint64_t, size_t) override {}
      bool finalizeMemory(std::string *) { return false; }
    };

    // Construct the jit layers.
    ObjectLinkingLayer<> BaseLayer;
    auto IdentityTransform = [](
        std::unique_ptr<llvm::object::OwningBinary<llvm::object::ObjectFile>>
            Obj) { return std::move(Obj); };
    ObjectTransformLayer<decltype(BaseLayer), decltype(IdentityTransform)>
        TransformLayer(BaseLayer, IdentityTransform);
    auto NullCompiler = [](llvm::Module &) {
      return llvm::object::OwningBinary<llvm::object::ObjectFile>();
    };
    IRCompileLayer<decltype(TransformLayer)> CompileLayer(TransformLayer,
                                                          NullCompiler);
    std::vector<llvm::Module *> Modules;

    // Make sure that the calls from IRCompileLayer to ObjectTransformLayer
    // compile.
    NullResolver Resolver;
    NullManager Manager;
    CompileLayer.addModuleSet(std::vector<llvm::Module *>(), &Manager,
                              &Resolver);

    // Make sure that the calls from ObjectTransformLayer to ObjectLinkingLayer
    // compile.
    decltype(TransformLayer)::ObjSetHandleT ObjSet;
    TransformLayer.emitAndFinalize(ObjSet);
    TransformLayer.findSymbolIn(ObjSet, Name, false);
    TransformLayer.findSymbol(Name, true);
    TransformLayer.mapSectionAddress(ObjSet, nullptr, 0);
    TransformLayer.removeObjectSet(ObjSet);
  }
}
}
<commit_msg>ObjectTransformLayerTest.cpp: Fix a warning. [-Winconsistent-missing-override]<commit_after>//===- ObjectTransformLayerTest.cpp - Unit tests for ObjectTransformLayer -===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/NullResolver.h"
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
#include "llvm/Object/ObjectFile.h"
#include "gtest/gtest.h"

using namespace llvm::orc;

namespace {

// Stand-in for RuntimeDyld::MemoryManager
typedef int MockMemoryManager;

// Stand-in for RuntimeDyld::SymbolResolver
typedef int MockSymbolResolver;

// stand-in for object::ObjectFile
typedef int MockObjectFile;

// stand-in for llvm::MemoryBuffer set
typedef int MockMemoryBufferSet;

// Mock transform that operates on unique pointers to object files, and
// allocates new object files rather than mutating the given ones.
struct AllocatingTransform {
  std::unique_ptr<MockObjectFile>
  operator()(std::unique_ptr<MockObjectFile> Obj) const {
    return llvm::make_unique<MockObjectFile>(*Obj + 1);
  }
};

// Mock base layer for verifying behavior of transform layer.
// Each method "T foo(args)" is accompanied by two auxiliary methods:
//  - "void expectFoo(args)", to be called before calling foo on the transform
//      layer; saves values of args, which mock layer foo then verifies against.
// - "void verifyFoo(T)", to be called after foo, which verifies that the
//      transform layer called the base layer and forwarded any return value.
class MockBaseLayer {
public:
  typedef int ObjSetHandleT;

  MockBaseLayer() : MockSymbol(nullptr) { resetExpectations(); }

  template <typename ObjSetT, typename MemoryManagerPtrT,
            typename SymbolResolverPtrT>
  ObjSetHandleT addObjectSet(ObjSetT Objects, MemoryManagerPtrT MemMgr,
                             SymbolResolverPtrT Resolver) {
    EXPECT_EQ(MockManager, *MemMgr) << "MM should pass through";
    EXPECT_EQ(MockResolver, *Resolver) << "Resolver should pass through";
    size_t I = 0;
    for (auto &ObjPtr : Objects) {
      EXPECT_EQ(MockObjects[I++] + 1, *ObjPtr) << "Transform should be applied";
    }
    EXPECT_EQ(MockObjects.size(), I) << "Number of objects should match";
    LastCalled = "addObjectSet";
    MockObjSetHandle = 111;
    return MockObjSetHandle;
  }
  template <typename ObjSetT>
  void expectAddObjectSet(ObjSetT &Objects, MockMemoryManager *MemMgr,
                          MockSymbolResolver *Resolver) {
    MockManager = *MemMgr;
    MockResolver = *Resolver;
    for (auto &ObjPtr : Objects) {
      MockObjects.push_back(*ObjPtr);
    }
  }
  void verifyAddObjectSet(ObjSetHandleT Returned) {
    EXPECT_EQ("addObjectSet", LastCalled);
    EXPECT_EQ(MockObjSetHandle, Returned) << "Return should pass through";
    resetExpectations();
  }

  void removeObjectSet(ObjSetHandleT H) {
    EXPECT_EQ(MockObjSetHandle, H);
    LastCalled = "removeObjectSet";
  }
  void expectRemoveObjectSet(ObjSetHandleT H) { MockObjSetHandle = H; }
  void verifyRemoveObjectSet() {
    EXPECT_EQ("removeObjectSet", LastCalled);
    resetExpectations();
  }

  JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
    EXPECT_EQ(MockName, Name) << "Name should pass through";
    EXPECT_EQ(MockBool, ExportedSymbolsOnly) << "Flag should pass through";
    LastCalled = "findSymbol";
    MockSymbol = JITSymbol(122, llvm::JITSymbolFlags::None);
    return MockSymbol;
  }
  void expectFindSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
    MockName = Name;
    MockBool = ExportedSymbolsOnly;
  }
  void verifyFindSymbol(llvm::orc::JITSymbol Returned) {
    EXPECT_EQ("findSymbol", LastCalled);
    EXPECT_EQ(MockSymbol.getAddress(), Returned.getAddress())
        << "Return should pass through";
    resetExpectations();
  }

  JITSymbol findSymbolIn(ObjSetHandleT H, const std::string &Name,
                         bool ExportedSymbolsOnly) {
    EXPECT_EQ(MockObjSetHandle, H) << "Handle should pass through";
    EXPECT_EQ(MockName, Name) << "Name should pass through";
    EXPECT_EQ(MockBool, ExportedSymbolsOnly) << "Flag should pass through";
    LastCalled = "findSymbolIn";
    MockSymbol = JITSymbol(122, llvm::JITSymbolFlags::None);
    return MockSymbol;
  }
  void expectFindSymbolIn(ObjSetHandleT H, const std::string &Name,
                          bool ExportedSymbolsOnly) {
    MockObjSetHandle = H;
    MockName = Name;
    MockBool = ExportedSymbolsOnly;
  }
  void verifyFindSymbolIn(llvm::orc::JITSymbol Returned) {
    EXPECT_EQ("findSymbolIn", LastCalled);
    EXPECT_EQ(MockSymbol.getAddress(), Returned.getAddress())
        << "Return should pass through";
    resetExpectations();
  }

  void emitAndFinalize(ObjSetHandleT H) {
    EXPECT_EQ(MockObjSetHandle, H) << "Handle should pass through";
    LastCalled = "emitAndFinalize";
  }
  void expectEmitAndFinalize(ObjSetHandleT H) { MockObjSetHandle = H; }
  void verifyEmitAndFinalize() {
    EXPECT_EQ("emitAndFinalize", LastCalled);
    resetExpectations();
  }

  void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
                         TargetAddress TargetAddr) {
    EXPECT_EQ(MockObjSetHandle, H);
    EXPECT_EQ(MockLocalAddress, LocalAddress);
    EXPECT_EQ(MockTargetAddress, TargetAddr);
    LastCalled = "mapSectionAddress";
  }
  void expectMapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
                               TargetAddress TargetAddr) {
    MockObjSetHandle = H;
    MockLocalAddress = LocalAddress;
    MockTargetAddress = TargetAddr;
  }
  void verifyMapSectionAddress() {
    EXPECT_EQ("mapSectionAddress", LastCalled);
    resetExpectations();
  }

private:
  // Backing fields for remembering parameter/return values
  std::string LastCalled;
  MockMemoryManager MockManager;
  MockSymbolResolver MockResolver;
  std::vector<MockObjectFile> MockObjects;
  ObjSetHandleT MockObjSetHandle;
  std::string MockName;
  bool MockBool;
  JITSymbol MockSymbol;
  const void *MockLocalAddress;
  TargetAddress MockTargetAddress;
  MockMemoryBufferSet MockBufferSet;

  // Clear remembered parameters between calls
  void resetExpectations() {
    LastCalled = "nothing";
    MockManager = 0;
    MockResolver = 0;
    MockObjects.clear();
    MockObjSetHandle = 0;
    MockName = "bogus";
    MockSymbol = JITSymbol(nullptr);
    MockLocalAddress = nullptr;
    MockTargetAddress = 0;
    MockBufferSet = 0;
  }
};

// Test each operation on ObjectTransformLayer.
TEST(ObjectTransformLayerTest, Main) {
  MockBaseLayer M;

  // Create one object transform layer using a transform (as a functor)
  // that allocates new objects, and deals in unique pointers.
  ObjectTransformLayer<MockBaseLayer, AllocatingTransform> T1(M);

  // Create a second object transform layer using a transform (as a lambda)
  // that mutates objects in place, and deals in naked pointers
  ObjectTransformLayer<MockBaseLayer,
                       std::function<MockObjectFile *(MockObjectFile *)>>
  T2(M, [](MockObjectFile *Obj) {
    ++(*Obj);
    return Obj;
  });

  // Instantiate some mock objects to use below
  MockObjectFile MockObject1 = 211;
  MockObjectFile MockObject2 = 222;
  MockMemoryManager MockManager = 233;
  MockSymbolResolver MockResolver = 244;

  // Test addObjectSet with T1 (allocating, unique pointers)
  std::vector<std::unique_ptr<MockObjectFile>> Objs1;
  Objs1.push_back(llvm::make_unique<MockObjectFile>(MockObject1));
  Objs1.push_back(llvm::make_unique<MockObjectFile>(MockObject2));
  auto MM = llvm::make_unique<MockMemoryManager>(MockManager);
  auto SR = llvm::make_unique<MockSymbolResolver>(MockResolver);
  M.expectAddObjectSet(Objs1, MM.get(), SR.get());
  auto H = T1.addObjectSet(std::move(Objs1), std::move(MM), std::move(SR));
  M.verifyAddObjectSet(H);

  // Test addObjectSet with T2 (mutating, naked pointers)
  llvm::SmallVector<MockObjectFile *, 2> Objs2Vec;
  Objs2Vec.push_back(&MockObject1);
  Objs2Vec.push_back(&MockObject2);
  llvm::MutableArrayRef<MockObjectFile *> Objs2(Objs2Vec);
  M.expectAddObjectSet(Objs2, &MockManager, &MockResolver);
  H = T2.addObjectSet(Objs2, &MockManager, &MockResolver);
  M.verifyAddObjectSet(H);
  EXPECT_EQ(212, MockObject1) << "Expected mutation";
  EXPECT_EQ(223, MockObject2) << "Expected mutation";

  // Test removeObjectSet
  M.expectRemoveObjectSet(H);
  T1.removeObjectSet(H);
  M.verifyRemoveObjectSet();

  // Test findSymbol
  std::string Name = "foo";
  bool ExportedOnly = true;
  M.expectFindSymbol(Name, ExportedOnly);
  JITSymbol Symbol = T2.findSymbol(Name, ExportedOnly);
  M.verifyFindSymbol(Symbol);

  // Test findSymbolIn
  Name = "bar";
  ExportedOnly = false;
  M.expectFindSymbolIn(H, Name, ExportedOnly);
  Symbol = T1.findSymbolIn(H, Name, ExportedOnly);
  M.verifyFindSymbolIn(Symbol);

  // Test emitAndFinalize
  M.expectEmitAndFinalize(H);
  T2.emitAndFinalize(H);
  M.verifyEmitAndFinalize();

  // Test mapSectionAddress
  char Buffer[24];
  TargetAddress MockAddress = 255;
  M.expectMapSectionAddress(H, Buffer, MockAddress);
  T1.mapSectionAddress(H, Buffer, MockAddress);
  M.verifyMapSectionAddress();

  // Verify transform getter (non-const)
  MockObjectFile Mutatee = 277;
  MockObjectFile *Out = T2.getTransform()(&Mutatee);
  EXPECT_EQ(&Mutatee, Out) << "Expected in-place transform";
  EXPECT_EQ(278, Mutatee) << "Expected incrementing transform";

  // Verify transform getter (const)
  auto OwnedObj = llvm::make_unique<MockObjectFile>(288);
  const auto &T1C = T1;
  OwnedObj = T1C.getTransform()(std::move(OwnedObj));
  EXPECT_EQ(289, *OwnedObj) << "Expected incrementing transform";

  volatile bool RunStaticChecks = false;
  if (RunStaticChecks) {
    // Make sure that ObjectTransformLayer implements the object layer concept
    // correctly by sandwitching one between an ObjectLinkingLayer and an
    // IRCompileLayer, verifying that it compiles if we have a call to the
    // IRComileLayer's addModuleSet that should call the transform layer's
    // addObjectSet, and also calling the other public transform layer methods
    // directly to make sure the methods they intend to forward to exist on
    // the ObjectLinkingLayer.

    // We'll need a concrete MemoryManager class.
    class NullManager : public llvm::RuntimeDyld::MemoryManager {
    public:
      uint8_t *allocateCodeSection(uintptr_t, unsigned, unsigned,
                                   llvm::StringRef) override {
        return nullptr;
      }
      uint8_t *allocateDataSection(uintptr_t, unsigned, unsigned,
                                   llvm::StringRef, bool) override {
        return nullptr;
      }
      void registerEHFrames(uint8_t *, uint64_t, size_t) override {}
      void deregisterEHFrames(uint8_t *, uint64_t, size_t) override {}
      virtual bool finalizeMemory(std::string *) { return false; }
    };

    // Construct the jit layers.
    ObjectLinkingLayer<> BaseLayer;
    auto IdentityTransform = [](
        std::unique_ptr<llvm::object::OwningBinary<llvm::object::ObjectFile>>
            Obj) { return std::move(Obj); };
    ObjectTransformLayer<decltype(BaseLayer), decltype(IdentityTransform)>
        TransformLayer(BaseLayer, IdentityTransform);
    auto NullCompiler = [](llvm::Module &) {
      return llvm::object::OwningBinary<llvm::object::ObjectFile>();
    };
    IRCompileLayer<decltype(TransformLayer)> CompileLayer(TransformLayer,
                                                          NullCompiler);
    std::vector<llvm::Module *> Modules;

    // Make sure that the calls from IRCompileLayer to ObjectTransformLayer
    // compile.
    NullResolver Resolver;
    NullManager Manager;
    CompileLayer.addModuleSet(std::vector<llvm::Module *>(), &Manager,
                              &Resolver);

    // Make sure that the calls from ObjectTransformLayer to ObjectLinkingLayer
    // compile.
    decltype(TransformLayer)::ObjSetHandleT ObjSet;
    TransformLayer.emitAndFinalize(ObjSet);
    TransformLayer.findSymbolIn(ObjSet, Name, false);
    TransformLayer.findSymbol(Name, true);
    TransformLayer.mapSectionAddress(ObjSet, nullptr, 0);
    TransformLayer.removeObjectSet(ObjSet);
  }
}
}
<|endoftext|>


<commit_before>#include <iostream>
#include <sstream>
#include <fstream>
#include <math.h>
#include <vector>
#include "classifier.h"
#include <numeric>

/**
 * Initializes GNB
 */
GNB::GNB() {

}

GNB::~GNB() {}

void GNB::train(vector<vector<double>> data, vector<string> labels)
{

	/*
		Trains the classifier with N data points and labels.

		INPUTS
		data - array of N observations
		  - Each observation is a tuple with 4 values: s, d,
		    s_dot and d_dot.
		  - Example : [
			  	[3.5, 0.1, 5.9, -0.02],
			  	[8.0, -0.3, 3.0, 2.2],
			  	...
		  	]

		labels - array of N labels
		  - Each label is one of "left", "keep", or "right".
	*/

	int n = data[0].size(); // number of features
	int m = data.size(); // number of instances
	int k = possible_labels.size(); // number of classes

	mean_.resize(k, vector<double>(n)); // n col and k row
	var_.resize(k, vector<double>(n)); // n col and k row

	// Separate data by class
	// separated[0] will contain all the instances for left turn
	// separated[1] will contain all the instances for keep going
	// separated[2] will contain all the instances for right turn
	vector< vector< vector<double >>> separated (k);
	for(int i = 0; i < m; i++)
		for(int j = 0; j < k; j++)
			if(labels[i] == possible_labels[j])
    			separated[j].push_back(data[i]);

    // Calculate Mean
    for(int ik = 0; ik < k; ik++){
    	for(int in = 0; in < n; in++){
			for(int im = 0; im < separated[ik].size(); im++){
				mean_[ik][in] += separated[ik][im][in];
			}
			mean_[ik][in] /= separated[ik].size();
		}
    }

    // Calculate the variance
    for(int ik = 0; ik < k; ik++){
    	for(int in = 0; in < n; in++){
			for(int im = 0; im < separated[ik].size(); im++){
				var_[ik][in] += pow(separated[ik][im][in] - mean_[ik][in], 2);
			}
			var_[ik][in] /= separated[ik].size();
		}
    }

}

string GNB::predict(vector<double> sample)
{
	/*
		Once trained, this method is called and expected to return
		a predicted behavior for the given observation.

		INPUTS

		observation - a 4 tuple with s, d, s_dot, d_dot.
		  - Example: [3.5, 0.1, 8.5, -0.2]

		OUTPUT

		A label representing the best guess of the classifier. Can
		be one of "left", "keep" or "right".
		"""
		# TODO - complete this
	*/

	return this->possible_labels[1];

}<commit_msg>feat: compute the prediction step<commit_after>#include <iostream>
#include <sstream>
#include <fstream>
#include <math.h>
#include <vector>
#include "classifier.h"
#include <numeric>

/**
 * Initializes GNB
 */
GNB::GNB() {

}

GNB::~GNB() {}

void GNB::train(vector<vector<double>> data, vector<string> labels)
{

	/*
		Trains the classifier with N data points and labels.

		INPUTS
		data - array of N observations
		  - Each observation is a tuple with 4 values: s, d,
		    s_dot and d_dot.
		  - Example : [
			  	[3.5, 0.1, 5.9, -0.02],
			  	[8.0, -0.3, 3.0, 2.2],
			  	...
		  	]

		labels - array of N labels
		  - Each label is one of "left", "keep", or "right".
	*/

	int n = data[0].size(); // number of features
	int m = data.size(); // number of instances
	int k = possible_labels.size(); // number of classes

	mean_.resize(k, vector<double>(n)); // n col and k row
	var_.resize(k, vector<double>(n)); // n col and k row

	// Separate data by class
	// separated[0] will contain all the instances for left turn
	// separated[1] will contain all the instances for keep going
	// separated[2] will contain all the instances for right turn
	vector< vector< vector<double >>> separated (k);
	for(int i = 0; i < m; i++)
		for(int j = 0; j < k; j++)
			if(labels[i] == possible_labels[j])
    			separated[j].push_back(data[i]);

    // Calculate Mean
    for(int ik = 0; ik < k; ik++){
    	for(int in = 0; in < n; in++){
			for(int im = 0; im < separated[ik].size(); im++){
				mean_[ik][in] += separated[ik][im][in];
			}
			mean_[ik][in] /= separated[ik].size();
		}
    }

    // Calculate the variance
    for(int ik = 0; ik < k; ik++){
    	for(int in = 0; in < n; in++){
			for(int im = 0; im < separated[ik].size(); im++){
				var_[ik][in] += pow(separated[ik][im][in] - mean_[ik][in], 2);
			}
			var_[ik][in] /= separated[ik].size();
		}
    }

}

string GNB::predict(vector<double> sample)
{
	/*
		Once trained, this method is called and expected to return
		a predicted behavior for the given observation.

		INPUTS

		observation - a 4 tuple with s, d, s_dot, d_dot.
		  - Example: [3.5, 0.1, 8.5, -0.2]

		OUTPUT

		A label representing the best guess of the classifier. Can
		be one of "left", "keep" or "right".
		"""
		# TODO - complete this
	*/

	vector<double> posterior(possible_labels.size());

	// calculate the posteriori for belong to each class
	for(int i = 0; i < possible_labels.size(); i++){
		posterior[i] = 0.33;
		for(int j = 0; j < sample.size(); j++){
			double x = sample[j];
			double gauss = exp(-pow(x - mean_[i][j], 2) / (2*var_[i][j])) / sqrt(2*M_PI*var_[i][j]);
			posterior[i] *= gauss;
		}
	}

	// take the maximum
	double max = 0;
	int r = 0;
	for(int i = 0; i < possible_labels.size(); i++){
		if(posterior[i] > max){
			max = posterior[i];
			r = i;
		}
	}

	return this->possible_labels[r];

}<|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS ooo19126 (1.7.158); FILE MERGED 2005/09/05 13:21:09 rt 1.7.158.1: #i54170# Change license header: remove SISSL<commit_after><|endoftext|>