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

#include "datacache.hh"

#include <boost/bind.hpp>
#include "principal_event.hh"
#include "vlog.hh"

#define SWITCH     0
#define LOCATION   1
#define HOST       2
#define HOST_NETID 3
#define USER       4

#define UNAUTHENTICATED "unauthenticated"
#define AUTHENTICATED   "authenticated"
#define UNKNOWN         "unknown"

namespace vigil {
namespace applications {

static Vlog_module lg("data_cache");

Data_cache::Data_cache(const container::Context* c,
                       const json_object*)
    : Component(c), reserved(5),
      unauthenticated(UNAUTHENTICATED),
      authenticated(AUTHENTICATED), unknown(UNKNOWN)
{}

void
Data_cache::getInstance(const container::Context* ctxt,
                        Data_cache*& d)
{
    d = dynamic_cast<Data_cache*>
        (ctxt->get_by_interface(container::Interface_description
                                (typeid(Data_cache).name())));
}

void
Data_cache::configure(const container::Configuration*)
{
    resolve(datatypes);
    register_event(Principal_delete_event::static_get_name());
}

void
Data_cache::install()
{
    // ugly...
    Principal add = { 0, 0 };
    add.type = datatypes->switch_type();
    add.id = reserved[SWITCH].unauth;
    add_id_mapping(add, unauthenticated);
    add.id = reserved[SWITCH].auth;
    add_id_mapping(add, authenticated);
    add.id = reserved[SWITCH].unknown;
    add_id_mapping(add, unknown);

    add.type = datatypes->location_type();
    add.id = reserved[LOCATION].unauth;
    add_id_mapping(add, unauthenticated);
    add.id = reserved[LOCATION].auth;
    add_id_mapping(add, authenticated);
    add.id = reserved[LOCATION].unknown;
    add_id_mapping(add, unknown);

    add.type = datatypes->host_type();
    add.id = reserved[HOST].unauth;
    add_id_mapping(add, unauthenticated);
    add.id = reserved[HOST].auth;
    add_id_mapping(add, authenticated);
    add.id = reserved[HOST].unknown;
    add_id_mapping(add, unknown);

    add.type = datatypes->host_netid_type();
    add.id = reserved[HOST_NETID].unauth;
    add_id_mapping(add, unauthenticated);
    add.id = reserved[HOST_NETID].auth;
    add_id_mapping(add, authenticated);
    add.id = reserved[HOST_NETID].unknown;
    add_id_mapping(add, unknown);

    add.type = datatypes->user_type();
    add.id = reserved[USER].unauth;
    add_id_mapping(add, unauthenticated);
    add.id = reserved[USER].auth;
    add_id_mapping(add, authenticated);
    add.id = reserved[USER].unknown;
    add_id_mapping(add, unknown);
}

int64_t
Data_cache::get_authenticated_id(PrincipalType ptype) const
{
    int32_t i = get_reserved_index(ptype);
    if (i < 0) {
        VLOG_ERR(lg, "Requesting unsupported principal type reserved name.");
        return -1;
    }
    return reserved[i].auth;
}

int64_t
Data_cache::get_unauthenticated_id(PrincipalType ptype) const
{
    int32_t i = get_reserved_index(ptype);
    if (i < 0) {
        VLOG_ERR(lg, "Requesting unsupported principal type reserved name.");
        return -1;
    }
    return reserved[i].unauth;
}

int64_t
Data_cache::get_unknown_id(PrincipalType ptype) const
{
    int32_t i = get_reserved_index(ptype);
    if (i < 0) {
        VLOG_ERR(lg, "Requesting unsupported principal type reserved name.");
        return -1;
    }
    return reserved[i].unknown;
}

bool
Data_cache::is_reserved_name(const std::string& name)
{
    return name == unauthenticated || name == authenticated
        || name == unknown;
}

int64_t
Data_cache::get_reserved_index(PrincipalType ptype) const
{
    if (ptype == datatypes->switch_type()) {
        return SWITCH;
    } else if (ptype == datatypes->location_type()) {
        return LOCATION;
    } else if (ptype == datatypes->host_type()) {
        return HOST;
    } else if (ptype == datatypes->host_netid_type()) {
        return HOST_NETID;
    } else if (ptype == datatypes->user_type()) {
        return USER;
    }
    return -1;
}

void
Data_cache::update_reserved_id(PrincipalType ptype, int64_t id,
                               const std::string& name)
{
    int32_t i = get_reserved_index(ptype);
    if (i < 0) {
        return;
    }

    Principal del = { ptype, 0 };
    Principal add = { ptype, 0 };
    if (name == unauthenticated) {
        del.id = reserved[i].unauth;
        reserved[i].unauth = id;
        add.id = id;
    } else if (name == authenticated) {
        del.id = reserved[i].auth;
        reserved[i].auth = id;
        add.id = id;
    } else if (name == unknown) {
        del.id = reserved[i].unknown;
        reserved[i].unknown = id;
        add.id = id;
    } else {
        return;
    }

    delete_principal(del);
    add_id_mapping(add, name);
}

void
Data_cache::delete_principal(const Principal& principal)
{
    if (principal.type == datatypes->address_type()) {
        AddressType type = 0;
        std::string name;
        if (get_address(principal.id, type, name, false)) {
            remove_addr_binding(principal.id, type, name);
        }
    }

    post(new Principal_delete_event(principal.type, principal.id));

    std::list<PrincipalDeletedFn>::const_iterator fn
        = principal_deleted_fns.begin();
    for (; fn != principal_deleted_fns.end(); ++fn) {
        (*fn)(principal);
    }
    delete_id_mapping(principal);
}

void
Data_cache::update_switch(int64_t id, const std::string& name,
                          int64_t dp_priority, const datapathid& dp)
{
    Principal principal = { datatypes->switch_type(), id };
    add_id_mapping(principal, name);
    std::list<SwitchUpdatedFn>::const_iterator fn = switch_updated_fns.begin();
    for (; fn != switch_updated_fns.end(); ++fn) {
        (*fn)(id, dp_priority, dp);
    }
}

void
Data_cache::update_location(int64_t id, const std::string& name,
                            int64_t port_priority, int64_t switch_id,
                            int64_t port, const std::string& portname)
{
    Principal principal = { datatypes->location_type(), id };
    add_id_mapping(principal, name);
    std::list<LocationUpdatedFn>::const_iterator fn
        = location_updated_fns.begin();
    for (; fn != location_updated_fns.end(); ++fn) {
        (*fn)(id, port_priority, switch_id, port, portname);
    }
}

void
Data_cache::update_host(int64_t id, const std::string& name)
{
    Principal principal = { datatypes->host_type(), id };
    add_id_mapping(principal, name);
    std::list<HostUpdatedFn>::const_iterator fn = host_updated_fns.begin();
    for (; fn != host_updated_fns.end(); ++fn) {
        (*fn)(id);
    }
}

void
Data_cache::update_host_netid(int64_t id, const std::string& name,
                              int64_t host_id, bool is_router,
                              bool is_gateway)
{
    Principal principal = { datatypes->host_netid_type(), id };
    add_id_mapping(principal, name);
    std::list<NetidUpdatedFn>::const_iterator fn
        = netid_updated_fns.begin();
    for (; fn != netid_updated_fns.end(); ++fn) {
        (*fn)(id, host_id, is_router, is_gateway);
    }
}

void
Data_cache::update_netid_binding(int64_t addr_id, int64_t host_netid,
                                 int64_t priority, const std::string& addr,
                                 AddressType type, bool deleted)
{
    std::list<NetidBindingUpdatedFn>::const_iterator fn
        = netid_binding_updated_fns.begin();
    for (; fn != netid_binding_updated_fns.end(); ++fn) {
        (*fn)(addr_id, host_netid, priority, addr, type, deleted);
    }
}

void
Data_cache::update_user(int64_t id, const std::string& name)
{
    Principal principal = { datatypes->user_type(), id };
    add_id_mapping(principal, name);
    std::list<UserUpdatedFn>::const_iterator fn = user_updated_fns.begin();
    for (; fn != user_updated_fns.end(); ++fn) {
        (*fn)(id);
    }
}

void
Data_cache::update_group(int64_t id, const std::string& name)
{
    Principal principal = { datatypes->group_type(), id };
    add_id_mapping(principal, name);
    std::list<GroupUpdatedFn>::const_iterator fn = group_updated_fns.begin();
    for (; fn != group_updated_fns.end(); ++fn) {
        (*fn)(id);
    }
}

void
Data_cache::update_address(int64_t id, const std::string& name,
                           AddressType type)
{
    bool removed = false;
    bool add = true;
    AddressType oldtype = 0;
    std::string oldname;
    if (get_address(id, type, oldname, false)) {
        if (type != oldtype || name != oldname) {
            remove_addr_binding(id, oldtype, oldname);
            removed = true;
        } else {
            add = false;
        }
    }

    if (add && name != "") {
        Principal principal = { datatypes->address_type(), id };
        add_id_mapping(principal, name);
        address_types[id] = type;
        if (type == datatypes->mac_type()) {
            add_dladdr_id(id, name);
        } else if (type == datatypes->ipv4_cidr_type()) {
            add_cidr_id(id, name);
        } else {
            VLOG_WARN(lg, "Unknown address type %"PRId64" %s.",
                      type, name.c_str());
        }
        std::list<AddrGroupsUpdatedFn>::const_iterator fn
            = addr_groups_updated_fns.begin();
        for (; fn != addr_groups_updated_fns.end(); ++fn) {
            (*fn)(type, name);
        }
        if (removed) {
            std::list<AddressUpdatedFn>::const_iterator fn2
                = address_updated_fns.begin();
            for (; fn2 != address_updated_fns.end(); ++fn2) {
                (*fn2)(id);
            }
        }
    }
}

void
Data_cache::update_group_member(int64_t id, int64_t group,
                                const Principal& principal,
                                ModifiedState& mod_state)
{
    if (!remove_group_member(id, group, principal, false, mod_state)) {
        return;
    }

    Membership membership = { group, principal };
    memberships[id] = membership;

    ParentMap::iterator p_parents = parents.find(principal);
    if (p_parents == parents.end()) {
        parents[principal] = Parents(1, group);
    } else {
        p_parents->second.push_back(group);
    }

    hash_map<int64_t, Members>::iterator g_members = members.find(group);
    if (g_members == members.end()) {
        members[group] = Members(1, principal);
    } else {
        g_members->second.push_back(principal);
    }
    // add members
    add_members(membership.principal, mod_state);
    mod_state.groups.insert(group);
}

void
Data_cache::delete_group_member(int64_t id, ModifiedState& mod_state)
{
    Principal principal = { 0, 0 };
    remove_group_member(id, 0, principal, true, mod_state);
}

bool
Data_cache::remove_group_member(int64_t id, int64_t group,
                                const Principal& principal, bool deleted,
                                ModifiedState& mod_state)
{
    hash_map<int64_t, Membership>::iterator miter = memberships.find(id);
    if (miter == memberships.end()) {
        return true;
    }

    Membership& membership = miter->second;
    if (!deleted && membership.group == group
        && membership.principal.type == principal.type
        && membership.principal.id == principal.id)
    {
        return false;
    }

    bool not_found = true;
    ParentMap::iterator p_parents = parents.find(membership.principal);
    if (p_parents != parents.end()) {
        for (Parents::iterator parent = p_parents->second.begin();
             parent != p_parents->second.end(); ++parent)
        {
            if (*parent == membership.group) {
                not_found = false;
                p_parents->second.erase(parent);
                if (p_parents->second.empty()) {
                    parents.erase(p_parents);
                }
                break;
            }
        }
    }

    if (not_found) {
        VLOG_ERR(lg, "Member %"PRId64" %"PRId64" parent %"PRId64" not found.",
                 membership.principal.type, membership.principal.id,
                 membership.group);
    }

    not_found = true;
    hash_map<int64_t, Members>::iterator g_members
        = members.find(membership.group);
    if (g_members != members.end()) {
        for (Members::iterator member = g_members->second.begin();
             member != g_members->second.end(); ++member)
        {
            if (member->type == membership.principal.type
                && member->id == membership.principal.id)
            {
                not_found = false;
                g_members->second.erase(member);
                if (g_members->second.empty()) {
                    members.erase(g_members);
                }
                break;
            }
        }
    }

    if (not_found) {
        VLOG_ERR(lg, "Group %"PRId64" member %"PRId64" %"PRId64" not found.",
                 membership.group, membership.principal.type,
                 membership.principal.id);
    }

    add_members(membership.principal, mod_state);
    mod_state.groups.insert(membership.group);

    memberships.erase(miter);
    return true;
}

void
Data_cache::add_members(const Principal& principal,
                        ModifiedState& mod_state) const
{
    if (principal.type != datatypes->group_type()) {
        mod_state.principals.insert(principal);
        return;
    }

    if (mod_state.processed.find(principal.id) == mod_state.processed.end()) {
        mod_state.processed.insert(principal.id);
        hash_map<int64_t, Members>::const_iterator g_members
            = members.find(principal.id);
        if (g_members == members.end()) {
            return;
        }

        for (Members::const_iterator member = g_members->second.begin();
             member != g_members->second.end(); ++member)
        {
            add_members(*member, mod_state);
        }
    }
}

void
Data_cache::add_id_mapping(Principal& principal,
                           const std::string& name)
{
    id_to_name[principal] = name;
}

void
Data_cache::delete_id_mapping(const Principal& principal)
{
    id_to_name.erase(principal);
}

void
Data_cache::add_dladdr_id(int64_t id, const std::string& name)
{
    ethernetaddr dladdr(name);
    uint64_t key = dladdr.hb_long();
    hash_map<uint64_t, std::list<int64_t> >::iterator found
        = dladdr_to_id.find(key);
    if (found == dladdr_to_id.end()) {
        dladdr_to_id[key] = std::list<int64_t>(1, id);
    } else {
        found->second.push_back(id);
    }
}

void
Data_cache::add_cidr_id(int64_t id, const std::string& name)
{
    cidr_ipaddr cidr(name);
    if (cidr.get_prefix_len() == 32) {
        uint32_t key = ntohl(cidr.addr.addr);
        hash_map<uint32_t, std::list<int64_t> >::iterator found
            = nwaddr_to_id.find(key);
        if (found == nwaddr_to_id.end()) {
            found = nwaddr_to_id.insert(
                std::make_pair(key, std::list<int64_t>())).first;
        }
        found->second.push_back(id);
    } else {
        id_to_cidr[id] = cidr;
    }
}

void
Data_cache::remove_addr_binding(int64_t id, AddressType type,
                                const std::string name)
{
    address_types.erase(id);
    if (type == datatypes->mac_type()) {
        remove_dladdr_id(id, name);
    } else if (type == datatypes->ipv4_cidr_type()) {
        remove_cidr_id(id, name);
    }
    std::list<AddrGroupsUpdatedFn>::const_iterator fn
        = addr_groups_updated_fns.begin();
    for (; fn != addr_groups_updated_fns.end(); ++fn) {
        (*fn)(type, name);
    }
}

void
Data_cache::remove_dladdr_id(int64_t id, const std::string& name)
{
    ethernetaddr dladdr(name);
    hash_map<uint64_t, std::list<int64_t> >::iterator entry
        = dladdr_to_id.find(dladdr.hb_long());
    for (std::list<int64_t>::iterator iter = entry->second.begin();
         iter != entry->second.end(); ++iter)
    {
        if (*iter == id) {
            entry->second.erase(iter);
            if (entry->second.empty()) {
                dladdr_to_id.erase(entry);
            }
            break;
        }
    }
}

void
Data_cache::remove_cidr_id(int64_t id, const std::string& name)
{
    cidr_ipaddr cidr(name);
    if (cidr.get_prefix_len() == 32) {
        hash_map<uint32_t, std::list<int64_t> >::iterator entry
            = nwaddr_to_id.find(ntohl(cidr.addr.addr));
        for (std::list<int64_t>::iterator iter = entry->second.begin();
             iter != entry->second.end(); ++iter)
        {
            if (*iter == id) {
                entry->second.erase(iter);
                if (entry->second.empty()) {
                    nwaddr_to_id.erase(entry);
                }
                break;
            }
        }
    } else {
        id_to_cidr.erase(id);
    }
}

bool
Data_cache::get_name(const Principal& principal, std::string& name) const
{
    IDMap::const_iterator id_entry = id_to_name.find(principal);
    if (id_entry != id_to_name.end()) {
        name = id_entry->second;
        return true;
    }
    return false;
}

const std::string&
Data_cache::get_name_ref(const Principal& principal) const
{
    IDMap::const_iterator id_entry = id_to_name.find(principal);
    if (id_entry != id_to_name.end()) {
        return id_entry->second;
    }
    return unknown;
}

bool
Data_cache::get_address(int64_t id, AddressType& type,
                        std::string& name, bool expect_addr) const
{
    Principal principal = { datatypes->address_type(), id };
    hash_map<int64_t, AddressType>::const_iterator atype
        = address_types.find(id);
    if (atype == address_types.end()) {
        return false;
    }

    type = atype->second;

    IDMap::const_iterator id_entry = id_to_name.find(principal);
    if (id_entry == id_to_name.end()) {
        if (expect_addr) {
            VLOG_ERR(lg, "Address mapping for %"PRId64" doesn't exist.", id);
        }
        return false;
    }

    name = id_entry->second;
    return true;
}

void
Data_cache::get_groups(const Principal& principal, GroupList& group_list) const
{
    std::list<int64_t> p_parents;
    add_parents(principal, p_parents);
    set_group_list(p_parents, group_list);
}

void
Data_cache::get_groups(const ethernetaddr& dladdr, GroupList& group_list) const
{
    hash_map<uint64_t, std::list<int64_t> >::const_iterator ids =
        dladdr_to_id.find(dladdr.hb_long());
    if (ids == dladdr_to_id.end()) {
        group_list.clear();
        return;
    }

    std::list<int64_t> p_parents;
    Principal principal = { datatypes->address_type(), 0 };
    for (std::list<int64_t>::const_iterator id = ids->second.begin();
         id != ids->second.end(); ++id)
    {
        principal.id = *id;
        add_parents(principal, p_parents);
    }

    set_group_list(p_parents, group_list);
}

void
Data_cache::get_groups(const ipaddr& nwaddr, GroupList& group_list) const
{
    std::list<int64_t> p_parents;
    Principal principal = { datatypes->address_type(), 0 };

    hash_map<uint32_t, std::list<int64_t> >::const_iterator ids =
        nwaddr_to_id.find(ntohl(nwaddr.addr));
    if (ids != nwaddr_to_id.end()) {
        for (std::list<int64_t>::const_iterator id = ids->second.begin();
             id != ids->second.end(); ++id)
        {
            principal.id = *id;
            add_parents(principal, p_parents);
        }
    }

    hash_map<int64_t, cidr_ipaddr>::const_iterator cidr = id_to_cidr.begin();
    for (; cidr != id_to_cidr.end(); ++cidr) {
        if (cidr->second.matches(nwaddr)) {
            principal.id = cidr->first;
            add_parents(principal, p_parents);
        }
    }

    set_group_list(p_parents, group_list);
}

void
Data_cache::get_all_group_members(const std::list<int64_t>& group_list,
                                  PrincipalSet& principals) const
{
    ModifiedState mod_state;
    Principal group = { datatypes->group_type(), 0 };
    for (std::list<int64_t>::const_iterator iter = group_list.begin();
         iter != group_list.end(); ++iter)
    {
        group.id = *iter;
        add_members(group, mod_state);
    }

    principals.swap(mod_state.principals);
}

bool
Data_cache::add_group(int64_t group, std::list<int64_t>& parent_list) const
{
    for (std::list<int64_t>::iterator iter = parent_list.begin();
         iter != parent_list.end(); ++iter)
    {
        if (*iter > group) {
            parent_list.insert(iter, group);
            return true;
        } else if (*iter == group) {
            return false;
        }
    }
    parent_list.push_back(group);
    return true;
}

void
Data_cache::add_parents(const Principal& principal,
                        std::list<int64_t>& parent_list) const
{
    ParentMap::const_iterator p_parents = parents.find(principal);
    if (p_parents == parents.end()) {
        return;
    }

    for (Parents::const_iterator parent = p_parents->second.begin();
         parent != p_parents->second.end(); ++parent)
    {
        if (add_group(*parent, parent_list)) {
            Principal parent_principal = { datatypes->group_type(), *parent };
            add_parents(parent_principal, parent_list);
        }
    }
}

void
Data_cache::set_group_list(const std::list<int64_t>& parent_list,
                           GroupList& group_list) const
{
    group_list.resize(parent_list.size());
    GroupList::iterator group = group_list.begin();
    for (std::list<int64_t>::const_iterator iter = parent_list.begin();
         iter != parent_list.end(); ++iter, ++group)
    {
        *group = *iter;
    }
}

void
Data_cache::process_modified_state(const ModifiedState& mod_state) const
{
    if (!mod_state.principals.empty()) {
        std::list<GroupsUpdatedFn>::const_iterator fn
            = groups_updated_fns.begin();
        for (; fn != groups_updated_fns.end(); ++fn) {
            (*fn)(mod_state.principals);
        }
    }
    if (!mod_state.groups.empty()) {
        std::list<MembersUpdatedFn>::const_iterator fn
            = members_updated_fns.begin();
        for (; fn != members_updated_fns.end(); ++fn) {
            (*fn)(mod_state.groups);
        }
    }
}

}
}

REGISTER_COMPONENT(vigil::container::Simple_component_factory
                   <vigil::applications::Data_cache>,
                   vigil::applications::Data_cache);

ext: cc

max_stars_repo_name: ayjazz/OESS

max_issues_repo_name: ayjazz/OESS

max_forks_repo_name: ayjazz/OESS


text:
//
// Copyright (c) 2011-2012 Krzysztof Jusiak (krzysztof at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include <gtest/gtest.h>
#include <boost/mpl/vector.hpp>
#include <boost/typeof/typeof.hpp>
#include "QFsm/Front/Operations/IsFinished.hpp"
#include "QFsm/Front/Operations/Transition.hpp"
#include "QFsm/Front/Operations/None.hpp"
#include "Common/Events.hpp"
#include "Common/States.hpp"
#include "Common/FsmStub.hpp"

namespace QFsm
{

using namespace Test::Common;

namespace Front
{
namespace Operations
{
namespace UT
{

TEST(IsFinished, Basic)
{
    //given
    typedef FsmStub
    <
        boost::mpl::vector
        <
            Transition<State1, e1, State2>
        >,
        State1
    >
    Fsm;
    Fsm l_fsm;
    l_fsm.currentStates[0] = 0;

    //when
    IsFinished<State1>()(e1(), l_fsm);

    //then
    //EXPECT_EQ(1u, l_fsm.deferralEvents.addDeferralEventCalls.size());
}

} // namespace UT
} // namespace Operations
} // namespace Front
} // namespace QFsm

ext: cpp

max_stars_repo_name: krzysztof-jusiak/qfsm

max_issues_repo_name: krzysztof-jusiak/qfsm

max_forks_repo_name: krzysztof-jusiak/qfsm


text:
/*
// Copyright (c) 2000-2009, Texas Engineering Experiment Station (TEES), a
// component of the Texas A&M University System.

// All rights reserved.

// The information and source code contained herein is the exclusive
// property of TEES and may not be disclosed, examined or reproduced
// in whole or in part without explicit written authorization from TEES.
*/

#ifndef STAPL_RUNTIME_CONFIG_COMPILER_HPP
#define STAPL_RUNTIME_CONFIG_COMPILER_HPP

//////////////////////////////////////////////////////////////////////
/// @file
/// Detects compilers and their capabilities.
///
/// @ingroup runtimeConfig
//////////////////////////////////////////////////////////////////////

#include <boost/config/select_compiler_config.hpp>

#endif

ext: hpp


text:
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef __SLAVE_MONITOR_HPP__
#define __SLAVE_MONITOR_HPP__

#include <map>
#include <string>

#include <boost/circular_buffer.hpp>

#include <mesos/mesos.hpp>

#include <process/future.hpp>
#include <process/limiter.hpp>
#include <process/statistics.hpp>

#include <stout/cache.hpp>
#include <stout/duration.hpp>
#include <stout/hashmap.hpp>
#include <stout/nothing.hpp>
#include <stout/option.hpp>
#include <stout/try.hpp>

#include "common/type_utils.hpp"

namespace mesos {
namespace internal {
namespace slave {

// Forward declarations.
class Containerizer;
class ResourceMonitorProcess;

const extern Duration MONITORING_TIME_SERIES_WINDOW;
const extern size_t MONITORING_TIME_SERIES_CAPACITY;

// Number of time series to maintain for completed executors.
const extern size_t MONITORING_ARCHIVED_TIME_SERIES;

// Provides resource monitoring for containers. Resource usage time
// series are stored using the Statistics module. Usage information
// is also exported via a JSON endpoint.
// TODO(bmahler): Forward usage information to the master.
// TODO(bmahler): Consider pulling out the resource collection into
// a Collector abstraction. The monitor can then become a true
// monitoring abstraction, allowing isolators to subscribe
// to resource usage events. (e.g. get a future for the executor
// hitting 75% memory consumption, the future would become ready
// when this occurs, and the isolator can discard the future
// when no longer interested).
class ResourceMonitor
{
public:
  explicit ResourceMonitor(Containerizer* containerizer);
  ~ResourceMonitor();

  // Starts monitoring resources for the given container.
  // Returns a failure if the container is already being watched.
  process::Future<Nothing> start(
      const ContainerID& containerId,
      const ExecutorInfo& executorInfo,
      const Duration& interval);

  // Stops monitoring resources for the given container.
  // Returns a failure if the container is unknown to the monitor.
  process::Future<Nothing> stop(
      const ContainerID& containerId);

private:
  ResourceMonitorProcess* process;
};

class ResourceMonitorProcess : public process::Process<ResourceMonitorProcess>
{
public:
  explicit ResourceMonitorProcess(Containerizer* _containerizer)
    : ProcessBase("monitor"),
      containerizer(_containerizer),
      limiter(2, Seconds(1)), // 2 permits per second.
      archive(MONITORING_ARCHIVED_TIME_SERIES) {}

  virtual ~ResourceMonitorProcess() {}

  process::Future<Nothing> start(
      const ContainerID& containerId,
      const ExecutorInfo& executorInfo,
      const Duration& interval);

  process::Future<Nothing> stop(
      const ContainerID& containerId);

protected:
  virtual void initialize()
  {
    route("/statistics.json",
          STATISTICS_HELP,
          &ResourceMonitorProcess::statistics);

    // TODO(bmahler): Add a archive.json endpoint that exposes
    // historical information, once we have path parameters for
    // routes.
  }

private:
  void collect(
      const ContainerID& containerId,
      const Duration& interval);
  void _collect(
      const process::Future<ResourceStatistics>& statistics,
      const ContainerID& containerId,
      const Duration& interval);

  // This is a convenience struct for bundling usage information.
  struct Usage
  {
    ContainerID containerId;
    ExecutorInfo executorInfo;
    process::Future<ResourceStatistics> statistics;
  };

  // Helper for returning the usage for a particular executor.
  Usage usage(
      const ContainerID& containerId,
      const ExecutorInfo& executorInfo);

  // HTTP Endpoints.
  // Returns the monitoring statistics. Requests have no parameters.
  process::Future<process::http::Response> statistics(
      const process::http::Request& request);
  process::Future<process::http::Response> _statistics(
      const process::http::Request& request);
  process::Future<process::http::Response> __statistics(
      const std::list<Usage>& usages,
      const process::http::Request& request);

  static const std::string STATISTICS_HELP;

  Containerizer* containerizer;

  // Used to rate limit the statistics.json endpoint.
  process::RateLimiter limiter;

  // Monitoring information for an executor.
  struct MonitoringInfo {
    // boost::circular_buffer needs a default constructor.
    MonitoringInfo() {}

    MonitoringInfo(const ExecutorInfo& _executorInfo,
                   const Duration& window,
                   size_t capacity)
      : executorInfo(_executorInfo), statistics(window, capacity) {}

    ExecutorInfo executorInfo;   // Non-const for assignability.
    process::TimeSeries<ResourceStatistics> statistics;
  };

  // The monitoring info is stored for each monitored container.
  hashmap<ContainerID, MonitoringInfo> monitored;

  // Fixed-size history of monitoring information.
  boost::circular_buffer<MonitoringInfo> archive;
};

} // namespace slave {
} // namespace internal {
} // namespace mesos {

#endif // __SLAVE_MONITOR_HPP__

max_stars_repo_name: dharmeshkakadia/mesos

max_issues_repo_name: dharmeshkakadia/mesos

max_forks_repo_name: dharmeshkakadia/mesos


text:
//==============================================================================
//         Copyright 2003 - 2011   LASMEA UMR 6602 CNRS/Univ. Clermont II
//         Copyright 2009 - 2011   LRI    UMR 8623 CNRS/Univ Paris Sud XI
//
//          Distributed under the Boost Software License, Version 1.0.
//                 See accompanying file LICENSE.txt or copy at
//                     http://www.boost.org/LICENSE_1_0.txt
//==============================================================================
#ifndef NT2_CORE_CONTAINER_COLON_COLON_HPP_INCLUDED
#define NT2_CORE_CONTAINER_COLON_COLON_HPP_INCLUDED

#include <nt2/include/functions/colon.hpp>
#include <nt2/core/container/dsl/forward.hpp>
#include <nt2/core/container/dsl/domain.hpp>
#include <nt2/core/container/table/kind.hpp>
#include <nt2/core/functions/table/details/is_vectorizable_indexer.hpp>
#include <nt2/sdk/memory/forward/container.hpp>
#include <boost/dispatch/meta/hierarchy_of.hpp>
#include <nt2/sdk/meta/as.hpp>
#include <boost/mpl/bool.hpp>

namespace nt2 { namespace container
{
  //==========================================================================
  // colon_ is an helper class that handles the _ placeholders behavior
  //==========================================================================
  struct colon_
  {
    // colon_ as a sink for tie
    template<class T> colon_ const& operator=(T const&) const { return *this; }

    // _() as []
    boost::proto::result_of::
    make_expr< nt2::tag::empty_colon_, container::domain
             , of_size_<0>
             , meta::constant_<nt2::tag::unity_colon_, double>
             , meta::as_<double>
             >::type
    operator()() const
    {
      return boost::proto::make_expr< nt2::tag::empty_colon_, container::domain >
            ( of_size_<0>(), meta::constant_<nt2::tag::unity_colon_, double>(1.), meta::as_<double>() );
    }

    // colon as a:b
    template<class Begin, class End>
    typename meta::call<nt2::tag::colon_(Begin,End)>::type
    operator()(Begin b, End e) const
    {
      return nt2::colon(b,e);
    }

    // colon as a:s:b
    template<class Begin, class Step, class End>
    typename meta::call<nt2::tag::colon_(Begin,Step,End)>::type
    operator()(Begin  b, Step s, End e) const
    {
      return nt2::colon(b,s,e);
    }
  };
} }

namespace nt2
{
  //==========================================================================
  /*!
   * _ is a multi-purpose placeholder in \nt2:
   *
   *   - it acts as \matlab \c : in indexing expression
   *   - it enables \c :(b,s,e) to mimic \matlab \c b:s:e iota notation
   *   - _() is Matlab []
   *   - it acts as a sink in tie expressions
   **/
  //==========================================================================
  container::colon_ const _ = {};
}

namespace nt2 { namespace ext
{
  /// INTERNAL ONLY
  template<>
  struct is_vectorizable_scalar
            < nt2::container::expression
                    < boost::proto::
                            basic_expr< nt2::tag::terminal_
                                      , boost::proto::term<nt2::container::colon_>
                                      , 0l
                                      >
                    , nt2::container::colon_
                    >
            >
        : boost::mpl::false_
  {
  };

  /// INTERNAL ONLY
  template<class Cardinal>
  struct is_vectorizable_indexer
            < nt2::container::expression
                    < boost::proto::
                            basic_expr< nt2::tag::terminal_
                                      , boost::proto::term<nt2::container::colon_>
                                      , 0l
                                      >
                    , nt2::container::colon_
                    >
            , Cardinal
            >
        : boost::mpl::true_
  {
  };
} }
#endif


text:
#include "Option.h"

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

#include "AllowedURI.h"
#include "Channel.h"
#include "Format.h"

#include "boost_filesystem_path_validation.h"

namespace RunFragment {

namespace fs = boost::filesystem;

namespace Option {

const Parameter image {"Image", 'i'};
const std::array<Parameter, 4> imageChannels = {{
	"Image-c0", "Image-c1", "Image-c2", "Image-c3"
}};

const std::array<Parameter, 4> bufs = {{"BufA", "BufB", "BufC", "BufD"}};
const std::array<std::array<Parameter, 4>, 4> bufChannels =
{{
	{{"BufA-c0", "BufA-c1", "BufA-c2", "BufA-c3"}},
	{{"BufB-c0", "BufB-c1", "BufB-c2", "BufB-c3"}},
	{{"BufC-c0", "BufC-c1", "BufC-c2", "BufC-c3"}},
	{{"BufD-c0", "BufD-c1", "BufD-c2", "BufD-c3"}},
}};

const Parameter config {"config", 'c'};
const Parameter download = {"download", 'd'};
const Parameter create {"create", 'p'};
const Parameter time {"time", 't'};
const Parameter help {"help", 'h'};
const Parameter format {"format", 'f'};
const Parameter main = "main";
const Parameter addUniform = "add-uniforms";

const Parameter iResolution = "iResolution";
const Parameter iGlobalTime = "iGlobalTime";
const Parameter iTimeDelta = "iTimeDelta";
const Parameter iFrame = "iFrame";
const Parameter iFrameRate = "iFrameRate";
const Parameter iChannelTime = "iChannelTime";
const Parameter iChannelResolution = "iChannelResolution";
const Parameter iMouse = "iMouse";
const Parameter iDate = "iDate";
const Parameter iSampleRate = "iSampleRate";
const Parameter iChannel = "iChannel";
const Parameter iSurfacePosition = "iSurfacePosition";

extern const std::string none = "none";

namespace po = boost::program_options;

const po::options_description helpOptions = [] {
	po::options_description general {"General"};
	general.add_options()
		(config.getPo(),   po::value<std::string>(), "Config file, .ini format where the variables are equals to CLI options")
		(download.getPo(), po::value<AllowedURI*>(), "Download a project from shadertoy.com or glslsanbox.com")
		(create.getPo(),   po::value<std::string>(), "Create a project (a directory with a config file and Image shader if '-f s' is given, otherwise a single Image shader)")
		(help.getPo(),                               "Display help message");

	po::options_description buffersChannels {"Buffers and their channels"};
	buffersChannels.add_options()
		(image.getPo(),           po::value<std::string>(), "Set Image shader file")
		("Buf(A | B | C | D)",            po::value<std::string>(), "Set Buf's shader file; 'none' if not used")
		("(Image | Buf(A | B | C | D))-c(0 | 1 | 2 | 3)", po::value<std::string>(), "Set Image's or Buf's channel:\n    <image file>[:flip] : image, ':flip' if flipped\n    Buf(A | B | C | D) : buffer as a channel (multipass)");

	po::options_description other {"Other"};
	other.add_options()
		(format.getPo(),             po::value<std::string>(), "Format of the uniforms:\n    (g | glslsandbox) : GLSLSandbox.com (default)\n    (s | shadertoy) : ShaderToy.com")
		(time.getPo(),               po::value<float>(),       "Set value that multiplies the time")
		(main.getPo(),               po::value<std::string>(), "Set the name of mainImage(out vec4, in vec2) function; 'none' if not used")
		(addUniform.getPo(),         po::bool_switch(),        "Add uniforms declaration to beginning of the shader file")
		(iResolution.getPo(),        po::value<std::string>(), "Set the name of iResolution uniform")
		(iGlobalTime.getPo(),        po::value<std::string>(), "Set the name of iGlobalTime uniform")
		(iTimeDelta.getPo(),         po::value<std::string>(), "Set the name of iTimeDelta uniform")
		(iFrame.getPo(),             po::value<std::string>(), "Set the name of iFrame uniform")
		(iFrameRate.getPo(),         po::value<std::string>(), "Set the name of iFrameRate uniform")
//		(iChannelTime.getPo(),       po::value<std::string>(), "Set the name of iChannelTime uniform")
//		(iChannelResolution.getPo(), po::value<std::string>(), "Set the name of iChannelResolution uniform")
		(iMouse.getPo(),             po::value<std::string>(), "Set the name of iMouse uniform")
		(iDate.getPo(),              po::value<std::string>(), "Set the name of iDate uniform")
//		(iSampleRate.getPo(),        po::value<std::string>(), "Set the name of iSampleRate uniform")
		(iChannel.getPo(),           po::value<std::string>(), "Set the name of iChannelN uniform")
		(iSurfacePosition.getPo(),   po::value<std::string>(), "Set the name of iSurfacePosition varying");

	po::options_description desc;
	desc.add(general).add(buffersChannels).add(other);
	return desc;
} ();

const po::options_description parsingOptions = [] {
	po::options_description general;
	general.add_options()
		(config.getPo(),   po::value<fs::path>())
		(download.getPo(), po::value<AllowedURI*>())
		(create.getPo(),   po::value<fs::path>())
		(help.getPo(), "");

	po::options_description buffersChannels;
	buffersChannels.add_options()
		(image.getPo(), po::value<fs::path>());

	for(std::size_t i = 0; i < imageChannels.size(); i++) {
		buffersChannels.add_options()
			(imageChannels.at(i).getPo(), po::value<Channel*>());
	}

	for(std::size_t i = 0; i < bufs.size(); i++) {
		buffersChannels.add_options()
			(bufs.at(i).getPo(), po::value<fs::path>());

		for(std::size_t j = 0; j < std::tuple_size<decltype(bufChannels)::value_type>::value; j++) {
			buffersChannels.add_options()
				(bufChannels.at(i).at(j).getPo(), po::value<Channel*>());
		}
	}

	po::options_description other;
	other.add_options()
		(format.getPo(),             po::value<Format>())
		(time.getPo(),               po::value<float>())
		(main.getPo(),               po::value<std::string>())
		(addUniform.getPo(),         po::bool_switch())
		(iResolution.getPo(),        po::value<std::string>())
		(iGlobalTime.getPo(),        po::value<std::string>())
		(iTimeDelta.getPo(),         po::value<std::string>())
		(iFrame.getPo(),             po::value<std::string>())
		(iFrameRate.getPo(),         po::value<std::string>())
		(iChannelTime.getPo(),       po::value<std::string>())
		(iChannelResolution.getPo(), po::value<std::string>())
		(iMouse.getPo(),             po::value<std::string>())
		(iDate.getPo(),              po::value<std::string>())
		(iSampleRate.getPo(),        po::value<std::string>())
		(iChannel.getPo(),           po::value<std::string>())
		(iSurfacePosition.getPo(),   po::value<std::string>());

	po::options_description desc;
	desc.add(general).add(buffersChannels).add(other);
	return desc;
} ();

}
}


text:
#ifndef TESTS_H
#define TESTS_H

#include "grune/grune_fwd.hpp"
#include "grune/sentence_iterator.hpp"
#include "grune-yaml/grune-yaml.hpp"

#include <boost/test/unit_test.hpp>

#ifndef COVERITY_BUILD
#define GRUNE_TEST_SUITE(suite) BOOST_AUTO_TEST_SUITE(suite)
#define GRUNE_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
#define GRUNE_TEST_CASE(suite, name) BOOST_AUTO_TEST_CASE(name)
#define GRUNE_TEST_CASE_END()
#else
#include <coverity-test-separation.h>
#define GRUNE_TEST_SUITE(suite) BOOST_AUTO_TEST_SUITE(suite)
#define GRUNE_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

#define GRUNE_TEST_CASE(suite, name)\
    BOOST_AUTO_TEST_CASE(name) \
    { \
        COVERITY_TS_START_TEST(#suite "/" #name);

#define GRUNE_TEST_CASE_END() \
        COVERITY_TS_END_TEST(); \
    }
#endif /* COVERITY_BUILD */

#ifdef GRUNE_ASSERTION_TRAITS_NO_YAML
#define GRUNE_TO_STRING(x) grune::to_string(x)
#else
#define GRUNE_TO_STRING(x) YAML::Dump(YAML::Node(x));
#endif /* GRUNE_ASSERTION_TRAITS_NO_YAML */

#define GRUNE_ASSERTION_TRAITS_FWD(t) \
    namespace boost { namespace test_tools { \
        template<> \
        struct print_log_value<t> {\
            void operator()(std::ostream& os, const t&); \
        }; \
    } }

GRUNE_ASSERTION_TRAITS_FWD(grune::symbol);
GRUNE_ASSERTION_TRAITS_FWD(grune::non_terminal);
GRUNE_ASSERTION_TRAITS_FWD(grune::sequence);
GRUNE_ASSERTION_TRAITS_FWD(grune::sequence_list);
GRUNE_ASSERTION_TRAITS_FWD(grune::production);
GRUNE_ASSERTION_TRAITS_FWD(grune::production_list);
GRUNE_ASSERTION_TRAITS_FWD(grune::grammar);

namespace boost {
namespace test_tools {
    template<>
    struct print_log_value<grune::sentence_iterator>
    {
        void operator()(std::ostream& os, const grune::sentence_iterator& v)
        {
            auto r =
                (v == grune::sentence_iterator()) ?
                "<end>" : grune::to_string(*v);
            os << r;
        }
    };
}
}

#endif /* TESTS_H */

max_stars_repo_name: Fifty-Nine/grune

max_issues_repo_name: Fifty-Nine/grune

max_forks_repo_name: Fifty-Nine/grune


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

#include <math.h>

#include <boost/format.hpp>
#include <boost/filesystem.hpp>

#include "luxrays/utils/thread.h"

#include "slg/samplers/sobol.h"
#include "slg/utils/pathdepthinfo.h"
#include "slg/engines/caches/photongi/photongicache.h"
#include "slg/engines/caches/photongi/tracephotonsthread.h"
#include "slg/utils/pathinfo.h"

using namespace std;
using namespace luxrays;
using namespace slg;

//------------------------------------------------------------------------------
// PhotonGICache
//------------------------------------------------------------------------------

PhotonGICache::PhotonGICache() :
		scene(nullptr),
		visibilityParticlesKdTree(nullptr),
		radiancePhotonsBVH(nullptr) ,
		causticPhotonsBVH(nullptr) {
}

PhotonGICache::PhotonGICache(const Scene *scn, const PhotonGICacheParams &p) :
		scene(scn), params(p),
		visibilityParticlesKdTree(nullptr),
		radiancePhotonsBVH(nullptr) ,
		indirectPhotonTracedCount(0),
		causticPhotonsBVH(nullptr),
		causticPhotonTracedCount(0),
		causticPhotonPass(0) {
}

PhotonGICache::~PhotonGICache() {
	delete visibilityParticlesKdTree;

	delete causticPhotonsBVH;
	delete radiancePhotonsBVH;
}

bool PhotonGICache::IsPhotonGIEnabled(const BSDF &bsdf) const {
	const BSDFEvent eventTypes = bsdf.GetEventTypes();

	if ((eventTypes & TRANSMIT) || (eventTypes & SPECULAR) ||
			((eventTypes & GLOSSY) && (bsdf.GetGlossiness() < params.glossinessUsageThreshold)))
		return false;
	else
		return bsdf.IsPhotonGIEnabled();
}

float PhotonGICache::GetIndirectUsageThreshold(const BSDFEvent lastBSDFEvent,
		const float lastGlossiness, const float u0) const {
	// Decide if the glossy surface is "nearly specular"

	if ((lastBSDFEvent & GLOSSY) && (lastGlossiness < params.glossinessUsageThreshold)) {
		// Disable the cache, the surface is "nearly specular"
		return numeric_limits<float>::infinity();
	} else {
		// Use a larger blend zone for glossy surface
		const float scale = (lastBSDFEvent & GLOSSY) ? 2.f : 1.f;

		// Enable the cache for diffuse or glossy "nearly diffuse" but only after
		// the threshold (before I brute force and cache between 0x and 1x the threshold)
		return scale * u0 * params.indirect.usageThresholdScale * params.indirect.lookUpRadius;
	}
}

bool PhotonGICache::IsDirectLightHitVisible(const EyePathInfo &pathInfo,
		const bool photonGICausticCacheUsed) const {
	// This is a specific check to cut fireflies created by some glossy or
	// specular bounce
	if (!(pathInfo.lastBSDFEvent & DIFFUSE) && (pathInfo.depth.diffuseDepth > 0))
		return false;
	else if (!params.caustic.enabled || !photonGICausticCacheUsed)
		return true;
	else if (!pathInfo.IsCausticPath() && (params.debugType == PGIC_DEBUG_NONE))
		return true;
	else
		return false;
}

void PhotonGICache::TracePhotons(const u_int seedBase, const u_int photonTracedCount,
		const bool indirectCacheDone, const bool causticCacheDone,
		boost::atomic<u_int> &globalIndirectPhotonsTraced, boost::atomic<u_int> &globalCausticPhotonsTraced,
		boost::atomic<u_int> &globalIndirectSize, boost::atomic<u_int> &globalCausticSize) {
	const size_t renderThreadCount = GetHardwareThreadCount();
	vector<TracePhotonsThread *> renderThreads(renderThreadCount, nullptr);

	boost::atomic<u_int> globalPhotonsCounter(0);

	// Create the photon tracing threads
	for (size_t i = 0; i < renderThreadCount; ++i) {
		renderThreads[i] = new TracePhotonsThread(*this, i,
				seedBase, photonTracedCount,
				indirectCacheDone, causticCacheDone,
				globalPhotonsCounter, globalIndirectPhotonsTraced,
				globalCausticPhotonsTraced, globalIndirectSize,
				globalCausticSize);
	}

	// Start photon tracing threads
	for (size_t i = 0; i < renderThreadCount; ++i)
		renderThreads[i]->Start();

	// Wait for the end of photon tracing threads
	u_int indirectPhotonStored = 0;
	u_int causticPhotonStored = 0;
	for (size_t i = 0; i < renderThreadCount; ++i) {
		renderThreads[i]->Join();

		// Copy all photons
		for (auto const &p : renderThreads[i]->indirectPhotons) {
			PGICVisibilityParticle &vp = visibilityParticles[p.visibilityParticelIndex];

			vp.alphaAccumulated.Add(p.lightID, p.alpha);
		}
		indirectPhotonStored += renderThreads[i]->indirectPhotons.size();

		causticPhotons.insert(causticPhotons.end(), renderThreads[i]->causticPhotons.begin(),
				renderThreads[i]->causticPhotons.end());
		causticPhotonStored += renderThreads[i]->causticPhotons.size();

		delete renderThreads[i];
	}

	// Update the count only if I have traced this kind of photons
	if (!indirectCacheDone)
		indirectPhotonTracedCount = globalIndirectPhotonsTraced;
	// Update the count only if I have traced this kind of photons
	if (!causticCacheDone)
		causticPhotonTracedCount = globalCausticPhotonsTraced;

	SLG_LOG("PhotonGI additional indirect photon stored: " << indirectPhotonStored);
	SLG_LOG("PhotonGI additional caustic photon stored: " << causticPhotonStored);
	// photonReacedCount isn't exactly but it is quite near
	SLG_LOG("PhotonGI total photon traced: " << Max(indirectPhotonTracedCount, causticPhotonTracedCount));
}

void PhotonGICache::TracePhotons(const bool indirectEnabled, const bool causticEnabled) {
	const size_t renderThreadCount = GetHardwareThreadCount();

	boost::atomic<u_int> globalIndirectPhotonsTraced(0);
	boost::atomic<u_int> globalCausticPhotonsTraced(0);
	boost::atomic<u_int> globalIndirectSize(0);
	boost::atomic<u_int> globalCausticSize(0);

	// Update the count only if I have traced this kind of photons
	if (indirectEnabled)
		indirectPhotonTracedCount = 0;
	// Update the count only if I have traced this kind of photons
	if (causticEnabled)
		causticPhotonTracedCount = 0;

	if (indirectEnabled && (params.indirect.maxSize == 0)) {
		// Automatic indirect cache convergence test is required

		const u_int photonTracedStep = 2000000;
		u_int photonTracedCount = 0;
		vector<SpectrumGroup> lastAlpha(visibilityParticles.size());
		vector<SpectrumGroup> currentAlpha(visibilityParticles.size());
		while (photonTracedCount < params.photon.maxTracedCount) {
			//------------------------------------------------------------------
			// Trace additional photons
			//------------------------------------------------------------------

			TracePhotons(updateSeedBase, photonTracedStep, false, !causticEnabled,
				globalIndirectPhotonsTraced, globalCausticPhotonsTraced,
				globalIndirectSize, globalCausticSize);
			photonTracedCount += photonTracedStep;

			//------------------------------------------------------------------
			// Check the convergence if it is not the first step
			//------------------------------------------------------------------

			if (photonTracedCount > photonTracedStep) {
				// Compute current alpha

				for (u_int i = 0; i < visibilityParticles.size(); ++i) {
					const PGICVisibilityParticle vp = visibilityParticles[i];

					currentAlpha[i] = vp.ComputeRadiance(params.indirect.lookUpRadius2, indirectPhotonTracedCount);
				}

				// Filter outgoing radiance

				if (params.indirect.filterRadiusScale > 0.f) {
					vector<SpectrumGroup> filteredCurrentAlpha(visibilityParticles.size());
					FilterVisibilityParticlesRadiance(currentAlpha, filteredCurrentAlpha);

					currentAlpha = filteredCurrentAlpha;
				}

				// Compute the scale for an auto-linear-like tone mapping of values

				float Y = 0.f;
				for (u_int i = 0; i < visibilityParticles.size(); ++i)
					Y += currentAlpha[i].Sum().Y();
				Y /= visibilityParticles.size();

				const float alphaScale = (Y > 0.f) ? (1.25f / Y * powf(118.f / 255.f, 2.2f)) : 1.f;
				for (u_int i = 0; i < visibilityParticles.size(); ++i)
					currentAlpha[i] *= alphaScale;

				// Look for the max. error

				float maxError = 0.f;
				for (u_int i = 0; i < visibilityParticles.size(); ++i) {
					if (!currentAlpha[i].Black()) {
						SpectrumGroup alpha = currentAlpha[i];
						alpha -= lastAlpha[i];

						for (u_int j = 0; j < alpha.Size(); ++j) {
							const float currentError = alpha[j].Abs().Max();

							maxError = Max(maxError, currentError);
						}
					}

					// Update last alpha cache entries
					lastAlpha[i] = currentAlpha[i];
				}

				SLG_LOG(boost::format("PhotonGI estimated current indirect photon error: %.2f%%") % (100.f * maxError));

				// If the error is under the threshold, stop tracing photons for indirect cache
				if (maxError < params.indirect.haltThreshold) {
					// Finish the work for caustic cache too
					if (causticEnabled &&
							(causticPhotons.size() < params.caustic.maxSize) &&
							(photonTracedCount < params.photon.maxTracedCount)) {
						updateSeedBase += renderThreadCount;

						TracePhotons(updateSeedBase,
								params.photon.maxTracedCount - photonTracedCount, true, false,
								globalIndirectPhotonsTraced, globalCausticPhotonsTraced,
								globalIndirectSize, globalCausticSize);
					}

					break;
				}
			} else {
				// Update last alpha cache entries

				for (u_int i = 0; i < visibilityParticles.size(); ++i) {
					const PGICVisibilityParticle vp = visibilityParticles[i];

					lastAlpha[i] = vp.ComputeRadiance(params.indirect.lookUpRadius2, indirectPhotonTracedCount);
				}
			}

			updateSeedBase += renderThreadCount;
		}
	} else {
		// Just trace the asked amount of photon paths
		TracePhotons(updateSeedBase, params.photon.maxTracedCount, !indirectEnabled, !causticEnabled,
				globalIndirectPhotonsTraced, globalCausticPhotonsTraced,
				globalIndirectSize, globalCausticSize);

	}

	updateSeedBase += renderThreadCount;

	causticPhotons.shrink_to_fit();
}

void PhotonGICache::FilterVisibilityParticlesRadiance(const vector<SpectrumGroup> &radianceValues,
			vector<SpectrumGroup> &filteredRadianceValues) const {
	const float lookUpRadius2 = Sqr(params.indirect.filterRadiusScale * params.indirect.lookUpRadius);
	const float lookUpCosNormalAngle = cosf(Radians(params.indirect.lookUpNormalAngle));

	#pragma omp parallel for
	for (
			// Visual C++ 2013 supports only OpenMP 2.5
#if _OPENMP >= 200805
			unsigned
#endif
			int index = 0; index < visibilityParticles.size(); ++index) {
		// Look for all near particles

		vector<u_int> nearParticleIndices;
		const PGICVisibilityParticle &vp = visibilityParticles[index];
		// I can use visibilityParticlesKdTree to get radiance photons indices
		// because there is a one on one correspondence
		visibilityParticlesKdTree->GetAllNearEntries(nearParticleIndices,
				vp.p, vp.n, vp.isVolume,
				lookUpRadius2, lookUpCosNormalAngle);

		if (nearParticleIndices.size() > 0) {
			SpectrumGroup &filtered = filteredRadianceValues[index];
			for (auto nearIndex : nearParticleIndices)
				filtered += radianceValues[nearIndex];

			filtered /= nearParticleIndices.size();
		}
	}
}

void PhotonGICache::CreateRadiancePhotons() {
	//--------------------------------------------------------------------------
	// Compute the outgoing radiance for each visibility entry
	//--------------------------------------------------------------------------

	vector<SpectrumGroup> outgoingRadianceValues(visibilityParticles.size());

	for (u_int index = 0 ; index < visibilityParticles.size(); ++index) {
		const PGICVisibilityParticle &vp = visibilityParticles[index];

		outgoingRadianceValues[index] = vp.ComputeRadiance(params.indirect.lookUpRadius2, indirectPhotonTracedCount);
		assert (outgoingRadianceValues[index].IsValid());
	}

	//--------------------------------------------------------------------------
	// Filter outgoing radiance
	//--------------------------------------------------------------------------

	if (params.indirect.filterRadiusScale > 0.f) {
		SLG_LOG("PhotonGI filtering radiance photons");

		vector<SpectrumGroup> filteredOutgoingRadianceValues(visibilityParticles.size());
		FilterVisibilityParticlesRadiance(outgoingRadianceValues, filteredOutgoingRadianceValues);

		outgoingRadianceValues = filteredOutgoingRadianceValues;
	}

	//--------------------------------------------------------------------------
	// Create a radiance map entry for each visibility entry
	//--------------------------------------------------------------------------

	for (u_int index = 0 ; index < visibilityParticles.size(); ++index) {
		if (!outgoingRadianceValues[index].Black()) {
			const PGICVisibilityParticle &vp = visibilityParticles[index];

			radiancePhotons.push_back(RadiancePhoton(vp.p,
					vp.n, outgoingRadianceValues[index], vp.isVolume));
		}
	}
	radiancePhotons.shrink_to_fit();

	SLG_LOG("PhotonGI total radiance photon stored: " << radiancePhotons.size());
}

void PhotonGICache::Preprocess(const u_int threadCnt) {
	threadCount = threadCnt;
	threadsSyncBarrier.reset(new boost::barrier(threadCount));
	lastUpdateSpp = 0;
	updateSeedBase = 1;

	if (params.persistent.fileName != "") {
		// Check if the file already exist
		if (boost::filesystem::exists(params.persistent.fileName)) {
			// Load the cache from the file
			LoadPersistentCache(params.persistent.fileName);

			return;
		}

		// The file doesn't exist so I have to go trough normal pre-processing
	}

	//--------------------------------------------------------------------------
	// Evaluate best radius if required
	//--------------------------------------------------------------------------

	if (params.indirect.enabled && (params.indirect.lookUpRadius == 0.f)) {
		params.indirect.lookUpRadius = EvaluateBestRadius();
		SLG_LOG("PhotonGI best indirect cache radius: " << params.indirect.lookUpRadius);
	}

	//--------------------------------------------------------------------------
	// Initialize all parameters
	//--------------------------------------------------------------------------

	if (!params.indirect.enabled)
		params.indirect.maxSize = 0;

	if (!params.caustic.enabled)
		params.caustic.maxSize = 0;

	if (params.indirect.enabled) {
		// I must use indirect cache parameters for Visibility particles if the
		// cache is enabled
		params.visibility.lookUpRadius = params.indirect.lookUpRadius;
		params.visibility.lookUpNormalAngle = params.indirect.lookUpNormalAngle;
	} else {
		if (params.visibility.lookUpRadius == 0.f) {
			if (params.caustic.enabled) {
				// Caustic radius is too small for visibility check
				params.visibility.lookUpRadius = EvaluateBestRadius();
				params.visibility.lookUpNormalAngle = params.caustic.lookUpNormalAngle;
			} else
				throw runtime_error("Indirect and/or caustic cache must be enabled in PhotonGI");
		}
	}
	SLG_LOG("PhotonGI visibility lookup radius: " << params.visibility.lookUpRadius);
	params.visibility.lookUpNormalCosAngle = cosf(Radians(params.visibility.lookUpNormalAngle));

	params.visibility.lookUpRadius2 = params.visibility.lookUpRadius * params.visibility.lookUpRadius;
	params.indirect.lookUpRadius2 = params.indirect.lookUpRadius * params.indirect.lookUpRadius;
	params.caustic.lookUpRadius2 = params.caustic.lookUpRadius * params.caustic.lookUpRadius;

	//--------------------------------------------------------------------------
	// Trace visibility particles
	//--------------------------------------------------------------------------

	TraceVisibilityParticles();
	if (visibilityParticles.size() == 0) {
		SLG_LOG("PhotonGI WARNING: nothing is visible and/or cache enabled.");
		return;
	}

	//--------------------------------------------------------------------------
	// Fill all photon vectors
	//--------------------------------------------------------------------------

	// I build indirect and caustic caches with 2 different steps in order to
	// have Metropolis work at beast for the 2 different tasks

	if (params.indirect.enabled) {
		SLG_LOG("PhotonGI tracing indirect cache photons");
		TracePhotons(true, false);
	}

	if (params.caustic.enabled) {
		SLG_LOG("PhotonGI tracing caustic cache photons");
		TracePhotons(false, true);
	}

	//--------------------------------------------------------------------------
	// Radiance photon map
	//--------------------------------------------------------------------------

	if (params.indirect.enabled) {
		SLG_LOG("PhotonGI building radiance photon data");
		CreateRadiancePhotons();

		if (radiancePhotons.size() > 0) {
			SLG_LOG("PhotonGI building radiance photons BVH");
			radiancePhotonsBVH = new PGICRadiancePhotonBvh(&radiancePhotons,
					params.indirect.lookUpRadius, params.indirect.lookUpNormalAngle);
		}
	}

	//--------------------------------------------------------------------------
	// Caustic photon map
	//--------------------------------------------------------------------------

	if ((causticPhotons.size() > 0) && params.caustic.enabled) {
		SLG_LOG("PhotonGI building caustic photons BVH");
		causticPhotonsBVH = new PGICPhotonBvh(&causticPhotons, causticPhotonTracedCount,
				params.caustic.lookUpRadius, params.caustic.lookUpNormalAngle);
	}

	//--------------------------------------------------------------------------
	// Free visibility map (only if it is not required for a further update
	//--------------------------------------------------------------------------

	if (!params.caustic.enabled || (params.caustic.updateSpp == 0)) {
		delete visibilityParticlesKdTree;
		visibilityParticlesKdTree = nullptr;
		visibilityParticles.clear();
		visibilityParticles.shrink_to_fit();
	}

	//--------------------------------------------------------------------------
	// Print some statistics about memory usage
	//--------------------------------------------------------------------------

	size_t totalMemUsage = 0;

	if (causticPhotonsBVH) {
		SLG_LOG("PhotonGI caustic cache photons memory usage: " << ToMemString(causticPhotons.size() * sizeof(Photon)));
		SLG_LOG("PhotonGI caustic cache BVH memory usage: " << ToMemString(causticPhotonsBVH->GetMemoryUsage()));

		totalMemUsage += causticPhotons.size() * sizeof(Photon) + causticPhotonsBVH->GetMemoryUsage();
	}

	if (radiancePhotonsBVH) {
		SLG_LOG("PhotonGI indirect cache photons memory usage: " << ToMemString(radiancePhotons.size() * sizeof(RadiancePhoton)));
		SLG_LOG("PhotonGI indirect cache BVH memory usage: " << ToMemString(radiancePhotonsBVH->GetMemoryUsage()));

		totalMemUsage += radiancePhotons.size() * sizeof(Photon) + radiancePhotonsBVH->GetMemoryUsage();
	}

	SLG_LOG("PhotonGI total memory usage: " << ToMemString(totalMemUsage));

	//--------------------------------------------------------------------------
	// Check if I have to save the persistent cache
	//--------------------------------------------------------------------------

	if (params.persistent.fileName != "")
		SavePersistentCache(params.persistent.fileName);
}

const SpectrumGroup *PhotonGICache::GetIndirectRadiance(const BSDF &bsdf) const {
	assert (IsPhotonGIEnabled(bsdf));

	if (radiancePhotonsBVH) {
		// Flip the normal if required
		const Normal n = (bsdf.hitPoint.intoObject ? 1.f: -1.f) * bsdf.hitPoint.geometryN;
		const RadiancePhoton *radiancePhoton = radiancePhotonsBVH->GetNearestEntry(bsdf.hitPoint.p, n, bsdf.IsVolume());

		if (radiancePhoton) {
			const SpectrumGroup *result = &radiancePhoton->outgoingRadiance;

			assert (result->IsValid());
			assert (DistanceSquared(radiancePhoton->p, bsdf.hitPoint.p) < radiancePhotonsBVH->GetEntryRadius());
			assert (bsdf.IsVolume() == radiancePhoton->isVolume);
			assert (radiancePhoton->isVolume || (Dot(radiancePhoton->n, n) > radiancePhotonsBVH->GetEntryNormalCosAngle()));

			return result;
		}
	}

	return nullptr;
}

SpectrumGroup PhotonGICache::ConnectWithCausticPaths(const BSDF &bsdf) const {
	assert (IsPhotonGIEnabled(bsdf));

	SpectrumGroup result;
	if (causticPhotonsBVH) {
		result = causticPhotonsBVH->ConnectAllNearEntries(bsdf);

		assert (result.IsValid());
	}

	return result;
}

PhotonGISamplerType PhotonGICache::String2SamplerType(const string &type) {
	if (type == "RANDOM")
		return PhotonGISamplerType::PGIC_SAMPLER_RANDOM;
	else if (type == "METROPOLIS")
		return PhotonGISamplerType::PGIC_SAMPLER_METROPOLIS;
	else
		throw runtime_error("Unknown PhotonGI cache debug type: " + type);
}

string PhotonGICache::SamplerType2String(const PhotonGISamplerType type) {
	switch (type) {
		case PhotonGISamplerType::PGIC_SAMPLER_RANDOM:
			return "RANDOM";
		case PhotonGISamplerType::PGIC_SAMPLER_METROPOLIS:
			return "METROPOLIS";
		default:
			throw runtime_error("Unsupported wrap type in PhotonGICache::SamplerType2String(): " + ToString(type));
	}
}

PhotonGIDebugType PhotonGICache::String2DebugType(const string &type) {
	if (type == "none")
		return PhotonGIDebugType::PGIC_DEBUG_NONE;
	else if (type == "showindirect")
		return PhotonGIDebugType::PGIC_DEBUG_SHOWINDIRECT;
	else if (type == "showcaustic")
		return PhotonGIDebugType::PGIC_DEBUG_SHOWCAUSTIC;
	else if (type == "showindirectpathmix")
		return PhotonGIDebugType::PGIC_DEBUG_SHOWINDIRECTPATHMIX;
	else
		throw runtime_error("Unknown PhotonGI cache debug type: " + type);
}

string PhotonGICache::DebugType2String(const PhotonGIDebugType type) {
	switch (type) {
		case PhotonGIDebugType::PGIC_DEBUG_NONE:
			return "none";
		case PhotonGIDebugType::PGIC_DEBUG_SHOWINDIRECT:
			return "showindirect";
		case PhotonGIDebugType::PGIC_DEBUG_SHOWCAUSTIC:
			return "showcaustic";
		case PhotonGIDebugType::PGIC_DEBUG_SHOWINDIRECTPATHMIX:
			return "showindirectpathmix";
		default:
			throw runtime_error("Unsupported wrap type in PhotonGICache::DebugType2String(): " + ToString(type));
	}
}

max_stars_repo_name: mbrukman/LuxCore

max_issues_repo_name: mbrukman/LuxCore

max_forks_repo_name: mbrukman/LuxCore


text:
#include "snapshot.h"

#include <dlib/image_transforms/assign_image.h>
#include <dlib/opencv/cv_image.h>

cv::VideoCapture &operator>>(cv::VideoCapture &input, snapshot &s) {
    input >> s.opencv_image;
    return input;
}

void snapshot::convert_image() {
    dlib::cv_image<dlib::bgr_pixel> CVImage(cvIplImage(opencv_image));
    assign_image(dlib_image, CVImage);
}


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

#ifndef CRYPTO3_DIGEST_HPP
#define CRYPTO3_DIGEST_HPP

#include <boost/static_assert.hpp>
#include <boost/assert.hpp>

#include <boost/container/small_vector.hpp>

#include <nil/crypto3/detail/pack.hpp>
#include <nil/crypto3/detail/octet.hpp>

namespace nil {
    namespace crypto3 {
        /*!
         * The digest class template stores a DigestBits-bit message digest as a sequence of 8-bit octets.
         * Octets are stored in the smallest unsigned type able to hold 8 bits, hereinafter referred to as
         * octet_type. DigestBits must be a multiple of 8.
         *
         * It is independent of any particular algorithm; For example sha2<224> and cubehash<224> both produce a
         * digest<224>. Each algorithm generates its digest such that it will be displayed in the canonical order
         * for that algorithm. The truncate and resize function templates are provided to handle digests with
         * lengths other than you're expecting. For instance, generating name-based UUIDs uses only 128 bits but
         * SHA-1 provides a 160-bit digest, so it would be truncated. (Using truncate instead of resize means
         * that a compilation error will result from trying to use a hash algorithm with too small an output.) On
         * the other hand, for storing as much as possible of the results of various algorithms, resize allows
         * you to pad them out to a large size, such as a digest<512>.
         *
         * digest<DigestBits> derives publicly from std::array<octet_type, DigestBits/8> and supports all of
         * its operations in order to provide direct access to the contained octets. Note that a digest is not
         * an aggregate; A default-constructed digest has all its contained octets set to zero. The base_array()
         * member function provides a reference to the std::array sub-object.
         *
         * digests with different numbers of bits may be compared. For the comparison, the smaller is considered
         * as though it were padded with 0s out to the size of the larger. The operator< provides a strict total
         * order. For convenience, equality comparison with narrow c-style strings is also provided.
         *
         * Always stored internally as a sequence of octets in display order.
         * This allows digests from different algorithms to have the same type,
         * allowing them to be more easily stored and compared.
         *
         * @tparam DigestBits
         */

        template<std::size_t DigestBits>
        using digest = boost::container::small_vector<octet_type, DigestBits / octet_bits>;

        namespace detail {
            template<std::size_t DigestBits, typename OutputIterator>
            OutputIterator to_ascii(const boost::container::small_vector<octet_type, DigestBits / octet_bits> &d,
                                    OutputIterator it) {
                for (std::size_t j = 0; j < d.size(); ++j) {
                    octet_type b = d[j];
                    *it++ = "0123456789abcdef"[(b >> 4) & 0xF];
                    *it++ = "0123456789abcdef"[(b >> 0) & 0xF];
                }
                return it;
            }

            template<std::size_t DigestBits>
            digest<DigestBits / 4 + 1>
                c_str(const boost::container::small_vector<octet_type, DigestBits / octet_bits> &d) {
                digest<DigestBits / 4 + 1> s;
                to_ascii<DigestBits>(d, std::back_inserter(s));
                s.push_back('\0');
                return s;
            }
        }    // namespace detail

        /*!
         *
         * @tparam NewBits
         * @tparam OldBits
         * @param od
         * @return Digest containing the first min(NewBits, OldBits) bits of the argument digest followed by max
         * (0, NewBits - OldBits) bits.
         */
        template<unsigned NewBits, unsigned OldBits>
        digest<NewBits> resize(const boost::container::small_vector<octet_type, OldBits / octet_bits> &od) {
            digest<NewBits> nd;
            unsigned bytes = sizeof(octet_type) * (NewBits < OldBits ? NewBits : OldBits) / octet_bits;
            std::memcpy(nd.data(), od.data(), bytes);
            return nd;
        }

        /*!
         * @tparam NewBits
         * @tparam OldBits
         * @return Digest containing only the first NewBits bits of the argument digest.
         *
         * Requires that NewBits <= OldBits.
         *
         * Truncating a message digest generally does not weaken the hash algorithm beyond the
         * amount necessitated by the shorted output size.
         */
        template<unsigned NewBits, unsigned OldBits>
        digest<NewBits> truncate(const boost::container::small_vector<octet_type, OldBits / octet_bits> &od) {
            BOOST_STATIC_ASSERT(NewBits <= OldBits);
            return resize<NewBits>(od);
        }

        template<unsigned DB1, unsigned DB2>
        bool operator==(const digest<DB1> &a, const digest<DB2> &b) {
            unsigned const DB = DB1 < DB2 ? DB2 : DB1;
            return resize<DB>(a).base_array() == resize<DB>(b).base_array();
        }

        template<unsigned DB1, unsigned DB2>
        bool operator!=(const digest<DB1> &a, const digest<DB2> &b) {
            return !(a == b);
        }

        template<unsigned DB1, unsigned DB2>
        bool operator<(const digest<DB1> &a, const digest<DB2> &b) {
            unsigned const DB = DB1 < DB2 ? DB2 : DB1;
            return resize<DB>(a).base_array() < resize<DB>(b).base_array();
        }

        template<unsigned DB1, unsigned DB2>
        bool operator>(const digest<DB1> &a, const digest<DB2> &b) {
            return b < a;
        }

        template<unsigned DB1, unsigned DB2>
        bool operator<=(const digest<DB1> &a, const digest<DB2> &b) {
            return !(b < a);
        }

        template<unsigned DB1, unsigned DB2>
        bool operator>=(const digest<DB1> &a, const digest<DB2> &b) {
            return !(b > a);
        }

        template<unsigned DB>
        bool operator!=(digest<DB> const &a, char const *b) {
            BOOST_ASSERT(std::strlen(b) == DB / 4);
            return static_cast<bool>(std::strcmp(a.cstring().data(), b));
        }

        template<unsigned DB>
        bool operator==(digest<DB> const &a, char const *b) {
            return !(a != b);
        }

        template<unsigned DB>
        bool operator!=(char const *b, digest<DB> const &a) {
            return a != b;
        }

        template<unsigned DB>
        bool operator==(char const *b, digest<DB> const &a) {
            return a == b;
        }

        template<unsigned DB>
        std::ostream &operator<<(std::ostream &sink, digest<DB> const &d) {
            d.to_ascii(std::ostream_iterator<char>(sink));
            return sink;
        }

        template<unsigned DB>
        std::istream &operator>>(std::istream &source, digest<DB> &d) {
            std::array<char, DB / 4> a = {{}};
            for (unsigned i = 0; i < a.size(); ++i) {
                char c;
                if (!source.get(c)) {
                    source.setstate(std::ios::failbit);
                    break;
                }
                if (!std::isxdigit(c, source.getloc())) {
                    source.unget();
                    source.setstate(std::ios::failbit);
                    break;
                }

                if (std::isdigit(c, source.getloc())) {
                    a[i] = (c - '0');
                } else {
                    a[i] = std::toupper(c, source.getloc()) - 'A' + 0xA;
                }
            }
            detail::pack<stream_endian::big_bit, 4, 8>(a, d);
            return source;
        }
    }    // namespace crypto3
}    // namespace nil

namespace std {
    template<std::size_t DigestBits>
    std::string to_string(const nil::crypto3::digest<DigestBits> &d) {
        nil::crypto3::digest<DigestBits / 4 + 1> cstr = nil::crypto3::detail::c_str(d);
        return std::string(cstr.begin(), cstr.begin() + cstr.size() - 1);
    }
}    // namespace std

#endif    // CRYPTO3_CODEC_DIGEST_HPP


text:
//
// Copyright (c) 2009 Rutger ter Borg
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//

#ifndef BOOST_NUMERIC_BINDINGS_BLAS_LEVEL3_HPP
#define BOOST_NUMERIC_BINDINGS_BLAS_LEVEL3_HPP

#include <boost/numeric/bindings/blas/level3/gemm.hpp>
#include <boost/numeric/bindings/blas/level3/hemm.hpp>
#include <boost/numeric/bindings/blas/level3/her2k.hpp>
#include <boost/numeric/bindings/blas/level3/herk.hpp>
#include <boost/numeric/bindings/blas/level3/symm.hpp>
#include <boost/numeric/bindings/blas/level3/syr2k.hpp>
#include <boost/numeric/bindings/blas/level3/syrk.hpp>
#include <boost/numeric/bindings/blas/level3/trmm.hpp>
#include <boost/numeric/bindings/blas/level3/trsm.hpp>

#endif

max_stars_repo_name: ljktest/siconos

max_issues_repo_name: ljktest/siconos

max_forks_repo_name: ljktest/siconos


text:
/**
 ** Isaac Genome Alignment Software
 ** Copyright (c) 2010-2017 Illumina, Inc.
 ** All rights reserved.
 **
 ** This software is provided under the terms and conditions of the
 ** Illumina Public License 1
 **
 ** You should have received a copy of the Illumina Public License 1
 ** along with this program. If not, see
 ** <https://github.com/sequencing/licenses/>.
 **
 ** \file FileSystem.hh
 **
 ** file system helper utilities.
 **
 ** \author Roman Petrovski
 **/

#ifndef iSAAC_COMMON_NUMA_CONTAINER_HH
#define iSAAC_COMMON_NUMA_CONTAINER_HH

#include <boost/foreach.hpp>

#include "common/config.h"

#ifdef HAVE_NUMA
#include <numa.h>
#include <numaif.h>
#endif //HAVE_NUMA

#include "common/Debug.hh"

#include "common/Numa.hh"
#include "common/Threads.hpp"

namespace isaac
{
namespace common
{

template <typename ReplicaT>
class NumaContainerReplicas
{
    std::vector<ReplicaT> nodeContainers_;
public:
    NumaContainerReplicas(ReplicaT &&node0Container)
    {
        if (common::isNumaAvailable())
        {
            const int nodes = getNumaNodeCount();

            nodeContainers_.reserve(nodes);
//            ISAAC_THREAD_CERR << "before std::move(node0Container)" << std::endl;
            nodeContainers_.push_back(std::move(node0Container));
//            ISAAC_THREAD_CERR << "after std::move(node0Container)" << std::endl;
            for (int node = 1; node < nodes; ++node)
            {
//                ISAAC_THREAD_CERR << "before creating replica from " << typeid(nodeContainers_.front()).name() <<
//                    " for node " << node << std::endl;
                ReplicaT replica(nodeContainers_.front(), common::NumaAllocator<void, 0> (node));
//                ISAAC_THREAD_CERR << "before nodeContainers_.push_back(). replica of type " << typeid(replica).name() << std::endl;
                nodeContainers_.push_back(std::move(replica));
//                ISAAC_THREAD_CERR << "after nodeContainers_.push_back()" << std::endl;
            }
        }
        else
        {
            nodeContainers_.push_back(std::move(node0Container));
        }
    }

    const ReplicaT &node0Container() const {return nodeContainers_.front();}
    const ReplicaT &threadNodeContainer() const {return nodeContainers_.at(common::ThreadVector::getThreadNumaNode());}
//        return hashes_[(common::ThreadVector::getThreadNumaNode()+1) % 2].findMatches(kmer);
};

} //namespace common
} //namespace isaac

#endif // #ifndef iSAAC_COMMON_NUMA_CONTAINER_HH

ext: hh


text:
#ifdef __APPLE__
#include "dsa_common.h"
#include "info.h"
#include <algorithm>
#include <arpa/inet.h>
#include <boost/filesystem.hpp>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <fstream>
#include <ifaddrs.h>
#include <iostream>
#include <iterator>
#include <map>
#include <netdb.h>
#include <sstream>
#include <string>
#include <sys/socket.h>
#include <sys/utsname.h>
#include <thread>
#include <unistd.h>
#include <vector>

std::string get_macos_info(std::string input) {
    char *line = NULL;
    ssize_t chars;
    size_t len = 0;
    try {
        FILE *data = popen(input.c_str(), "r");
        if (!data)
            return "NA";

        if ((chars = getline(&line, &len, data)) != -1){
          std::string str = std::string(line, chars);
          str.erase(std::remove(str.begin(), str.end(), '\n'), str.end());
            return str;
        }
        else
            return "NA";
    } catch (int e) {
        return "NA";
    }
}

std::string info::cpu::get_architecture() {
  utsname buf;

  if (uname(&buf) == -1)
    return "Unknown";
  else
    return buf.machine;
}

std::string info::cpu::get_frequency() {
    return std::to_string(std::strtoul(get_macos_info("sysctl -n hw.cpufrequency").c_str(), nullptr, 10) / 1000000) + " MHz";
}

std::string info::cpu::get_cpu_cores() {
  return get_macos_info("sysctl -n hw.ncpu");
}

std::string info::cpu::get_product_name() {
    return get_macos_info("sw_vers -productName");
}

static std::string cpuinfo_value(const char *key) {
  std::ifstream cpuinfo("/proc/cpuinfo");

  if (!cpuinfo.is_open() || !cpuinfo)
    return 0;

  for (std::string line; std::getline(cpuinfo, line);)
    if (line.find(key) == 0) {
      const auto colon_id = line.find_first_of(':');
      const auto nonspace_id = line.find_first_not_of(" \t", colon_id) + 1;
      return line.c_str() + nonspace_id;
    }

  return {};
}

std::string info::cpu::get_vendor() { return get_macos_info("sysctl -n machdep.cpu.vendor"); }

std::string info::cpu::get_model_name() { return get_macos_info("sysctl -n machdep.cpu.brand_string"); }

std::string info::system::get_os_full_name() { return get_macos_info("sw_vers -productName") + get_macos_info("sw_vers -productVersion"); }

info::system::kernel_info_t info::system::get_kernel_info() {
  utsname uts;
  uname(&uts);

  char *marker = uts.release;
  const unsigned int major = std::strtoul(marker, &marker, 10);
  const unsigned int minor = std::strtoul(marker + 1, &marker, 10);
  const unsigned int patch = std::strtoul(marker + 1, &marker, 10);
  const unsigned int build_number = std::strtoul(marker + 1, nullptr, 10);

  std::string kernel = "Unknown";
  if (!std::strcmp(uts.sysname, "Linux"))
    kernel = "Linux";
  else if (!std::strcmp(uts.sysname, "Darwin"))
    kernel = "Darwin";

  return {kernel, major, minor, patch, build_number};
}

std::string info::system::get_kernel_variant() {
  return get_kernel_info().variant;
}

std::string info::system::get_memory_usage() {
    std::string memory_usage_percentage(16, '\0');
    auto percentage = std::snprintf(
            &memory_usage_percentage[0], memory_usage_percentage.size(), "%.2f",
            (((float)(std::strtoul(get_used_memory().c_str(), nullptr, 10)) / (float)(std::strtoul(get_total_memory().c_str(), nullptr, 10))) * 100));
    memory_usage_percentage.resize(percentage);
    return memory_usage_percentage + "%";
}

std::string info::system::get_total_memory() {
  return std::to_string(std::strtoul(get_macos_info("sysctl -n hw.memsize").c_str(), nullptr, 10) / 1024 /1024) + " MByte";
}

std::string info::system::get_used_memory() {
  return std::to_string((std::strtoul(get_macos_info("sysctl -n hw.memsize").c_str(), nullptr, 10) / 1024 /1024) - std::strtoul(get_free_memory().c_str(), nullptr, 10)) + " MByte";
}

std::string info::system::get_free_memory() {
  char *line = NULL;
  long free_pages;
  long speculative_pages;
  size_t len = 0;
  ssize_t read;
  try {
    FILE *data = popen("vm_stat", "r");
    if (!data) {
      data = nullptr;
      return "NA";
    }

    while ((getline(&line, &len, data)) != -1) {
      std::string test(line);
      const auto colon_id = test.find_first_of(':');
      const auto value = std::strtoul(test.c_str() + colon_id + 1, nullptr, 10);

      if (test.find("Pages free") == 0) {
          free_pages = value;
      }
        else if (test.find("Pages speculative") == 0){
          speculative_pages = value;
      }
    }
      return std::to_string((free_pages + speculative_pages) * 4096 / 1024 /1024) + " MByte";
  } catch (int e) {
    return "0.0°C";
  }
  return "0.0°C";
}

info::system::diskspace_t info::system::get_diskspace_info() {

  info::system::diskspace_t ret;
  boost::filesystem::space_info _space_info = boost::filesystem::space(".");

  ret._diskspace_total =
      std::to_string(_space_info.capacity / 1024 / 1024) + " MB";
  ret._diskspace_available =
      std::to_string(_space_info.available / 1024 / 1024) + " MB";
  ret._diskspace_free = std::to_string(_space_info.free / 1024 / 1024) + " MB";
  ret._diskspace_used =
      std::to_string((_space_info.capacity - _space_info.available) / 1024 /
                     1024) +
      " MB";

  std::string disk_usage_percentage(16, '\0');
  auto percentage = std::snprintf(
      &disk_usage_percentage[0], disk_usage_percentage.size(), "%.2f",
      ((float)(_space_info.capacity - _space_info.available) /
       (float)_space_info.capacity) *
          100);
  disk_usage_percentage.resize(percentage);

  ret._disk_usage = disk_usage_percentage + "%";

  return ret;
}

std::string info::system::get_disk_usage() {
  return get_diskspace_info()._disk_usage;
}

std::string info::system::get_total_disk_space() {
  return get_diskspace_info()._diskspace_total;
}

std::string info::system::get_used_disk_space() {
  return get_diskspace_info()._diskspace_used;
}

std::string info::system::get_free_disk_space() {
  return get_diskspace_info()._diskspace_free;
}

std::string info::system::get_system_time() {

  time_t now = time(0);

  return ctime(&now);
}

std::string info::system::get_hostname() {

  char hostname[1024];
  gethostname(hostname, 1024);

  return hostname;
}

std::string info::system::get_open_files() {
    return get_macos_info("sysctl -n kern.num_files");
}

std::string info::system::get_process_count() {
  return get_macos_info("ps axo state | wc -l");
}

std::string info::cpu::get_cpu_usage() {
 return get_macos_info("ps -A -o %cpu | awk '{s+=$1} END {print s \"%\"}'");
}

std::string info::cpu::get_cpu_temp() {
  return get_macos_info("iStats cpu temp --value-only") + "°C";
}

std::map<std::string, std::string> info::system::get_network_interfaces() {
  struct ifaddrs *ifaddr, *ifa;
  int family, s, n;
  char host[NI_MAXHOST];
  std::map<std::string, std::string> interfaces;

  if (getifaddrs(&ifaddr) == -1) {
    perror("getifaddrs");
    exit(EXIT_FAILURE);
  }

  interfaces.clear();

  /* Walk through linked list, maintaining head pointer so we
     can free list later */

  for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {

    family = ifa->ifa_addr->sa_family;

    if (family == AF_INET || family == AF_INET6) {

      s = getnameinfo(ifa->ifa_addr,
                      (family == AF_INET) ? sizeof(struct sockaddr_in)
                                          : sizeof(struct sockaddr_in6),
                      host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
      if (s != 0) {
        printf("getnameinfo() failed: %s\n", gai_strerror(s));
        exit(EXIT_FAILURE);
      }

      interfaces[ifa->ifa_name] += host;
      interfaces[ifa->ifa_name] += " ";
    }
  }

  for (std::map<std::string, std::string>::iterator it = interfaces.begin();
       it != interfaces.end(); ++it) {
    std::cout << it->first << " :: " << it->second << std::endl;
  }

  freeifaddrs(ifaddr);
  return (interfaces);
}
#endif


text:
#include <burst/iterator/variant_iterator.hpp>
#include <burst/type_traits/iterator_category.hpp>

#include <doctest/doctest.h>

#include <boost/range/concepts.hpp>

#include <deque>
#include <forward_list>
#include <iterator>
#include <list>
#include <type_traits>
#include <vector>

TEST_SUITE("variant_iterator")
{
    TEST_CASE("Наследует минимальную из категорий переданных итераторов")
    {
        using forward_list_iterator = std::forward_list<int>::iterator;
        using list_iterator = std::list<int>::iterator;
        using deque_iterator = std::deque<int>::iterator;
        using vector_iterator = std::vector<int>::iterator;

        using variant_iterator =
            burst::variant_iterator
            <
                forward_list_iterator,
                list_iterator,
                deque_iterator,
                vector_iterator
            >;
        using category = burst::iterator_category_t<variant_iterator>;

        CHECK(std::is_same<category, burst::iterator_category_t<forward_list_iterator>>::value);
    }

    TEST_CASE("Наследует модель самого слабого итератора")
    {
        using forward_list_iterator = std::forward_list<int>::iterator;
        using list_iterator = std::list<int>::iterator;
        using deque_iterator = std::deque<int>::iterator;
        using vector_iterator = std::vector<int>::iterator;

        // Однонаправленный итератор
        {
        using variant_iterator =
            burst::variant_iterator
            <
                forward_list_iterator,
                list_iterator,
                deque_iterator,
                vector_iterator
            >;
            BOOST_CONCEPT_ASSERT((boost::ForwardIterator<variant_iterator>));
        }
        // Двунаправленный итератор
        {
            using variant_iterator =
                burst::variant_iterator<list_iterator, deque_iterator, vector_iterator>;
            BOOST_CONCEPT_ASSERT((boost::BidirectionalIterator<variant_iterator>));
        }
        // Итератор произвольного доступа
        {
            using variant_iterator = burst::variant_iterator<deque_iterator, vector_iterator>;
            BOOST_CONCEPT_ASSERT((boost::RandomAccessIterator<variant_iterator>));
        }
    }

    TEST_CASE("Параллелен обёрнутому итератору")
    {
        using list_iterator = std::list<int>::const_iterator;
        using vector_iterator = std::vector<int>::const_iterator;

        const auto d = std::list<int>{1, 2, 3};
        auto raw = d.begin();
        auto wrapped = burst::variant_iterator<list_iterator, vector_iterator>(raw);

        CHECK(*wrapped == *raw);

        ++wrapped;
        ++raw;
        CHECK(*wrapped == *raw);
    }

    TEST_CASE("Обладает конструктором по умолчанию")
    {
        using forward_list_iterator = std::forward_list<int>::const_iterator;
        using list_iterator = std::list<int>::const_iterator;
        using deque_iterator = std::deque<int>::const_iterator;
        using vector_iterator = std::vector<int>::const_iterator;

        using variant_iterator =
            burst::variant_iterator
            <
                forward_list_iterator,
                list_iterator,
                deque_iterator,
                vector_iterator,
                const int *
            >;

        auto i = variant_iterator{};
        static_cast<void>(i);
    }

    TEST_CASE("Допускает запись в неконстантный итератор")
    {
        using list_iterator = std::list<long>::iterator;
        using vector_iterator = std::vector<long>::iterator;

        auto l = std::list<long>{1, 2, 3};
        auto raw = l.begin();
        auto wrapped = burst::variant_iterator<list_iterator, vector_iterator>(raw);

        *wrapped = 111;
        CHECK(l.front() == 111);
    }

    TEST_CASE("Копируется как обычный итератор")
    {
        using list_iterator = std::list<int>::iterator;
        using deque_iterator = std::deque<int>::iterator;

        auto d = std::deque<int>{1, 2, 3};
        auto original = burst::variant_iterator<list_iterator, deque_iterator>(d.begin());
        auto copy = original;

        *original = 17;

        CHECK(*copy == 17);
    }

    TEST_CASE("Итератор произвольного доступа умеет продвигаться на N элементов вперёд и назад")
    {
        using vector_iterator = std::vector<char>::iterator;
        using deque_iterator = std::deque<char>::iterator;
        auto v = std::vector<char>{'a', 'b', 'c', 'd'};

        auto iterator = burst::variant_iterator<vector_iterator, deque_iterator>(v.begin());

        iterator += 3;
        CHECK(*iterator == 'd');

        iterator -= 2;
        CHECK(*iterator == 'b');
    }

    TEST_CASE("Итератор произвольного доступа допускает вычисление расстояния при помощи разности")
    {
        using vector_iterator = std::vector<char>::iterator;
        using deque_iterator = std::deque<char>::iterator;
        auto v = std::vector<char>{'a', 'b', 'c', 'd'};

        auto one = burst::variant_iterator<vector_iterator, deque_iterator>(v.begin());

        const auto another = std::next(one, 3);
        CHECK(another - one == 3);
    }

    TEST_CASE("Двунаправленный владеющий итератор умеет продвигаться вперёд и назад")
    {
        using list_iterator = std::list<char>::iterator;
        auto l = std::list<char>{'a', 'b', 'c', 'd'};

        auto iterator = burst::variant_iterator<list_iterator, char *>(l.begin());

        ++iterator;
        CHECK(*iterator == 'b');

        iterator++;
        CHECK(*iterator == 'c');

        --iterator;
        CHECK(*iterator == 'b');

        iterator--;
        CHECK(*iterator == 'a');
    }
}

max_stars_repo_name: izvolov/thrust

max_issues_repo_name: izvolov/burst

max_forks_repo_name: izvolov/thrust