<commit_before>#include "command.hh"
#include "common-args.hh"
#include "shared.hh"
#include "store-api.hh"
#include "derivations.hh"
#include "local-store.hh"
#include "finally.hh"
#include "fs-accessor.hh"
#include "progress-bar.hh"

#if __linux__
#include <sys/mount.h>
#endif

using namespace nix;

std::string chrootHelperName = "__run_in_chroot";

extern char * * environ;

struct CmdRun : InstallablesCommand
{
    std::vector<std::string> command = { "bash" };
    StringSet keep, unset;
    bool ignoreEnvironment = false;

    CmdRun()
    {
        mkFlag()
            .longName("command")
            .shortName('c')
            .description("command and arguments to be executed; defaults to 'bash'")
            .arity(ArityAny)
            .labels({"command", "args"})
            .handler([&](std::vector<std::string> ss) {
                if (ss.empty()) throw UsageError("--command requires at least one argument");
                command = ss;
            });

        mkFlag()
            .longName("ignore-environment")
            .shortName('i')
            .description("clear the entire environment (except those specified with --keep)")
            .set(&ignoreEnvironment, true);

        mkFlag()
            .longName("keep")
            .shortName('k')
            .description("keep specified environment variable")
            .arity(1)
            .labels({"name"})
            .handler([&](std::vector<std::string> ss) { keep.insert(ss.front()); });

        mkFlag()
            .longName("unset")
            .shortName('u')
            .description("unset specified environment variable")
            .arity(1)
            .labels({"name"})
            .handler([&](std::vector<std::string> ss) { unset.insert(ss.front()); });
    }

    std::string name() override
    {
        return "run";
    }

    std::string description() override
    {
        return "run a shell in which the specified packages are available";
    }

    Examples examples() override
    {
        return {
            Example{
                "To start a shell providing GNU Hello from NixOS 17.03:",
                "nix run -f channel:nixos-17.03 hello"
            },
            Example{
                "To start a shell providing youtube-dl from your 'nixpkgs' channel:",
                "nix run nixpkgs.youtube-dl"
            },
            Example{
                "To run GNU Hello:",
                "nix run nixpkgs.hello -c hello --greeting 'Hi everybody!'"
            },
        };
    }

    void run(ref<Store> store) override
    {
        auto outPaths = toStorePaths(store, Build, installables);

        auto accessor = store->getFSAccessor();

        if (ignoreEnvironment) {

            if (!unset.empty())
                throw UsageError("--unset does not make sense with --ignore-environment");

            std::map<std::string, std::string> kept;
            for (auto & var : keep) {
                auto s = getenv(var.c_str());
                if (s) kept[var] = s;
            }

            environ = nullptr;

            for (auto & var : kept)
                setenv(var.first.c_str(), var.second.c_str(), 1);

        } else {

            if (!keep.empty())
                throw UsageError("--keep does not make sense without --ignore-environment");

            for (auto & var : unset)
                unsetenv(var.c_str());
        }

        auto unixPath = tokenizeString<Strings>(getEnv("PATH"), ":");
        for (auto & path : outPaths)
            if (accessor->stat(path + "/bin").type != FSAccessor::tMissing)
                unixPath.push_front(path + "/bin");
        setenv("PATH", concatStringsSep(":", unixPath).c_str(), 1);

        std::string cmd = *command.begin();
        Strings args;
        for (auto & arg : command) args.push_back(arg);

        stopProgressBar();

        restoreSignals();

        /* If this is a diverted store (i.e. its "logical" location
           (typically /nix/store) differs from its "physical" location
           (e.g. /home/eelco/nix/store), then run the command in a
           chroot. For non-root users, this requires running it in new
           mount and user namespaces. Unfortunately,
           unshare(CLONE_NEWUSER) doesn't work in a multithreaded
           program (which "nix" is), so we exec() a single-threaded
           helper program (chrootHelper() below) to do the work. */
        auto store2 = store.dynamic_pointer_cast<LocalStore>();

        if (store2 && store->storeDir != store2->realStoreDir) {
            Strings helperArgs = { chrootHelperName, store->storeDir, store2->realStoreDir, cmd };
            for (auto & arg : args) helperArgs.push_back(arg);

            execv(readLink("/proc/self/exe").c_str(), stringsToCharPtrs(helperArgs).data());

            throw SysError("could not execute chroot helper");
        }

        execvp(cmd.c_str(), stringsToCharPtrs(args).data());

        throw SysError("unable to exec '%s'", cmd);
    }
};

static RegisterCommand r1(make_ref<CmdRun>());

void chrootHelper(int argc, char * * argv)
{
    int p = 1;
    std::string storeDir = argv[p++];
    std::string realStoreDir = argv[p++];
    std::string cmd = argv[p++];
    Strings args;
    while (p < argc)
        args.push_back(argv[p++]);

#if __linux__
    uid_t uid = getuid();
    uid_t gid = getgid();

    if (unshare(CLONE_NEWUSER | CLONE_NEWNS) == -1)
        throw SysError("setting up a private mount namespace");

    /* Bind-mount realStoreDir on /nix/store. If the latter mount
       point doesn't already exists, we have to create a chroot
       environment containing the mount point and bind mounts for the
       children of /. Would be nice if we could use overlayfs here,
       but that doesn't work in a user namespace yet (Ubuntu has a
       patch for this:
       https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1478578). */
    if (!pathExists(storeDir)) {
        // FIXME: Use overlayfs?

        Path tmpDir = createTempDir();

        createDirs(tmpDir + storeDir);

        if (mount(realStoreDir.c_str(), (tmpDir + storeDir).c_str(), "", MS_BIND, 0) == -1)
            throw SysError("mounting '%s' on '%s'", realStoreDir, storeDir);

        for (auto entry : readDirectory("/")) {
            auto src = "/" + entry.name;
            auto st = lstat(src);
            if (!S_ISDIR(st.st_mode)) continue;
            Path dst = tmpDir + "/" + entry.name;
            if (pathExists(dst)) continue;
            if (mkdir(dst.c_str(), 0700) == -1)
                throw SysError("creating directory '%s'", dst);
            if (mount(src.c_str(), dst.c_str(), "", MS_BIND | MS_REC, 0) == -1)
                throw SysError("mounting '%s' on '%s'", src, dst);
        }

        char * cwd = getcwd(0, 0);
        if (!cwd) throw SysError("getting current directory");
        Finally freeCwd([&]() { free(cwd); });

        if (chroot(tmpDir.c_str()) == -1)
            throw SysError(format("chrooting into '%s'") % tmpDir);

        if (chdir(cwd) == -1)
            throw SysError(format("chdir to '%s' in chroot") % cwd);
    } else
        if (mount(realStoreDir.c_str(), storeDir.c_str(), "", MS_BIND, 0) == -1)
            throw SysError("mounting '%s' on '%s'", realStoreDir, storeDir);

    writeFile("/proc/self/setgroups", "deny");
    writeFile("/proc/self/uid_map", fmt("%d %d %d", uid, uid, 1));
    writeFile("/proc/self/gid_map", fmt("%d %d %d", gid, gid, 1));

    execvp(cmd.c_str(), stringsToCharPtrs(args).data());

    throw SysError("unable to exec '%s'", cmd);

#else
    throw Error("mounting the Nix store on '%s' is not supported on this platform", storeDir);
#endif
}
<commit_msg>nix run: Fix "flag '--command' requires 2 argument(s)"<commit_after>#include "command.hh"
#include "common-args.hh"
#include "shared.hh"
#include "store-api.hh"
#include "derivations.hh"
#include "local-store.hh"
#include "finally.hh"
#include "fs-accessor.hh"
#include "progress-bar.hh"

#if __linux__
#include <sys/mount.h>
#endif

using namespace nix;

std::string chrootHelperName = "__run_in_chroot";

extern char * * environ;

struct CmdRun : InstallablesCommand
{
    std::vector<std::string> command = { "bash" };
    StringSet keep, unset;
    bool ignoreEnvironment = false;

    CmdRun()
    {
        mkFlag()
            .longName("command")
            .shortName('c')
            .description("command and arguments to be executed; defaults to 'bash'")
            .labels({"command", "args"})
            .arity(ArityAny)
            .handler([&](std::vector<std::string> ss) {
                if (ss.empty()) throw UsageError("--command requires at least one argument");
                command = ss;
            });

        mkFlag()
            .longName("ignore-environment")
            .shortName('i')
            .description("clear the entire environment (except those specified with --keep)")
            .set(&ignoreEnvironment, true);

        mkFlag()
            .longName("keep")
            .shortName('k')
            .description("keep specified environment variable")
            .arity(1)
            .labels({"name"})
            .handler([&](std::vector<std::string> ss) { keep.insert(ss.front()); });

        mkFlag()
            .longName("unset")
            .shortName('u')
            .description("unset specified environment variable")
            .arity(1)
            .labels({"name"})
            .handler([&](std::vector<std::string> ss) { unset.insert(ss.front()); });
    }

    std::string name() override
    {
        return "run";
    }

    std::string description() override
    {
        return "run a shell in which the specified packages are available";
    }

    Examples examples() override
    {
        return {
            Example{
                "To start a shell providing GNU Hello from NixOS 17.03:",
                "nix run -f channel:nixos-17.03 hello"
            },
            Example{
                "To start a shell providing youtube-dl from your 'nixpkgs' channel:",
                "nix run nixpkgs.youtube-dl"
            },
            Example{
                "To run GNU Hello:",
                "nix run nixpkgs.hello -c hello --greeting 'Hi everybody!'"
            },
        };
    }

    void run(ref<Store> store) override
    {
        auto outPaths = toStorePaths(store, Build, installables);

        auto accessor = store->getFSAccessor();

        if (ignoreEnvironment) {

            if (!unset.empty())
                throw UsageError("--unset does not make sense with --ignore-environment");

            std::map<std::string, std::string> kept;
            for (auto & var : keep) {
                auto s = getenv(var.c_str());
                if (s) kept[var] = s;
            }

            environ = nullptr;

            for (auto & var : kept)
                setenv(var.first.c_str(), var.second.c_str(), 1);

        } else {

            if (!keep.empty())
                throw UsageError("--keep does not make sense without --ignore-environment");

            for (auto & var : unset)
                unsetenv(var.c_str());
        }

        auto unixPath = tokenizeString<Strings>(getEnv("PATH"), ":");
        for (auto & path : outPaths)
            if (accessor->stat(path + "/bin").type != FSAccessor::tMissing)
                unixPath.push_front(path + "/bin");
        setenv("PATH", concatStringsSep(":", unixPath).c_str(), 1);

        std::string cmd = *command.begin();
        Strings args;
        for (auto & arg : command) args.push_back(arg);

        stopProgressBar();

        restoreSignals();

        /* If this is a diverted store (i.e. its "logical" location
           (typically /nix/store) differs from its "physical" location
           (e.g. /home/eelco/nix/store), then run the command in a
           chroot. For non-root users, this requires running it in new
           mount and user namespaces. Unfortunately,
           unshare(CLONE_NEWUSER) doesn't work in a multithreaded
           program (which "nix" is), so we exec() a single-threaded
           helper program (chrootHelper() below) to do the work. */
        auto store2 = store.dynamic_pointer_cast<LocalStore>();

        if (store2 && store->storeDir != store2->realStoreDir) {
            Strings helperArgs = { chrootHelperName, store->storeDir, store2->realStoreDir, cmd };
            for (auto & arg : args) helperArgs.push_back(arg);

            execv(readLink("/proc/self/exe").c_str(), stringsToCharPtrs(helperArgs).data());

            throw SysError("could not execute chroot helper");
        }

        execvp(cmd.c_str(), stringsToCharPtrs(args).data());

        throw SysError("unable to exec '%s'", cmd);
    }
};

static RegisterCommand r1(make_ref<CmdRun>());

void chrootHelper(int argc, char * * argv)
{
    int p = 1;
    std::string storeDir = argv[p++];
    std::string realStoreDir = argv[p++];
    std::string cmd = argv[p++];
    Strings args;
    while (p < argc)
        args.push_back(argv[p++]);

#if __linux__
    uid_t uid = getuid();
    uid_t gid = getgid();

    if (unshare(CLONE_NEWUSER | CLONE_NEWNS) == -1)
        throw SysError("setting up a private mount namespace");

    /* Bind-mount realStoreDir on /nix/store. If the latter mount
       point doesn't already exists, we have to create a chroot
       environment containing the mount point and bind mounts for the
       children of /. Would be nice if we could use overlayfs here,
       but that doesn't work in a user namespace yet (Ubuntu has a
       patch for this:
       https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1478578). */
    if (!pathExists(storeDir)) {
        // FIXME: Use overlayfs?

        Path tmpDir = createTempDir();

        createDirs(tmpDir + storeDir);

        if (mount(realStoreDir.c_str(), (tmpDir + storeDir).c_str(), "", MS_BIND, 0) == -1)
            throw SysError("mounting '%s' on '%s'", realStoreDir, storeDir);

        for (auto entry : readDirectory("/")) {
            auto src = "/" + entry.name;
            auto st = lstat(src);
            if (!S_ISDIR(st.st_mode)) continue;
            Path dst = tmpDir + "/" + entry.name;
            if (pathExists(dst)) continue;
            if (mkdir(dst.c_str(), 0700) == -1)
                throw SysError("creating directory '%s'", dst);
            if (mount(src.c_str(), dst.c_str(), "", MS_BIND | MS_REC, 0) == -1)
                throw SysError("mounting '%s' on '%s'", src, dst);
        }

        char * cwd = getcwd(0, 0);
        if (!cwd) throw SysError("getting current directory");
        Finally freeCwd([&]() { free(cwd); });

        if (chroot(tmpDir.c_str()) == -1)
            throw SysError(format("chrooting into '%s'") % tmpDir);

        if (chdir(cwd) == -1)
            throw SysError(format("chdir to '%s' in chroot") % cwd);
    } else
        if (mount(realStoreDir.c_str(), storeDir.c_str(), "", MS_BIND, 0) == -1)
            throw SysError("mounting '%s' on '%s'", realStoreDir, storeDir);

    writeFile("/proc/self/setgroups", "deny");
    writeFile("/proc/self/uid_map", fmt("%d %d %d", uid, uid, 1));
    writeFile("/proc/self/gid_map", fmt("%d %d %d", gid, gid, 1));

    execvp(cmd.c_str(), stringsToCharPtrs(args).data());

    throw SysError("unable to exec '%s'", cmd);

#else
    throw Error("mounting the Nix store on '%s' is not supported on this platform", storeDir);
#endif
}
<|endoftext|>


<commit_before>#include "atmospheric-sensor.h"

#include "constants.h"

namespace rcr {
namespace geovis {

namespace {
  constexpr const char* const kAtmDisplayName = "Atmospheric Sensor";
  constexpr const char* const KAtmCsvHeader = "Ambient Temperature (*Celcius),Ambient Pressure (Pascal) [raw],Ambient Pressure (Pascal) [filtered],Relative Humidity (%),Altitude (meters) [raw],Altitude (meters) [filtered],";

  constexpr uint8_t BME_SCK = 13;
  constexpr uint8_t BME_MISO = 1;
  constexpr uint8_t BME_MOSI = 0;
  constexpr uint8_t BME_CS = 31;

  constexpr float std_pressure = 1013.25f; // hecto-Pascals
} // namespace

AtmosphericSensor::AtmosphericSensor()
  : Sensor(KALMAN_PROCESS_NOISE, KALMAN_MEASUREMENT_NOISE, KALMAN_ERROR,
    kAtmDisplayName, KAtmCsvHeader) {
  bme_ = Adafruit_BME280(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI
  altitude_ = kalmanInit(0.);
  pressure_ = kalmanInit(0.);
}

bool AtmosphericSensor::Init() {
  init_result_ = bme_.begin();
  return init_result_;
}

double AtmosphericSensor::ambient_pressure() {
  kalmanUpdate(&pressure_, (double)ambient_pressure_raw());
  return pressure_.value;
}

float AtmosphericSensor::ambient_pressure_raw() {
  return bme_.readPressure();
}

float AtmosphericSensor::humidity() {
  return bme_.readHumidity();
}

double AtmosphericSensor::pressure_altitude() {
  // @ std. pressure (i.e., 101325 Pa)
  kalmanUpdate(&altitude_, (double)pressure_altitude_raw());
  return altitude_.value;
}

float AtmosphericSensor::pressure_altitude_raw() {
  return bme_.readAltitude(std_pressure); // std. pressure
}

float AtmosphericSensor::temperature() {
  return bme_.readTemperature();
}

String AtmosphericSensor::GetCsvLine() {
  String line = "";

  // Temperature (*C)
  line += temperature();
  line += ",";

  // Ambient pressure (Pascals)
  line += ambient_pressure_raw();
  line += ",";
  line += ambient_pressure();
  line += ",";

  // Relative humidity (%)
  line += humidity();
  line += ",";

  // Pressure altitude (meters)
  line += pressure_altitude_raw();
  line += ",";
  line += pressure_altitude();
  line += ",";

  return line;
}

} // namespace geovis
} // namespace rcr
<commit_msg>update initial kalman values<commit_after>#include "atmospheric-sensor.h"

#include "constants.h"

namespace rcr {
namespace geovis {

namespace {
  constexpr const char* const kAtmDisplayName = "Atmospheric Sensor";
  constexpr const char* const KAtmCsvHeader = "Ambient Temperature (*Celcius),Ambient Pressure (Pascal) [raw],Ambient Pressure (Pascal) [filtered],Relative Humidity (%),Altitude (meters) [raw],Altitude (meters) [filtered],";

  constexpr uint8_t BME_SCK = 13;
  constexpr uint8_t BME_MISO = 1;
  constexpr uint8_t BME_MOSI = 0;
  constexpr uint8_t BME_CS = 31;

  constexpr float std_pressure = 1013.25f; // hecto-Pascals
} // namespace

AtmosphericSensor::AtmosphericSensor()
  : Sensor(KALMAN_PROCESS_NOISE, KALMAN_MEASUREMENT_NOISE, KALMAN_ERROR,
    kAtmDisplayName, KAtmCsvHeader) {
  bme_ = Adafruit_BME280(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI
  altitude_ = kalmanInit(1.);
  pressure_ = kalmanInit(1.);
}

bool AtmosphericSensor::Init() {
  init_result_ = bme_.begin();
  return init_result_;
}

double AtmosphericSensor::ambient_pressure() {
  kalmanUpdate(&pressure_, (double)ambient_pressure_raw());
  return pressure_.value;
}

float AtmosphericSensor::ambient_pressure_raw() {
  return bme_.readPressure();
}

float AtmosphericSensor::humidity() {
  return bme_.readHumidity();
}

double AtmosphericSensor::pressure_altitude() {
  // @ std. pressure (i.e., 101325 Pa)
  kalmanUpdate(&altitude_, (double)pressure_altitude_raw());
  return altitude_.value;
}

float AtmosphericSensor::pressure_altitude_raw() {
  return bme_.readAltitude(std_pressure); // std. pressure
}

float AtmosphericSensor::temperature() {
  return bme_.readTemperature();
}

String AtmosphericSensor::GetCsvLine() {
  String line = "";

  // Temperature (*C)
  line += temperature();
  line += ",";

  // Ambient pressure (Pascals)
  line += ambient_pressure_raw();
  line += ",";
  line += ambient_pressure();
  line += ",";

  // Relative humidity (%)
  line += humidity();
  line += ",";

  // Pressure altitude (meters)
  line += pressure_altitude_raw();
  line += ",";
  line += pressure_altitude();
  line += ",";

  return line;
}

} // namespace geovis
} // namespace rcr
<|endoftext|>


<commit_before><commit_msg>Prediction: fix missing field during dumping data<commit_after><|endoftext|>


<commit_before>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkAutoMalloc.h"
#include "vk/GrVkBackendContext.h"
#include "vk/GrVkExtensions.h"
#include "vk/GrVkInterface.h"
#include "vk/GrVkUtil.h"

////////////////////////////////////////////////////////////////////////////////
// Helper code to set up Vulkan context objects

#ifdef SK_ENABLE_VK_LAYERS
const char* kDebugLayerNames[] = {
    // elements of VK_LAYER_LUNARG_standard_validation
    "VK_LAYER_GOOGLE_threading",
    "VK_LAYER_LUNARG_parameter_validation",
    "VK_LAYER_LUNARG_object_tracker",
    "VK_LAYER_LUNARG_image",
    "VK_LAYER_LUNARG_core_validation",
    "VK_LAYER_LUNARG_swapchain",
    "VK_LAYER_GOOGLE_unique_objects",
    // not included in standard_validation
    //"VK_LAYER_LUNARG_api_dump",
    //"VK_LAYER_LUNARG_vktrace",
    //"VK_LAYER_LUNARG_screenshot",
};
#endif

// the minimum version of Vulkan supported
#ifdef SK_BUILD_FOR_ANDROID
const uint32_t kGrVkMinimumVersion = VK_MAKE_VERSION(1, 0, 3);
#else
const uint32_t kGrVkMinimumVersion = VK_MAKE_VERSION(1, 0, 8);
#endif

#define ACQUIRE_VK_PROC(name, instance, device)                                \
    PFN_vk##name grVk##name =                                                  \
        reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device)); \
    if (grVk##name == nullptr) {                                               \
        SkDebugf("Function ptr for vk%s could not be acquired\n", #name);      \
        return nullptr;                                                        \
    }

// Create the base Vulkan objects needed by the GrVkGpu object
const GrVkBackendContext* GrVkBackendContext::Create(uint32_t* presentQueueIndexPtr,
                                                     CanPresentFn canPresent,
                                                     GrVkInterface::GetProc getProc) {
    if (!getProc) {
        return nullptr;
    }
    SkASSERT(getProc);

    VkPhysicalDevice physDev;
    VkDevice device;
    VkInstance inst;
    VkResult err;

    const VkApplicationInfo app_info = {
        VK_STRUCTURE_TYPE_APPLICATION_INFO, // sType
        nullptr,                            // pNext
        "vktest",                           // pApplicationName
        0,                                  // applicationVersion
        "vktest",                           // pEngineName
        0,                                  // engineVerison
        kGrVkMinimumVersion,                // apiVersion
    };

    GrVkExtensions extensions(getProc);
    extensions.initInstance(kGrVkMinimumVersion);

    SkTArray<const char*> instanceLayerNames;
    SkTArray<const char*> instanceExtensionNames;
    uint32_t extensionFlags = 0;
#ifdef SK_ENABLE_VK_LAYERS
    for (size_t i = 0; i < SK_ARRAY_COUNT(kDebugLayerNames); ++i) {
        if (extensions.hasInstanceLayer(kDebugLayerNames[i])) {
            instanceLayerNames.push_back(kDebugLayerNames[i]);
        }
    }
    if (extensions.hasInstanceExtension(VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
        instanceExtensionNames.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
        extensionFlags |= kEXT_debug_report_GrVkExtensionFlag;
    }
#endif

    if (extensions.hasInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME)) {
        instanceExtensionNames.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
        extensionFlags |= kKHR_surface_GrVkExtensionFlag;
    }
    if (extensions.hasInstanceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
        instanceExtensionNames.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
        extensionFlags |= kKHR_swapchain_GrVkExtensionFlag;
    }
#ifdef SK_BUILD_FOR_WIN
    if (extensions.hasInstanceExtension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME)) {
        instanceExtensionNames.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
        extensionFlags |= kKHR_win32_surface_GrVkExtensionFlag;
    }
#elif defined(SK_BUILD_FOR_ANDROID)
    if (extensions.hasInstanceExtension(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)) {
        instanceExtensionNames.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
        extensionFlags |= kKHR_android_surface_GrVkExtensionFlag;
    }
#elif defined(SK_BUILD_FOR_UNIX) && !defined(__Fuchsia__)
    if (extensions.hasInstanceExtension(VK_KHR_XCB_SURFACE_EXTENSION_NAME)) {
        instanceExtensionNames.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
        extensionFlags |= kKHR_xcb_surface_GrVkExtensionFlag;
    }
#endif

    const VkInstanceCreateInfo instance_create = {
        VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,    // sType
        nullptr,                                   // pNext
        0,                                         // flags
        &app_info,                                 // pApplicationInfo
        (uint32_t) instanceLayerNames.count(),     // enabledLayerNameCount
        instanceLayerNames.begin(),                // ppEnabledLayerNames
        (uint32_t) instanceExtensionNames.count(), // enabledExtensionNameCount
        instanceExtensionNames.begin(),            // ppEnabledExtensionNames
    };

    ACQUIRE_VK_PROC(CreateInstance, VK_NULL_HANDLE, VK_NULL_HANDLE);
    err = grVkCreateInstance(&instance_create, nullptr, &inst);
    if (err < 0) {
        SkDebugf("vkCreateInstance failed: %d\n", err);
        return nullptr;
    }

    ACQUIRE_VK_PROC(DestroyInstance, inst, VK_NULL_HANDLE);
    ACQUIRE_VK_PROC(EnumeratePhysicalDevices, inst, VK_NULL_HANDLE);
    ACQUIRE_VK_PROC(GetPhysicalDeviceQueueFamilyProperties, inst, VK_NULL_HANDLE);
    ACQUIRE_VK_PROC(GetPhysicalDeviceFeatures, inst, VK_NULL_HANDLE);
    ACQUIRE_VK_PROC(CreateDevice, inst, VK_NULL_HANDLE);
    ACQUIRE_VK_PROC(GetDeviceQueue, inst, VK_NULL_HANDLE);
    ACQUIRE_VK_PROC(DeviceWaitIdle, inst, VK_NULL_HANDLE);
    ACQUIRE_VK_PROC(DestroyDevice, inst, VK_NULL_HANDLE);

    uint32_t gpuCount;
    err = grVkEnumeratePhysicalDevices(inst, &gpuCount, nullptr);
    if (err) {
        SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
        grVkDestroyInstance(inst, nullptr);
        return nullptr;
    }
    if (!gpuCount) {
        SkDebugf("vkEnumeratePhysicalDevices returned no supported devices.\n");
        grVkDestroyInstance(inst, nullptr);
        return nullptr;
    }
    // Just returning the first physical device instead of getting the whole array.
    // TODO: find best match for our needs
    gpuCount = 1;
    err = grVkEnumeratePhysicalDevices(inst, &gpuCount, &physDev);
    if (err) {
        SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
        grVkDestroyInstance(inst, nullptr);
        return nullptr;
    }

    // query to get the initial queue props size
    uint32_t queueCount;
    grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, nullptr);
    if (!queueCount) {
        SkDebugf("vkGetPhysicalDeviceQueueFamilyProperties returned no queues.\n");
        grVkDestroyInstance(inst, nullptr);
        return nullptr;
    }

    SkAutoMalloc queuePropsAlloc(queueCount * sizeof(VkQueueFamilyProperties));
    // now get the actual queue props
    VkQueueFamilyProperties* queueProps = (VkQueueFamilyProperties*)queuePropsAlloc.get();

    grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, queueProps);

    // iterate to find the graphics queue
    uint32_t graphicsQueueIndex = queueCount;
    for (uint32_t i = 0; i < queueCount; i++) {
        if (queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
            graphicsQueueIndex = i;
            break;
        }
    }
    if (graphicsQueueIndex == queueCount) {
        SkDebugf("Could not find any supported graphics queues.\n");
        grVkDestroyInstance(inst, nullptr);
        return nullptr;
    }

    // iterate to find the present queue, if needed
    uint32_t presentQueueIndex = queueCount;
    if (presentQueueIndexPtr && canPresent) {
        for (uint32_t i = 0; i < queueCount; i++) {
            if (canPresent(inst, physDev, i)) {
                presentQueueIndex = i;
                break;
            }
        }
        if (presentQueueIndex == queueCount) {
            SkDebugf("Could not find any supported present queues.\n");
            grVkDestroyInstance(inst, nullptr);
            return nullptr;
        }
        *presentQueueIndexPtr = presentQueueIndex;
    } else {
        // Just setting this so we end up make a single queue for graphics since there was no
        // request for a present queue.
        presentQueueIndex = graphicsQueueIndex;
    }

    extensions.initDevice(kGrVkMinimumVersion, inst, physDev);

    SkTArray<const char*> deviceLayerNames;
    SkTArray<const char*> deviceExtensionNames;
#ifdef SK_ENABLE_VK_LAYERS
    for (size_t i = 0; i < SK_ARRAY_COUNT(kDebugLayerNames); ++i) {
        if (extensions.hasDeviceLayer(kDebugLayerNames[i])) {
            deviceLayerNames.push_back(kDebugLayerNames[i]);
        }
    }
#endif
    if (extensions.hasDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
        deviceExtensionNames.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
        extensionFlags |= kKHR_swapchain_GrVkExtensionFlag;
    }
    if (extensions.hasDeviceExtension("VK_NV_glsl_shader")) {
        deviceExtensionNames.push_back("VK_NV_glsl_shader");
        extensionFlags |= kNV_glsl_shader_GrVkExtensionFlag;
    }

    // query to get the physical device properties
    VkPhysicalDeviceFeatures deviceFeatures;
    grVkGetPhysicalDeviceFeatures(physDev, &deviceFeatures);
    // this looks like it would slow things down,
    // and we can't depend on it on all platforms
    deviceFeatures.robustBufferAccess = VK_FALSE;

    uint32_t featureFlags = 0;
    if (deviceFeatures.geometryShader) {
        featureFlags |= kGeometryShader_GrVkFeatureFlag;
    }
    if (deviceFeatures.dualSrcBlend) {
        featureFlags |= kDualSrcBlend_GrVkFeatureFlag;
    }
    if (deviceFeatures.sampleRateShading) {
        featureFlags |= kSampleRateShading_GrVkFeatureFlag;
    }

    float queuePriorities[1] = { 0.0 };
    // Here we assume no need for swapchain queue
    // If one is needed, the client will need its own setup code
    const VkDeviceQueueCreateInfo queueInfo[2] = {
        {
            VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
            nullptr,                                    // pNext
            0,                                          // VkDeviceQueueCreateFlags
            graphicsQueueIndex,                         // queueFamilyIndex
            1,                                          // queueCount
            queuePriorities,                            // pQueuePriorities
        },
        {
            VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
            nullptr,                                    // pNext
            0,                                          // VkDeviceQueueCreateFlags
            presentQueueIndex,                          // queueFamilyIndex
            1,                                          // queueCount
            queuePriorities,                            // pQueuePriorities
        }
    };
    uint32_t queueInfoCount = (presentQueueIndex != graphicsQueueIndex) ? 2 : 1;

    const VkDeviceCreateInfo deviceInfo = {
        VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,    // sType
        nullptr,                                 // pNext
        0,                                       // VkDeviceCreateFlags
        queueInfoCount,                          // queueCreateInfoCount
        queueInfo,                               // pQueueCreateInfos
        (uint32_t) deviceLayerNames.count(),     // layerCount
        deviceLayerNames.begin(),                // ppEnabledLayerNames
        (uint32_t) deviceExtensionNames.count(), // extensionCount
        deviceExtensionNames.begin(),            // ppEnabledExtensionNames
        &deviceFeatures                          // ppEnabledFeatures
    };

    err = grVkCreateDevice(physDev, &deviceInfo, nullptr, &device);
    if (err) {
        SkDebugf("CreateDevice failed: %d\n", err);
        grVkDestroyInstance(inst, nullptr);
        return nullptr;
    }

    auto interface =
        sk_make_sp<GrVkInterface>(getProc, inst, device, extensionFlags);
    if (!interface->validate(extensionFlags)) {
        SkDebugf("Vulkan interface validation failed\n");
        grVkDeviceWaitIdle(device);
        grVkDestroyDevice(device, nullptr);
        grVkDestroyInstance(inst, nullptr);
        return nullptr;
    }

    VkQueue queue;
    grVkGetDeviceQueue(device, graphicsQueueIndex, 0, &queue);

    GrVkBackendContext* ctx = new GrVkBackendContext();
    ctx->fInstance = inst;
    ctx->fPhysicalDevice = physDev;
    ctx->fDevice = device;
    ctx->fQueue = queue;
    ctx->fGraphicsQueueIndex = graphicsQueueIndex;
    ctx->fMinAPIVersion = kGrVkMinimumVersion;
    ctx->fExtensions = extensionFlags;
    ctx->fFeatures = featureFlags;
    ctx->fInterface.reset(interface.release());
    ctx->fOwnsInstanceAndDevice = true;

    return ctx;
}

GrVkBackendContext::~GrVkBackendContext() {
    if (fInterface == nullptr || !fOwnsInstanceAndDevice) {
        return;
    }

    fInterface->fFunctions.fDeviceWaitIdle(fDevice);
    fInterface->fFunctions.fDestroyDevice(fDevice, nullptr);
    fDevice = VK_NULL_HANDLE;
    fInterface->fFunctions.fDestroyInstance(fInstance, nullptr);
    fInstance = VK_NULL_HANDLE;
}
<commit_msg>vulkan: Fix an optimus-related failure with vkEnumeratePhysicalDevices<commit_after>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkAutoMalloc.h"
#include "vk/GrVkBackendContext.h"
#include "vk/GrVkExtensions.h"
#include "vk/GrVkInterface.h"
#include "vk/GrVkUtil.h"

////////////////////////////////////////////////////////////////////////////////
// Helper code to set up Vulkan context objects

#ifdef SK_ENABLE_VK_LAYERS
const char* kDebugLayerNames[] = {
    // elements of VK_LAYER_LUNARG_standard_validation
    "VK_LAYER_GOOGLE_threading",
    "VK_LAYER_LUNARG_parameter_validation",
    "VK_LAYER_LUNARG_object_tracker",
    "VK_LAYER_LUNARG_image",
    "VK_LAYER_LUNARG_core_validation",
    "VK_LAYER_LUNARG_swapchain",
    "VK_LAYER_GOOGLE_unique_objects",
    // not included in standard_validation
    //"VK_LAYER_LUNARG_api_dump",
    //"VK_LAYER_LUNARG_vktrace",
    //"VK_LAYER_LUNARG_screenshot",
};
#endif

// the minimum version of Vulkan supported
#ifdef SK_BUILD_FOR_ANDROID
const uint32_t kGrVkMinimumVersion = VK_MAKE_VERSION(1, 0, 3);
#else
const uint32_t kGrVkMinimumVersion = VK_MAKE_VERSION(1, 0, 8);
#endif

#define ACQUIRE_VK_PROC(name, instance, device)                                \
    PFN_vk##name grVk##name =                                                  \
        reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device)); \
    if (grVk##name == nullptr) {                                               \
        SkDebugf("Function ptr for vk%s could not be acquired\n", #name);      \
        return nullptr;                                                        \
    }

// Create the base Vulkan objects needed by the GrVkGpu object
const GrVkBackendContext* GrVkBackendContext::Create(uint32_t* presentQueueIndexPtr,
                                                     CanPresentFn canPresent,
                                                     GrVkInterface::GetProc getProc) {
    if (!getProc) {
        return nullptr;
    }
    SkASSERT(getProc);

    VkPhysicalDevice physDev;
    VkDevice device;
    VkInstance inst;
    VkResult err;

    const VkApplicationInfo app_info = {
        VK_STRUCTURE_TYPE_APPLICATION_INFO, // sType
        nullptr,                            // pNext
        "vktest",                           // pApplicationName
        0,                                  // applicationVersion
        "vktest",                           // pEngineName
        0,                                  // engineVerison
        kGrVkMinimumVersion,                // apiVersion
    };

    GrVkExtensions extensions(getProc);
    extensions.initInstance(kGrVkMinimumVersion);

    SkTArray<const char*> instanceLayerNames;
    SkTArray<const char*> instanceExtensionNames;
    uint32_t extensionFlags = 0;
#ifdef SK_ENABLE_VK_LAYERS
    for (size_t i = 0; i < SK_ARRAY_COUNT(kDebugLayerNames); ++i) {
        if (extensions.hasInstanceLayer(kDebugLayerNames[i])) {
            instanceLayerNames.push_back(kDebugLayerNames[i]);
        }
    }
    if (extensions.hasInstanceExtension(VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
        instanceExtensionNames.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
        extensionFlags |= kEXT_debug_report_GrVkExtensionFlag;
    }
#endif

    if (extensions.hasInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME)) {
        instanceExtensionNames.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
        extensionFlags |= kKHR_surface_GrVkExtensionFlag;
    }
    if (extensions.hasInstanceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
        instanceExtensionNames.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
        extensionFlags |= kKHR_swapchain_GrVkExtensionFlag;
    }
#ifdef SK_BUILD_FOR_WIN
    if (extensions.hasInstanceExtension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME)) {
        instanceExtensionNames.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
        extensionFlags |= kKHR_win32_surface_GrVkExtensionFlag;
    }
#elif defined(SK_BUILD_FOR_ANDROID)
    if (extensions.hasInstanceExtension(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)) {
        instanceExtensionNames.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
        extensionFlags |= kKHR_android_surface_GrVkExtensionFlag;
    }
#elif defined(SK_BUILD_FOR_UNIX) && !defined(__Fuchsia__)
    if (extensions.hasInstanceExtension(VK_KHR_XCB_SURFACE_EXTENSION_NAME)) {
        instanceExtensionNames.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
        extensionFlags |= kKHR_xcb_surface_GrVkExtensionFlag;
    }
#endif

    const VkInstanceCreateInfo instance_create = {
        VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,    // sType
        nullptr,                                   // pNext
        0,                                         // flags
        &app_info,                                 // pApplicationInfo
        (uint32_t) instanceLayerNames.count(),     // enabledLayerNameCount
        instanceLayerNames.begin(),                // ppEnabledLayerNames
        (uint32_t) instanceExtensionNames.count(), // enabledExtensionNameCount
        instanceExtensionNames.begin(),            // ppEnabledExtensionNames
    };

    ACQUIRE_VK_PROC(CreateInstance, VK_NULL_HANDLE, VK_NULL_HANDLE);
    err = grVkCreateInstance(&instance_create, nullptr, &inst);
    if (err < 0) {
        SkDebugf("vkCreateInstance failed: %d\n", err);
        return nullptr;
    }

    ACQUIRE_VK_PROC(DestroyInstance, inst, VK_NULL_HANDLE);
    ACQUIRE_VK_PROC(EnumeratePhysicalDevices, inst, VK_NULL_HANDLE);
    ACQUIRE_VK_PROC(GetPhysicalDeviceQueueFamilyProperties, inst, VK_NULL_HANDLE);
    ACQUIRE_VK_PROC(GetPhysicalDeviceFeatures, inst, VK_NULL_HANDLE);
    ACQUIRE_VK_PROC(CreateDevice, inst, VK_NULL_HANDLE);
    ACQUIRE_VK_PROC(GetDeviceQueue, inst, VK_NULL_HANDLE);
    ACQUIRE_VK_PROC(DeviceWaitIdle, inst, VK_NULL_HANDLE);
    ACQUIRE_VK_PROC(DestroyDevice, inst, VK_NULL_HANDLE);

    uint32_t gpuCount;
    err = grVkEnumeratePhysicalDevices(inst, &gpuCount, nullptr);
    if (err) {
        SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
        grVkDestroyInstance(inst, nullptr);
        return nullptr;
    }
    if (!gpuCount) {
        SkDebugf("vkEnumeratePhysicalDevices returned no supported devices.\n");
        grVkDestroyInstance(inst, nullptr);
        return nullptr;
    }
    // Just returning the first physical device instead of getting the whole array.
    // TODO: find best match for our needs
    gpuCount = 1;
    err = grVkEnumeratePhysicalDevices(inst, &gpuCount, &physDev);
    // VK_INCOMPLETE is returned when the count we provide is less than the total device count.
    if (err && VK_INCOMPLETE != err) {
        SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
        grVkDestroyInstance(inst, nullptr);
        return nullptr;
    }

    // query to get the initial queue props size
    uint32_t queueCount;
    grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, nullptr);
    if (!queueCount) {
        SkDebugf("vkGetPhysicalDeviceQueueFamilyProperties returned no queues.\n");
        grVkDestroyInstance(inst, nullptr);
        return nullptr;
    }

    SkAutoMalloc queuePropsAlloc(queueCount * sizeof(VkQueueFamilyProperties));
    // now get the actual queue props
    VkQueueFamilyProperties* queueProps = (VkQueueFamilyProperties*)queuePropsAlloc.get();

    grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, queueProps);

    // iterate to find the graphics queue
    uint32_t graphicsQueueIndex = queueCount;
    for (uint32_t i = 0; i < queueCount; i++) {
        if (queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
            graphicsQueueIndex = i;
            break;
        }
    }
    if (graphicsQueueIndex == queueCount) {
        SkDebugf("Could not find any supported graphics queues.\n");
        grVkDestroyInstance(inst, nullptr);
        return nullptr;
    }

    // iterate to find the present queue, if needed
    uint32_t presentQueueIndex = queueCount;
    if (presentQueueIndexPtr && canPresent) {
        for (uint32_t i = 0; i < queueCount; i++) {
            if (canPresent(inst, physDev, i)) {
                presentQueueIndex = i;
                break;
            }
        }
        if (presentQueueIndex == queueCount) {
            SkDebugf("Could not find any supported present queues.\n");
            grVkDestroyInstance(inst, nullptr);
            return nullptr;
        }
        *presentQueueIndexPtr = presentQueueIndex;
    } else {
        // Just setting this so we end up make a single queue for graphics since there was no
        // request for a present queue.
        presentQueueIndex = graphicsQueueIndex;
    }

    extensions.initDevice(kGrVkMinimumVersion, inst, physDev);

    SkTArray<const char*> deviceLayerNames;
    SkTArray<const char*> deviceExtensionNames;
#ifdef SK_ENABLE_VK_LAYERS
    for (size_t i = 0; i < SK_ARRAY_COUNT(kDebugLayerNames); ++i) {
        if (extensions.hasDeviceLayer(kDebugLayerNames[i])) {
            deviceLayerNames.push_back(kDebugLayerNames[i]);
        }
    }
#endif
    if (extensions.hasDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
        deviceExtensionNames.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
        extensionFlags |= kKHR_swapchain_GrVkExtensionFlag;
    }
    if (extensions.hasDeviceExtension("VK_NV_glsl_shader")) {
        deviceExtensionNames.push_back("VK_NV_glsl_shader");
        extensionFlags |= kNV_glsl_shader_GrVkExtensionFlag;
    }

    // query to get the physical device properties
    VkPhysicalDeviceFeatures deviceFeatures;
    grVkGetPhysicalDeviceFeatures(physDev, &deviceFeatures);
    // this looks like it would slow things down,
    // and we can't depend on it on all platforms
    deviceFeatures.robustBufferAccess = VK_FALSE;

    uint32_t featureFlags = 0;
    if (deviceFeatures.geometryShader) {
        featureFlags |= kGeometryShader_GrVkFeatureFlag;
    }
    if (deviceFeatures.dualSrcBlend) {
        featureFlags |= kDualSrcBlend_GrVkFeatureFlag;
    }
    if (deviceFeatures.sampleRateShading) {
        featureFlags |= kSampleRateShading_GrVkFeatureFlag;
    }

    float queuePriorities[1] = { 0.0 };
    // Here we assume no need for swapchain queue
    // If one is needed, the client will need its own setup code
    const VkDeviceQueueCreateInfo queueInfo[2] = {
        {
            VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
            nullptr,                                    // pNext
            0,                                          // VkDeviceQueueCreateFlags
            graphicsQueueIndex,                         // queueFamilyIndex
            1,                                          // queueCount
            queuePriorities,                            // pQueuePriorities
        },
        {
            VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
            nullptr,                                    // pNext
            0,                                          // VkDeviceQueueCreateFlags
            presentQueueIndex,                          // queueFamilyIndex
            1,                                          // queueCount
            queuePriorities,                            // pQueuePriorities
        }
    };
    uint32_t queueInfoCount = (presentQueueIndex != graphicsQueueIndex) ? 2 : 1;

    const VkDeviceCreateInfo deviceInfo = {
        VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,    // sType
        nullptr,                                 // pNext
        0,                                       // VkDeviceCreateFlags
        queueInfoCount,                          // queueCreateInfoCount
        queueInfo,                               // pQueueCreateInfos
        (uint32_t) deviceLayerNames.count(),     // layerCount
        deviceLayerNames.begin(),                // ppEnabledLayerNames
        (uint32_t) deviceExtensionNames.count(), // extensionCount
        deviceExtensionNames.begin(),            // ppEnabledExtensionNames
        &deviceFeatures                          // ppEnabledFeatures
    };

    err = grVkCreateDevice(physDev, &deviceInfo, nullptr, &device);
    if (err) {
        SkDebugf("CreateDevice failed: %d\n", err);
        grVkDestroyInstance(inst, nullptr);
        return nullptr;
    }

    auto interface =
        sk_make_sp<GrVkInterface>(getProc, inst, device, extensionFlags);
    if (!interface->validate(extensionFlags)) {
        SkDebugf("Vulkan interface validation failed\n");
        grVkDeviceWaitIdle(device);
        grVkDestroyDevice(device, nullptr);
        grVkDestroyInstance(inst, nullptr);
        return nullptr;
    }

    VkQueue queue;
    grVkGetDeviceQueue(device, graphicsQueueIndex, 0, &queue);

    GrVkBackendContext* ctx = new GrVkBackendContext();
    ctx->fInstance = inst;
    ctx->fPhysicalDevice = physDev;
    ctx->fDevice = device;
    ctx->fQueue = queue;
    ctx->fGraphicsQueueIndex = graphicsQueueIndex;
    ctx->fMinAPIVersion = kGrVkMinimumVersion;
    ctx->fExtensions = extensionFlags;
    ctx->fFeatures = featureFlags;
    ctx->fInterface.reset(interface.release());
    ctx->fOwnsInstanceAndDevice = true;

    return ctx;
}

GrVkBackendContext::~GrVkBackendContext() {
    if (fInterface == nullptr || !fOwnsInstanceAndDevice) {
        return;
    }

    fInterface->fFunctions.fDeviceWaitIdle(fDevice);
    fInterface->fFunctions.fDestroyDevice(fDevice, nullptr);
    fDevice = VK_NULL_HANDLE;
    fInterface->fFunctions.fDestroyInstance(fInstance, nullptr);
    fInstance = VK_NULL_HANDLE;
}
<|endoftext|>


<commit_before>#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
#include <iostream>
#include <stdio.h>
#include "Timer.h"
#include <iostream>     // std::cin, std::cout
#include <fstream>      // std::ifstream

using namespace std;

int MethodOne(char* fileOne, char* fileTwo)
{
    ifstream input;
    input.open(fileOne);

    if (!input.is_open())
    {
        cerr << "Could not open file" << endl;
        return -1;
    }

    ofstream output(fileTwo);

        while (input.good())          // loop while extraction from file is possible
        {
            char c = input.get();       // get character from file
            if (input.good())
            {
                output.put(c);
            }
        }

    input.close();
    output.close();

    return 0;
}

int MethodTwo(char* fileOne, char* fileTwo)
{
    char buf[1];
    int num;
    int fdi = open(fileOne, O_RDONLY);
    if (fdi == -1)
    {
        perror("open");
        return -1;
    }

    int fdo = open(fileTwo, O_WRONLY | O_CREAT);
    if (fdo == -1)
    {
        perror("open");
        return -1;
    }

    while ((num = read(fdi, buf, 1)))
    {
        if (num == -1)
        {
            perror("read");
            return -1;
        }

        num = write(fdo, buf, 1);

        if (num == -1)
        {
            perror("write");
            return -1;
        }
    }

    num = close(fdi);
    if (num == -1)
    {
        perror("closei");
        return -1;
    }
    fdo = close(fdo);
    if (fdo ==-1)
    {
        perror("closeo");
        return -1;
    }

    return 0;
}

int MethodThree(char* fileOne, char* fileTwo)
{
    char buf[BUFSIZ];
    int num;
    int fdi = open(fileOne, O_RDONLY);
    if (fdi == -1)
    {
        perror("open");
        return -1;
    }

    int fdo = open(fileTwo, O_WRONLY | O_CREAT);
    if (fdo == -1)
    {
        perror("open");
        return -1;
    }

    while ((num = read(fdi, buf, BUFSIZ)))
    {
        if (num == -1)
        {
            perror("read");
            return -1;
        }

        num = write(fdo, buf, num);

        if (num == -1)
        {
            perror("write");
            return -1;
        }
    }

    num = close(fdi);
    if (num == -1)
    {
        perror("close input");
        return -1;
    }
    fdo = close(fdo);
    if (fdo ==-1)
    {
        perror("close output");
        return -1;
    }

    return 0;
}

int main(int argc, char* argv[])
{
    if (argc < 3 || argc > 4)
    {
        return -1;
    }

    struct stat sb;

    if( stat (argv[1], &sb) != 0)
    {
        cerr<<"Input file does not exist. Filename entered:"<<argv[1] <<endl;
        return -1;
    }

    if( S_ISDIR(sb.st_mode))
    {
        cerr<<"Input file is a directory. file: "<<argv[1] <<endl;
        return -1;
    }
    if (stat (argv[2], &sb) == 0)
    {
        cerr<<"Output file exists. file: "<<argv[2] <<endl;
        return -1;
    }
    if( S_ISDIR(sb.st_mode))
    {
        cerr<<"Output file is a directory. file: "<<argv[2]<<endl;
    }

    if (argc == 3)
    {
         if(MethodThree(argv[1], argv[2]) != 0)
        {
            cerr << "cp failed: MethodThree" << endl;
            return -1;
        }

        return 0;

    }

    Timer t1;
    Timer t2;
    Timer t3;

    double wallTime;
    double userTime;
    double SysTime;

    t1.start();

    cout<<"METHOD 1: GET.IN/ OUT.PUT: "<<endl;

    if (MethodOne(argv[1], argv[2]) != 0)
    {
       cout<<"cp failed: MethodOne." << endl;
    }

    t1.elapsedTime(wallTime, userTime, SysTime);
        cout<<"Elapsed Time: "<<endl
        <<"Wall: "<< wallTime<< endl
        <<"System: "  <<SysTime<<endl
        <<"User: "<<userTime<<endl;

        cout<<"=================="<<endl<<endl;

    t2.start();

    cout<<"METHOD 2: READ/WRITE 1 CHAR: "<<endl;

    if(MethodTwo(argv[1], argv[2]) != 0)
    {
        cerr << "cp failed: MethodTwo" << endl;
    }

    t2.elapsedTime(wallTime, userTime, SysTime);
    cout<<"Elapsed Time: "<<endl
        <<"Wall: "<< wallTime<< endl
        <<"System: "  <<SysTime<<endl
        <<"User: "<<userTime<<endl;

        cout<<"=================="<<endl<<endl;

    t3.start();

     cout<<"METHOD 3: READ/WRITE BUFSIZ: "<<endl;

    if(MethodThree(argv[1], argv[2]) != 0)
    {
        cerr << "cp failed: MethodThree" << endl;
    }

    t3.elapsedTime(wallTime, userTime, SysTime);
    cout<<"Elapsed Time: "<<endl
        <<"Wall: "<< wallTime<< endl
        <<"System: "  <<SysTime<<endl
        <<"User: "<<userTime<<endl;

        cout<<"=================="<<endl<<endl;
}
<commit_msg>updating cp.cpp<commit_after>#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
#include <iostream>
#include <stdio.h>
#include "Timer.h"
#include <iostream>     // std::cin, std::cout
#include <fstream>      // std::ifstream
#include <cstring>

using namespace std;

int MethodOne(char* fileOne, char* fileTwo)
{
    ifstream input;
    input.open(fileOne);

    if (!input.is_open())
    {
        cerr << "Error opening file: \"" << fileOne << endl;
        return -1;
    }

    ofstream output(fileTwo);
    if (!output.is_open())
    {
        cerr << "Error opening file: \"" << fileTwo << "\"";
        return -1;
    }

        while (input.good())          // loop while extraction from file is possible
        {
            char c = input.get();       // get character from file
            if (input.good())
            {
                output.put(c);
            }
        }

    input.close();
    if (input.is_open())
    {
        cerr << "Error closing file : \"" << fileOne << "\"" << endl;
        return -1;
    }

    output.close();
    if (output.is_open())
    {
        cerr << "Error closing file : \"" << fileTwo << "\"" << endl;
        return -1;
    }

    return 0;
}

int MethodTwo(char* fileOne, char* fileTwo)
{
    char buf[1];
    int num;
    int fdi = open(fileOne, O_RDONLY);
    if (fdi == -1)
    {
        perror("open");
        return -1;
    }

    int fdo = open(fileTwo, O_WRONLY | O_CREAT);
    if (fdo == -1)
    {
        perror("open");
        return -1;
    }

    while ((num = read(fdi, buf, 1)))
    {
        if (num == -1)
        {
            perror("read");
            return -1;
        }

        num = write(fdo, buf, 1);

        if (num == -1)
        {
            perror("write");
            return -1;
        }
    }

    num = close(fdi);
    if (num == -1)
    {
        perror("close input");
        return -1;
    }
    fdo = close(fdo);
    if (fdo ==-1)
    {
        perror("close output");
        return -1;
    }

    return 0;
}

int MethodThree(char* fileOne, char* fileTwo)
{
    char buf[BUFSIZ];
    int num;
    int fdi = open(fileOne, O_RDONLY);
    if (fdi == -1)
    {
        perror("open");
        return -1;
    }

    int fdo = open(fileTwo, O_WRONLY | O_CREAT);
    if (fdo == -1)
    {
        perror("open");
        return -1;
    }

    while ((num = read(fdi, buf, BUFSIZ)))
    {
        if (num == -1)
        {
            perror("read");
            return -1;
        }

        num = write(fdo, buf, num);

        if (num == -1)
        {
            perror("write");
            return -1;
        }
    }

    num = close(fdi);
    if (num == -1)
    {
        perror("close input");
        return -1;
    }
    fdo = close(fdo);
    if (fdo ==-1)
    {
        perror("close output");
        return -1;
    }

    return 0;
}

int main(int argc, char* argv[])
{
    if (argc < 3)
    {
        cerr << "Error: Not enough arguments" << endl;
        return -1;
    }

    if (argc > 4)
    {
        cerr << "Error: Too many arguments" << endl;
        return -1;
    }

    if (argc == 4)
    {
        int i = 1;

        for (; i < argc; ++i)
        {
            if (strncmp(argv[i], "-a", 3) == 0)
            {
                break;
            }
        }

        if (i == 4)
        {
            cerr << "Error: Too many of arguments" << endl;
            return -1;
        }

        if (i < 3)
        {
            while (i < 4)
            {
                argv[i] = argv[i + 1];
                i++;
            }
        }
    }

    struct stat sb;

    if( stat (argv[1], &sb) != 0)
    {
        cerr<<"Input file does not exist. Filename entered:"<<argv[1] <<endl;
        return -1;
    }

    if( S_ISDIR(sb.st_mode))
    {
        cerr<<"Input file is a directory. file: "<<argv[1] <<endl;
        return -1;
    }
    if (stat (argv[2], &sb) == 0)
    {
        cerr<<"Output file exists. file: "<<argv[2] <<endl;
        return -1;
    }
    if( S_ISDIR(sb.st_mode))
    {
        cerr<<"Output file is a directory. file: "<<argv[2]<<endl;
    }

    if (argc == 3)
    {
        if(MethodThree(argv[1], argv[2]) != 0)
        {
            cerr << "cp failed: MethodThree" << endl;
            return -1;
        }

        return 0;

    }

    Timer t1;
    Timer t2;
    Timer t3;

    double wallTime;
    double userTime;
    double SysTime;

    t1.start();

    cout<<"METHOD 1: GET.IN/ OUT.PUT: "<<endl;

    if (MethodOne(argv[1], argv[2]) != 0)
    {
        cout<<"cp failed: MethodOne." << endl;
    }

    t1.elapsedTime(wallTime, userTime, SysTime);
    cout<<"Elapsed Time: "<<endl
        <<"Wall: "<< wallTime<< endl
        <<"System: "  <<SysTime<<endl
        <<"User: "<<userTime<<endl;

    cout<<"=================="<<endl<<endl;

    t2.start();

    cout<<"METHOD 2: READ/WRITE 1 CHAR: "<<endl;

    if(MethodTwo(argv[1], argv[2]) != 0)
    {
        cerr << "cp failed: MethodTwo" << endl;
    }

    t2.elapsedTime(wallTime, userTime, SysTime);
    cout<<"Elapsed Time: "<<endl
        <<"Wall: "<< wallTime<< endl
        <<"System: "  <<SysTime<<endl
        <<"User: "<<userTime<<endl;

    cout<<"=================="<<endl<<endl;

    t3.start();

    cout<<"METHOD 3: READ/WRITE BUFSIZ: "<<endl;

    if(MethodThree(argv[1], argv[2]) != 0)
    {
        cerr << "cp failed: MethodThree" << endl;
    }

    t3.elapsedTime(wallTime, userTime, SysTime);
    cout<<"Elapsed Time: "<<endl
        <<"Wall: "<< wallTime<< endl
        <<"System: "  <<SysTime<<endl
        <<"User: "<<userTime<<endl;

    cout<<"=================="<<endl<<endl;

    return 0;
}
<|endoftext|>


<commit_before>#include "global.h"
#include "shutdown.h"
#include "RoleFactory.h"
#include "config/constraints.h"
#include "dclass/file/read.h"
#include "dclass/dc/Class.h"
using dclass::Class;

#include <boost/filesystem.hpp>
#include <cstring>
#include <string>  // std::string
#include <vector>  // std::vector
#include <fstream> // std::ifstream
using namespace std;

static LogCategory mainlog("main", "Main");

static ConfigGroup general_config("general");
static ConfigVariable<vector<string> > dc_files("dc_files", vector<string>(), general_config);
static ConfigVariable<string> eventlogger_addr("eventlogger", "", general_config);
static ValidAddressConstraint valid_eventlogger_addr(eventlogger_addr);

static ConfigList uberdogs_config("uberdogs");
static ConfigVariable<doid_t> uberdog_id("id", INVALID_DO_ID, uberdogs_config);
static ConfigVariable<string> uberdog_class("class", "", uberdogs_config);
static ConfigVariable<bool> uberdog_anon("anonymous", false, uberdogs_config);
static InvalidDoidConstraint id_not_invalid(uberdog_id);
static ReservedDoidConstraint id_not_reserved(uberdog_id);
static BooleanValueConstraint anonymous_is_boolean(uberdog_anon);

static void printHelp(ostream &s);
static void printCompiledOptions(ostream &s);

int main(int argc, char *argv[])
{
    string cfg_file;

#ifdef _WIN32
    bool prettyPrint = false;
#else
    bool prettyPrint = true;
#endif

    int config_arg_index = -1;
    cfg_file = "astrond.yml";
    LogSeverity sev = g_logger->get_min_severity();
    for(int i = 1; i < argc; i++) {
        if((strcmp(argv[i], "--log") == 0 || strcmp(argv[i], "-L") == 0) && i + 1 < argc) {
            g_logger.reset(new Logger(argv[++i], sev));
        } else if((strcmp(argv[i], "--loglevel") == 0 || strcmp(argv[i], "-l") == 0) && i + 1 < argc) {
            string llstr(argv[++i]);
            if(llstr == "packet") {
                sev = LSEVERITY_PACKET;
                g_logger->set_min_severity(sev);
            } else if(llstr == "trace") {
                sev = LSEVERITY_TRACE;
                g_logger->set_min_severity(sev);
            } else if(llstr == "debug") {
                sev = LSEVERITY_DEBUG;
                g_logger->set_min_severity(sev);
            } else if(llstr == "info") {
                sev = LSEVERITY_INFO;
                g_logger->set_min_severity(sev);
            } else if(llstr == "warning") {
                sev = LSEVERITY_INFO;
                g_logger->set_min_severity(sev);
            } else if(llstr == "security") {
                sev = LSEVERITY_SECURITY;
                g_logger->set_min_severity(sev);
            } else if(llstr != "error" && llstr != "fatal") {
                cerr << "Unknown log-level \"" << llstr << "\"." << endl;
                printHelp(cerr);
                return 1;
            }
        } else if(strcmp(argv[i], "--pretty") == 0 || strcmp(argv[i], "-p") == 0) {
            prettyPrint = true;
        } else if(strcmp(argv[i], "--boring") == 0 || strcmp(argv[i], "-b") == 0) {
            prettyPrint = false;
        } else if(strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
            printHelp(cout);
            return 0;
        } else if(strcmp(argv[i], "--version") == 0 || strcmp(argv[i], "-v") == 0) {
            cout << "A Server Technology for Realtime Object Networking (Astron)\n"
                 "http://github.com/astron/astron\n"

#ifdef GIT_SHA1
                 "Revision: " << GIT_SHA1 << "\n"
#else
                 "Revision: NOT-IN-GIT\n"
#endif
                 "Compiled at " << __TIME__ << " on " << __DATE__ << endl;

            printCompiledOptions(cout);

            return 0;
        } else if(argv[i][0] == '-') {
            cerr << "Unrecognized option \"" << string(argv[i]) << "\".\n";
            printHelp(cerr);
            return 1;
        } else {
            if(config_arg_index != -1) {
                cerr << "Recieved additional positional argument \""
                     << string(argv[i]) << "\" but can only accept one."
                     << "\n  First positional: \""
                     << string(argv[config_arg_index]) << "\".\n";
            } else {
                config_arg_index = i;
            }
        }
    }

    g_logger->set_color_enabled(prettyPrint);

    if(config_arg_index != -1) {
        string filename = "";
        cfg_file = argv[config_arg_index];

        try {
            // seperate path
            boost::filesystem::path p(cfg_file);
            boost::filesystem::path dir = p.parent_path();
            filename = p.filename().string();
            string dir_str = dir.string();

            // change directory
            if(!dir_str.empty()) {
                boost::filesystem::current_path(dir_str);
            }
        } catch(const boost::filesystem::filesystem_error&) {
            mainlog.fatal() << "Could not change working directory to config directory.\n";
            return 1;
        }

        cfg_file = filename;
    }

    mainlog.info() << "Loading configuration file...\n";

    ifstream file(cfg_file.c_str());
    if(!file.is_open()) {
        mainlog.fatal() << "Failed to open configuration file \"" << cfg_file << "\".\n";
        return 1;
    }

    if(!g_config->load(file)) {
        mainlog.fatal() << "Errors parsing YAML configuration file \"" << cfg_file << "\"!\n";
        return 1;
    }
    file.close();

    if(!ConfigGroup::root().validate(g_config->copy_node())) {
        mainlog.fatal() << "Configuration file contains errors.\n";
        return 1;
    }

    dclass::File* dcf = new dclass::File();
    dcf->add_keyword("required");
    dcf->add_keyword("ram");
    dcf->add_keyword("db");
    dcf->add_keyword("broadcast");
    dcf->add_keyword("clrecv");
    dcf->add_keyword("clsend");
    dcf->add_keyword("ownsend");
    dcf->add_keyword("ownrecv");
    dcf->add_keyword("airecv");
    vector<string> dc_file_names = dc_files.get_val();
    for(auto it = dc_file_names.begin(); it != dc_file_names.end(); ++it) {
        bool ok = dclass::append(dcf, *it);
        if(!ok) {
            mainlog.fatal() << "Could not read DC file " << *it << endl;
            return 1;
        }
    }
    g_dcf = dcf;

    // Now hook up our speciailize signal handler
    astron_handle_signals();

    try {
        // Initialize configured MessageDirector
        MessageDirector::singleton.init_network();
        g_eventsender.init(eventlogger_addr.get_val());

        // Load uberdog metadata from configuration
        ConfigNode udnodes = g_config->copy_node()["uberdogs"];
        if(!udnodes.IsNull()) {
            for(auto it = udnodes.begin(); it != udnodes.end(); ++it) {
                ConfigNode udnode = *it;
                Uberdog ud;

                // Get the uberdog's class
                const Class* dcc = g_dcf->get_class_by_name(udnode["class"].as<std::string>());
                if(!dcc) {
                    // Make sure it exists
                    mainlog.fatal() << "For uberdog " << udnode["id"].as<doid_t>()
                                    << " Distributed class " << udnode["class"].as<std::string>()
                                    << " does not exist!" << std::endl;
                    return 1;
                }

                // Setup uberdog
                ud.dcc = dcc;
                ud.anonymous = udnode["anonymous"].as<bool>();
                g_uberdogs[udnode["id"].as<doid_t>()] = ud;
            }
        }

        // Initialize configured roles
        ConfigNode node = g_config->copy_node();
        node = node["roles"];
        for(auto it = node.begin(); it != node.end(); ++it) {
            RoleFactory::singleton().instantiate_role((*it)["type"].as<std::string>(), *it);
        }
    }
    // This exception is propogated if astron_shutdown is called
    catch(const ShutdownException& e) {
        return e.exit_code();
    }

    // Run the main event loop
    int exit_code = 0;
    try {
        io_service.run();
    }

    // This exception is propogated if astron_shutdown is called
    catch(const ShutdownException& e) {
        exit_code = e.exit_code();
    }

    // Catch any other exception that propogates
    catch(const exception &e) {
        mainlog.fatal() << "Uncaught exception from the main event loop: "
                        << e.what() << endl;
        return 1;
    }

    return exit_code;
}

// printHelp outputs the cli help-text to the given stream.
void printHelp(ostream &s)
{
    s << "Usage:    astrond [options]... [CONFIG_FILE]\n"
      "\n"
      "Astrond is a distributed server daemon.\n"
      "By default Astron looks for a configuration file in the current\n"
      "working directory as \"astrond.yml\".  A different config file path\n"
      "can be specified as a positional argument.\n"
      "\n"
      "-h, --help      Print this help dialog.\n"
      "-v, --version   Print Version, Module and Compilation Information\n"
      "-L, --log       Specify a file to write log messages to.\n"
      "-p, --pretty    Enables colored pretty printing. \n"
      "-b, --boring    Disables colored pretty printing. \n"
      "-l, --loglevel  Specify the minimum log level that should be logged;\n"
      "                  Security, Error, and Fatal will always be logged;\n"
#ifdef ASTRON_DEBUG_MESSAGES
      "                (available): packet, trace, debug, info, warning, security\n"
#else
      "                (available): info, warning, security\n"
      "                (unavailable): packet, trace, debug\n"
      "                        [build with -DCMAKE_BUILD_TYPE=Debug]\n"
#endif
      "\n"
      "Example:\n"
      "    astrond /tmp/my_config_file.yaml\n"
      "\n";
    s.flush();
}

void printCompiledOptions(ostream &s)
{
    s << "Compilation options: "

      //If on, datagrams and dclass fields will use 32-bit length tags instead of 16-bit.
#ifdef ASTRON_32BIT_DATAGRAMS
      "32-bit length tag Datagrams, "
#else
      "16-bit length tag Datagrams, "
#endif

      //If on, channels will be 128-bit and doids and zones will be 64-bit (instead of 64/32).
#ifdef ASTRON_128BIT_CHANNELS
      "128-bit channel space, 64-bit distributed object id's, 64-bit zones"
#else
      "64-bit channel space, 32-bit distributed object id's, 32-bit zones"
#endif
      << "\n";

    //Now print what parts are compiled in.
    s << "Components: "
#ifdef BUILD_STATESERVER
      "State Server "
#ifdef BUILD_STATESERVER_DBSS
      "(With DBSS capablities)"
#endif //End DBSS
      ", "
#endif //End SS

#ifdef BUILD_EVENTLOGGER
      "Event Logger, "
#endif

#ifdef BUILD_CLIENTAGENT
      "Client Agent, "
#endif

#ifdef BUILD_DBSERVER
      "Database "

#ifdef BUILD_DB_YAML
      "(With YAML Support) "
#endif //End DB_YAML

#ifdef BUILD_DB_SQL
      "(With SQL DB Support) "
#endif //End DB_SQL

#endif //End DBSERVER
      "\n";

}
<commit_msg>main: Work around MSVC thread cleanup bug.<commit_after>#include "global.h"
#include "shutdown.h"
#include "RoleFactory.h"
#include "config/constraints.h"
#include "dclass/file/read.h"
#include "dclass/dc/Class.h"
using dclass::Class;

#include <boost/filesystem.hpp>
#include <cstring>
#include <string>  // std::string
#include <vector>  // std::vector
#include <fstream> // std::ifstream
using namespace std;

static LogCategory mainlog("main", "Main");

static ConfigGroup general_config("general");
static ConfigVariable<vector<string> > dc_files("dc_files", vector<string>(), general_config);
static ConfigVariable<string> eventlogger_addr("eventlogger", "", general_config);
static ValidAddressConstraint valid_eventlogger_addr(eventlogger_addr);

static ConfigList uberdogs_config("uberdogs");
static ConfigVariable<doid_t> uberdog_id("id", INVALID_DO_ID, uberdogs_config);
static ConfigVariable<string> uberdog_class("class", "", uberdogs_config);
static ConfigVariable<bool> uberdog_anon("anonymous", false, uberdogs_config);
static InvalidDoidConstraint id_not_invalid(uberdog_id);
static ReservedDoidConstraint id_not_reserved(uberdog_id);
static BooleanValueConstraint anonymous_is_boolean(uberdog_anon);

static void printHelp(ostream &s);
static void printCompiledOptions(ostream &s);

int main(int argc, char *argv[])
{
    string cfg_file;

#ifdef _WIN32
    bool prettyPrint = false;
#else
    bool prettyPrint = true;
#endif

    int config_arg_index = -1;
    cfg_file = "astrond.yml";
    LogSeverity sev = g_logger->get_min_severity();
    for(int i = 1; i < argc; i++) {
        if((strcmp(argv[i], "--log") == 0 || strcmp(argv[i], "-L") == 0) && i + 1 < argc) {
            g_logger.reset(new Logger(argv[++i], sev));
        } else if((strcmp(argv[i], "--loglevel") == 0 || strcmp(argv[i], "-l") == 0) && i + 1 < argc) {
            string llstr(argv[++i]);
            if(llstr == "packet") {
                sev = LSEVERITY_PACKET;
                g_logger->set_min_severity(sev);
            } else if(llstr == "trace") {
                sev = LSEVERITY_TRACE;
                g_logger->set_min_severity(sev);
            } else if(llstr == "debug") {
                sev = LSEVERITY_DEBUG;
                g_logger->set_min_severity(sev);
            } else if(llstr == "info") {
                sev = LSEVERITY_INFO;
                g_logger->set_min_severity(sev);
            } else if(llstr == "warning") {
                sev = LSEVERITY_INFO;
                g_logger->set_min_severity(sev);
            } else if(llstr == "security") {
                sev = LSEVERITY_SECURITY;
                g_logger->set_min_severity(sev);
            } else if(llstr != "error" && llstr != "fatal") {
                cerr << "Unknown log-level \"" << llstr << "\"." << endl;
                printHelp(cerr);
                return 1;
            }
        } else if(strcmp(argv[i], "--pretty") == 0 || strcmp(argv[i], "-p") == 0) {
            prettyPrint = true;
        } else if(strcmp(argv[i], "--boring") == 0 || strcmp(argv[i], "-b") == 0) {
            prettyPrint = false;
        } else if(strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
            printHelp(cout);
            return 0;
        } else if(strcmp(argv[i], "--version") == 0 || strcmp(argv[i], "-v") == 0) {
            cout << "A Server Technology for Realtime Object Networking (Astron)\n"
                 "http://github.com/astron/astron\n"

#ifdef GIT_SHA1
                 "Revision: " << GIT_SHA1 << "\n"
#else
                 "Revision: NOT-IN-GIT\n"
#endif
                 "Compiled at " << __TIME__ << " on " << __DATE__ << endl;

            printCompiledOptions(cout);

            return 0;
        } else if(argv[i][0] == '-') {
            cerr << "Unrecognized option \"" << string(argv[i]) << "\".\n";
            printHelp(cerr);
            return 1;
        } else {
            if(config_arg_index != -1) {
                cerr << "Recieved additional positional argument \""
                     << string(argv[i]) << "\" but can only accept one."
                     << "\n  First positional: \""
                     << string(argv[config_arg_index]) << "\".\n";
            } else {
                config_arg_index = i;
            }
        }
    }

    g_logger->set_color_enabled(prettyPrint);

    if(config_arg_index != -1) {
        string filename = "";
        cfg_file = argv[config_arg_index];

        try {
            // seperate path
            boost::filesystem::path p(cfg_file);
            boost::filesystem::path dir = p.parent_path();
            filename = p.filename().string();
            string dir_str = dir.string();

            // change directory
            if(!dir_str.empty()) {
                boost::filesystem::current_path(dir_str);
            }
        } catch(const boost::filesystem::filesystem_error&) {
            mainlog.fatal() << "Could not change working directory to config directory.\n";
            return 1;
        }

        cfg_file = filename;
    }

    mainlog.info() << "Loading configuration file...\n";

    ifstream file(cfg_file.c_str());
    if(!file.is_open()) {
        mainlog.fatal() << "Failed to open configuration file \"" << cfg_file << "\".\n";
        return 1;
    }

    if(!g_config->load(file)) {
        mainlog.fatal() << "Errors parsing YAML configuration file \"" << cfg_file << "\"!\n";
        return 1;
    }
    file.close();

    if(!ConfigGroup::root().validate(g_config->copy_node())) {
        mainlog.fatal() << "Configuration file contains errors.\n";
        return 1;
    }

    dclass::File* dcf = new dclass::File();
    dcf->add_keyword("required");
    dcf->add_keyword("ram");
    dcf->add_keyword("db");
    dcf->add_keyword("broadcast");
    dcf->add_keyword("clrecv");
    dcf->add_keyword("clsend");
    dcf->add_keyword("ownsend");
    dcf->add_keyword("ownrecv");
    dcf->add_keyword("airecv");
    vector<string> dc_file_names = dc_files.get_val();
    for(auto it = dc_file_names.begin(); it != dc_file_names.end(); ++it) {
        bool ok = dclass::append(dcf, *it);
        if(!ok) {
            mainlog.fatal() << "Could not read DC file " << *it << endl;
            return 1;
        }
    }
    g_dcf = dcf;

    // Now hook up our speciailize signal handler
    astron_handle_signals();

    try {
        // Initialize configured MessageDirector
        MessageDirector::singleton.init_network();
        g_eventsender.init(eventlogger_addr.get_val());

        // Load uberdog metadata from configuration
        ConfigNode udnodes = g_config->copy_node()["uberdogs"];
        if(!udnodes.IsNull()) {
            for(auto it = udnodes.begin(); it != udnodes.end(); ++it) {
                ConfigNode udnode = *it;
                Uberdog ud;

                // Get the uberdog's class
                const Class* dcc = g_dcf->get_class_by_name(udnode["class"].as<std::string>());
                if(!dcc) {
                    // Make sure it exists
                    mainlog.fatal() << "For uberdog " << udnode["id"].as<doid_t>()
                                    << " Distributed class " << udnode["class"].as<std::string>()
                                    << " does not exist!" << std::endl;
                    return 1;
                }

                // Setup uberdog
                ud.dcc = dcc;
                ud.anonymous = udnode["anonymous"].as<bool>();
                g_uberdogs[udnode["id"].as<doid_t>()] = ud;
            }
        }

        // Initialize configured roles
        ConfigNode node = g_config->copy_node();
        node = node["roles"];
        for(auto it = node.begin(); it != node.end(); ++it) {
            RoleFactory::singleton().instantiate_role((*it)["type"].as<std::string>(), *it);
        }
    }
    // This exception is propogated if astron_shutdown is called
    catch(const ShutdownException& e) {
        return e.exit_code();
    }

    // Run the main event loop
    int exit_code = 0;
    try {
        io_service.run();
    }

    // This exception is propogated if astron_shutdown is called
    catch(const ShutdownException& e) {
        exit_code = e.exit_code();
    }

    // Catch any other exception that propogates
    catch(const exception &e) {
        mainlog.fatal() << "Uncaught exception from the main event loop: "
                        << e.what() << endl;
        return 1;
    }

    return exit_code;
}

// printHelp outputs the cli help-text to the given stream.
void printHelp(ostream &s)
{
    s << "Usage:    astrond [options]... [CONFIG_FILE]\n"
      "\n"
      "Astrond is a distributed server daemon.\n"
      "By default Astron looks for a configuration file in the current\n"
      "working directory as \"astrond.yml\".  A different config file path\n"
      "can be specified as a positional argument.\n"
      "\n"
      "-h, --help      Print this help dialog.\n"
      "-v, --version   Print Version, Module and Compilation Information\n"
      "-L, --log       Specify a file to write log messages to.\n"
      "-p, --pretty    Enables colored pretty printing. \n"
      "-b, --boring    Disables colored pretty printing. \n"
      "-l, --loglevel  Specify the minimum log level that should be logged;\n"
      "                  Security, Error, and Fatal will always be logged;\n"
#ifdef ASTRON_DEBUG_MESSAGES
      "                (available): packet, trace, debug, info, warning, security\n"
#else
      "                (available): info, warning, security\n"
      "                (unavailable): packet, trace, debug\n"
      "                        [build with -DCMAKE_BUILD_TYPE=Debug]\n"
#endif
      "\n"
      "Example:\n"
      "    astrond /tmp/my_config_file.yaml\n"
      "\n";
    s.flush();
}

void printCompiledOptions(ostream &s)
{
    s << "Compilation options: "

      //If on, datagrams and dclass fields will use 32-bit length tags instead of 16-bit.
#ifdef ASTRON_32BIT_DATAGRAMS
      "32-bit length tag Datagrams, "
#else
      "16-bit length tag Datagrams, "
#endif

      //If on, channels will be 128-bit and doids and zones will be 64-bit (instead of 64/32).
#ifdef ASTRON_128BIT_CHANNELS
      "128-bit channel space, 64-bit distributed object id's, 64-bit zones"
#else
      "64-bit channel space, 32-bit distributed object id's, 32-bit zones"
#endif
      << "\n";

    //Now print what parts are compiled in.
    s << "Components: "
#ifdef BUILD_STATESERVER
      "State Server "
#ifdef BUILD_STATESERVER_DBSS
      "(With DBSS capablities)"
#endif //End DBSS
      ", "
#endif //End SS

#ifdef BUILD_EVENTLOGGER
      "Event Logger, "
#endif

#ifdef BUILD_CLIENTAGENT
      "Client Agent, "
#endif

#ifdef BUILD_DBSERVER
      "Database "

#ifdef BUILD_DB_YAML
      "(With YAML Support) "
#endif //End DB_YAML

#ifdef BUILD_DB_SQL
      "(With SQL DB Support) "
#endif //End DB_SQL

#endif //End DBSERVER
      "\n";

}

// http://stackoverflow.com/a/34207323
#if defined(_MSC_VER) && (_MSC_VER < 1900)
struct VS2013_threading_fix
{
	VS2013_threading_fix()
	{
		_Cnd_do_broadcast_at_thread_exit();
	}
} threading_fix;
#endif
<|endoftext|>


<commit_before><commit_msg>Prediction: fix still obstacle issue in multi-thread predictor<commit_after><|endoftext|>


<commit_before>// Copyright (C) 2016 xaizek <xaizek@openmailbox.org>
//
// This file is part of uncov.
//
// uncov is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// uncov 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 uncov.  If not, see <http://www.gnu.org/licenses/>.

#include "listings.hpp"

#include <boost/filesystem/path.hpp>
#include <boost/optional.hpp>

#include <map>
#include <ostream>
#include <string>
#include <vector>

#include "utils/fs.hpp"
#include "BuildHistory.hpp"
#include "coverage.hpp"
#include "printing.hpp"

static std::map<std::string, CovInfo>
getDirsCoverage(const Build &build, const std::string &dirFilter);
static CovChange getBuildCovChange(BuildHistory *bh, const Build &build,
                                   const CovInfo &covInfo);
static void printFileHeader(std::ostream &os, const std::string &filePath,
                            const CovInfo &covInfo, const CovChange &covChange);
static CovChange getFileCovChange(BuildHistory *bh, const Build &build,
                                  const std::string &path,
                                  boost::optional<Build> *prevBuildHint,
                                  const CovInfo &covInfo);

std::vector<std::string>
describeBuild(BuildHistory *bh, const Build &build)
{
    CovInfo covInfo(build);
    CovChange covChange = getBuildCovChange(bh, build, covInfo);

    return {
        "#" + std::to_string(build.getId()),
        covInfo.formatCoverageRate(),
        covInfo.formatLines(" / "),
        covChange.formatCoverageRate(),
        covChange.formatLines(" / "),
        build.getRefName(),
        Revision{build.getRef()},
        Time{build.getTimestamp()}
    };
}

std::vector<std::vector<std::string>>
describeBuildDirs(BuildHistory *bh, const Build &build,
                  const std::string &dirFilter)
{
    std::map<std::string, CovInfo> newDirs = getDirsCoverage(build, dirFilter);

    std::map<std::string, CovInfo> prevDirs;
    if (const int prevBuildId = bh->getPreviousBuildId(build.getId())) {
        prevDirs = getDirsCoverage(*bh->getBuild(prevBuildId), dirFilter);
    }

    std::vector<std::vector<std::string>> rows;
    rows.reserve(newDirs.size());

    for (const auto &entry : newDirs) {
        const CovInfo &covInfo = entry.second;
        CovChange covChange(prevDirs[entry.first], covInfo);

        rows.push_back({
            entry.first + '/',
            covInfo.formatCoverageRate(),
            covInfo.formatLines(" / "),
            covChange.formatCoverageRate(),
            covChange.formatLines(" / ")
        });
    }

    return rows;
}

static std::map<std::string, CovInfo>
getDirsCoverage(const Build &build, const std::string &dirFilter)
{
    std::map<std::string, CovInfo> dirs;
    for (const std::string &filePath : build.getPaths()) {
        if (!pathIsInSubtree(dirFilter, filePath)) {
            continue;
        }

        boost::filesystem::path dirPath = filePath;
        dirPath.remove_filename();

        File &file = *build.getFile(filePath);
        CovInfo &info = dirs[dirPath.string()];

        info.add(CovInfo(file));
    }
    return dirs;
}

std::vector<std::vector<std::string>>
describeBuildFiles(BuildHistory *bh, const Build &build,
                   const std::string &dirFilter, bool changedOnly)
{
    const std::vector<std::string> &paths = build.getPaths();

    std::vector<std::vector<std::string>> rows;
    rows.reserve(paths.size());

    boost::optional<Build> prevBuild;
    if (const int prevBuildId = bh->getPreviousBuildId(build.getId())) {
        prevBuild = bh->getBuild(prevBuildId);
    }

    for (const std::string &filePath : paths) {
        if (!pathIsInSubtree(dirFilter, filePath)) {
            continue;
        }

        CovInfo covInfo(*build.getFile(filePath));
        CovChange covChange = getFileCovChange(bh, build, filePath,
                                               &prevBuild, covInfo);

        if (changedOnly && !covChange.isChanged()) {
            continue;
        }

        rows.push_back({
            filePath,
            covInfo.formatCoverageRate(),
            covInfo.formatLines(" / "),
            covChange.formatCoverageRate(),
            covChange.formatLines(" / "),
        });
    }

    return rows;
}

void
printBuildHeader(std::ostream &os, BuildHistory *bh, const Build &build)
{
    CovInfo covInfo(build);
    CovChange covChange = getBuildCovChange(bh, build, covInfo);

    os << Label{"Build"} << ": #" << build.getId() << ", "
       << covInfo.formatCoverageRate() << ' '
       << '(' << covInfo.formatLines("/") << "), "
       << covChange.formatCoverageRate() << ' '
       << '(' << covChange.formatLines("/") << "), "
       << build.getRefName() << " at " << Revision{build.getRef()} << '\n';
}

static CovChange
getBuildCovChange(BuildHistory *bh, const Build &build, const CovInfo &covInfo)
{
    CovInfo prevCovInfo;
    if (const int prevBuildId = bh->getPreviousBuildId(build.getId())) {
        prevCovInfo = CovInfo(*bh->getBuild(prevBuildId));
    }

    return CovChange(prevCovInfo, covInfo);
}

void
printFileHeader(std::ostream &os, BuildHistory *bh, const Build &build,
                const File &file)
{
    CovInfo covInfo(file);
    CovChange covChange = getFileCovChange(bh, build, file.getPath(), nullptr,
                                           covInfo);
    printFileHeader(os, file.getPath(), covInfo, covChange);
}

void
printFileHeader(std::ostream &os, BuildHistory *bh, const Build &build,
                const std::string &filePath)
{
    CovInfo covInfo;
    if (boost::optional<File &> file = build.getFile(filePath)) {
        covInfo = CovInfo(*file);
    }

    CovChange covChange = getFileCovChange(bh, build, filePath, nullptr,
                                           covInfo);
    printFileHeader(os, filePath, covInfo, covChange);
}

static void
printFileHeader(std::ostream &os, const std::string &filePath,
                const CovInfo &covInfo, const CovChange &covChange)
{
    os << Label{"File"} << ": " << filePath << ", "
       << covInfo.formatCoverageRate() << ' '
       << '(' << covInfo.formatLines("/") << "), "
       << covChange.formatCoverageRate() << ' '
       << '(' << covChange.formatLines("/") << ")\n";
}

static CovChange
getFileCovChange(BuildHistory *bh, const Build &build, const std::string &path,
                 boost::optional<Build> *prevBuildHint, const CovInfo &covInfo)
{
    boost::optional<Build> prevBuild;
    if (prevBuildHint == nullptr) {
        if (const int prevBuildId = bh->getPreviousBuildId(build.getId())) {
            prevBuild = bh->getBuild(prevBuildId);
        }
        prevBuildHint = &prevBuild;
    }

    CovInfo prevCovInfo;
    if (*prevBuildHint) {
        if (boost::optional<File &> file = (*prevBuildHint)->getFile(path)) {
            prevCovInfo = CovInfo(*file);
        }
    }

    return CovChange(prevCovInfo, covInfo);
}
<commit_msg>Drop commit hash from build header<commit_after>// Copyright (C) 2016 xaizek <xaizek@openmailbox.org>
//
// This file is part of uncov.
//
// uncov is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// uncov 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 uncov.  If not, see <http://www.gnu.org/licenses/>.

#include "listings.hpp"

#include <boost/filesystem/path.hpp>
#include <boost/optional.hpp>

#include <map>
#include <ostream>
#include <string>
#include <vector>

#include "utils/fs.hpp"
#include "BuildHistory.hpp"
#include "coverage.hpp"
#include "printing.hpp"

static std::map<std::string, CovInfo>
getDirsCoverage(const Build &build, const std::string &dirFilter);
static CovChange getBuildCovChange(BuildHistory *bh, const Build &build,
                                   const CovInfo &covInfo);
static void printFileHeader(std::ostream &os, const std::string &filePath,
                            const CovInfo &covInfo, const CovChange &covChange);
static CovChange getFileCovChange(BuildHistory *bh, const Build &build,
                                  const std::string &path,
                                  boost::optional<Build> *prevBuildHint,
                                  const CovInfo &covInfo);

std::vector<std::string>
describeBuild(BuildHistory *bh, const Build &build)
{
    CovInfo covInfo(build);
    CovChange covChange = getBuildCovChange(bh, build, covInfo);

    return {
        "#" + std::to_string(build.getId()),
        covInfo.formatCoverageRate(),
        covInfo.formatLines(" / "),
        covChange.formatCoverageRate(),
        covChange.formatLines(" / "),
        build.getRefName(),
        Revision{build.getRef()},
        Time{build.getTimestamp()}
    };
}

std::vector<std::vector<std::string>>
describeBuildDirs(BuildHistory *bh, const Build &build,
                  const std::string &dirFilter)
{
    std::map<std::string, CovInfo> newDirs = getDirsCoverage(build, dirFilter);

    std::map<std::string, CovInfo> prevDirs;
    if (const int prevBuildId = bh->getPreviousBuildId(build.getId())) {
        prevDirs = getDirsCoverage(*bh->getBuild(prevBuildId), dirFilter);
    }

    std::vector<std::vector<std::string>> rows;
    rows.reserve(newDirs.size());

    for (const auto &entry : newDirs) {
        const CovInfo &covInfo = entry.second;
        CovChange covChange(prevDirs[entry.first], covInfo);

        rows.push_back({
            entry.first + '/',
            covInfo.formatCoverageRate(),
            covInfo.formatLines(" / "),
            covChange.formatCoverageRate(),
            covChange.formatLines(" / ")
        });
    }

    return rows;
}

static std::map<std::string, CovInfo>
getDirsCoverage(const Build &build, const std::string &dirFilter)
{
    std::map<std::string, CovInfo> dirs;
    for (const std::string &filePath : build.getPaths()) {
        if (!pathIsInSubtree(dirFilter, filePath)) {
            continue;
        }

        boost::filesystem::path dirPath = filePath;
        dirPath.remove_filename();

        File &file = *build.getFile(filePath);
        CovInfo &info = dirs[dirPath.string()];

        info.add(CovInfo(file));
    }
    return dirs;
}

std::vector<std::vector<std::string>>
describeBuildFiles(BuildHistory *bh, const Build &build,
                   const std::string &dirFilter, bool changedOnly)
{
    const std::vector<std::string> &paths = build.getPaths();

    std::vector<std::vector<std::string>> rows;
    rows.reserve(paths.size());

    boost::optional<Build> prevBuild;
    if (const int prevBuildId = bh->getPreviousBuildId(build.getId())) {
        prevBuild = bh->getBuild(prevBuildId);
    }

    for (const std::string &filePath : paths) {
        if (!pathIsInSubtree(dirFilter, filePath)) {
            continue;
        }

        CovInfo covInfo(*build.getFile(filePath));
        CovChange covChange = getFileCovChange(bh, build, filePath,
                                               &prevBuild, covInfo);

        if (changedOnly && !covChange.isChanged()) {
            continue;
        }

        rows.push_back({
            filePath,
            covInfo.formatCoverageRate(),
            covInfo.formatLines(" / "),
            covChange.formatCoverageRate(),
            covChange.formatLines(" / "),
        });
    }

    return rows;
}

void
printBuildHeader(std::ostream &os, BuildHistory *bh, const Build &build)
{
    CovInfo covInfo(build);
    CovChange covChange = getBuildCovChange(bh, build, covInfo);

    os << Label{"Build"} << ": #" << build.getId() << ", "
       << covInfo.formatCoverageRate() << ' '
       << '(' << covInfo.formatLines("/") << "), "
       << covChange.formatCoverageRate() << ' '
       << '(' << covChange.formatLines("/") << "), "
       << build.getRefName() << '\n';
}

static CovChange
getBuildCovChange(BuildHistory *bh, const Build &build, const CovInfo &covInfo)
{
    CovInfo prevCovInfo;
    if (const int prevBuildId = bh->getPreviousBuildId(build.getId())) {
        prevCovInfo = CovInfo(*bh->getBuild(prevBuildId));
    }

    return CovChange(prevCovInfo, covInfo);
}

void
printFileHeader(std::ostream &os, BuildHistory *bh, const Build &build,
                const File &file)
{
    CovInfo covInfo(file);
    CovChange covChange = getFileCovChange(bh, build, file.getPath(), nullptr,
                                           covInfo);
    printFileHeader(os, file.getPath(), covInfo, covChange);
}

void
printFileHeader(std::ostream &os, BuildHistory *bh, const Build &build,
                const std::string &filePath)
{
    CovInfo covInfo;
    if (boost::optional<File &> file = build.getFile(filePath)) {
        covInfo = CovInfo(*file);
    }

    CovChange covChange = getFileCovChange(bh, build, filePath, nullptr,
                                           covInfo);
    printFileHeader(os, filePath, covInfo, covChange);
}

static void
printFileHeader(std::ostream &os, const std::string &filePath,
                const CovInfo &covInfo, const CovChange &covChange)
{
    os << Label{"File"} << ": " << filePath << ", "
       << covInfo.formatCoverageRate() << ' '
       << '(' << covInfo.formatLines("/") << "), "
       << covChange.formatCoverageRate() << ' '
       << '(' << covChange.formatLines("/") << ")\n";
}

static CovChange
getFileCovChange(BuildHistory *bh, const Build &build, const std::string &path,
                 boost::optional<Build> *prevBuildHint, const CovInfo &covInfo)
{
    boost::optional<Build> prevBuild;
    if (prevBuildHint == nullptr) {
        if (const int prevBuildId = bh->getPreviousBuildId(build.getId())) {
            prevBuild = bh->getBuild(prevBuildId);
        }
        prevBuildHint = &prevBuild;
    }

    CovInfo prevCovInfo;
    if (*prevBuildHint) {
        if (boost::optional<File &> file = (*prevBuildHint)->getFile(path)) {
            prevCovInfo = CovInfo(*file);
        }
    }

    return CovChange(prevCovInfo, covInfo);
}
<|endoftext|>