<commit_before>#include "common/Version.hpp"

#include "common/Modes.hpp"

#define UGLYMACROHACK1(s) #s
#define FROM_EXTERNAL_DEFINE(s) UGLYMACROHACK1(s)

namespace chatterino {

Version::Version()
{
    // Version
    this->version_ = CHATTERINO_VERSION;

    // Commit hash
    this->commitHash_ =
        QString(FROM_EXTERNAL_DEFINE(CHATTERINO_GIT_HASH)).remove('"');

    // Date of build
#ifdef CHATTERINO_NIGHTLY_VERSION_STRING
    this->dateOfBuild_ =
        QString(FROM_EXTERNAL_DEFINE(CHATTERINO_NIGHTLY_VERSION_STRING))
            .remove('"');
#endif

    // "Full" version string, as displayed in window title
    this->fullVersion_ = "Chatterino ";
    if (Modes::getInstance().isNightly)
    {
        this->fullVersion_ += "Nightly ";
    }

    this->fullVersion_ += this->version_;

    if (Modes::getInstance().isNightly)
    {
        this->fullVersion_ += this->dateOfBuild_;
    }
}

const Version &Version::getInstance()
{
    static Version instance;
    return instance;
}

const QString &Version::getVersion() const
{
    return this->version_;
}

const QString &Version::getFullVersion() const
{
    return this->fullVersion_;
}

const QString &Version::getCommitHash() const
{
    return this->commitHash_;
}

const QString &Version::getDateOfBuild() const
{
    return this->dateOfBuild_;
}

}  // namespace chatterino
<commit_msg>Fix Version::dateOfBuild_ on Windows<commit_after>#include "common/Version.hpp"

#include "common/Modes.hpp"

#define UGLYMACROHACK1(s) #s
#define FROM_EXTERNAL_DEFINE(s) UGLYMACROHACK1(s)

namespace chatterino {

Version::Version()
{
    // Version
    this->version_ = CHATTERINO_VERSION;

    // Commit hash
    this->commitHash_ =
        QString(FROM_EXTERNAL_DEFINE(CHATTERINO_GIT_HASH)).remove('"');

    // Date of build, this is depended on the format not changing
#ifdef CHATTERINO_NIGHTLY_VERSION_STRING
    this->dateOfBuild_ =
        QString(FROM_EXTERNAL_DEFINE(CHATTERINO_NIGHTLY_VERSION_STRING))
            .remove('"').split(' ')[0];
#endif

    // "Full" version string, as displayed in window title
    this->fullVersion_ = "Chatterino ";
    if (Modes::getInstance().isNightly)
    {
        this->fullVersion_ += "Nightly ";
    }

    this->fullVersion_ += this->version_;
}

const Version &Version::getInstance()
{
    static Version instance;
    return instance;
}

const QString &Version::getVersion() const
{
    return this->version_;
}

const QString &Version::getFullVersion() const
{
    return this->fullVersion_;
}

const QString &Version::getCommitHash() const
{
    return this->commitHash_;
}

const QString &Version::getDateOfBuild() const
{
    return this->dateOfBuild_;
}

}  // namespace chatterino
<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

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

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_DEBUG_HPP_INCLUDED
#define TORRENT_DEBUG_HPP_INCLUDED

#include <string>
#include "libtorrent/config.hpp"
#include "libtorrent/file.hpp"

#if TORRENT_USE_IOSTREAM
#include <fstream>
#include <iostream>
#endif

namespace libtorrent
{
	// DEBUG API

	struct logger
	{
		logger(std::string const& logpath, std::string const& filename
			, int instance, bool append = true)
		{
#if TORRENT_USE_IOSTREAM

#ifndef BOOST_NO_EXCEPTIONS
			try
			{
#endif
				char log_name[256];
				snprintf(log_name, sizeof(log_name), "libtorrent_logs%d", instance);
				std::string dir(complete(combine_path(logpath, log_name)));
				error_code ec;
				if (!exists(dir)) create_directories(dir, ec);
				m_file.open(combine_path(dir, filename).c_str()
					, std::ios_base::out | (append ? std::ios_base::app : std::ios_base::out));
				*this << "\n\n\n*** starting log ***\n";
#ifndef BOOST_NO_EXCEPTIONS
			}
			catch (std::exception& e)
			{
				std::cerr << "failed to create log '" << filename << "': " << e.what() << std::endl;
			}
#endif
#endif
		}

		template <class T>
		logger& operator<<(T const& v)
		{
#if TORRENT_USE_IOSTREAM
			m_file << v;
			m_file.flush();
#endif
			return *this;
		}

#if TORRENT_USE_IOSTREAM
		std::ofstream m_file;
#endif
	};

}

#endif // TORRENT_DEBUG_HPP_INCLUDED

<commit_msg>fixed debug logging to not use up one extra file descriptor per connection<commit_after>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

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

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_DEBUG_HPP_INCLUDED
#define TORRENT_DEBUG_HPP_INCLUDED

#include <string>
#include "libtorrent/config.hpp"
#include "libtorrent/file.hpp"

#if TORRENT_USE_IOSTREAM
#include <fstream>
#include <iostream>
#endif

namespace libtorrent
{
	// DEBUG API

#if TORRENT_USE_IOSTREAM
	// all log streams share a single file descriptor
	// and re-opens the file for each log line
	static std::ofstream log_file;
	static std::string open_filename;
#endif

	struct logger
	{
		logger(std::string const& logpath, std::string const& filename
			, int instance, bool append)
		{
			char log_name[512];
			snprintf(log_name, sizeof(log_name), "libtorrent_logs%d", instance);
			std::string dir(complete(combine_path(logpath, log_name)));
			error_code ec;
			if (!exists(dir)) create_directories(dir, ec);
			m_filename = combine_path(dir, filename);
			m_append = append;
			*this << "\n\n\n*** starting log ***\n";
		}

#if TORRENT_USE_IOSTREAM
		void open()
		{
			if (open_filename == m_filename) return;
			log_file.close();
			log_file.open(m_filename.c_str(), m_append ? std::ios_base::app : std::ios_base::out);
			open_filename = m_filename;
			if (!log_file.good())
				fprintf(stderr, "Failed to open logfile %s: %s\n", m_filename.c_str(), strerror(errno));
		}
#endif

		template <class T>
		logger& operator<<(T const& v)
		{
#if TORRENT_USE_IOSTREAM
			open();
			log_file << v;
#endif
			return *this;
		}

		std::string m_filename;
		bool m_append;
	};

}

#endif // TORRENT_DEBUG_HPP_INCLUDED

<|endoftext|>


<commit_before>/*
 * TimeStamp.hh
 *
 * Copyright 2001, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
 * Copyright 2001, Bastiaan Bakker. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#ifndef _LOG4CPP_TIMESTAMP_HH
#define _LOG4CPP_TIMESTAMP_HH

#include "log4cpp/Portability.hh"
#include "log4cpp/Export.hh"

namespace log4cpp {

    /**
     * A simple TimeStamp abstraction
     **/
    class LOG4CPP_EXPORT TimeStamp {
        public:
        /**
           Constructs a TimeStamp representing 'now'.
        **/
        TimeStamp();

        /**
           Constructs a TimeStamp representing the given offset since the
           epoch ( 00:00:00 1970/1/1 UTC).
        **/
        TimeStamp(unsigned int seconds, unsigned int microSeconds = 0);

        inline int getSeconds() const {
            return _seconds;
        };

        inline int getMilliSeconds() const {
            return _microSeconds / 1000;
        };

        inline int getMicroSeconds() const {
            return _microSeconds;
        };

        static inline const TimeStamp& getStartTime() {
            return _startStamp;
        };

        protected:
        static TimeStamp _startStamp;

        int _seconds;
        int _microSeconds;
    };
}

#endif // _LOG4CPP_TIMESTAMP_HH

<commit_msg>added #include of Portability.hh<commit_after>/*
 * TimeStamp.hh
 *
 * Copyright 2001, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
 * Copyright 2001, Bastiaan Bakker. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#ifndef _LOG4CPP_TIMESTAMP_HH
#define _LOG4CPP_TIMESTAMP_HH

#include <log4cpp/Portability.hh>

namespace log4cpp {

    /**
     * A simple TimeStamp abstraction
     **/
    class LOG4CPP_EXPORT TimeStamp {
        public:
        /**
           Constructs a TimeStamp representing 'now'.
        **/
        TimeStamp();

        /**
           Constructs a TimeStamp representing the given offset since the
           epoch ( 00:00:00 1970/1/1 UTC).
        **/
        TimeStamp(unsigned int seconds, unsigned int microSeconds = 0);

        inline int getSeconds() const {
            return _seconds;
        };

        inline int getMilliSeconds() const {
            return _microSeconds / 1000;
        };

        inline int getMicroSeconds() const {
            return _microSeconds;
        };

        static inline const TimeStamp& getStartTime() {
            return _startStamp;
        };

        protected:
        static TimeStamp _startStamp;

        int _seconds;
        int _microSeconds;
    };
}

#endif // _LOG4CPP_TIMESTAMP_HH

<|endoftext|>


<commit_before><commit_msg>[io] Enable auto schema conversion for vector<ARITH_TYPE>:<commit_after><|endoftext|>


<commit_before><commit_msg>Make ui-test much, much smaller<commit_after><|endoftext|>


<commit_before>#ifndef MOS_BOX_HPP
#define MOS_BOX_HPP

#include <array>
#include <glm/glm.hpp>
#include <glm/gtx/io.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <utility>
#include <algorithm>
#include <tuple>
#include <iostream>
#include "vertex.hpp"
#include <optional.hpp>

namespace mos
{

/**
 * @brief The BoxIntersection struct
 * Data from a box box intersection.
 *
 */
struct BoxIntersection {
    BoxIntersection(const glm::vec3 & normal,
                    const float distance): normal(normal),
        distance(distance){
    }

    /**
     * @brief Normal of the intersection.
     */
    glm::vec3 normal;
    /**
     * @brief Distance of the intersection.
     */
    float distance;
};

/**
 * @brief The RayIntersection struct
 * Intersection data from a ray and box intersection.
 *
 */
struct RayIntersection {
    /**
     * @brief RayIntersection constructor.
     * @param hit
     * @param distance
     */
    RayIntersection(float distance = 0.0f): distance(distance){
    }

    /**
     * @brief distance
     *
     * Distance from
     */
    float distance;
};

/**
 * @brief The Box class
 *
 * Axis aligned bounding box class. Used for colission detection and sound obstruction.
 */
class Box
{
public:
    template<class VertexIt>
    /**
     * @brief Box constructor.
     * @param begin Vertex iterator.
     * @param end Vertex iterator.
     * @param transform Location of the box.
     * @param obstruction Obstruction factor for sound.
     *
     * Constructor for an AABB box, created from vertices.
     *
     */
    Box(VertexIt begin,
        VertexIt end,
        const glm::mat4 & transform,
        const float obstruction = 0.0f,
        const bool step = false) :
        obstruction_(obstruction),
        step_(step) {
        glm::vec3 min, max;

        glm::vec3 position(transform[3][0], transform[3][1], transform[3][2]);

        std::vector<glm::vec3> positions;
        std::transform(begin, end, std::back_inserter(positions),
                       [&](const Vertex & vertex) {
            //return vertex.position + position;
            return (glm::vec3)(transform * glm::vec4(vertex.position, 1.0f));
        });

        if (positions.begin() != positions.end()) {
            auto x_extremes = std::minmax_element(positions.begin(),
                                                  positions.end(),
                                                  [](const glm::vec3 & left, const glm::vec3& right) {
                return left.x < right.x;
            });

            auto y_extremes = std::minmax_element(positions.begin(),
                                                  positions.end(),
                                                  [](const glm::vec3 & left, const glm::vec3& right) {
                return left.y < right.y;
            });

            auto z_extremes = std::minmax_element(positions.begin(),
                                                  positions.end(),
                                                  [](const glm::vec3 & left, const glm::vec3& right) {
                return left.z < right.z;
            });

            min = glm::vec3(x_extremes.first->x, y_extremes.first->y, z_extremes.first->z);
            max = glm::vec3(x_extremes.second->x, y_extremes.second->y, z_extremes.second->z);
        }
        extent_ = (max - min) / 2.0f;
        //position_ = position;
        position_ = min + extent_;
     }

    /**
     * @brief Box default constructor.
     */
    Box();

    /**
     * @brief min
     * @return Min corner.
     */
    glm::vec3 min() const;

    /**
     * @brief max
     * @return Max corner.
     */
    glm::vec3 max() const;

#if 0
    /**
     * @brief Intersection with ray between points.
     * @param point1
     * @param point2
     * @return
     */
    RayIntersection intersect(glm::vec3 point1, glm::vec3 point2);

    /**
     * @brief Intersection with ray
     * @param origin
     * @param direction
     * @param t1
     * @param t2
     * @return
     */
    RayIntersection intersect(const glm::vec3 & origin, const glm::vec3 direction, float t1, float t2);
#endif
    /**
     * @brief intersects
     * @param other
     * @return
     */
    std::experimental::optional<BoxIntersection> intersects(const Box & other) const;

    /**
     * @brief Simple intersect method.
     * @param other
     * @return
     */
    glm::vec3 intersects_simple(const Box & other);

    /**
     * @brief position
     * @return
     */
    glm::vec3 position() const;

    /**
     * @brief position
     * @param position
     */
    void position(const glm::vec3 & position);

    /**
     * @brief Set the box transform, only uses position elements.
     * @param transform
     */
    void transform(const glm::mat4 & transform);

    /**
     * @brief Get box volume.
     */
    float volume() const;

    /**
     * @brief Obstruction factor for sound.
     *
     * Between 0.0 - 1.0
     */
    float obstruction() const;

    /**
     * @brief Size of box.
     * @return size in x, y and z directions.
     */
    glm::vec3 size() const;

    /**
     * @brief step
     * @param step
     */
    void step(const bool step);
    bool step() const;
private:
    glm::vec3 extent_;
    glm::vec3 position_;
    float obstruction_;
    bool step_;

};

}
#endif // MOS_BOX_HPP
<commit_msg>Check<commit_after>#ifndef MOS_BOX_HPP
#define MOS_BOX_HPP

#include <array>
#include <glm/glm.hpp>
#include <glm/gtx/io.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <utility>
#include <algorithm>
#include <tuple>
#include <iostream>
#include "vertex.hpp"
#include <optional.hpp>

namespace mos
{

/**
 * @brief The BoxIntersection struct
 * Data from a box box intersection.
 *
 */
struct BoxIntersection {
    BoxIntersection(const glm::vec3 & normal,
                    const float distance): normal(normal),
        distance(distance) {
    }

    /**
     * @brief Normal of the intersection.
     */
    glm::vec3 normal;
    /**
     * @brief Distance of the intersection.
     */
    float distance;
};

/**
 * @brief The RayIntersection struct
 * Intersection data from a ray and box intersection.
 *
 */
struct RayIntersection {
    /**
     * @brief RayIntersection constructor.
     * @param hit
     * @param distance
     */
    RayIntersection(float distance = 0.0f): distance(distance){
    }

    /**
     * @brief distance
     *
     * Distance from
     */
    float distance;
};

/**
 * @brief The Box class
 *
 * Axis aligned bounding box class. Used for colission detection and sound obstruction.
 */
class Box
{
public:
    template<class VertexIt>
    /**
     * @brief Box constructor.
     * @param begin Vertex iterator.
     * @param end Vertex iterator.
     * @param transform Location of the box.
     * @param obstruction Obstruction factor for sound.
     *
     * Constructor for an AABB box, created from vertices.
     *
     */
    Box(VertexIt begin,
        VertexIt end,
        const glm::mat4 & transform,
        const float obstruction = 0.0f,
        const bool step = false) :
        obstruction_(obstruction),
        step_(step) {
        glm::vec3 min, max;

        glm::vec3 position(transform[3][0], transform[3][1], transform[3][2]);

        std::vector<glm::vec3> positions;
        std::transform(begin, end, std::back_inserter(positions),
                       [&](const Vertex & vertex) {
            //return vertex.position + position;
            return (glm::vec3)(transform * glm::vec4(vertex.position, 1.0f));
        });

        if (positions.begin() != positions.end()) {
            auto x_extremes = std::minmax_element(positions.begin(),
                                                  positions.end(),
                                                  [](const glm::vec3 & left, const glm::vec3& right) {
                return left.x < right.x;
            });

            auto y_extremes = std::minmax_element(positions.begin(),
                                                  positions.end(),
                                                  [](const glm::vec3 & left, const glm::vec3& right) {
                return left.y < right.y;
            });

            auto z_extremes = std::minmax_element(positions.begin(),
                                                  positions.end(),
                                                  [](const glm::vec3 & left, const glm::vec3& right) {
                return left.z < right.z;
            });

            min = glm::vec3(x_extremes.first->x, y_extremes.first->y, z_extremes.first->z);
            max = glm::vec3(x_extremes.second->x, y_extremes.second->y, z_extremes.second->z);
        }
        extent_ = (max - min) / 2.0f;
        //position_ = position;
        position_ = min + extent_;
     }

    /**
     * @brief Box default constructor.
     */
    Box();

    /**
     * @brief min
     * @return Min corner.
     */
    glm::vec3 min() const;

    /**
     * @brief max
     * @return Max corner.
     */
    glm::vec3 max() const;

#if 0
    /**
     * @brief Intersection with ray between points.
     * @param point1
     * @param point2
     * @return
     */
    RayIntersection intersect(glm::vec3 point1, glm::vec3 point2);

    /**
     * @brief Intersection with ray
     * @param origin
     * @param direction
     * @param t1
     * @param t2
     * @return
     */
    RayIntersection intersect(const glm::vec3 & origin, const glm::vec3 direction, float t1, float t2);
#endif
    /**
     * @brief intersects
     * @param other
     * @return
     */
    std::experimental::optional<BoxIntersection> intersects(const Box & other) const;

    /**
     * @brief Simple intersect method.
     * @param other
     * @return
     */
    glm::vec3 intersects_simple(const Box & other);

    /**
     * @brief position
     * @return
     */
    glm::vec3 position() const;

    /**
     * @brief position
     * @param position
     */
    void position(const glm::vec3 & position);

    /**
     * @brief Set the box transform, only uses position elements.
     * @param transform
     */
    void transform(const glm::mat4 & transform);

    /**
     * @brief Get box volume.
     */
    float volume() const;

    /**
     * @brief Obstruction factor for sound.
     *
     * Between 0.0 - 1.0
     */
    float obstruction() const;

    /**
     * @brief Size of box.
     * @return size in x, y and z directions.
     */
    glm::vec3 size() const;

    /**
     * @brief step
     * @param step
     */
    void step(const bool step);
    bool step() const;
private:
    glm::vec3 extent_;
    glm::vec3 position_;
    float obstruction_;
    bool step_;

};

}
#endif // MOS_BOX_HPP
<|endoftext|>


<commit_before>#ifndef _STATEFS_PROVIDER_HPP_
#define _STATEFS_PROVIDER_HPP_

#include <statefs/provider.h>

#include <cor/util.hpp>

#include <string>
#include <map>
#include <memory>

#include <string.h>
// TODO TMP
#include <iostream>

namespace statefs {

class ANode
{
public:
    virtual ::statefs_node *get_node() =0;
    virtual ::statefs_node const* get_node() const =0;
    virtual ::statefs_node_type get_type() const =0;
    virtual std::string get_name() const =0;
    virtual void release() =0;
    virtual ~ANode();
};

class ABranch
{
public:
    virtual ::statefs_branch *get_branch() =0;
    virtual ::statefs_branch const* get_branch() const =0;
    virtual ~ABranch();
};

static inline statefs_node* node_from(statefs_provider *v)
{
    return &v->root.node;
}

static inline statefs_node const* node_from(statefs_provider const* v)
{
    return &v->root.node;
}

template <typename T>
statefs_node* node_from(T *v)
{
    return &v->node;
}

template <typename T>
statefs_node const* node_from(T const* v)
{
    return &v->node;
}

template <typename T>
T* node_to(::statefs_node *n)
{
    return cor::member_container(n, &T::node);
}

template <>
statefs_provider* node_to<statefs_provider>(::statefs_node *);

template <typename NodeT>
class NodeWrapper : public NodeT, public ANode
{
public:
    ::statefs_node *node_cast()
    { return node_from(static_cast<NodeT*>(this)); }
    ::statefs_node const* node_cast() const
    { return node_from(static_cast<NodeT const*>(this)); }

    virtual ::statefs_node *get_node() { return node_cast(); }
    virtual ::statefs_node const* get_node() const { return node_cast(); }
    virtual ::statefs_node_type get_type() const { return node_cast()->type; }
    virtual std::string get_name() const { return node_cast()->name; }

    NodeWrapper(char const *name, statefs_node const& node_template)
    {
        memcpy(node_cast(), &node_template, sizeof(statefs_node));
        node_cast()->name = strdup(name);
        node_cast()->release = &release_bridge;
    }
    virtual ~NodeWrapper()
    {
        free(const_cast<char*>(node_cast()->name));
    }

private:
    static void release_bridge(::statefs_node *n)
    {
        NodeWrapper *self = static_cast<NodeWrapper*>(node_to<NodeT>(n));
        static_cast<ANode*>(self)->release();
    }
};

template <typename T>
statefs_branch* branch_from(T *v)
{
    return &v->branch;
}

template <typename T>
statefs_branch const* branch_from(T const* v)
{
    return &v->branch;
}

static inline statefs_branch* branch_from(statefs_provider *v)
{
    return &v->root.branch;
}

static inline statefs_branch const* branch_from(statefs_provider const* v)
{
    return &v->root.branch;
}

template <typename BranchT>
class BranchWrapper;

template <typename T>
BranchWrapper<T> *branch_to(statefs_branch *src)
{
    T *t = cor::member_container(src, &T::branch);
    return static_cast<BranchWrapper<T> *>(t);
}

template <typename T>
BranchWrapper<T> const* branch_to(statefs_branch const* src)
{
    T const* t = cor::member_container(src, &T::branch);
    return static_cast<BranchWrapper<T> const*>(t);
}

template <>
BranchWrapper<statefs_provider> *branch_to<statefs_provider>(statefs_branch *);

template <>
BranchWrapper<statefs_provider> const* branch_to<statefs_provider>(statefs_branch const*);

template <typename BranchT>
class BranchWrapper : public NodeWrapper<BranchT>
{
public:

    ::statefs_branch *branch_cast()
    { return branch_from(static_cast<BranchT*>(this)); }
    ::statefs_branch const* branch_cast() const
    { return branch_from(static_cast<BranchT const*>(this)); }

    BranchWrapper
    (char const *name
     , statefs_node const& node_template
     , statefs_branch const &branch_template)
        : NodeWrapper<BranchT>(name, node_template)
    {
        memcpy(branch_cast(), &branch_template, sizeof(statefs_branch));
    }

    static BranchWrapper<BranchT> *self_cast(statefs_branch *src)
    {
        return branch_to<BranchT>(src);
    }

    static BranchWrapper<BranchT> const* self_cast(statefs_branch const* src)
    {
        return branch_to<BranchT>(src);
    }

};

class BranchStorage
{
public:
    typedef std::shared_ptr<ANode> child_ptr;

protected:
    typedef std::map<std::string, child_ptr> storage_type;
    typedef storage_type::const_iterator iter_type;

public:

    BranchStorage();

    child_ptr insert(child_ptr child);
    child_ptr insert(ANode *child);

protected:

    statefs_node* find(char const*) const;
    statefs_node* get(statefs_handle_t) const;
    statefs_handle_t first() const;
    void next(statefs_handle_t*) const;
    bool release(statefs_handle_t) const;

private:

    storage_type props_;
};

template <class BranchT>
class Branch : public BranchWrapper<BranchT>, public BranchStorage
{
private:

    static const statefs_branch branch_template;

    typedef BranchWrapper<BranchT> base_type;

    static statefs_node * child_find(statefs_branch const* branch
                                     , char const *name)
    {
        auto self = self_cast(branch);
        return self->BranchStorage::find(name);
    }

    static statefs_node * child_get(statefs_branch const* branch, statefs_handle_t h)
    {
        auto self = self_cast(branch);
        return self->BranchStorage::get(h);
    }

    static statefs_handle_t child_first(statefs_branch const* branch)
    {
        auto self = self_cast(branch);
        return self->BranchStorage::first();
    }

    static void child_next(statefs_branch const* branch, statefs_handle_t *h)
    {
        auto self = self_cast(branch);
        return self->BranchStorage::next(h);
    }

    static bool child_release(statefs_branch const* branch, statefs_handle_t h)
    {
        auto self = self_cast(branch);
        return self->BranchStorage::release(h);
    }

protected:
    // implement
    // static WrapperT const *self_cast(statefs_branch const*);
    // in WrapperT
    static Branch const *self_cast(statefs_branch const* branch)
    {
        return static_cast<Branch const*>
            (base_type::self_cast(branch));
    }

public:
    Branch(char const *name, statefs_node const& node_template)
        : base_type(name, node_template, branch_template)
    {}

    virtual ~Branch() {}
};

class PropertyWrapper : public NodeWrapper<statefs_property>
{
    typedef NodeWrapper<statefs_property> base_type;

    static const statefs_node node_template;
public:
    PropertyWrapper(char const *name);
    virtual ~PropertyWrapper();

    static PropertyWrapper *self_cast(::statefs_property *);
    static PropertyWrapper const* self_cast(::statefs_property const*);
};

class APropertyAccessor
{
public:
    virtual ~APropertyAccessor();

    virtual int read(char *dst, statefs_size_t len, statefs_off_t off) =0;
    virtual int write(char const*, statefs_size_t, statefs_off_t) =0;
};

class AProperty : public PropertyWrapper
{
public:
    AProperty(char const *name);
    virtual ~AProperty();

    virtual int getattr() const =0;
    virtual statefs_ssize_t size() const =0;
    virtual APropertyAccessor* open(int flags) =0;

    virtual bool connect(::statefs_slot *) =0;
    virtual void disconnect() =0;

    static AProperty *self_cast(::statefs_property *p);
    static AProperty const* self_cast(::statefs_property const* p);
};

template <typename T, typename HandleT>
class BasicPropertyAccessor : public APropertyAccessor
{
public:
    BasicPropertyAccessor(std::shared_ptr<T> p, HandleT *h)
        : prop_(p), handle_(h) {}

    virtual int read(char *dst, statefs_size_t len, statefs_off_t off)
    {
        return prop_->read(handle_.get(), dst, len, off);
    }

    virtual int write(char const *src, statefs_size_t len, statefs_off_t off)
    {
        return prop_->write(handle_.get(), src, len, off);
    }

protected:
    std::shared_ptr<T> prop_;
    std::unique_ptr<HandleT> handle_;
};

template <typename T, typename HandleT>
BasicPropertyAccessor<T, HandleT>* mk_prop_accessor
(std::shared_ptr<T> p, HandleT *h)
{
    return new BasicPropertyAccessor<T, HandleT>(p, h);
}

template <typename T>
class APropertyOwner : public AProperty
{
public:
    template <typename ... Args>
    APropertyOwner(char const *name, Args&& ...args)
        : AProperty(name)
        , impl_(new T(this, std::forward<Args>(args)...))
    {}

    virtual ~APropertyOwner() {}

    virtual int getattr() const { return impl_->getattr(); }
    virtual statefs_ssize_t size() const { return impl_->size(); }
    virtual APropertyAccessor* open(int flags) =0;

    virtual bool connect(::statefs_slot *s) { return impl_->connect(s); }
    virtual void disconnect() { return impl_->disconnect(); }

    virtual void release() { return impl_->release(); }

protected:
    std::shared_ptr<T> impl_;
};

template <typename T, typename HandleT>
class BasicPropertyOwner : public APropertyOwner<T>
{
public:
    template <typename ... Args>
    BasicPropertyOwner(char const *name, Args&& ...args)
        : APropertyOwner<T>(name, std::forward<Args>(args)...)
    {}

    template <typename ... Args>
    BasicPropertyOwner(std::string const &name, Args&& ...args)
        : APropertyOwner<T>(name.c_str(), std::forward<Args>(args)...)
    {}

    virtual statefs::APropertyAccessor* open(int flags)
    {
        return statefs::mk_prop_accessor(this->impl_, new HandleT());
    }

    std::shared_ptr<T> get_impl() { return this->impl_; }
};

class Namespace : public Branch<statefs_namespace>
{
    typedef Branch<statefs_namespace> base_type;
    static const statefs_node node_template;

public:
    Namespace(char const *name);
    virtual ~Namespace();
};

class AProvider : public Branch<statefs_provider>
{
public:
    AProvider(char const *name, statefs_server *server);
    virtual ~AProvider();

protected:
    static AProvider* self_cast();

    void event(statefs_event);

private:
    typedef Branch<statefs_provider> base_type;

    static const statefs_io io_template;
    static const statefs_node node_template;

    static int getattr(::statefs_property const *);
    static statefs_ssize_t size(::statefs_property const *);
    static statefs_handle_t open(::statefs_property *self, int flags);
    static int read(statefs_handle_t h, char *dst, statefs_size_t len, statefs_off_t off);
    static int write(statefs_handle_t, char const*, statefs_size_t, statefs_off_t);
    static void close(statefs_handle_t);
    static bool connect(::statefs_property *, ::statefs_slot *);
    static void disconnect(::statefs_property *);

    void init_data();

    statefs_server *server_;
};

// class Namespace : public ABranch
// {
//     static statefs_node node_template;
// protected:
//     typedef statefs::BranchWrapper<statefs_namespace> data_type;
// public:
//     static Namespace *self_cast(statefs_branch*);
//     static Namespace const* self_cast(statefs_branch const*);

//     Namespace(char const* name)
//         : prop_(name, node_template)
//     {
//     }

//     virtual statefs_node *get_node()
//     {
//         return &prop_.node;
//     }
//     virtual statefs_node const* get_node() const
//     {
//         return &prop_.node;
//     }

//     virtual statefs_node_type get_type() const
//     {
//         return prop_.node.type;
//     }

// protected:
//     data_type data_;
//     static data_type Namespace::* data_offset_;
// };

extern template class NodeWrapper<statefs_property>;
extern template class NodeWrapper<statefs_namespace>;
extern template class NodeWrapper<statefs_provider>;

extern template class BranchWrapper<statefs_provider>;
extern template class BranchWrapper<statefs_namespace>;

} // namespace

#endif // _STATEFS_PROVIDER_HPP_
<commit_msg>[statefs-pp] BranchStorage as a Branch<> member<commit_after>#ifndef _STATEFS_PROVIDER_HPP_
#define _STATEFS_PROVIDER_HPP_

#include <statefs/provider.h>

#include <cor/util.hpp>

#include <string>
#include <map>
#include <memory>

#include <string.h>
// TODO TMP
#include <iostream>

namespace statefs {

class ANode
{
public:
    virtual ::statefs_node *get_node() =0;
    virtual ::statefs_node const* get_node() const =0;
    virtual ::statefs_node_type get_type() const =0;
    virtual std::string get_name() const =0;
    virtual void release() =0;
    virtual ~ANode();
};

class ABranch
{
public:
    virtual ::statefs_branch *get_branch() =0;
    virtual ::statefs_branch const* get_branch() const =0;
    virtual ~ABranch();
};

static inline statefs_node* node_from(statefs_provider *v)
{
    return &v->root.node;
}

static inline statefs_node const* node_from(statefs_provider const* v)
{
    return &v->root.node;
}

template <typename T>
statefs_node* node_from(T *v)
{
    return &v->node;
}

template <typename T>
statefs_node const* node_from(T const* v)
{
    return &v->node;
}

template <typename T>
T* node_to(::statefs_node *n)
{
    return cor::member_container(n, &T::node);
}

template <>
statefs_provider* node_to<statefs_provider>(::statefs_node *);

template <typename NodeT>
class NodeWrapper : public NodeT, public ANode
{
public:
    ::statefs_node *node_cast()
    { return node_from(static_cast<NodeT*>(this)); }
    ::statefs_node const* node_cast() const
    { return node_from(static_cast<NodeT const*>(this)); }

    virtual ::statefs_node *get_node() { return node_cast(); }
    virtual ::statefs_node const* get_node() const { return node_cast(); }
    virtual ::statefs_node_type get_type() const { return node_cast()->type; }
    virtual std::string get_name() const { return node_cast()->name; }

    NodeWrapper(char const *name, statefs_node const& node_template)
    {
        memcpy(node_cast(), &node_template, sizeof(statefs_node));
        node_cast()->name = strdup(name);
        node_cast()->release = &release_bridge;
    }
    virtual ~NodeWrapper()
    {
        free(const_cast<char*>(node_cast()->name));
    }

private:
    static void release_bridge(::statefs_node *n)
    {
        auto self = static_cast<NodeWrapper*>(node_to<NodeT>(n));
        static_cast<ANode*>(self)->release();
    }
};

template <typename T>
statefs_branch* branch_from(T *v)
{
    return &v->branch;
}

template <typename T>
statefs_branch const* branch_from(T const* v)
{
    return &v->branch;
}

static inline statefs_branch* branch_from(statefs_provider *v)
{
    return &v->root.branch;
}

static inline statefs_branch const* branch_from(statefs_provider const* v)
{
    return &v->root.branch;
}

template <typename BranchT>
class BranchWrapper;

template <typename T>
BranchWrapper<T> *branch_to(statefs_branch *src)
{
    T *t = cor::member_container(src, &T::branch);
    return static_cast<BranchWrapper<T> *>(t);
}

template <typename T>
BranchWrapper<T> const* branch_to(statefs_branch const* src)
{
    T const* t = cor::member_container(src, &T::branch);
    return static_cast<BranchWrapper<T> const*>(t);
}

template <>
BranchWrapper<statefs_provider> *branch_to<statefs_provider>(statefs_branch *);

template <>
BranchWrapper<statefs_provider> const* branch_to<statefs_provider>(statefs_branch const*);

template <typename BranchT>
class BranchWrapper : public NodeWrapper<BranchT>
{
    typedef NodeWrapper<BranchT> base_type;
public:

    ::statefs_branch *branch_cast() {
        base_type *base = static_cast<base_type*>(this);
        return branch_from(static_cast<BranchT*>(base));
    }

    ::statefs_branch const* branch_cast() const {
        base_type const *base = static_cast<base_type const*>(this);
        return branch_from(static_cast<BranchT const*>(base));
    }

    BranchWrapper
    (char const *name
     , statefs_node const& node_template
     , statefs_branch const &branch_template)
        : NodeWrapper<BranchT>(name, node_template)
    {
        memcpy(branch_cast(), &branch_template, sizeof(statefs_branch));
    }

    static BranchWrapper<BranchT> *self_cast(statefs_branch *src)
    {
        return branch_to<BranchT>(src);
    }

    static BranchWrapper<BranchT> const* self_cast(statefs_branch const* src)
    {
        return branch_to<BranchT>(src);
    }

};

class BranchStorage
{
public:
    typedef std::shared_ptr<ANode> child_ptr;

    typedef std::map<std::string, child_ptr> storage_type;
    typedef storage_type::const_iterator iter_type;

public:

    BranchStorage();

    child_ptr insert(child_ptr child);
    child_ptr insert(ANode *child);

    statefs_node* find(char const*) const;
    statefs_node* get(statefs_handle_t) const;
    statefs_handle_t first() const;
    void next(statefs_handle_t*) const;
    bool release(statefs_handle_t) const;

private:

    storage_type props_;
};

template <class BranchT>
class Branch : public BranchWrapper<BranchT>
{
public:

    Branch(char const *name, statefs_node const& node_template)
        : base_type(name, node_template, branch_template)
    {}

    virtual ~Branch() {}

    typedef typename BranchStorage::child_ptr child_ptr;

    child_ptr insert(child_ptr child)
    {
        return storage_.insert(child);
    }

    child_ptr insert(ANode *child)
    {
        return storage_.insert(child);
    }

private:

    static const statefs_branch branch_template;

    typedef BranchWrapper<BranchT> base_type;

    static statefs_node * child_find(statefs_branch const* branch
                                     , char const *name)
    {
        auto self = self_cast(branch);
        return self->find(name);
    }

    static statefs_node * child_get(statefs_branch const* branch, statefs_handle_t h)
    {
        auto self = self_cast(branch);
        return self->get(h);
    }

    static statefs_handle_t child_first(statefs_branch const* branch)
    {
        auto self = self_cast(branch);
        return self->first();
    }

    static void child_next(statefs_branch const* branch, statefs_handle_t *h)
    {
        auto self = self_cast(branch);
        return self->next(h);
    }

    static bool child_release(statefs_branch const* branch, statefs_handle_t h)
    {
        auto self = self_cast(branch);
        return self->release(h);
    }

protected:
    // implement
    // static WrapperT const *self_cast(statefs_branch const*);
    // in WrapperT
    static Branch const *self_cast(statefs_branch const* branch)
    {
        return static_cast<Branch const*>
            (base_type::self_cast(branch));
    }

    statefs_node* find(char const *name) const
    {
        return storage_.find(name);
    }

    statefs_node* get(statefs_handle_t h) const
    {
        return storage_.get(h);
    }

    statefs_handle_t first() const
    {
        return storage_.first();
    }
    void next(statefs_handle_t *ph) const
    {
        return storage_.next(ph);
    }
    bool release(statefs_handle_t h) const
    {
        return storage_.release(h);
    }

private:
    BranchStorage storage_;
};

class PropertyWrapper : public NodeWrapper<statefs_property>
{
    typedef NodeWrapper<statefs_property> base_type;

    static const statefs_node node_template;
public:
    PropertyWrapper(char const *name);
    virtual ~PropertyWrapper();

    static PropertyWrapper *self_cast(::statefs_property *);
    static PropertyWrapper const* self_cast(::statefs_property const*);
};

class APropertyAccessor
{
public:
    virtual ~APropertyAccessor();

    virtual int read(char *dst, statefs_size_t len, statefs_off_t off) =0;
    virtual int write(char const*, statefs_size_t, statefs_off_t) =0;
};

class AProperty : public PropertyWrapper
{
public:
    AProperty(char const *name);
    virtual ~AProperty();

    virtual int getattr() const =0;
    virtual statefs_ssize_t size() const =0;
    virtual APropertyAccessor* open(int flags) =0;

    virtual bool connect(::statefs_slot *) =0;
    virtual void disconnect() =0;

    static AProperty *self_cast(::statefs_property *p);
    static AProperty const* self_cast(::statefs_property const* p);
};

template <typename T, typename HandleT>
class BasicPropertyAccessor : public APropertyAccessor
{
public:
    BasicPropertyAccessor(std::shared_ptr<T> p, HandleT *h)
        : prop_(p), handle_(h) {}

    virtual int read(char *dst, statefs_size_t len, statefs_off_t off)
    {
        return prop_->read(handle_.get(), dst, len, off);
    }

    virtual int write(char const *src, statefs_size_t len, statefs_off_t off)
    {
        return prop_->write(handle_.get(), src, len, off);
    }

protected:
    std::shared_ptr<T> prop_;
    std::unique_ptr<HandleT> handle_;
};

template <typename T, typename HandleT>
BasicPropertyAccessor<T, HandleT>* mk_prop_accessor
(std::shared_ptr<T> p, HandleT *h)
{
    return new BasicPropertyAccessor<T, HandleT>(p, h);
}

template <typename T>
class APropertyOwner : public AProperty
{
public:
    template <typename ... Args>
    APropertyOwner(char const *name, Args&& ...args)
        : AProperty(name)
        , impl_(new T(this, std::forward<Args>(args)...))
    {}

    virtual ~APropertyOwner() {}

    virtual int getattr() const { return impl_->getattr(); }
    virtual statefs_ssize_t size() const { return impl_->size(); }
    virtual APropertyAccessor* open(int flags) =0;

    virtual bool connect(::statefs_slot *s) { return impl_->connect(s); }
    virtual void disconnect() { return impl_->disconnect(); }

    virtual void release() { return impl_->release(); }

protected:
    std::shared_ptr<T> impl_;
};

template <typename T, typename HandleT>
class BasicPropertyOwner : public APropertyOwner<T>
{
public:
    template <typename ... Args>
    BasicPropertyOwner(char const *name, Args&& ...args)
        : APropertyOwner<T>(name, std::forward<Args>(args)...)
    {}

    template <typename ... Args>
    BasicPropertyOwner(std::string const &name, Args&& ...args)
        : APropertyOwner<T>(name.c_str(), std::forward<Args>(args)...)
    {}

    virtual statefs::APropertyAccessor* open(int flags)
    {
        return statefs::mk_prop_accessor(this->impl_, new HandleT());
    }

    std::shared_ptr<T> get_impl() { return this->impl_; }
};

class Namespace : public Branch<statefs_namespace>
{
    typedef Branch<statefs_namespace> base_type;
    static const statefs_node node_template;

public:
    Namespace(char const *name);
    virtual ~Namespace();
};

class AProvider : public Branch<statefs_provider>
{
public:
    AProvider(char const *name, statefs_server *server);
    virtual ~AProvider();

protected:
    static AProvider* self_cast();

    void event(statefs_event);

private:
    typedef Branch<statefs_provider> base_type;

    static const statefs_io io_template;
    static const statefs_node node_template;

    static int getattr(::statefs_property const *);
    static statefs_ssize_t size(::statefs_property const *);
    static statefs_handle_t open(::statefs_property *self, int flags);
    static int read(statefs_handle_t h, char *dst, statefs_size_t len, statefs_off_t off);
    static int write(statefs_handle_t, char const*, statefs_size_t, statefs_off_t);
    static void close(statefs_handle_t);
    static bool connect(::statefs_property *, ::statefs_slot *);
    static void disconnect(::statefs_property *);

    void init_data();

    statefs_server *server_;
};

// class Namespace : public ABranch
// {
//     static statefs_node node_template;
// protected:
//     typedef statefs::BranchWrapper<statefs_namespace> data_type;
// public:
//     static Namespace *self_cast(statefs_branch*);
//     static Namespace const* self_cast(statefs_branch const*);

//     Namespace(char const* name)
//         : prop_(name, node_template)
//     {
//     }

//     virtual statefs_node *get_node()
//     {
//         return &prop_.node;
//     }
//     virtual statefs_node const* get_node() const
//     {
//         return &prop_.node;
//     }

//     virtual statefs_node_type get_type() const
//     {
//         return prop_.node.type;
//     }

// protected:
//     data_type data_;
//     static data_type Namespace::* data_offset_;
// };

extern template class NodeWrapper<statefs_property>;
extern template class NodeWrapper<statefs_namespace>;
extern template class NodeWrapper<statefs_provider>;

extern template class BranchWrapper<statefs_provider>;
extern template class BranchWrapper<statefs_namespace>;

} // namespace

#endif // _STATEFS_PROVIDER_HPP_
<|endoftext|>


<commit_before>#include "types.h"
#include "stat.h"
#include "user.h"
#include "mtrace.h"
#include "amd64.h"
#include "uspinlock.h"

static struct uspinlock l;
static volatile int tcount;
enum { readaccess = 0 };
enum { verbose = 0 };
enum { npg = 1 };

void
thr(void *arg)
{
  u64 tid = (u64)arg;

  for (int i = 0; i < 1000000; i++) {
    if (verbose && ((i % 100) == 0))
      fprintf(1, "%d: %d ops\n", tid, i);

    volatile char *p = (char*) (0x40000UL + tid * npg * 4096);
    if (map((void *) p, npg * 4096) < 0) {
      fprintf(1, "%d: map failed\n", tid);
      exit();
    }

    if (readaccess) {
      for (int j = 0; j < npg * 4096; j++)
	p[j] = '\0';
    }

    if (unmap((void *) p, npg * 4096) < 0) {
      fprintf(1, "%d: unmap failed\n", tid);
      exit();
    }
  }

  acquire(&l);
  // fprintf(1, "mapbench[%d]: done\n", getpid());
  tcount++;
  release(&l);
}

int
main(int ac, char **av)
{
  mtenable("xv6-mapbench");

  if (ac != 2) {
    fprintf(1, "usage: %s nthreads\n", av[0]);
    exit();
  }

  int nthread = atoi(av[1]);

  acquire(&l);
  // fprintf(1, "mapbench[%d]: start esp %x, nthread=%d\n", getpid(), rrsp(), nthread);

  for(int i = 0; i < nthread; i++) {
    sbrk(8192);
    void *tstack = sbrk(0);
    // fprintf(1, "tstack %lx\n", tstack);
    int tid = forkt(tstack, (void*) thr, (void *)(u64)i);
    if (0) fprintf(1, "mapbench[%d]: child %d\n", getpid(), tid);
  }

  for(;;){
    int lastc = tcount;
    // fprintf(1, "mapbench[%d]: tcount=%d\n", getpid(), lastc);
    release(&l);
    if(lastc==nthread)
      break;
    while(tcount==lastc)
      __asm __volatile("":::"memory");
    acquire(&l);
  }
  release(&l);
  // fprintf(1, "mapbench[%d]: done\n", getpid());

  for(int i = 0; i < nthread; i++)
    wait();

  mtdisable("xv6-mapbench");
  // halt();
  exit();
}
<commit_msg>use wait() in mapbench instead of spinning<commit_after>#include "types.h"
#include "stat.h"
#include "user.h"
#include "mtrace.h"
#include "amd64.h"
#include "uspinlock.h"

enum { readaccess = 0 };
enum { verbose = 0 };
enum { npg = 1 };

void
thr(void *arg)
{
  u64 tid = (u64)arg;

  for (int i = 0; i < 1000000; i++) {
    if (verbose && ((i % 100) == 0))
      fprintf(1, "%d: %d ops\n", tid, i);

    volatile char *p = (char*) (0x40000UL + tid * npg * 4096);
    if (map((void *) p, npg * 4096) < 0) {
      fprintf(1, "%d: map failed\n", tid);
      exit();
    }

    if (readaccess) {
      for (int j = 0; j < npg * 4096; j++)
	p[j] = '\0';
    }

    if (unmap((void *) p, npg * 4096) < 0) {
      fprintf(1, "%d: unmap failed\n", tid);
      exit();
    }
  }
}

int
main(int ac, char **av)
{
  mtenable("xv6-mapbench");

  if (ac != 2) {
    fprintf(1, "usage: %s nthreads\n", av[0]);
    exit();
  }

  int nthread = atoi(av[1]);

  // fprintf(1, "mapbench[%d]: start esp %x, nthread=%d\n", getpid(), rrsp(), nthread);

  for(int i = 0; i < nthread; i++) {
    sbrk(8192);
    void *tstack = sbrk(0);
    // fprintf(1, "tstack %lx\n", tstack);
    int tid = forkt(tstack, (void*) thr, (void *)(u64)i);
    if (0) fprintf(1, "mapbench[%d]: child %d\n", getpid(), tid);
  }

  for(int i = 0; i < nthread; i++)
    wait();

  // fprintf(1, "mapbench[%d]: done\n", getpid());
  mtdisable("xv6-mapbench");
  // halt();
  exit();
}
<|endoftext|>


<commit_before>#include <nano/lib/timer.hpp>
#include <nano/node/node.hpp>
#include <nano/node/vote_processor.hpp>

nano::vote_processor::vote_processor (nano::node & node_a) :
node (node_a),
started (false),
stopped (false),
active (false),
thread ([this]() {
	nano::thread_role::set (nano::thread_role::name::vote_processing);
	process_loop ();
})
{
	nano::unique_lock<std::mutex> lock (mutex);
	condition.wait (lock, [& started = started] { return started; });
}

void nano::vote_processor::process_loop ()
{
	nano::timer<std::chrono::milliseconds> elapsed;
	bool log_this_iteration;

	nano::unique_lock<std::mutex> lock (mutex);
	started = true;

	lock.unlock ();
	condition.notify_all ();
	lock.lock ();

	while (!stopped)
	{
		if (!votes.empty ())
		{
			std::deque<std::pair<std::shared_ptr<nano::vote>, std::shared_ptr<nano::transport::channel>>> votes_l;
			votes_l.swap (votes);

			log_this_iteration = false;
			if (node.config.logging.network_logging () && votes_l.size () > 50)
			{
				/*
				 * Only log the timing information for this iteration if
				 * there are a sufficient number of items for it to be relevant
				 */
				log_this_iteration = true;
				elapsed.start ();
			}
			active = true;
			lock.unlock ();
			verify_votes (votes_l);
			{
				nano::unique_lock<std::mutex> active_single_lock (node.active.mutex);
				auto transaction (node.store.tx_begin_read ());
				uint64_t count (1);
				for (auto & i : votes_l)
				{
					vote_blocking (transaction, i.first, i.second, true);
					// Free active_transactions mutex each 100 processed votes
					if (count % 100 == 0)
					{
						active_single_lock.unlock ();
						transaction.refresh ();
						active_single_lock.lock ();
					}
					count++;
				}
			}
			lock.lock ();
			active = false;

			lock.unlock ();
			condition.notify_all ();
			lock.lock ();

			if (log_this_iteration && elapsed.stop () > std::chrono::milliseconds (100))
			{
				node.logger.try_log (boost::str (boost::format ("Processed %1% votes in %2% milliseconds (rate of %3% votes per second)") % votes_l.size () % elapsed.value ().count () % ((votes_l.size () * 1000ULL) / elapsed.value ().count ())));
			}
		}
		else
		{
			condition.wait (lock);
		}
	}
}

void nano::vote_processor::vote (std::shared_ptr<nano::vote> vote_a, std::shared_ptr<nano::transport::channel> channel_a)
{
	nano::unique_lock<std::mutex> lock (mutex);
	if (!stopped)
	{
		bool process (false);
		/* Random early delection levels
		 Always process votes for test network (process = true)
		 Stop processing with max 144 * 1024 votes */
		if (!node.network_params.network.is_test_network ())
		{
			// Level 0 (< 0.1%)
			if (votes.size () < 96 * 1024)
			{
				process = true;
			}
			// Level 1 (0.1-1%)
			else if (votes.size () < 112 * 1024)
			{
				process = (representatives_1.find (vote_a->account) != representatives_1.end ());
			}
			// Level 2 (1-5%)
			else if (votes.size () < 128 * 1024)
			{
				process = (representatives_2.find (vote_a->account) != representatives_2.end ());
			}
			// Level 3 (> 5%)
			else if (votes.size () < 144 * 1024)
			{
				process = (representatives_3.find (vote_a->account) != representatives_3.end ());
			}
		}
		else
		{
			// Process for test network
			process = true;
		}
		if (process)
		{
			votes.push_back (std::make_pair (vote_a, channel_a));

			lock.unlock ();
			condition.notify_all ();
			lock.lock ();
		}
		else
		{
			node.stats.inc (nano::stat::type::vote, nano::stat::detail::vote_overflow);
		}
	}
}

void nano::vote_processor::verify_votes (std::deque<std::pair<std::shared_ptr<nano::vote>, std::shared_ptr<nano::transport::channel>>> & votes_a)
{
	auto size (votes_a.size ());
	std::vector<unsigned char const *> messages;
	messages.reserve (size);
	std::vector<nano::block_hash> hashes;
	hashes.reserve (size);
	std::vector<size_t> lengths (size, sizeof (nano::block_hash));
	std::vector<unsigned char const *> pub_keys;
	pub_keys.reserve (size);
	std::vector<unsigned char const *> signatures;
	signatures.reserve (size);
	std::vector<int> verifications;
	verifications.resize (size);
	for (auto & vote : votes_a)
	{
		hashes.push_back (vote.first->hash ());
		messages.push_back (hashes.back ().bytes.data ());
		pub_keys.push_back (vote.first->account.bytes.data ());
		signatures.push_back (vote.first->signature.bytes.data ());
	}
	nano::signature_check_set check = { size, messages.data (), lengths.data (), pub_keys.data (), signatures.data (), verifications.data () };
	node.checker.verify (check);
	std::remove_reference_t<decltype (votes_a)> result;
	auto i (0);
	for (auto & vote : votes_a)
	{
		assert (verifications[i] == 1 || verifications[i] == 0);
		if (verifications[i] == 1)
		{
			result.push_back (vote);
		}
		++i;
	}
	votes_a.swap (result);
}

// node.active.mutex lock required
nano::vote_code nano::vote_processor::vote_blocking (nano::transaction const & transaction_a, std::shared_ptr<nano::vote> vote_a, std::shared_ptr<nano::transport::channel> channel_a, bool validated)
{
	assert (!node.active.mutex.try_lock ());
	auto result (nano::vote_code::invalid);
	if (validated || !vote_a->validate ())
	{
		auto max_vote (node.store.vote_max (transaction_a, vote_a));
		result = nano::vote_code::replay;
		if (!node.active.vote (vote_a, true))
		{
			result = nano::vote_code::vote;
		}
		switch (result)
		{
			case nano::vote_code::vote:
				node.observers.vote.notify (vote_a, channel_a);
			case nano::vote_code::replay:
				// This tries to assist rep nodes that have lost track of their highest sequence number by replaying our highest known vote back to them
				// Only do this if the sequence number is significantly different to account for network reordering
				// Amplify attack considerations: We're sending out a confirm_ack in response to a confirm_ack for no net traffic increase
				if (max_vote->sequence > vote_a->sequence + 10000)
				{
					nano::confirm_ack confirm (max_vote);
					channel_a->send (confirm); // this is non essential traffic as it will be resolicited if not received
				}
				break;
			case nano::vote_code::invalid:
				assert (false);
				break;
		}
	}
	std::string status;
	switch (result)
	{
		case nano::vote_code::invalid:
			status = "Invalid";
			node.stats.inc (nano::stat::type::vote, nano::stat::detail::vote_invalid);
			break;
		case nano::vote_code::replay:
			status = "Replay";
			node.stats.inc (nano::stat::type::vote, nano::stat::detail::vote_replay);
			break;
		case nano::vote_code::vote:
			status = "Vote";
			node.stats.inc (nano::stat::type::vote, nano::stat::detail::vote_valid);
			break;
	}
	if (node.config.logging.vote_logging ())
	{
		node.logger.try_log (boost::str (boost::format ("Vote from: %1% sequence: %2% block(s): %3%status: %4%") % vote_a->account.to_account () % std::to_string (vote_a->sequence) % vote_a->hashes_string () % status));
	}
	return result;
}

void nano::vote_processor::stop ()
{
	{
		nano::lock_guard<std::mutex> lock (mutex);
		stopped = true;
	}
	condition.notify_all ();
	if (thread.joinable ())
	{
		thread.join ();
	}
}

void nano::vote_processor::flush ()
{
	nano::unique_lock<std::mutex> lock (mutex);
	while (active || !votes.empty ())
	{
		condition.wait (lock);
	}
}

void nano::vote_processor::calculate_weights ()
{
	nano::unique_lock<std::mutex> lock (mutex);
	if (!stopped)
	{
		representatives_1.clear ();
		representatives_2.clear ();
		representatives_3.clear ();
		auto supply (node.online_reps.online_stake ());
		auto rep_amounts = node.ledger.rep_weights.get_rep_amounts ();
		for (auto const & rep_amount : rep_amounts)
		{
			nano::account const & representative (rep_amount.first);
			auto weight (node.ledger.weight (representative));
			if (weight > supply / 1000) // 0.1% or above (level 1)
			{
				representatives_1.insert (representative);
				if (weight > supply / 100) // 1% or above (level 2)
				{
					representatives_2.insert (representative);
					if (weight > supply / 20) // 5% or above (level 3)
					{
						representatives_3.insert (representative);
					}
				}
			}
		}
	}
}

namespace nano
{
std::unique_ptr<seq_con_info_component> collect_seq_con_info (vote_processor & vote_processor, const std::string & name)
{
	size_t votes_count = 0;
	size_t representatives_1_count = 0;
	size_t representatives_2_count = 0;
	size_t representatives_3_count = 0;

	{
		nano::lock_guard<std::mutex> guard (vote_processor.mutex);
		votes_count = vote_processor.votes.size ();
		representatives_1_count = vote_processor.representatives_1.size ();
		representatives_2_count = vote_processor.representatives_2.size ();
		representatives_3_count = vote_processor.representatives_3.size ();
	}

	auto composite = std::make_unique<seq_con_info_composite> (name);
	composite->add_component (std::make_unique<seq_con_info_leaf> (seq_con_info{ "votes", votes_count, sizeof (decltype (vote_processor.votes)::value_type) }));
	composite->add_component (std::make_unique<seq_con_info_leaf> (seq_con_info{ "representatives_1", representatives_1_count, sizeof (decltype (vote_processor.representatives_1)::value_type) }));
	composite->add_component (std::make_unique<seq_con_info_leaf> (seq_con_info{ "representatives_2", representatives_2_count, sizeof (decltype (vote_processor.representatives_2)::value_type) }));
	composite->add_component (std::make_unique<seq_con_info_leaf> (seq_con_info{ "representatives_3", representatives_3_count, sizeof (decltype (vote_processor.representatives_3)::value_type) }));
	return composite;
}
}
<commit_msg>Fix non-restarting timer in vote processor log (#2368)<commit_after>#include <nano/lib/timer.hpp>
#include <nano/node/node.hpp>
#include <nano/node/vote_processor.hpp>

nano::vote_processor::vote_processor (nano::node & node_a) :
node (node_a),
started (false),
stopped (false),
active (false),
thread ([this]() {
	nano::thread_role::set (nano::thread_role::name::vote_processing);
	process_loop ();
})
{
	nano::unique_lock<std::mutex> lock (mutex);
	condition.wait (lock, [& started = started] { return started; });
}

void nano::vote_processor::process_loop ()
{
	nano::timer<std::chrono::milliseconds> elapsed;
	bool log_this_iteration;

	nano::unique_lock<std::mutex> lock (mutex);
	started = true;

	lock.unlock ();
	condition.notify_all ();
	lock.lock ();

	while (!stopped)
	{
		if (!votes.empty ())
		{
			std::deque<std::pair<std::shared_ptr<nano::vote>, std::shared_ptr<nano::transport::channel>>> votes_l;
			votes_l.swap (votes);

			log_this_iteration = false;
			if (node.config.logging.network_logging () && votes_l.size () > 50)
			{
				/*
				 * Only log the timing information for this iteration if
				 * there are a sufficient number of items for it to be relevant
				 */
				log_this_iteration = true;
				elapsed.restart ();
			}
			active = true;
			lock.unlock ();
			verify_votes (votes_l);
			{
				nano::unique_lock<std::mutex> active_single_lock (node.active.mutex);
				auto transaction (node.store.tx_begin_read ());
				uint64_t count (1);
				for (auto & i : votes_l)
				{
					vote_blocking (transaction, i.first, i.second, true);
					// Free active_transactions mutex each 100 processed votes
					if (count % 100 == 0)
					{
						active_single_lock.unlock ();
						transaction.refresh ();
						active_single_lock.lock ();
					}
					count++;
				}
			}
			lock.lock ();
			active = false;

			lock.unlock ();
			condition.notify_all ();
			lock.lock ();

			if (log_this_iteration && elapsed.stop () > std::chrono::milliseconds (100))
			{
				node.logger.try_log (boost::str (boost::format ("Processed %1% votes in %2% milliseconds (rate of %3% votes per second)") % votes_l.size () % elapsed.value ().count () % ((votes_l.size () * 1000ULL) / elapsed.value ().count ())));
			}
		}
		else
		{
			condition.wait (lock);
		}
	}
}

void nano::vote_processor::vote (std::shared_ptr<nano::vote> vote_a, std::shared_ptr<nano::transport::channel> channel_a)
{
	nano::unique_lock<std::mutex> lock (mutex);
	if (!stopped)
	{
		bool process (false);
		/* Random early delection levels
		 Always process votes for test network (process = true)
		 Stop processing with max 144 * 1024 votes */
		if (!node.network_params.network.is_test_network ())
		{
			// Level 0 (< 0.1%)
			if (votes.size () < 96 * 1024)
			{
				process = true;
			}
			// Level 1 (0.1-1%)
			else if (votes.size () < 112 * 1024)
			{
				process = (representatives_1.find (vote_a->account) != representatives_1.end ());
			}
			// Level 2 (1-5%)
			else if (votes.size () < 128 * 1024)
			{
				process = (representatives_2.find (vote_a->account) != representatives_2.end ());
			}
			// Level 3 (> 5%)
			else if (votes.size () < 144 * 1024)
			{
				process = (representatives_3.find (vote_a->account) != representatives_3.end ());
			}
		}
		else
		{
			// Process for test network
			process = true;
		}
		if (process)
		{
			votes.push_back (std::make_pair (vote_a, channel_a));

			lock.unlock ();
			condition.notify_all ();
			lock.lock ();
		}
		else
		{
			node.stats.inc (nano::stat::type::vote, nano::stat::detail::vote_overflow);
		}
	}
}

void nano::vote_processor::verify_votes (std::deque<std::pair<std::shared_ptr<nano::vote>, std::shared_ptr<nano::transport::channel>>> & votes_a)
{
	auto size (votes_a.size ());
	std::vector<unsigned char const *> messages;
	messages.reserve (size);
	std::vector<nano::block_hash> hashes;
	hashes.reserve (size);
	std::vector<size_t> lengths (size, sizeof (nano::block_hash));
	std::vector<unsigned char const *> pub_keys;
	pub_keys.reserve (size);
	std::vector<unsigned char const *> signatures;
	signatures.reserve (size);
	std::vector<int> verifications;
	verifications.resize (size);
	for (auto & vote : votes_a)
	{
		hashes.push_back (vote.first->hash ());
		messages.push_back (hashes.back ().bytes.data ());
		pub_keys.push_back (vote.first->account.bytes.data ());
		signatures.push_back (vote.first->signature.bytes.data ());
	}
	nano::signature_check_set check = { size, messages.data (), lengths.data (), pub_keys.data (), signatures.data (), verifications.data () };
	node.checker.verify (check);
	std::remove_reference_t<decltype (votes_a)> result;
	auto i (0);
	for (auto & vote : votes_a)
	{
		assert (verifications[i] == 1 || verifications[i] == 0);
		if (verifications[i] == 1)
		{
			result.push_back (vote);
		}
		++i;
	}
	votes_a.swap (result);
}

// node.active.mutex lock required
nano::vote_code nano::vote_processor::vote_blocking (nano::transaction const & transaction_a, std::shared_ptr<nano::vote> vote_a, std::shared_ptr<nano::transport::channel> channel_a, bool validated)
{
	assert (!node.active.mutex.try_lock ());
	auto result (nano::vote_code::invalid);
	if (validated || !vote_a->validate ())
	{
		auto max_vote (node.store.vote_max (transaction_a, vote_a));
		result = nano::vote_code::replay;
		if (!node.active.vote (vote_a, true))
		{
			result = nano::vote_code::vote;
		}
		switch (result)
		{
			case nano::vote_code::vote:
				node.observers.vote.notify (vote_a, channel_a);
			case nano::vote_code::replay:
				// This tries to assist rep nodes that have lost track of their highest sequence number by replaying our highest known vote back to them
				// Only do this if the sequence number is significantly different to account for network reordering
				// Amplify attack considerations: We're sending out a confirm_ack in response to a confirm_ack for no net traffic increase
				if (max_vote->sequence > vote_a->sequence + 10000)
				{
					nano::confirm_ack confirm (max_vote);
					channel_a->send (confirm); // this is non essential traffic as it will be resolicited if not received
				}
				break;
			case nano::vote_code::invalid:
				assert (false);
				break;
		}
	}
	std::string status;
	switch (result)
	{
		case nano::vote_code::invalid:
			status = "Invalid";
			node.stats.inc (nano::stat::type::vote, nano::stat::detail::vote_invalid);
			break;
		case nano::vote_code::replay:
			status = "Replay";
			node.stats.inc (nano::stat::type::vote, nano::stat::detail::vote_replay);
			break;
		case nano::vote_code::vote:
			status = "Vote";
			node.stats.inc (nano::stat::type::vote, nano::stat::detail::vote_valid);
			break;
	}
	if (node.config.logging.vote_logging ())
	{
		node.logger.try_log (boost::str (boost::format ("Vote from: %1% sequence: %2% block(s): %3%status: %4%") % vote_a->account.to_account () % std::to_string (vote_a->sequence) % vote_a->hashes_string () % status));
	}
	return result;
}

void nano::vote_processor::stop ()
{
	{
		nano::lock_guard<std::mutex> lock (mutex);
		stopped = true;
	}
	condition.notify_all ();
	if (thread.joinable ())
	{
		thread.join ();
	}
}

void nano::vote_processor::flush ()
{
	nano::unique_lock<std::mutex> lock (mutex);
	while (active || !votes.empty ())
	{
		condition.wait (lock);
	}
}

void nano::vote_processor::calculate_weights ()
{
	nano::unique_lock<std::mutex> lock (mutex);
	if (!stopped)
	{
		representatives_1.clear ();
		representatives_2.clear ();
		representatives_3.clear ();
		auto supply (node.online_reps.online_stake ());
		auto rep_amounts = node.ledger.rep_weights.get_rep_amounts ();
		for (auto const & rep_amount : rep_amounts)
		{
			nano::account const & representative (rep_amount.first);
			auto weight (node.ledger.weight (representative));
			if (weight > supply / 1000) // 0.1% or above (level 1)
			{
				representatives_1.insert (representative);
				if (weight > supply / 100) // 1% or above (level 2)
				{
					representatives_2.insert (representative);
					if (weight > supply / 20) // 5% or above (level 3)
					{
						representatives_3.insert (representative);
					}
				}
			}
		}
	}
}

namespace nano
{
std::unique_ptr<seq_con_info_component> collect_seq_con_info (vote_processor & vote_processor, const std::string & name)
{
	size_t votes_count = 0;
	size_t representatives_1_count = 0;
	size_t representatives_2_count = 0;
	size_t representatives_3_count = 0;

	{
		nano::lock_guard<std::mutex> guard (vote_processor.mutex);
		votes_count = vote_processor.votes.size ();
		representatives_1_count = vote_processor.representatives_1.size ();
		representatives_2_count = vote_processor.representatives_2.size ();
		representatives_3_count = vote_processor.representatives_3.size ();
	}

	auto composite = std::make_unique<seq_con_info_composite> (name);
	composite->add_component (std::make_unique<seq_con_info_leaf> (seq_con_info{ "votes", votes_count, sizeof (decltype (vote_processor.votes)::value_type) }));
	composite->add_component (std::make_unique<seq_con_info_leaf> (seq_con_info{ "representatives_1", representatives_1_count, sizeof (decltype (vote_processor.representatives_1)::value_type) }));
	composite->add_component (std::make_unique<seq_con_info_leaf> (seq_con_info{ "representatives_2", representatives_2_count, sizeof (decltype (vote_processor.representatives_2)::value_type) }));
	composite->add_component (std::make_unique<seq_con_info_leaf> (seq_con_info{ "representatives_3", representatives_3_count, sizeof (decltype (vote_processor.representatives_3)::value_type) }));
	return composite;
}
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef TWSM_MAIN_WINDOW
#define TWSM_MAIN_WINDOW

#include "serverbrowser.hpp"
#include "ui_main_window.h"

#include <QMainWindow>
#include <QTimer>
#include <QDebug>

namespace Ui
{class main_window;}

namespace twsm
{
	class main_window : public QMainWindow
	{
		Q_OBJECT

		Ui::main_window* m_ui{new Ui::main_window};

		server_browser m_srvbrowser{*m_ui};

		QTimer m_updatetimer;

	public:
		explicit main_window(QWidget* parent = nullptr) :
			QMainWindow{parent}
		{this->init();}

		~main_window()
		{delete m_ui;}

	private:
		void init()
		{
			// setup ui
			m_ui->setupUi(this);

			// setup timer
			m_updatetimer.start(0);
			this->connect(&m_updatetimer, SIGNAL(timeout()), this, SLOT(update()));
		}

	private slots:
		void update()
		{
			m_srvbrowser.update();
		}

		void on_m_tw_menu_itemSelectionChanged()
		{
			m_ui->m_sw_main->setCurrentIndex(m_ui->m_tw_menu->currentIndex().row() / 2);
		}

		void on_m_pb_srvb_refresh_clicked()
		{
			m_srvbrowser.refresh();
		}
	};
}

#endif // TWSM_MAIN_WINDOW
<commit_msg>adapted main_window.hpp<commit_after>//
// Copyright (c) 2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef TWSM_MAIN_WINDOW
#define TWSM_MAIN_WINDOW

#include "econ.hpp"
#include "serverbrowser.hpp"
#include "ui_main_window.h"

#include <QMainWindow>
#include <QTimer>
#include <QDebug>

namespace Ui
{class main_window;}

namespace twsm
{
	class main_window : public QMainWindow
	{
		Q_OBJECT

		Ui::main_window* m_ui{new Ui::main_window};

		server_browser m_srvbrowser{*m_ui};
		econ m_econ{*m_ui};

		QTimer m_updatetimer;

	public:
		explicit main_window(QWidget* parent = nullptr) :
			QMainWindow{parent}
		{this->init();}

		~main_window()
		{delete m_ui;}

	private:
		void init()
		{
			// setup ui
			m_ui->setupUi(this);

			// setup components
			m_srvbrowser.init();
			m_econ.init();

			// setup timer
			m_updatetimer.start(0);
			this->connect(&m_updatetimer, SIGNAL(timeout()), this, SLOT(update()));
		}

	private slots:
		void update()
		{
			m_srvbrowser.update();
			m_econ.update();
		}

		// menu
		void on_m_tw_menu_itemSelectionChanged()
		{
			m_ui->m_sw_main->setCurrentIndex(m_ui->m_tw_menu->currentIndex().row() / 2);
		}
	};
}

#endif // TWSM_MAIN_WINDOW
<|endoftext|>


<commit_before>/*
 * Copyright 2001 - 2009 Todd Richmond
 *
 * This file is part of Blister - a light weight, scalable, high performance
 * C++ server infrastructure.
 *
 * Blister is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or any later version.
 *
 * Blister is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Blister. If not, see <http://www.gnu.org/licenses/>.
 */

#include "stdapi.h"
#include <algorithm>
#include "Timing.h"

// UNIX loaders may try to construct static objects > 1 time
static Timing &_dtiming(void) {
    static Timing timing;

    return timing;
}

Timing &dtiming(_dtiming());

void Timing::add(const tchar *key, timing_t diff) {
    SpinLocker lkr(lck);
    timingmap::const_iterator it = tmap.find(key);
    uint slot;
    Stats *stats;
    static timing_t limits[TIMINGSLOTS - 1] = {
	10, 100, 1000, 10000, 100000, 1000000, 5000000, 10000000, 30000000
    };

    if (it == tmap.end()) {
	key = tstrdup(key);
	stats = tmap[key] = new Stats(key);
    } else {
	stats = it->second;
    }
    for (slot = 0; slot < TIMINGSLOTS - 1; slot++) {
	if (diff <= limits[slot])
	    break;
    }
    stats->cnt++;
    stats->cnts[slot]++;
    stats->tot += diff;
}

void Timing::clear() {
    timingmap::iterator it;
    SpinLocker lkr(lck);

    while ((it = tmap.begin()) != tmap.end()) {
	const tchar *p = it->first;

	delete it->second;
	tmap.erase(it);
	free((tchar *)p);
    }
}

const tstring Timing::data(bool sortbyname, uint columns) const {
    timingmap::const_iterator it;
    uint last = 0, start = 0;
    SpinLocker lkr(lck);
    tstring s;
    vector<const Stats *>::const_iterator sit;
    vector<const Stats *> sorted;
    const Stats *stats;
    uint u;
    static const tchar *hdrs[TIMINGSLOTS] = {
	T("10u"), T(".1m"), T(" 1m"), T("10m"), T(".1s"), T(" 1s"), T(" 5s"),
	T("10s"), T("30s"), T("...")
    };

    for (it = tmap.begin(); it != tmap.end(); it++)
	sorted.push_back(it->second);
    sort(sorted.begin(), sorted.end(), sortbyname ? less_name : less_time);
    for (sit = sorted.begin(); sit != sorted.end(); sit++) {
	stats = *sit;
	for (u = TIMINGSLOTS - 1; u > last; u--) {
	    if (stats->cnts[u]) {
		last = u;
		break;
	    }
	}
    }
    if (columns) {
	if (columns > TIMINGSLOTS)
	    columns = TIMINGSLOTS;
	start = last < columns ? 0 : last - columns + 1;
	s = T("key                            msec   cnt   avg");
	for (u = start; u <= last; u++) {
	    s += (tchar)' ';
	    s += hdrs[u];
	}
	s += (tchar)'\n';
    }
    for (sit = sorted.begin(); sit != sorted.end(); sit++) {
	tchar abuf[16], buf[128], cbuf[16], sbuf[16];
	ulong sum = 0;
	timing_t tot;

	stats = *sit;
	tot = stats->tot;
	if (columns) {
	    for (u = 0; u <= start; u++)
		sum += stats->cnts[u];
	    if (stats->cnt >= 100000000)
		tsprintf(cbuf, T("%5lum"), stats->cnt / 1000000);
	    else if (stats->cnt >= 100000)
		tsprintf(cbuf, T("%5luk"), stats->cnt / 1000);
	    else
		tsprintf(cbuf, T("%5lu"), stats->cnt);
	    if (tot)
		tsprintf(buf, T("%-29s%6s%6s%6s"), stats->name, format(tot,
		    sbuf), cbuf, format(tot / stats->cnt, abuf));
	    else
		tsprintf(buf, T("%-35s%6s"), stats->name, cbuf);
	} else {
	    if (!s.empty())
		s += (tchar)',';
	    tsprintf(buf, T("%s,%s,%lu"), stats->name, format(tot, sbuf),
		stats->cnt);
	}
	s += buf;
	for (u = start; u <= last && tot; u++) {
	    ulong cnt = (columns && u == start) ? sum : stats->cnts[u];

	    if (!columns) {
		tsprintf(buf, T(",%lu"), cnt);
		s += buf;
	    } else if (cnt == 0) {
		s += T("    ");
	    } else if (cnt < 100) {
		tsprintf(buf, T(" %3lu"), cnt);
		s += buf;
	    } else if (cnt == stats->cnt) {
		s += T("   *");
	    } else {
		tsprintf(buf, T(" %2u%%"), (uint)(cnt * 100 / stats->cnt));
		s += buf;
	    }
	}
	if (columns)
	    s += (tchar)'\n';
    }
    return s;
}

void Timing::erase(const tchar *key) {
    SpinLocker lkr(lck);
    timingmap::iterator it = tmap.find(key);

    if (it != tmap.end()) {
	const tchar *p = it->first;

	delete it->second;
	tmap.erase(it);
	free((tchar *)p);
    }
}

const tchar *Timing::format(timing_t t, tchar *buf) {
    float f(t / 1000.0f);

    if (f < 10)
	tsprintf(buf, T("%.3f"), f);
    else if (f < 100)
        tsprintf(buf, T("%.2f"), f);
    else if (f < 10000)
        tsprintf(buf, T("%.0f"), f);
    else if (f < 1000000)
        tsprintf(buf, T("%.0fk"), f / 1000);
    else
        tsprintf(buf, T("%.0fm"), f / 1000000);
    return buf;
}

void Timing::record(const tchar *key) {
    timing_t n = now();
    tstring caller;
    timing_t diff;
    Tlsdata &tlsd(*tls);

    do {
	vector<tstring>::reverse_iterator it = tlsd.callers.rbegin();

	if (it == tlsd.callers.rend()) {
	    tcerr << T("timing mismatch for ") << (key ? key : T("stack")) <<
		endl;
	    return;
	}
	caller = *it;
	tlsd.callers.pop_back();
	if (!key)
	    key = caller.c_str();
	diff = n - *(tlsd.starts.rbegin());
	tlsd.starts.pop_back();
    } while (!caller.empty() && caller != key);
    if (!caller.empty() && !tlsd.callers.empty()) {
	tstring s;

	for (vector<tstring>::const_iterator it = tlsd.callers.begin();
	    it != tlsd.callers.end(); it++) {
	    if (!s.empty())
		s += T("->");
	    s += *it;
	}
	s += T("->");
	s += key;
	add(s.c_str(), diff);
    }
    add(key, diff);
}

void Timing::restart() {
    Tlsdata &tlsd(*tls);

    if (!tlsd.callers.empty()) {
	tlsd.starts.pop_back();
	tlsd.starts.push_back(now());
    }
}

void Timing::start(const tchar *key) {
    Tlsdata &tlsd(*tls);

    tlsd.callers.push_back(key ? key : T(""));
    tlsd.starts.push_back(now());
}

void Timing::stop(uint lvl) {
    Tlsdata &tlsd(*tls);

    while (lvl-- && !tlsd.callers.empty()) {
	tlsd.callers.pop_back();
	tlsd.starts.pop_back();
    }
}

<commit_msg>minor locking performance improvement<commit_after>/*
 * Copyright 2001 - 2009 Todd Richmond
 *
 * This file is part of Blister - a light weight, scalable, high performance
 * C++ server infrastructure.
 *
 * Blister is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or any later version.
 *
 * Blister is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Blister. If not, see <http://www.gnu.org/licenses/>.
 */

#include "stdapi.h"
#include <algorithm>
#include "Timing.h"

// UNIX loaders may try to construct static objects > 1 time
static Timing &_dtiming(void) {
    static Timing timing;

    return timing;
}

Timing &dtiming(_dtiming());

void Timing::add(const tchar *key, timing_t diff) {
    uint slot;
    Stats *stats;
    static timing_t limits[TIMINGSLOTS - 1] = {
	10, 100, 1000, 10000, 100000, 1000000, 5000000, 10000000, 30000000
    };

    for (slot = 0; slot < TIMINGSLOTS - 1; slot++) {
	if (diff <= limits[slot])
	    break;
    }

    FastSpinLocker lkr(lck);
    timingmap::const_iterator it = tmap.find(key);

    if (it == tmap.end()) {
	key = tstrdup(key);
	stats = tmap[key] = new Stats(key);
    } else {
	stats = it->second;
    }
    stats->cnt++;
    stats->cnts[slot]++;
    stats->tot += diff;
}

void Timing::clear() {
    timingmap::iterator it;
    FastSpinLocker lkr(lck);

    while ((it = tmap.begin()) != tmap.end()) {
	const tchar *p = it->first;

	delete it->second;
	tmap.erase(it);
	free((tchar *)p);
    }
}

const tstring Timing::data(bool sortbyname, uint columns) const {
    timingmap::const_iterator it;
    uint last = 0, start = 0;
    SpinLocker lkr(lck);
    tstring s;
    vector<const Stats *>::const_iterator sit;
    vector<const Stats *> sorted;
    const Stats *stats;
    uint u;
    static const tchar *hdrs[TIMINGSLOTS] = {
	T("10u"), T(".1m"), T(" 1m"), T("10m"), T(".1s"), T(" 1s"), T(" 5s"),
	T("10s"), T("30s"), T("...")
    };

    for (it = tmap.begin(); it != tmap.end(); it++)
	sorted.push_back(it->second);
    sort(sorted.begin(), sorted.end(), sortbyname ? less_name : less_time);
    for (sit = sorted.begin(); sit != sorted.end(); sit++) {
	stats = *sit;
	for (u = TIMINGSLOTS - 1; u > last; u--) {
	    if (stats->cnts[u]) {
		last = u;
		break;
	    }
	}
    }
    if (columns) {
	if (columns > TIMINGSLOTS)
	    columns = TIMINGSLOTS;
	start = last < columns ? 0 : last - columns + 1;
	s = T("key                            msec   cnt   avg");
	for (u = start; u <= last; u++) {
	    s += (tchar)' ';
	    s += hdrs[u];
	}
	s += (tchar)'\n';
    }
    for (sit = sorted.begin(); sit != sorted.end(); sit++) {
	tchar abuf[16], buf[128], cbuf[16], sbuf[16];
	ulong sum = 0;
	timing_t tot;

	stats = *sit;
	tot = stats->tot;
	if (columns) {
	    for (u = 0; u <= start; u++)
		sum += stats->cnts[u];
	    if (stats->cnt >= 100000000)
		tsprintf(cbuf, T("%5lum"), stats->cnt / 1000000);
	    else if (stats->cnt >= 100000)
		tsprintf(cbuf, T("%5luk"), stats->cnt / 1000);
	    else
		tsprintf(cbuf, T("%5lu"), stats->cnt);
	    if (tot)
		tsprintf(buf, T("%-29s%6s%6s%6s"), stats->name, format(tot,
		    sbuf), cbuf, format(tot / stats->cnt, abuf));
	    else
		tsprintf(buf, T("%-35s%6s"), stats->name, cbuf);
	} else {
	    if (!s.empty())
		s += (tchar)',';
	    tsprintf(buf, T("%s,%s,%lu"), stats->name, format(tot, sbuf),
		stats->cnt);
	}
	s += buf;
	for (u = start; u <= last && tot; u++) {
	    ulong cnt = (columns && u == start) ? sum : stats->cnts[u];

	    if (!columns) {
		tsprintf(buf, T(",%lu"), cnt);
		s += buf;
	    } else if (cnt == 0) {
		s += T("    ");
	    } else if (cnt < 100) {
		tsprintf(buf, T(" %3lu"), cnt);
		s += buf;
	    } else if (cnt == stats->cnt) {
		s += T("   *");
	    } else {
		tsprintf(buf, T(" %2u%%"), (uint)(cnt * 100 / stats->cnt));
		s += buf;
	    }
	}
	if (columns)
	    s += (tchar)'\n';
    }
    return s;
}

void Timing::erase(const tchar *key) {
    FastSpinLocker lkr(lck);
    timingmap::iterator it = tmap.find(key);

    if (it != tmap.end()) {
	const tchar *p = it->first;

	delete it->second;
	tmap.erase(it);
	free((tchar *)p);
    }
}

const tchar *Timing::format(timing_t t, tchar *buf) {
    float f(t / 1000.0f);

    if (f < 10)
	tsprintf(buf, T("%.3f"), f);
    else if (f < 100)
        tsprintf(buf, T("%.2f"), f);
    else if (f < 10000)
        tsprintf(buf, T("%.0f"), f);
    else if (f < 1000000)
        tsprintf(buf, T("%.0fk"), f / 1000);
    else
        tsprintf(buf, T("%.0fm"), f / 1000000);
    return buf;
}

void Timing::record(const tchar *key) {
    timing_t n = now();
    tstring caller;
    timing_t diff;
    Tlsdata &tlsd(*tls);

    do {
	vector<tstring>::reverse_iterator it = tlsd.callers.rbegin();

	if (it == tlsd.callers.rend()) {
	    tcerr << T("timing mismatch for ") << (key ? key : T("stack")) <<
		endl;
	    return;
	}
	caller = *it;
	tlsd.callers.pop_back();
	if (!key)
	    key = caller.c_str();
	diff = n - *(tlsd.starts.rbegin());
	tlsd.starts.pop_back();
    } while (!caller.empty() && caller != key);
    if (!caller.empty() && !tlsd.callers.empty()) {
	tstring s;

	for (vector<tstring>::const_iterator it = tlsd.callers.begin();
	    it != tlsd.callers.end(); it++) {
	    if (!s.empty())
		s += T("->");
	    s += *it;
	}
	s += T("->");
	s += key;
	add(s.c_str(), diff);
    }
    add(key, diff);
}

void Timing::restart() {
    Tlsdata &tlsd(*tls);

    if (!tlsd.callers.empty()) {
	tlsd.starts.pop_back();
	tlsd.starts.push_back(now());
    }
}

void Timing::start(const tchar *key) {
    Tlsdata &tlsd(*tls);

    tlsd.callers.push_back(key ? key : T(""));
    tlsd.starts.push_back(now());
}

void Timing::stop(uint lvl) {
    Tlsdata &tlsd(*tls);

    while (lvl-- && !tlsd.callers.empty()) {
	tlsd.callers.pop_back();
	tlsd.starts.pop_back();
    }
}

<|endoftext|>


<commit_before>#pragma once

#include <string>
#include <sstream>
#include <iomanip>

namespace usagi
{
  namespace url_encode
  {
    /// @reference http://stackoverflow.com/a/17708801/1211392
    template < typename T = std::string >
    static inline auto encode( const T& in )
      -> T
    {
      std::basic_ostringstream< T::value_type > escaped;
      escaped.fill( T::value_type( '0' ) );
      escaped << std::hex;

      for ( const auto c : in )
      {
        if
        (    std::isalnum( c )
          or c == T::value_type( '-' )
          or c == T::value_type( '_' )
          or c == T::value_type( '.' )
          or c == T::value_type( '~' )
        )
        {
          escaped << c;
          continue;
        }

        escaped
          << std::uppercase
          << T::value_type( '%' )
          << std::setw( 2 )
          << static_cast< int >( *reinterpret_cast< const unsigned char* >( &c ) )
          << std::nouppercase
          ;
      }

      return escaped.str();
    }

  }
}<commit_msg>fixup<commit_after>#pragma once

#include <string>
#include <sstream>
#include <iomanip>

namespace usagi
{
  namespace url_encode
  {
    /// @reference http://stackoverflow.com/a/17708801/1211392
    template < typename T = std::string >
    static inline auto encode( const T& in )
      -> T
    {
      std::basic_ostringstream< typename T::value_type > escaped;
      escaped.fill( T::value_type( '0' ) );
      escaped << std::hex;

      for ( const auto c : in )
      {
        if
        (    std::isalnum( c )
          or c == T::value_type( '-' )
          or c == T::value_type( '_' )
          or c == T::value_type( '.' )
          or c == T::value_type( '~' )
        )
        {
          escaped << c;
          continue;
        }

        escaped
          << std::uppercase
          << T::value_type( '%' )
          << std::setw( 2 )
          << static_cast< int >( *reinterpret_cast< const unsigned char* >( &c ) )
          << std::nouppercase
          ;
      }

      return escaped.str();
    }

  }
}<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 Smirnov Vladimir mapron1@gmail.com
 * Source code 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 or in file COPYING-APACHE-2.0.txt
 *
 * 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.h
 */

#include "StringUtils.h"

#include <algorithm>
#include <sstream>
#include <functional>

namespace Wuild { namespace StringUtils {

std::string JoinString(const StringVector &list, char glue)
{
	std::string ret;
	for (size_t i =0 ; i< list.size(); ++i)
	{
		if (i > 0)
			ret += glue;
		ret += list[i];
	}
	return ret;
}

// trim from start (in place)
static inline void ltrim(std::string &s) {
    s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) {
        return !std::isspace(ch);
    }));
}

// trim from end (in place)
static inline void rtrim(std::string &s) {
    s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
        return !std::isspace(ch);
    }).base(), s.end());
}

std::string Trim(const std::string & s) {
	auto result = s;
	ltrim(result);
	rtrim(result);
	return result;
}

void SplitString(const std::string & str, StringVector & outList, char delim, bool trimEach, bool skipEmpty)
{
	std::istringstream ss(str);
	std::string item;
	while (std::getline(ss, item, delim))
	{
		if (trimEach)
			Trim(item);
		if (skipEmpty && item.empty())
			continue;

		outList.push_back(item);
	}
}

StringVector StringVectorFromArgv(int argc, char **argv, bool skipFirstArg)
{
	StringVector ret;
	for (int i = int(skipFirstArg); i < argc; ++i)
	{
		std::string arg(argv[i]);
		std::string escapedArg = arg;
		if (arg.find(' ') != std::string::npos && arg[0] != '"')
			escapedArg = '"' + arg + '"';

		ret.emplace_back(escapedArg);
	}
	return ret;
}

} }
<commit_msg>Fixed MSVC include.<commit_after>/*
 * Copyright (C) 2017 Smirnov Vladimir mapron1@gmail.com
 * Source code 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 or in file COPYING-APACHE-2.0.txt
 *
 * 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.h
 */

#include "StringUtils.h"

#include <algorithm>
#include <sstream>
#include <functional>
#include <cctype>

namespace Wuild { namespace StringUtils {

std::string JoinString(const StringVector &list, char glue)
{
	std::string ret;
	for (size_t i =0 ; i< list.size(); ++i)
	{
		if (i > 0)
			ret += glue;
		ret += list[i];
	}
	return ret;
}

// trim from start (in place)
static inline void ltrim(std::string &s) {
    s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) {
        return !std::isspace(ch);
    }));
}

// trim from end (in place)
static inline void rtrim(std::string &s) {
    s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
        return !std::isspace(ch);
    }).base(), s.end());
}

std::string Trim(const std::string & s) {
	auto result = s;
	ltrim(result);
	rtrim(result);
	return result;
}

void SplitString(const std::string & str, StringVector & outList, char delim, bool trimEach, bool skipEmpty)
{
	std::istringstream ss(str);
	std::string item;
	while (std::getline(ss, item, delim))
	{
		if (trimEach)
			Trim(item);
		if (skipEmpty && item.empty())
			continue;

		outList.push_back(item);
	}
}

StringVector StringVectorFromArgv(int argc, char **argv, bool skipFirstArg)
{
	StringVector ret;
	for (int i = int(skipFirstArg); i < argc; ++i)
	{
		std::string arg(argv[i]);
		std::string escapedArg = arg;
		if (arg.find(' ') != std::string::npos && arg[0] != '"')
			escapedArg = '"' + arg + '"';

		ret.emplace_back(escapedArg);
	}
	return ret;
}

} }
<|endoftext|>


<commit_before>#ifndef XWIDGET_HPP
#define XWIDGET_HPP

#include "xobject.hpp"

namespace xeus
{
    class xlayout final : public xobject<xlayout>
    {
    public:

        using base_type = xobject<xlayout>;

        xlayout();

        xjson get_state() const;

    private:

        void set_defaults();
    };

    template <class D>
    class xwidget : public xobject<D>
    {
    public:

        using base_type = xobject<D>;
        using derived_type = D;

        xwidget();

        XPROPERTY(::xeus::xlayout, derived_type, layout);

        xjson get_state() const;

    private:

        void set_defaults();
    };

    /**************************
     * xlayout implementation *
     **************************/

    inline xlayout::xlayout()
        : base_type()
    {
        set_defaults();
        this->open();
    }

    inline xjson xlayout::get_state() const
    {
        xjson state = base_type::get_state();
        return state;
    }

    inline void xlayout::set_defaults()
    {
        base_type::_model_name() = "LayoutModel";
        base_type::_view_name() = "LayoutView";
    }

    /**************************
     * xwidget implementation *
     **************************/

    template <class D>
    inline xwidget<D>::xwidget()
        : base_type()
    {
        set_defaults();
    }

    template <class D>
    inline xjson xwidget<D>::get_state() const
    {
        xjson state = base_type::get_state();
        state["layout"] = xlayout();
        return state;
    }

    template <class D>
    inline void xwidget<D>::set_defaults()
    {
        base_type::_model_name() = "DOMWidgetModel";
        base_type::_view_name() = "DOMWidgetView";
        layout() = ::xeus::xlayout();
    }
}

#endif
<commit_msg>Support state_request<commit_after>#ifndef XWIDGET_HPP
#define XWIDGET_HPP

#include "xobject.hpp"

namespace xeus
{
    class xlayout final : public xobject<xlayout>
    {
    public:

        using base_type = xobject<xlayout>;

        xlayout();

        xjson get_state() const;

    private:

        void set_defaults();
    };

    template <class D>
    class xwidget : public xobject<D>
    {
    public:

        using base_type = xobject<D>;
        using derived_type = D;

        xwidget();

        XPROPERTY(::xeus::xlayout, derived_type, layout);

        xjson get_state() const;

    private:

        void set_defaults();
    };

    /**************************
     * xlayout implementation *
     **************************/

    inline xlayout::xlayout()
        : base_type()
    {
        set_defaults();
        this->open();
    }

    inline xjson xlayout::get_state() const
    {
        xjson state = base_type::get_state();
        return state;
    }

    inline void xlayout::set_defaults()
    {
        base_type::_model_name() = "LayoutModel";
        base_type::_view_name() = "LayoutView";
    }

    /**************************
     * xwidget implementation *
     **************************/

    template <class D>
    inline xwidget<D>::xwidget()
        : base_type()
    {
        set_defaults();
    }

    template <class D>
    inline xjson xwidget<D>::get_state() const
    {
        xjson state = base_type::get_state();
        state["layout"] = layout();
        return state;
    }

    template <class D>
    inline void xwidget<D>::set_defaults()
    {
        base_type::_model_name() = "DOMWidgetModel";
        base_type::_view_name() = "DOMWidgetView";
    }
}

#endif
<|endoftext|>