<commit_before>#ifndef DELEGATE_HPP
#define DELEGATE_HPP

#include <type_traits>

namespace ctl {
    template<typename T>
    struct delegate;

    /// Wrapper to store lambda functions.
    /** This structure is a simple wrapper that, much like std::bind(), stores the "this" pointer of
        member functions in order to use member functions like normal functions.
        The bound member function does not need to have the same signature as that of the delegate. The
        delegate parameters just need to be implicitly convertible to that of the member function,
        and the converse is true for the return value.

        Use case:

        \code{.cpp}
            std::vector<delegate<int(int)>> v;
            v.push_back([](int i) { return 1*i; });
            v.push_back([](int i) { return 2*i; });
            v.push_back([](int i) { return 3*i; });
            for (auto& d : v) {
                std::cout << d(12) << std::endl;
            }
        \endcode

        It shares similar features with std::function, except that it does not support free functions
        and custom allocators (not needed). On the other hand, it is tailored for use with lambda
        functions (or any other functor), and provides substantial performance improvements over
        std::function (about a factor 2 faster with clang & gcc in -O3).

        Based on "Impossibly fast C++ delegates".
        http://www.codeproject.com/Articles/11015/The-Impossibly-Fast-C-Delegates
    **/
    template<typename R, typename ... Args>
    struct delegate<R(Args...)> {
        /// Construct a new delegate.
        /** In all constructors, the first argument is the object on which the delegate acts, and the
            second argument is the member function that is to be called. When the object is given as a
            reference or a pointer, then only a pointer to this object is kept inside the delegate, and
            the object is expected to outlive the delegate. On the other hand, is the object is given as
            an r-value (either a temporary or an r-value reference), a new instance is move constructed
            inside the delegate, and its lifetime is bound to that of the delegate.
            The member function can be given either as a function pointer, or as an
            std::integral_constant. The latter is usually faster because the function pointer is a
            template argument, and can be more easily inlined by the compiler, but it is also more
            tedious to write.
            Lastly, if no member function is provided, T::operator() is assumed.
        **/
        template<typename ... TArgs>
        delegate(TArgs&&... args) {
            create_(std::forward<TArgs>(args)...);
        }

        /// Default constructor.
        /** When default constructed, a delegate is in "empty" state. See empty().
        **/
        delegate() = default;
        delegate(std::nullptr_t) : delegate() {}

        ~delegate() {
            if (del_) {
                (*del_)(obj_);
            }
        }

        delegate(const delegate&) = delete;
        delegate& operator= (const delegate&) = delete;

        /// Move constructor.
        /** The delegate object that is moved into this one is left in empty state.
        **/
        delegate(delegate&& d) :
            fun_(d.fun_), wfun_(d.wfun_), del_(d.del_), mov_(d.mov_) {
            if (mov_) {
                (*mov_)(std::move(d), *this);
                d.mov_ = nullptr;
            } else {
                obj_ = d.obj_;
            }

            d.obj_ = nullptr;
            d.del_ = nullptr;
            d.fun_ = nullptr;
            d.wfun_ = nullptr;
        }

        /// Move assignment.
        /** The delegate object that is moved into this one is left in empty state.
        **/
        delegate& operator= (delegate&& d) {
            if (del_) {
                (*del_)(obj_);
            }

            del_ = d.del_;
            mov_ = d.mov_;
            fun_ = d.fun_;
            wfun_ = d.wfun_;

            if (mov_) {
                (*mov_)(std::move(d), *this);
                d.mov_ = nullptr;
            } else {
                obj_ = d.obj_;
            }

            d.obj_ = nullptr;
            d.del_ = nullptr;
            d.fun_ = nullptr;
            d.wfun_ = nullptr;

            return *this;
        }

        /// Put the delegate in "empty" state. See empty().
        void clear() {
            if (del_) {
                (*del_)(obj_);
            }

            obj_ = nullptr;
            del_ = nullptr;
            mov_ = nullptr;
            fun_ = nullptr;
            wfun_ = nullptr;
        }

        /// Re-assign the underlying object and function.
        template<typename ... TArgs>
        void assign(TArgs&&... args) {
            clear();
            create_(std::forward<TArgs>(args)...);
        }

        /// Return 'true' if in "empty" state.
        /** When in "empty" state, a delegate has minimal memory usage.
            Trying to call an empty delegate will crash the program.
        **/
        bool empty() const {
            return obj_ == nullptr;
        }

        /// Check if the delegate is not in "empty" state.
        explicit operator bool () const {
            return !empty();
        }

        bool operator == (std::nullptr_t) const {
            return empty();
        }

        bool operator != (std::nullptr_t) const {
            return !empty();
        }

        /// Call the delegate.
        template<typename ... TArgs>
        R operator() (TArgs&& ... args) const {
            return (*wfun_)(obj_, fun_, std::forward<TArgs>(args)...);
        }

    private :
        using wfun_t = R (*)(void*, void*, Args...);
        using dfun_t = void (*)(void*);
        using mfun_t = void (*)(delegate&&, delegate&);

        static const std::size_t max_small_object_size = 2*sizeof(std::size_t);

        void* obj_ = nullptr;
        char inplace_[max_small_object_size];

        void* fun_ = nullptr;
        wfun_t wfun_ = nullptr;

        dfun_t del_ = nullptr;
        mfun_t mov_ = nullptr;

        template<typename T>
        static void deleter_(void* obj) {
            delete static_cast<T*>(obj);
        }

        template<typename T>
        static void inplace_deleter_(void* obj) {
            static_cast<T*>(obj)->~T();
        }

        template<typename T>
        static void inplace_mover_(delegate&& from, delegate& to) {
            to.obj_ = new ((void*)to.inplace_) T(std::move(*static_cast<T*>(from.obj_)));
            inplace_deleter_<T>(from.obj_);
        }

        template<typename T, typename M>
        static R wrapper_(void* obj, void* fun, Args... args) {
            M cfun = nullptr;
            *reinterpret_cast<void**>(&cfun) = fun;
            return (static_cast<T*>(obj)->*cfun)(std::forward<Args>(args)...);
        }

        template<typename T, typename M, M m>
        static R template_wrapper_(void* obj, void*, Args... args) {
            return (static_cast<T*>(obj)->*m)(std::forward<Args>(args)...);
        }

        template<typename T>
        void init_obj_(T& obj) {
            obj_ = &obj;
        }

        template<typename T>
        void init_obj_(T* obj) {
            obj_ = obj;
        }

        template<typename T>
        void init_obj_(T&& obj, std::false_type) {
            obj_ = new T(std::forward<T>(obj));
            del_ = &deleter_<T>;
        }

        template<typename T>
        void init_obj_(T&& obj, std::true_type) {
            // Small object optimization
            obj_ = new ((void*)inplace_) T(std::forward<T>(obj));
            del_ = &inplace_deleter_<T>;
            mov_ = &inplace_mover_<T>;
        }

        template<typename T>
        void init_obj_(T&& obj) {
            init_obj_(std::forward<T>(obj),
                std::integral_constant<bool, sizeof(T) <= max_small_object_size>{});
        }

        template<typename T, typename FT, FT F>
        void init_fun_(std::integral_constant<FT,F>) {
            using RT = typename std::remove_reference<T>::type;
            wfun_ = &template_wrapper_<RT, FT, F>;
        }

        template<typename T, typename M>
        void init_fun_(M fun) {
            fun_ = *reinterpret_cast<void**>(&fun);
            using RT = typename std::remove_reference<T>::type;
            wfun_ = &wrapper_<RT, M>;
        }

        template<typename T, typename M>
        void create_(T&& obj, M&& fun) {
            init_obj_(std::forward<T>(obj));
            init_fun_<T>(std::forward<M>(fun));
        }

        template<typename T>
        void create_(T&& obj) {
            init_obj_(std::forward<T>(obj));
            using RT = typename std::remove_reference<T>::type;
            init_fun_<T>(std::integral_constant<decltype(&RT::operator()),&RT::operator()>());
        }
    };
}

#endif
<commit_msg>Added make_delegate() macro.<commit_after>#ifndef DELEGATE_HPP
#define DELEGATE_HPP

#include <type_traits>

namespace ctl {
    template<typename T>
    struct delegate;

    /// Wrapper to store lambda functions.
    /** This structure is a simple wrapper that, much like std::bind(), stores the "this" pointer of
        member functions in order to use member functions like normal functions.
        The bound member function does not need to have the same signature as that of the delegate. The
        delegate parameters just need to be implicitly convertible to that of the member function,
        and the converse is true for the return value.

        Use case:

        \code{.cpp}
            std::vector<delegate<int(int)>> v;
            v.push_back([](int i) { return 1*i; });
            v.push_back([](int i) { return 2*i; });
            v.push_back([](int i) { return 3*i; });
            for (auto& d : v) {
                std::cout << d(12) << std::endl;
            }
        \endcode

        It shares similar features with std::function, except that it does not support free functions
        and custom allocators (not needed). On the other hand, it is tailored for use with lambda
        functions (or any other functor), and provides substantial performance improvements over
        std::function (about a factor 2 faster with clang & gcc in -O3).

        Based on "Impossibly fast C++ delegates".
        http://www.codeproject.com/Articles/11015/The-Impossibly-Fast-C-Delegates
    **/
    template<typename R, typename ... Args>
    struct delegate<R(Args...)> {
        /// Construct a new delegate.
        /** In all constructors, the first argument is the object on which the delegate acts, and the
            second argument is the member function that is to be called. When the object is given as a
            reference or a pointer, then only a pointer to this object is kept inside the delegate, and
            the object is expected to outlive the delegate. On the other hand, is the object is given as
            an r-value (either a temporary or an r-value reference), a new instance is move constructed
            inside the delegate, and its lifetime is bound to that of the delegate.
            The member function can be given either as a function pointer, or as an
            std::integral_constant. The latter is usually faster because the function pointer is a
            template argument, and can be more easily inlined by the compiler, but it is also more
            tedious to write.
            Lastly, if no member function is provided, T::operator() is assumed.
        **/
        template<typename ... TArgs>
        delegate(TArgs&&... args) {
            create_(std::forward<TArgs>(args)...);
        }

        /// Default constructor.
        /** When default constructed, a delegate is in "empty" state. See empty().
        **/
        delegate() = default;
        delegate(std::nullptr_t) : delegate() {}

        ~delegate() {
            if (del_) {
                (*del_)(obj_);
            }
        }

        delegate(const delegate&) = delete;
        delegate& operator= (const delegate&) = delete;

        /// Move constructor.
        /** The delegate object that is moved into this one is left in empty state.
        **/
        delegate(delegate&& d) :
            fun_(d.fun_), wfun_(d.wfun_), del_(d.del_), mov_(d.mov_) {
            if (mov_) {
                (*mov_)(std::move(d), *this);
                d.mov_ = nullptr;
            } else {
                obj_ = d.obj_;
            }

            d.obj_ = nullptr;
            d.del_ = nullptr;
            d.fun_ = nullptr;
            d.wfun_ = nullptr;
        }

        /// Move assignment.
        /** The delegate object that is moved into this one is left in empty state.
        **/
        delegate& operator= (delegate&& d) {
            if (del_) {
                (*del_)(obj_);
            }

            del_ = d.del_;
            mov_ = d.mov_;
            fun_ = d.fun_;
            wfun_ = d.wfun_;

            if (mov_) {
                (*mov_)(std::move(d), *this);
                d.mov_ = nullptr;
            } else {
                obj_ = d.obj_;
            }

            d.obj_ = nullptr;
            d.del_ = nullptr;
            d.fun_ = nullptr;
            d.wfun_ = nullptr;

            return *this;
        }

        /// Put the delegate in "empty" state. See empty().
        void clear() {
            if (del_) {
                (*del_)(obj_);
            }

            obj_ = nullptr;
            del_ = nullptr;
            mov_ = nullptr;
            fun_ = nullptr;
            wfun_ = nullptr;
        }

        /// Re-assign the underlying object and function.
        template<typename ... TArgs>
        void assign(TArgs&&... args) {
            clear();
            create_(std::forward<TArgs>(args)...);
        }

        /// Return 'true' if in "empty" state.
        /** When in "empty" state, a delegate has minimal memory usage.
            Trying to call an empty delegate will crash the program.
        **/
        bool empty() const {
            return obj_ == nullptr;
        }

        /// Check if the delegate is not in "empty" state.
        explicit operator bool () const {
            return !empty();
        }

        bool operator == (std::nullptr_t) const {
            return empty();
        }

        bool operator != (std::nullptr_t) const {
            return !empty();
        }

        /// Call the delegate.
        template<typename ... TArgs>
        R operator() (TArgs&& ... args) const {
            return (*wfun_)(obj_, fun_, std::forward<TArgs>(args)...);
        }

    private :
        using wfun_t = R (*)(void*, void*, Args...);
        using dfun_t = void (*)(void*);
        using mfun_t = void (*)(delegate&&, delegate&);

        static const std::size_t max_small_object_size = 2*sizeof(std::size_t);

        void* obj_ = nullptr;
        char inplace_[max_small_object_size];

        void* fun_ = nullptr;
        wfun_t wfun_ = nullptr;

        dfun_t del_ = nullptr;
        mfun_t mov_ = nullptr;

        template<typename T>
        static void deleter_(void* obj) {
            delete static_cast<T*>(obj);
        }

        template<typename T>
        static void inplace_deleter_(void* obj) {
            static_cast<T*>(obj)->~T();
        }

        template<typename T>
        static void inplace_mover_(delegate&& from, delegate& to) {
            to.obj_ = new ((void*)to.inplace_) T(std::move(*static_cast<T*>(from.obj_)));
            inplace_deleter_<T>(from.obj_);
        }

        template<typename T, typename M>
        static R wrapper_(void* obj, void* fun, Args... args) {
            M cfun = nullptr;
            *reinterpret_cast<void**>(&cfun) = fun;
            return (static_cast<T*>(obj)->*cfun)(std::forward<Args>(args)...);
        }

        template<typename T, typename M, M m>
        static R template_wrapper_(void* obj, void*, Args... args) {
            return (static_cast<T*>(obj)->*m)(std::forward<Args>(args)...);
        }

        template<typename T>
        void init_obj_(T& obj) {
            obj_ = &obj;
        }

        template<typename T>
        void init_obj_(T* obj) {
            obj_ = obj;
        }

        template<typename T>
        void init_obj_(T&& obj, std::false_type) {
            obj_ = new T(std::forward<T>(obj));
            del_ = &deleter_<T>;
        }

        template<typename T>
        void init_obj_(T&& obj, std::true_type) {
            // Small object optimization
            obj_ = new ((void*)inplace_) T(std::forward<T>(obj));
            del_ = &inplace_deleter_<T>;
            mov_ = &inplace_mover_<T>;
        }

        template<typename T>
        void init_obj_(T&& obj) {
            init_obj_(std::forward<T>(obj),
                std::integral_constant<bool, sizeof(T) <= max_small_object_size>{});
        }

        template<typename T, typename FT, FT F>
        void init_fun_(std::integral_constant<FT,F>) {
            using RT = typename std::remove_reference<T>::type;
            wfun_ = &template_wrapper_<RT, FT, F>;
        }

        template<typename T, typename M>
        void init_fun_(M fun) {
            fun_ = *reinterpret_cast<void**>(&fun);
            using RT = typename std::remove_reference<T>::type;
            wfun_ = &wrapper_<RT, M>;
        }

        template<typename T, typename M>
        void create_(T&& obj, M&& fun) {
            init_obj_(std::forward<T>(obj));
            init_fun_<T>(std::forward<M>(fun));
        }

        template<typename T>
        void create_(T&& obj) {
            init_obj_(std::forward<T>(obj));
            using RT = typename std::remove_reference<T>::type;
            init_fun_<T>(std::integral_constant<decltype(&RT::operator()),&RT::operator()>());
        }
    };
}

#define make_delegate(obj,func) ctl::delegate<ctl::get_signature<decltype(func)>>( \
    obj, std::integral_constant<decltype(func),func>{})

#endif
<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Common.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 */

#include "Common.h"

using namespace std;
using namespace dev;

namespace dev
{

char const* Version = "0.9.0";

}

<commit_msg>Version bump.<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Common.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 */

#include "Common.h"

using namespace std;
using namespace dev;

namespace dev
{

char const* Version = "0.9.1";

}

<|endoftext|>


<commit_before>/*
   fskit: a library for creating multi-threaded in-RAM filesystems
   Copyright (C) 2014  Jude Nelson

   This program is dual-licensed: you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License version 3 or later as
   published by the Free Software Foundation. For the terms of this
   license, see LICENSE.LGPLv3+ or <http://www.gnu.org/licenses/>.

   You are free to use this program under the terms of the GNU Lesser General
   Public License, but WITHOUT ANY WARRANTY; without even the implied
   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   See the GNU Lesser General Public License for more details.

   Alternatively, you are free to use this program under the terms of the
   Internet Software Consortium License, but WITHOUT ANY WARRANTY; without
   even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   For the terms of this license, see LICENSE.ISC or
   <http://www.isc.org/downloads/software-support-policy/isc-license/>.
*/

#include <fskit/deferred.h>
#include <fskit/path.h>
#include <fskit/wq.h>
#include <fskit/util.h>

// fskit remove_all context
struct fskit_deferred_remove_all_ctx {

   struct fskit_core* core;
   char* fs_path;               // path to the (root) entry
   struct fskit_entry* child;   // only used for removing a single entry
   fskit_entry_set* children;   // only used for removing a tree of entries
};

// helper to asynchronously reap a directory of inodes, recursively.
// used by fskit_entry_remove_all; invoked by the core deferred work queue
static int fskit_deferred_remove_all_cb( struct fskit_wreq* wreq, void* cls ) {

   struct fskit_deferred_remove_all_ctx* ctx = (struct fskit_deferred_remove_all_ctx*)cls;
   int rc = 0;

   fskit_debug("DEFERRED: garbage-collect all children of %s\n", ctx->fs_path);

   rc = fskit_detach_all( ctx->core, ctx->fs_path, ctx->children );

   if( rc != 0 ) {
      fskit_error("LEAK: fskit_detach_all(%s) rc = %d\n", ctx->fs_path, rc );
   }

   safe_free( ctx->fs_path );
   safe_delete( ctx->children );
   safe_free( ctx );

   return 0;
}

// helper to asynchronously try to reap a node, ensuring that if it's not open, it gets destroyed.
// used by fskit_entry_remove; invoked by the core deferred work queue
static int fskit_deferred_remove_cb( struct fskit_wreq* wreq, void* cls ) {

   struct fskit_deferred_remove_all_ctx* ctx = (struct fskit_deferred_remove_all_ctx*)cls;
   int rc = 0;

   fskit_debug("DEFERRED: garbage-collect %s\n", ctx->fs_path);

   // NOTE: safe, since in fskit_entry_remove we incremented the open count.
   // the child will not have been freed yet.
   fskit_entry_wlock( ctx->child );

   ctx->child->open_count--;

   rc = fskit_entry_try_destroy_and_free( ctx->core, ctx->fs_path, ctx->child );
   if( rc >= 0 ) {

      // success!
      if( rc == 0 ) {
         // not destroyed
         fskit_entry_unlock( ctx->child );
      }
      else {
         // destroyed
         rc = 0;
      }
   }
   else {
      fskit_error("LEAK: fskit_entry_try_destroy_and_free(%s) rc = %d\n", ctx->fs_path, rc );
   }

   return 0;
}

// Mark an inode as removed from the filesystem.
// This will cause all subsequent path resolutions on this inode to fail, regardless of its parents.
// The inode will be garbage-collected asynchronously
// child must be write-locked.
// return 0 on success
// return -EISDIR if the child is a directory (use fskit_entry_remove_all for directories)
// NOTE: child must be write-locked
int fskit_deferred_remove( struct fskit_core* core, char const* child_path, struct fskit_entry* child ) {

   struct fskit_deferred_remove_all_ctx* ctx = NULL;
   struct fskit_wreq work;
   int rc = 0;

   if( child->type == FSKIT_ENTRY_TYPE_DIR ) {
      return -EISDIR;
   }

   ctx = CALLOC_LIST( struct fskit_deferred_remove_all_ctx, 1 );
   if( ctx == NULL ) {
      return -ENOMEM;
   }

   // queue for destruction
   ctx->core = core;
   ctx->fs_path = strdup( child_path );
   ctx->child = child;

   if( ctx->fs_path == NULL ) {
      safe_free( ctx );
      return -ENOMEM;
   }

   // mark the child as dead--it won't be resolvable again
   child->link_count = 0;
   child->deletion_in_progress = true;

   // reference the child--don't want it to disappear on us
   child->open_count++;

   // defer deletion
   fskit_wreq_init( &work, fskit_deferred_remove_cb, ctx, 0 );

   rc = fskit_wq_add( core->deferred, &work );
   if( rc != 0 ) {
      // not running, or OOM
      fskit_error("fskit_wq_add( fskit_deferred_remove_cb, %s ) rc = %d\n", child_path, rc );
      return -EAGAIN;
   }

   return 0;
}

// Mark a directory and all of its children as removed from the filesystem.
// This will cause all subsequent path resolutions on this inode and its children to fail.
// They will be garbage-collected asynchronously.
// return 0 on success
// return -ENOTDIR if child is not a directory
// NOTE: child must be write-locked
int fskit_deferred_remove_all( struct fskit_core* core, char const* child_path, struct fskit_entry* child ) {

   struct fskit_deferred_remove_all_ctx* ctx = NULL;
   struct fskit_entry* parent = NULL;
   struct fskit_wreq work;
   int rc = 0;

   if( child->type != FSKIT_ENTRY_TYPE_DIR ) {
      return -ENOTDIR;
   }

   parent = fskit_entry_set_find_name( child->children, ".." );
   if( parent == NULL ) {
      // malformatted child
      return -EINVAL;
   }

   ctx = CALLOC_LIST( struct fskit_deferred_remove_all_ctx, 1 );
   if( ctx == NULL ) {
      return -ENOMEM;
   }

   // queue all children for destruction
   ctx->core = core;
   ctx->fs_path = strdup( child_path );
   ctx->children = child->children;

   if( ctx->fs_path == NULL ) {
      safe_free( ctx );
      return -ENOMEM;
   }

   // make sure we can't resolve the children again
   child->children = fskit_entry_set_new( child, parent );

   if( child->children == NULL ) {
      safe_free( ctx->fs_path );
      safe_free( ctx );
      return -ENOMEM;
   }

   // mark the child as dead--it won't be resolvable again
   child->link_count = 0;
   child->deletion_in_progress = true;

   // defer deletion
   fskit_wreq_init( &work, fskit_deferred_remove_all_cb, ctx, 0 );

   rc = fskit_wq_add( core->deferred, &work );
   if( rc != 0 ) {
      // not running, or OOM
      fskit_error("fskit_wq_add( fskit_deferred_remove_all_cb, %s ) rc = %d\n", child_path, rc );
      return -EAGAIN;
   }

   return 0;
}
<commit_msg>On deferred inode deletion, use the new fskit_unlink_nolock() method to run the user's detach method and remove the inode from its parent without deadlocking.<commit_after>/*
   fskit: a library for creating multi-threaded in-RAM filesystems
   Copyright (C) 2014  Jude Nelson

   This program is dual-licensed: you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License version 3 or later as
   published by the Free Software Foundation. For the terms of this
   license, see LICENSE.LGPLv3+ or <http://www.gnu.org/licenses/>.

   You are free to use this program under the terms of the GNU Lesser General
   Public License, but WITHOUT ANY WARRANTY; without even the implied
   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   See the GNU Lesser General Public License for more details.

   Alternatively, you are free to use this program under the terms of the
   Internet Software Consortium License, but WITHOUT ANY WARRANTY; without
   even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   For the terms of this license, see LICENSE.ISC or
   <http://www.isc.org/downloads/software-support-policy/isc-license/>.
*/

#include <fskit/deferred.h>
#include <fskit/path.h>
#include <fskit/wq.h>
#include <fskit/unlink.h>
#include <fskit/util.h>

// fskit remove_all context
struct fskit_deferred_remove_all_ctx {

   struct fskit_core* core;
   char* fs_path;               // path to the (root) entry
   struct fskit_entry* child;   // only used for removing a single entry
   fskit_entry_set* children;   // only used for removing a tree of entries
};

// helper to asynchronously reap a directory of inodes, recursively.
// used by fskit_entry_remove_all; invoked by the core deferred work queue
static int fskit_deferred_remove_all_cb( struct fskit_wreq* wreq, void* cls ) {

   struct fskit_deferred_remove_all_ctx* ctx = (struct fskit_deferred_remove_all_ctx*)cls;
   int rc = 0;

   fskit_debug("DEFERRED: garbage-collect all children of %s\n", ctx->fs_path);

   rc = fskit_detach_all( ctx->core, ctx->fs_path, ctx->children );

   if( rc != 0 ) {
      fskit_error("LEAK: fskit_detach_all(%s) rc = %d\n", ctx->fs_path, rc );
   }

   safe_free( ctx->fs_path );
   safe_delete( ctx->children );
   safe_free( ctx );

   return 0;
}

// helper to asynchronously try to reap a node, ensuring that if it's not open, it gets destroyed.
// used by fskit_entry_remove; invoked by the core deferred work queue
static int fskit_deferred_remove_cb( struct fskit_wreq* wreq, void* cls ) {

   struct fskit_deferred_remove_all_ctx* ctx = (struct fskit_deferred_remove_all_ctx*)cls;
   int rc = 0;

   fskit_debug("DEFERRED: garbage-collect %s\n", ctx->fs_path);

   // NOTE: safe, since in fskit_entry_remove we incremented the open count.
   // the child will not have been freed yet.
   fskit_entry_wlock( ctx->child );

   ctx->child->open_count--;

   rc = fskit_unlink_nolock( ctx->core, ctx->fs_path, 0, 0 );
   if( rc < 0 ) {

      fskit_error("fskit_unlink(%s) rc = %d\n", ctx->fs_path, rc);
      fskit_entry_unlock( ctx->child );
   }
   if( rc == 0 ) {

      // not destroyed
      fskit_entry_unlock( ctx->child );
   }
   else {

      // destroyed
      rc = 0;
   }

   safe_free( ctx->fs_path );
   safe_free( ctx );

   return 0;
}

// Mark an inode as removed from the filesystem.
// This will cause all subsequent path resolutions on this inode to fail, regardless of its parents.
// The inode will be garbage-collected asynchronously
// child must be write-locked.
// return 0 on success
// return -EISDIR if the child is a directory (use fskit_entry_remove_all for directories)
// NOTE: child must be write-locked
int fskit_deferred_remove( struct fskit_core* core, char const* child_path, struct fskit_entry* child ) {

   struct fskit_deferred_remove_all_ctx* ctx = NULL;
   struct fskit_wreq work;
   int rc = 0;

   if( child->type == FSKIT_ENTRY_TYPE_DIR ) {
      return -EISDIR;
   }

   ctx = CALLOC_LIST( struct fskit_deferred_remove_all_ctx, 1 );
   if( ctx == NULL ) {
      return -ENOMEM;
   }

   // queue for destruction
   ctx->core = core;
   ctx->fs_path = strdup( child_path );
   ctx->child = child;

   if( ctx->fs_path == NULL ) {
      safe_free( ctx );
      return -ENOMEM;
   }

   // mark the child as dead--it won't be resolvable again
   child->deletion_in_progress = true;

   // reference the child--don't want it to disappear on us
   child->open_count++;

   // defer deletion
   fskit_wreq_init( &work, fskit_deferred_remove_cb, ctx, 0 );

   rc = fskit_wq_add( core->deferred, &work );
   if( rc != 0 ) {
      // not running, or OOM
      fskit_error("fskit_wq_add( fskit_deferred_remove_cb, %s ) rc = %d\n", child_path, rc );
      return -EAGAIN;
   }

   return 0;
}

// Mark a directory and all of its children as removed from the filesystem.
// This will cause all subsequent path resolutions on this inode and its children to fail.
// They will be garbage-collected asynchronously.
// return 0 on success
// return -ENOTDIR if child is not a directory
// NOTE: child must be write-locked
int fskit_deferred_remove_all( struct fskit_core* core, char const* child_path, struct fskit_entry* child ) {

   struct fskit_deferred_remove_all_ctx* ctx = NULL;
   struct fskit_entry* parent = NULL;
   struct fskit_wreq work;
   int rc = 0;

   if( child->type != FSKIT_ENTRY_TYPE_DIR ) {
      return -ENOTDIR;
   }

   parent = fskit_entry_set_find_name( child->children, ".." );
   if( parent == NULL ) {
      // malformatted child
      return -EINVAL;
   }

   ctx = CALLOC_LIST( struct fskit_deferred_remove_all_ctx, 1 );
   if( ctx == NULL ) {
      return -ENOMEM;
   }

   // queue all children for destruction
   ctx->core = core;
   ctx->fs_path = strdup( child_path );
   ctx->children = child->children;

   if( ctx->fs_path == NULL ) {
      safe_free( ctx );
      return -ENOMEM;
   }

   // make sure we can't resolve the children again
   child->children = fskit_entry_set_new( child, parent );

   if( child->children == NULL ) {
      safe_free( ctx->fs_path );
      safe_free( ctx );
      return -ENOMEM;
   }

   // mark the child as dead--it won't be resolvable again
   child->link_count = 0;
   child->deletion_in_progress = true;

   // defer deletion
   fskit_wreq_init( &work, fskit_deferred_remove_all_cb, ctx, 0 );

   rc = fskit_wq_add( core->deferred, &work );
   if( rc != 0 ) {
      // not running, or OOM
      fskit_error("fskit_wq_add( fskit_deferred_remove_all_cb, %s ) rc = %d\n", child_path, rc );
      return -EAGAIN;
   }

   return 0;
}
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2010-2012, Willow Garage, Inc.
 *
 *  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 Willow Garage, Inc. 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.
 *
 */

#include "pcl/common/time_trigger.h"
#include "pcl/common/time.h"
#include <iostream>

//////////////////////////////////////////////////////////////////////////////////////////////
pcl::TimeTrigger::TimeTrigger (double interval, const callback_type& callback)
: callbacks_ ()
, interval_ (interval)
, quit_ (false)
, running_ (false)
, timer_thread_ (boost::bind (&TimeTrigger::thread_function, this))
, condition_ ()
, condition_mutex_ ()
{
  registerCallback (callback);
}

//////////////////////////////////////////////////////////////////////////////////////////////
pcl::TimeTrigger::TimeTrigger (double interval)
: callbacks_ ()
, interval_ (interval)
, quit_ (false)
, running_ (false)
, timer_thread_ (boost::bind (&TimeTrigger::thread_function, this))
, condition_ ()
, condition_mutex_ ()
{
}

//////////////////////////////////////////////////////////////////////////////////////////////
pcl::TimeTrigger::~TimeTrigger ()
{
  boost::unique_lock<boost::mutex> lock (condition_mutex_);
  quit_ = true;
  condition_.notify_all ();
  lock.unlock ();

  timer_thread_.join ();
}

//////////////////////////////////////////////////////////////////////////////////////////////
boost::signals2::connection
pcl::TimeTrigger::registerCallback (const callback_type& callback)
{
  boost::unique_lock<boost::mutex> lock (condition_mutex_);
  return (callbacks_.connect (callback));
}

//////////////////////////////////////////////////////////////////////////////////////////////
void
pcl::TimeTrigger::setInterval (double interval_seconds)
{
  boost::unique_lock<boost::mutex> lock (condition_mutex_);
  interval_ = interval_seconds;
  // notify, since we could switch from a large interval to a shorter one -> interrupt waiting for timeout!
  condition_.notify_all ();
}

//////////////////////////////////////////////////////////////////////////////////////////////
void
pcl::TimeTrigger::start ()
{
  boost::unique_lock<boost::mutex> lock (condition_mutex_);
  if (!running_)
  {
    running_ = true;
    condition_.notify_all ();
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////
void
pcl::TimeTrigger::stop ()
{
  boost::unique_lock<boost::mutex> lock (condition_mutex_);
  if (running_)
  {
    running_ = false;
    condition_.notify_all ();
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////
void
pcl::TimeTrigger::thread_function ()
{
  static double time = 0;
  while (!quit_)
  {
    time = getTime ();
    boost::unique_lock<boost::mutex> lock (condition_mutex_);
    if (!running_)
      condition_.wait (lock); // wait util start is called or destructor is called
    else
    {
      callbacks_();
      double rest = interval_ + time - getTime ();
      condition_.timed_wait (lock, boost::posix_time::microseconds ((int64_t) (rest * 1000000)));
    }
  }
}

<commit_msg>Windows fix<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2010-2012, Willow Garage, Inc.
 *
 *  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 Willow Garage, Inc. 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.
 *
 */

#include "pcl/common/time_trigger.h"
#include "pcl/common/time.h"
#include <iostream>

//////////////////////////////////////////////////////////////////////////////////////////////
pcl::TimeTrigger::TimeTrigger (double interval, const callback_type& callback)
: callbacks_ ()
, interval_ (interval)
, quit_ (false)
, running_ (false)
, timer_thread_ ()
, condition_ ()
, condition_mutex_ ()
{
  timer_thread_ = boost::thread (boost::bind (&TimeTrigger::thread_function, this));
  registerCallback (callback);
}

//////////////////////////////////////////////////////////////////////////////////////////////
pcl::TimeTrigger::TimeTrigger (double interval)
: callbacks_ ()
, interval_ (interval)
, quit_ (false)
, running_ (false)
, timer_thread_ ()
, condition_ ()
, condition_mutex_ ()
{
  timer_thread_ = boost::thread (boost::bind (&TimeTrigger::thread_function, this));
}

//////////////////////////////////////////////////////////////////////////////////////////////
pcl::TimeTrigger::~TimeTrigger ()
{
  boost::unique_lock<boost::mutex> lock (condition_mutex_);
  quit_ = true;
  condition_.notify_all ();
  lock.unlock ();

  timer_thread_.join ();
}

//////////////////////////////////////////////////////////////////////////////////////////////
boost::signals2::connection
pcl::TimeTrigger::registerCallback (const callback_type& callback)
{
  boost::unique_lock<boost::mutex> lock (condition_mutex_);
  return (callbacks_.connect (callback));
}

//////////////////////////////////////////////////////////////////////////////////////////////
void
pcl::TimeTrigger::setInterval (double interval_seconds)
{
  boost::unique_lock<boost::mutex> lock (condition_mutex_);
  interval_ = interval_seconds;
  // notify, since we could switch from a large interval to a shorter one -> interrupt waiting for timeout!
  condition_.notify_all ();
}

//////////////////////////////////////////////////////////////////////////////////////////////
void
pcl::TimeTrigger::start ()
{
  boost::unique_lock<boost::mutex> lock (condition_mutex_);
  if (!running_)
  {
    running_ = true;
    condition_.notify_all ();
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////
void
pcl::TimeTrigger::stop ()
{
  boost::unique_lock<boost::mutex> lock (condition_mutex_);
  if (running_)
  {
    running_ = false;
    condition_.notify_all ();
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////
void
pcl::TimeTrigger::thread_function ()
{
  static double time = 0;
  while (!quit_)
  {
    time = getTime ();
    boost::unique_lock<boost::mutex> lock (condition_mutex_);
    if (!running_)
      condition_.wait (lock); // wait util start is called or destructor is called
    else
    {
      callbacks_();
      double rest = interval_ + time - getTime ();
      condition_.timed_wait (lock, boost::posix_time::microseconds ((int64_t) (rest * 1000000)));
    }
  }
}

<|endoftext|>


<commit_before>#include "vtkObjectFactory.h"
#include "vtkObjectFactoryCollection.h"
#include "vtkDynamicLoader.h"
#include "vtkDirectory.h"
#include "vtkVersion.h"

vtkObjectFactoryCollection* vtkObjectFactory::RegisterdFactories = 0;

// Create an instance of a named vtk object using the loaded
// factories

vtkObject* vtkObjectFactory::CreateInstance(const char* vtkclassname)
{
  if(!vtkObjectFactory::RegisterdFactories)
    {
    vtkObjectFactory::Init();
    }

  vtkObjectFactory* factory = 0;

  for(vtkObjectFactory::RegisterdFactories->InitTraversal();
      (factory = vtkObjectFactory::RegisterdFactories->GetNextItem());)
    {
    vtkObject* newobject = factory->CreateObject(vtkclassname);
    if(newobject)
      {
      return newobject;
      }
    }
  return 0;
}

// A one time initialization method.
void vtkObjectFactory::Init()
{
  // Don't do anything if we are already initialized
  if(vtkObjectFactory::RegisterdFactories)
    {
    return;
    }

  vtkObjectFactory::RegisterdFactories = vtkObjectFactoryCollection::New();
  vtkObjectFactory::RegisterDefaults();
  vtkObjectFactory::LoadDynamicFactories();
}

// Register any factories that are always present in VTK like
// the OpenGL factory, currently this is not done.

void vtkObjectFactory::RegisterDefaults()
{
}

// Load all libraries in VTK_AUTOLOAD_PATH

void vtkObjectFactory::LoadDynamicFactories()
{
  // follow PATH convensions
#ifdef _WIN32
  char PathSeparator = ';';
#else
  char PathSeparator = ':';
#endif
  char* LoadPath = getenv("VTK_AUTOLOAD_PATH");
  if(LoadPath == 0)
    {
    return;
    }

  char* CurrentPath = new char[strlen(LoadPath)+1];
  char* SeparatorPosition = LoadPath; // initialize to env variable
  while(SeparatorPosition)
  {
    int PathLength =0;
    // find PathSeparator in LoadPath
    SeparatorPosition = strchr(LoadPath, PathSeparator);
    // if not found then use the whole string
    if(SeparatorPosition == 0)
    {
      PathLength = strlen(LoadPath);
    }
    else
    {
      PathLength = SeparatorPosition - LoadPath;
    }
    // copy the path out of LoadPath into CurrentPath
    strncpy(CurrentPath, LoadPath, PathLength);
    // add a null terminator
    CurrentPath[PathLength] = 0;
    // Get ready for the next path
    LoadPath = SeparatorPosition+1;
    // Load the libraries in the current path
    vtkObjectFactory::LoadLibrariesInPath(CurrentPath);
  }
  // clean up memory
  delete [] CurrentPath;
}

// A file scope helper function to concat path and file into
// a full path
static char* CreateFullPath(const char* path, const char* file)
{
  int lenpath = strlen(path);
  char* ret = new char[lenpath + strlen(file)+2];
#ifdef _WIN32
  const char sep = '\\';
#else
  const char sep = '/';
#endif
  // make sure the end of path is a separator
  strcpy(ret, path);
  if(ret[lenpath-1] != sep)
    {
    ret[lenpath] = sep;
    ret[lenpath+1] = 0;
    }
  strcat(ret, file);
  return ret;
}

// A file scope typedef to make the cast code to the load
// function cleaner to read.
typedef vtkObjectFactory* (* VTK_LOAD_FUNCTION)();

void vtkObjectFactory::LoadLibrariesInPath(const char* path)
{
  vtkDirectory* dir = vtkDirectory::New();
  if(!dir->Open(path))
    {
    return;
    }

  // Attempt to load each file in the directory as a shared library
  for(int i = 0; i < dir->GetNumberOfFiles(); i++)
    {
    const char* file = dir->GetFile(i);
    char* fullpath = CreateFullPath(path, file);
    vtkLibHandle lib = vtkDynamicLoader::OpenLibrary(fullpath);
    if(lib)
      {
      // Look for the symbol vtkLoad in the library
      VTK_LOAD_FUNCTION loadfunction
	= (VTK_LOAD_FUNCTION)vtkDynamicLoader::GetSymbolAddress(lib, "vtkLoad");
      // if the symbol is found call it to create the factory
      // from the library
      if(loadfunction)
	{
	vtkObjectFactory* newfactory = (*loadfunction)();
	// initialize class members if load worked
	newfactory->LibraryHandle = (void*)lib;
	newfactory->LibraryPath = strcpy(new char[strlen(fullpath)+1], fullpath);
	newfactory->LibraryDate = 0; // unused for now...
	vtkObjectFactory::RegisterFactory(newfactory);
	}
      }
    delete [] fullpath;
    }
}

// Recheck the VTK_AUTOLOAD_PATH for new libraries

void vtkObjectFactory::ReHash()
{
  vtkObjectFactory::UnRegisterAllFactories();
  vtkObjectFactory::Init();
}

// initialize class members
vtkObjectFactory::vtkObjectFactory()
:LibraryHandle(0), LibraryPath(0), LibraryDate(0)
{
}

// Unload the library and free the path string
vtkObjectFactory::~vtkObjectFactory()
{
  delete [] this->LibraryPath;
  vtkDynamicLoader::CloseLibrary((vtkLibHandle)this->LibraryHandle);
}

// Add a factory to the registerd list
void vtkObjectFactory::RegisterFactory(vtkObjectFactory* factory)
{
  if(factory->LibraryHandle == 0)
    {
    const char* nonDynamicName = "Non-Dynamic loaded vtkObjectFactory";
    factory->LibraryPath = strcpy(new char[strlen(nonDynamicName)+1],
				  nonDynamicName);
    }
  if(strcmp(factory->GetVTKSourceVersion(),
	    vtkVersion::GetVTKSourceVersion()) != 0)
    {
    vtkGenericWarningMacro(<< "Possible incompatible factory load:"
    << "\nRunning vtk version :\n" << vtkVersion::GetVTKSourceVersion()
    << "\nLoaded Factory version:\n" << factory->GetVTKSourceVersion()
    << "\nLoading factory: " << factory->LibraryPath << "\n");
    }
  vtkObjectFactory::Init();
  vtkObjectFactory::RegisterdFactories->AddItem(factory);
}

void vtkObjectFactory::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkObject::PrintSelf(os, indent);
  os << indent
     << "vtk Object Factory loaded from " << this->LibraryPath << "\n";
}

void vtkObjectFactory::UnRegisterFactory(vtkObjectFactory* factory)
{
  vtkObjectFactory::RegisterdFactories->RemoveItem(factory);
  factory->Delete();
}

// unregister all factories and delete the RegisterdFactories list
void vtkObjectFactory::UnRegisterAllFactories()
{
  vtkObjectFactory* factory = 0;

  for(vtkObjectFactory::RegisterdFactories->InitTraversal();
      (factory = vtkObjectFactory::RegisterdFactories->GetNextItem());)
    {
    factory->Delete();
    }
  vtkObjectFactory::RegisterdFactories->RemoveAllItems();
  vtkObjectFactory::RegisterdFactories->Delete();
  vtkObjectFactory::RegisterdFactories = 0;
}

<commit_msg>ENH: change factory to only attempt to load files that have the shared library extension in the name<commit_after>#include "vtkObjectFactory.h"
#include "vtkObjectFactoryCollection.h"
#include "vtkDynamicLoader.h"
#include "vtkDirectory.h"
#include "vtkVersion.h"
#include <stdlib.h>
#include <ctype.h>

vtkObjectFactoryCollection* vtkObjectFactory::RegisterdFactories = 0;

// Create an instance of a named vtk object using the loaded
// factories

vtkObject* vtkObjectFactory::CreateInstance(const char* vtkclassname)
{
  if(!vtkObjectFactory::RegisterdFactories)
    {
    vtkObjectFactory::Init();
    }

  vtkObjectFactory* factory = 0;

  for(vtkObjectFactory::RegisterdFactories->InitTraversal();
      (factory = vtkObjectFactory::RegisterdFactories->GetNextItem());)
    {
    vtkObject* newobject = factory->CreateObject(vtkclassname);
    if(newobject)
      {
      return newobject;
      }
    }
  return 0;
}

// A one time initialization method.
void vtkObjectFactory::Init()
{
  // Don't do anything if we are already initialized
  if(vtkObjectFactory::RegisterdFactories)
    {
    return;
    }

  vtkObjectFactory::RegisterdFactories = vtkObjectFactoryCollection::New();
  vtkObjectFactory::RegisterDefaults();
  vtkObjectFactory::LoadDynamicFactories();
}

// Register any factories that are always present in VTK like
// the OpenGL factory, currently this is not done.

void vtkObjectFactory::RegisterDefaults()
{
}

// Load all libraries in VTK_AUTOLOAD_PATH

void vtkObjectFactory::LoadDynamicFactories()
{
  // follow PATH convensions
#ifdef _WIN32
  char PathSeparator = ';';
#else
  char PathSeparator = ':';
#endif
  char* LoadPath = getenv("VTK_AUTOLOAD_PATH");
  if(LoadPath == 0)
    {
    return;
    }

  char* CurrentPath = new char[strlen(LoadPath)+1];
  char* SeparatorPosition = LoadPath; // initialize to env variable
  while(SeparatorPosition)
  {
    int PathLength =0;
    // find PathSeparator in LoadPath
    SeparatorPosition = strchr(LoadPath, PathSeparator);
    // if not found then use the whole string
    if(SeparatorPosition == 0)
    {
      PathLength = strlen(LoadPath);
    }
    else
    {
      PathLength = SeparatorPosition - LoadPath;
    }
    // copy the path out of LoadPath into CurrentPath
    strncpy(CurrentPath, LoadPath, PathLength);
    // add a null terminator
    CurrentPath[PathLength] = 0;
    // Get ready for the next path
    LoadPath = SeparatorPosition+1;
    // Load the libraries in the current path
    vtkObjectFactory::LoadLibrariesInPath(CurrentPath);
  }
  // clean up memory
  delete [] CurrentPath;
}

// A file scope helper function to concat path and file into
// a full path
static char* CreateFullPath(const char* path, const char* file)
{
  int lenpath = strlen(path);
  char* ret = new char[lenpath + strlen(file)+2];
#ifdef _WIN32
  const char sep = '\\';
#else
  const char sep = '/';
#endif
  // make sure the end of path is a separator
  strcpy(ret, path);
  if(ret[lenpath-1] != sep)
    {
    ret[lenpath] = sep;
    ret[lenpath+1] = 0;
    }
  strcat(ret, file);
  return ret;
}

// A file scope typedef to make the cast code to the load
// function cleaner to read.
typedef vtkObjectFactory* (* VTK_LOAD_FUNCTION)();

// A file scoped function to determine if a file has
// the shared library extension in its name, this converts name to lower
// case before the compare, vtkDynamicLoader always uses
// lower case for LibExtension values.

inline int vtkNameIsSharedLibrary(const char* name)
{
  int len = strlen(name);
  char* copy = new char[len+1];

  for(int i = 0; i < len; i++)
    {
    copy[i] = tolower(name[i]);
    }
  char* ret = strstr(copy, vtkDynamicLoader::LibExtension());
  delete [] copy;
  return (int)ret;
}

void vtkObjectFactory::LoadLibrariesInPath(const char* path)
{
  vtkDirectory* dir = vtkDirectory::New();
  if(!dir->Open(path))
    {
    return;
    }

  // Attempt to load each file in the directory as a shared library
  for(int i = 0; i < dir->GetNumberOfFiles(); i++)
    {
    const char* file = dir->GetFile(i);
    // try to make sure the file has at least the extension
    // for a shared library in it.
    if(vtkNameIsSharedLibrary(file))
      {
      vtkGenericWarningMacro("Attempt to load dll: " << file);
      char* fullpath = CreateFullPath(path, file);
      vtkLibHandle lib = vtkDynamicLoader::OpenLibrary(fullpath);
      if(lib)
	{
	// Look for the symbol vtkLoad in the library
	VTK_LOAD_FUNCTION loadfunction
	  = (VTK_LOAD_FUNCTION)vtkDynamicLoader::GetSymbolAddress(lib, "vtkLoad");
	// if the symbol is found call it to create the factory
	// from the library
	if(loadfunction)
	  {
	  vtkObjectFactory* newfactory = (*loadfunction)();
	  // initialize class members if load worked
	  newfactory->LibraryHandle = (void*)lib;
	  newfactory->LibraryPath = strcpy(new char[strlen(fullpath)+1], fullpath);
	  newfactory->LibraryDate = 0; // unused for now...
	  vtkObjectFactory::RegisterFactory(newfactory);
	  }
	}
      delete [] fullpath;
      }
    }
}

// Recheck the VTK_AUTOLOAD_PATH for new libraries

void vtkObjectFactory::ReHash()
{
  vtkObjectFactory::UnRegisterAllFactories();
  vtkObjectFactory::Init();
}

// initialize class members
vtkObjectFactory::vtkObjectFactory()
:LibraryHandle(0), LibraryPath(0), LibraryDate(0)
{
}

// Unload the library and free the path string
vtkObjectFactory::~vtkObjectFactory()
{
  delete [] this->LibraryPath;
  vtkDynamicLoader::CloseLibrary((vtkLibHandle)this->LibraryHandle);
}

// Add a factory to the registerd list
void vtkObjectFactory::RegisterFactory(vtkObjectFactory* factory)
{
  if(factory->LibraryHandle == 0)
    {
    const char* nonDynamicName = "Non-Dynamic loaded vtkObjectFactory";
    factory->LibraryPath = strcpy(new char[strlen(nonDynamicName)+1],
				  nonDynamicName);
    }
  if(strcmp(factory->GetVTKSourceVersion(),
	    vtkVersion::GetVTKSourceVersion()) != 0)
    {
    vtkGenericWarningMacro(<< "Possible incompatible factory load:"
    << "\nRunning vtk version :\n" << vtkVersion::GetVTKSourceVersion()
    << "\nLoaded Factory version:\n" << factory->GetVTKSourceVersion()
    << "\nLoading factory: " << factory->LibraryPath << "\n");
    }
  vtkObjectFactory::Init();
  vtkObjectFactory::RegisterdFactories->AddItem(factory);
}

void vtkObjectFactory::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkObject::PrintSelf(os, indent);
  os << indent
     << "vtk Object Factory loaded from " << this->LibraryPath << "\n";
}

void vtkObjectFactory::UnRegisterFactory(vtkObjectFactory* factory)
{
  vtkObjectFactory::RegisterdFactories->RemoveItem(factory);
  factory->Delete();
}

// unregister all factories and delete the RegisterdFactories list
void vtkObjectFactory::UnRegisterAllFactories()
{
  vtkObjectFactory* factory = 0;

  for(vtkObjectFactory::RegisterdFactories->InitTraversal();
      (factory = vtkObjectFactory::RegisterdFactories->GetNextItem());)
    {
    factory->Delete();
    }
  vtkObjectFactory::RegisterdFactories->RemoveAllItems();
  vtkObjectFactory::RegisterdFactories->Delete();
  vtkObjectFactory::RegisterdFactories = 0;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
 * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of EITHER:                                  *
 *   (1) The GNU Lesser General Public License as published by the Free  *
 *       Software Foundation; either version 2.1 of the License, or (at  *
 *       your option) any later version. The text of the GNU Lesser      *
 *       General Public License is included with this library in the     *
 *       file LICENSE.TXT.                                               *
 *   (2) The BSD-style license that is included with this library in     *
 *       the file LICENSE-BSD.TXT.                                       *
 *                                                                       *
 * This library is distributed in the hope that it will be useful,       *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
 * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
 *                                                                       *
 *************************************************************************/

#include <ode/config.h>
#include <ode/mass.h>
#include <ode/odemath.h>
#include <ode/matrix.h>

#define _I(i,j) I[(i)*4+(j)]

// return 1 if ok, 0 if bad

static int checkMass (dMass *m)
{
  int i;

  if (m->mass <= 0) {
    dDEBUGMSG ("mass must be > 0");
    return 0;
  }
  if (!dIsPositiveDefinite (m->I,3)) {
    dDEBUGMSG ("inertia must be positive definite");
    return 0;
  }

  // verify that the center of mass position is consistent with the mass
  // and inertia matrix. this is done by checking that the inertia around
  // the center of mass is also positive definite. from the comment in
  // dMassTranslate(), if the body is translated so that its center of mass
  // is at the point of reference, then the new inertia is:
  //   I + mass*crossmat(c)^2
  // note that requiring this to be positive definite is exactly equivalent
  // to requiring that the spatial inertia matrix
  //   [ mass*eye(3,3)   M*crossmat(c)^T ]
  //   [ M*crossmat(c)   I               ]
  // is positive definite, given that I is PD and mass>0. see the theorem
  // about partitioned PD matrices for proof.

  dMatrix3 I2,chat;
  dSetZero (chat,12);
  dCROSSMAT (chat,m->c,4,+,-);
  dMULTIPLY0_333 (I2,chat,chat);
  for (i=0; i<3; i++) I2[i] = m->I[i] + m->mass*I2[i];
  for (i=4; i<7; i++) I2[i] = m->I[i] + m->mass*I2[i];
  for (i=8; i<11; i++) I2[i] = m->I[i] + m->mass*I2[i];
  if (!dIsPositiveDefinite (I2,3)) {
    dDEBUGMSG ("center of mass inconsistent with mass parameters");
    return 0;
  }
  return 1;
}

void dMassSetZero (dMass *m)
{
  dAASSERT (m);
  m->mass = REAL(0.0);
  dSetZero (m->c,sizeof(m->c) / sizeof(dReal));
  dSetZero (m->I,sizeof(m->I) / sizeof(dReal));
}

void dMassSetParameters (dMass *m, dReal themass,
			 dReal cgx, dReal cgy, dReal cgz,
			 dReal I11, dReal I22, dReal I33,
			 dReal I12, dReal I13, dReal I23)
{
  dAASSERT (m);
  dMassSetZero (m);
  m->mass = themass;
  m->c[0] = cgx;
  m->c[1] = cgy;
  m->c[2] = cgz;
  m->_I(0,0) = I11;
  m->_I(1,1) = I22;
  m->_I(2,2) = I33;
  m->_I(0,1) = I12;
  m->_I(0,2) = I13;
  m->_I(1,2) = I23;
  m->_I(1,0) = I12;
  m->_I(2,0) = I13;
  m->_I(2,1) = I23;
  checkMass (m);
}

void dMassSetSphere (dMass *m, dReal density, dReal radius)
{
  dMassSetSphereTotal (m, (REAL(4.0)/REAL(3.0)) * M_PI *
			  radius*radius*radius * density, radius);
}

void dMassSetSphereTotal (dMass *m, dReal total_mass, dReal radius)
{
  dAASSERT (m);
  dMassSetZero (m);
  m->mass = total_mass;
  dReal II = REAL(0.4) * total_mass * radius*radius;
  m->_I(0,0) = II;
  m->_I(1,1) = II;
  m->_I(2,2) = II;

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassSetCappedCylinder (dMass *m, dReal density, int direction,
			     dReal radius, dReal length)
{
  dReal M1,M2,Ia,Ib;
  dAASSERT (m);
  dUASSERT (direction >= 1 && direction <= 3,"bad direction number");
  dMassSetZero (m);
  M1 = M_PI*radius*radius*length*density;			// cylinder mass
  M2 = (REAL(4.0)/REAL(3.0))*M_PI*radius*radius*radius*density;	// total cap mass
  m->mass = M1+M2;
  Ia = M1*(REAL(0.25)*radius*radius + (REAL(1.0)/REAL(12.0))*length*length) +
    M2*(REAL(0.4)*radius*radius + REAL(0.375)*radius*length + REAL(0.25)*length*length);
  Ib = (M1*REAL(0.5) + M2*REAL(0.4))*radius*radius;
  m->_I(0,0) = Ia;
  m->_I(1,1) = Ia;
  m->_I(2,2) = Ia;
  m->_I(direction-1,direction-1) = Ib;

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassSetCappedCylinderTotal (dMass *m, dReal total_mass, int direction,
			     dReal a, dReal b)
{
  dMassSetCappedCylinder (m, 1.0, direction, a, b);
  dMassAdjust (m, total_mass);
}

void dMassSetCylinder (dMass *m, dReal density, int direction,
		       dReal radius, dReal length)
{
  dMassSetCylinderTotal (m, M_PI*radius*radius*length*density,
			    direction, radius, length);
}

void dMassSetCylinderTotal (dMass *m, dReal total_mass, int direction,
			    dReal radius, dReal length)
{
  dReal r2,I;
  dAASSERT (m);
  dMassSetZero (m);
  r2 = radius*radius;
  m->mass = total_mass;
  I = total_mass*(REAL(0.25)*r2 + (REAL(1.0)/REAL(12.0))*length*length);
  m->_I(0,0) = I;
  m->_I(1,1) = I;
  m->_I(2,2) = I;
  m->_I(direction-1,direction-1) = total_mass*REAL(0.5)*r2;

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassSetBox (dMass *m, dReal density,
		  dReal lx, dReal ly, dReal lz)
{
  dMassSetBoxTotal (m, lx*ly*lz*density, lx, ly, lz);
}

void dMassSetBoxTotal (dMass *m, dReal total_mass,
		       dReal lx, dReal ly, dReal lz)
{
  dAASSERT (m);
  dMassSetZero (m);
  m->mass = total_mass;
  m->_I(0,0) = total_mass/REAL(12.0) * (ly*ly + lz*lz);
  m->_I(1,1) = total_mass/REAL(12.0) * (lx*lx + lz*lz);
  m->_I(2,2) = total_mass/REAL(12.0) * (lx*lx + ly*ly);

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassAdjust (dMass *m, dReal newmass)
{
  dAASSERT (m);
  dReal scale = newmass / m->mass;
  m->mass = newmass;
  for (int i=0; i<3; i++) for (int j=0; j<3; j++) m->_I(i,j) *= scale;

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassTranslate (dMass *m, dReal x, dReal y, dReal z)
{
  // if the body is translated by `a' relative to its point of reference,
  // the new inertia about the point of reference is:
  //
  //   I + mass*(crossmat(c)^2 - crossmat(c+a)^2)
  //
  // where c is the existing center of mass and I is the old inertia.

  int i,j;
  dMatrix3 ahat,chat,t1,t2;
  dReal a[3];

  dAASSERT (m);

  // adjust inertia matrix
  dSetZero (chat,12);
  dCROSSMAT (chat,m->c,4,+,-);
  a[0] = x + m->c[0];
  a[1] = y + m->c[1];
  a[2] = z + m->c[2];
  dSetZero (ahat,12);
  dCROSSMAT (ahat,a,4,+,-);
  dMULTIPLY0_333 (t1,ahat,ahat);
  dMULTIPLY0_333 (t2,chat,chat);
  for (i=0; i<3; i++) for (j=0; j<3; j++)
    m->_I(i,j) += m->mass * (t2[i*4+j]-t1[i*4+j]);

  // ensure perfect symmetry
  m->_I(1,0) = m->_I(0,1);
  m->_I(2,0) = m->_I(0,2);
  m->_I(2,1) = m->_I(1,2);

  // adjust center of mass
  m->c[0] += x;
  m->c[1] += y;
  m->c[2] += z;

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassRotate (dMass *m, const dMatrix3 R)
{
  // if the body is rotated by `R' relative to its point of reference,
  // the new inertia about the point of reference is:
  //
  //   R * I * R'
  //
  // where I is the old inertia.

  dMatrix3 t1;
  dReal t2[3];

  dAASSERT (m);

  // rotate inertia matrix
  dMULTIPLY2_333 (t1,m->I,R);
  dMULTIPLY0_333 (m->I,R,t1);

  // ensure perfect symmetry
  m->_I(1,0) = m->_I(0,1);
  m->_I(2,0) = m->_I(0,2);
  m->_I(2,1) = m->_I(1,2);

  // rotate center of mass
  dMULTIPLY0_331 (t2,R,m->c);
  m->c[0] = t2[0];
  m->c[1] = t2[1];
  m->c[2] = t2[2];

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassAdd (dMass *a, const dMass *b)
{
  int i;
  dAASSERT (a && b);
  dReal denom = dRecip (a->mass + b->mass);
  for (i=0; i<3; i++) a->c[i] = (a->c[i]*a->mass + b->c[i]*b->mass)*denom;
  a->mass += b->mass;
  for (i=0; i<12; i++) a->I[i] += b->I[i];
}
<commit_msg>Applied 1431709: assert added<commit_after>/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
 * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of EITHER:                                  *
 *   (1) The GNU Lesser General Public License as published by the Free  *
 *       Software Foundation; either version 2.1 of the License, or (at  *
 *       your option) any later version. The text of the GNU Lesser      *
 *       General Public License is included with this library in the     *
 *       file LICENSE.TXT.                                               *
 *   (2) The BSD-style license that is included with this library in     *
 *       the file LICENSE-BSD.TXT.                                       *
 *                                                                       *
 * This library is distributed in the hope that it will be useful,       *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
 * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
 *                                                                       *
 *************************************************************************/

#include <ode/config.h>
#include <ode/mass.h>
#include <ode/odemath.h>
#include <ode/matrix.h>

#define _I(i,j) I[(i)*4+(j)]

// return 1 if ok, 0 if bad

static int checkMass (dMass *m)
{
  int i;

  if (m->mass <= 0) {
    dDEBUGMSG ("mass must be > 0");
    return 0;
  }
  if (!dIsPositiveDefinite (m->I,3)) {
    dDEBUGMSG ("inertia must be positive definite");
    return 0;
  }

  // verify that the center of mass position is consistent with the mass
  // and inertia matrix. this is done by checking that the inertia around
  // the center of mass is also positive definite. from the comment in
  // dMassTranslate(), if the body is translated so that its center of mass
  // is at the point of reference, then the new inertia is:
  //   I + mass*crossmat(c)^2
  // note that requiring this to be positive definite is exactly equivalent
  // to requiring that the spatial inertia matrix
  //   [ mass*eye(3,3)   M*crossmat(c)^T ]
  //   [ M*crossmat(c)   I               ]
  // is positive definite, given that I is PD and mass>0. see the theorem
  // about partitioned PD matrices for proof.

  dMatrix3 I2,chat;
  dSetZero (chat,12);
  dCROSSMAT (chat,m->c,4,+,-);
  dMULTIPLY0_333 (I2,chat,chat);
  for (i=0; i<3; i++) I2[i] = m->I[i] + m->mass*I2[i];
  for (i=4; i<7; i++) I2[i] = m->I[i] + m->mass*I2[i];
  for (i=8; i<11; i++) I2[i] = m->I[i] + m->mass*I2[i];
  if (!dIsPositiveDefinite (I2,3)) {
    dDEBUGMSG ("center of mass inconsistent with mass parameters");
    return 0;
  }
  return 1;
}

void dMassSetZero (dMass *m)
{
  dAASSERT (m);
  m->mass = REAL(0.0);
  dSetZero (m->c,sizeof(m->c) / sizeof(dReal));
  dSetZero (m->I,sizeof(m->I) / sizeof(dReal));
}

void dMassSetParameters (dMass *m, dReal themass,
			 dReal cgx, dReal cgy, dReal cgz,
			 dReal I11, dReal I22, dReal I33,
			 dReal I12, dReal I13, dReal I23)
{
  dAASSERT (m);
  dMassSetZero (m);
  m->mass = themass;
  m->c[0] = cgx;
  m->c[1] = cgy;
  m->c[2] = cgz;
  m->_I(0,0) = I11;
  m->_I(1,1) = I22;
  m->_I(2,2) = I33;
  m->_I(0,1) = I12;
  m->_I(0,2) = I13;
  m->_I(1,2) = I23;
  m->_I(1,0) = I12;
  m->_I(2,0) = I13;
  m->_I(2,1) = I23;
  checkMass (m);
}

void dMassSetSphere (dMass *m, dReal density, dReal radius)
{
  dMassSetSphereTotal (m, (REAL(4.0)/REAL(3.0)) * M_PI *
			  radius*radius*radius * density, radius);
}

void dMassSetSphereTotal (dMass *m, dReal total_mass, dReal radius)
{
  dAASSERT (m);
  dMassSetZero (m);
  m->mass = total_mass;
  dReal II = REAL(0.4) * total_mass * radius*radius;
  m->_I(0,0) = II;
  m->_I(1,1) = II;
  m->_I(2,2) = II;

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassSetCappedCylinder (dMass *m, dReal density, int direction,
			     dReal radius, dReal length)
{
  dReal M1,M2,Ia,Ib;
  dAASSERT (m);
  dUASSERT (direction >= 1 && direction <= 3,"bad direction number");
  dMassSetZero (m);
  M1 = M_PI*radius*radius*length*density;			// cylinder mass
  M2 = (REAL(4.0)/REAL(3.0))*M_PI*radius*radius*radius*density;	// total cap mass
  m->mass = M1+M2;
  Ia = M1*(REAL(0.25)*radius*radius + (REAL(1.0)/REAL(12.0))*length*length) +
    M2*(REAL(0.4)*radius*radius + REAL(0.375)*radius*length + REAL(0.25)*length*length);
  Ib = (M1*REAL(0.5) + M2*REAL(0.4))*radius*radius;
  m->_I(0,0) = Ia;
  m->_I(1,1) = Ia;
  m->_I(2,2) = Ia;
  m->_I(direction-1,direction-1) = Ib;

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassSetCappedCylinderTotal (dMass *m, dReal total_mass, int direction,
			     dReal a, dReal b)
{
  dMassSetCappedCylinder (m, 1.0, direction, a, b);
  dMassAdjust (m, total_mass);
}

void dMassSetCylinder (dMass *m, dReal density, int direction,
		       dReal radius, dReal length)
{
  dMassSetCylinderTotal (m, M_PI*radius*radius*length*density,
			    direction, radius, length);
}

void dMassSetCylinderTotal (dMass *m, dReal total_mass, int direction,
			    dReal radius, dReal length)
{
  dReal r2,I;
  dAASSERT (m);
  dUASSERT (direction >= 1 && direction <= 3,"bad direction number");
  dMassSetZero (m);
  r2 = radius*radius;
  m->mass = total_mass;
  I = total_mass*(REAL(0.25)*r2 + (REAL(1.0)/REAL(12.0))*length*length);
  m->_I(0,0) = I;
  m->_I(1,1) = I;
  m->_I(2,2) = I;
  m->_I(direction-1,direction-1) = total_mass*REAL(0.5)*r2;

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassSetBox (dMass *m, dReal density,
		  dReal lx, dReal ly, dReal lz)
{
  dMassSetBoxTotal (m, lx*ly*lz*density, lx, ly, lz);
}

void dMassSetBoxTotal (dMass *m, dReal total_mass,
		       dReal lx, dReal ly, dReal lz)
{
  dAASSERT (m);
  dMassSetZero (m);
  m->mass = total_mass;
  m->_I(0,0) = total_mass/REAL(12.0) * (ly*ly + lz*lz);
  m->_I(1,1) = total_mass/REAL(12.0) * (lx*lx + lz*lz);
  m->_I(2,2) = total_mass/REAL(12.0) * (lx*lx + ly*ly);

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassAdjust (dMass *m, dReal newmass)
{
  dAASSERT (m);
  dReal scale = newmass / m->mass;
  m->mass = newmass;
  for (int i=0; i<3; i++) for (int j=0; j<3; j++) m->_I(i,j) *= scale;

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassTranslate (dMass *m, dReal x, dReal y, dReal z)
{
  // if the body is translated by `a' relative to its point of reference,
  // the new inertia about the point of reference is:
  //
  //   I + mass*(crossmat(c)^2 - crossmat(c+a)^2)
  //
  // where c is the existing center of mass and I is the old inertia.

  int i,j;
  dMatrix3 ahat,chat,t1,t2;
  dReal a[3];

  dAASSERT (m);

  // adjust inertia matrix
  dSetZero (chat,12);
  dCROSSMAT (chat,m->c,4,+,-);
  a[0] = x + m->c[0];
  a[1] = y + m->c[1];
  a[2] = z + m->c[2];
  dSetZero (ahat,12);
  dCROSSMAT (ahat,a,4,+,-);
  dMULTIPLY0_333 (t1,ahat,ahat);
  dMULTIPLY0_333 (t2,chat,chat);
  for (i=0; i<3; i++) for (j=0; j<3; j++)
    m->_I(i,j) += m->mass * (t2[i*4+j]-t1[i*4+j]);

  // ensure perfect symmetry
  m->_I(1,0) = m->_I(0,1);
  m->_I(2,0) = m->_I(0,2);
  m->_I(2,1) = m->_I(1,2);

  // adjust center of mass
  m->c[0] += x;
  m->c[1] += y;
  m->c[2] += z;

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassRotate (dMass *m, const dMatrix3 R)
{
  // if the body is rotated by `R' relative to its point of reference,
  // the new inertia about the point of reference is:
  //
  //   R * I * R'
  //
  // where I is the old inertia.

  dMatrix3 t1;
  dReal t2[3];

  dAASSERT (m);

  // rotate inertia matrix
  dMULTIPLY2_333 (t1,m->I,R);
  dMULTIPLY0_333 (m->I,R,t1);

  // ensure perfect symmetry
  m->_I(1,0) = m->_I(0,1);
  m->_I(2,0) = m->_I(0,2);
  m->_I(2,1) = m->_I(1,2);

  // rotate center of mass
  dMULTIPLY0_331 (t2,R,m->c);
  m->c[0] = t2[0];
  m->c[1] = t2[1];
  m->c[2] = t2[2];

# ifndef dNODEBUG
  checkMass (m);
# endif
}

void dMassAdd (dMass *a, const dMass *b)
{
  int i;
  dAASSERT (a && b);
  dReal denom = dRecip (a->mass + b->mass);
  for (i=0; i<3; i++) a->c[i] = (a->c[i]*a->mass + b->c[i]*b->mass)*denom;
  a->mass += b->mass;
  for (i=0; i<12; i++) a->I[i] += b->I[i];
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 Stanford University
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

#include <unistd.h>
#include <fcntl.h>

#include "logging.h"

FILE *logfd = NULL;

void
ori_fuse_log_enable()
{
    if (logfd == NULL) {
        logfd = fopen("fuse.log", "wb+");
        if (logfd == NULL) {
            perror("fopen");
            exit(1);
        }
    }
}

void
ori_fuse_log(const char *what, ...)
{
    va_list vl;
    va_start(vl, what);
    vfprintf(logfd, what, vl);

#ifdef DEBUG
    fflush(logfd);
#endif
}

<commit_msg>missing change<commit_after>/*
 * Copyright (c) 2012 Stanford University
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

#include <unistd.h>
#include <fcntl.h>

#include "logging.h"

FILE *logfd = NULL;

void
ori_fuse_log_enable()
{
    if (logfd == NULL) {
        logfd = fopen("fuse.log", "wb+");
        if (logfd == NULL) {
            perror("fopen");
            exit(1);
        }
    }
}

void
ori_fuse_log(const char *what, ...)
{
    va_list vl;
    va_start(vl, what);

    if (logfd == NULL) {
        return;
    }

    vfprintf(logfd, what, vl);

#ifdef DEBUG
    fflush(logfd);
#endif
}

<|endoftext|>


<commit_before>/**
 * Copyright 2014 Open Connectome Project (http://openconnecto.me)
 * Written by Da Zheng (zhengda1936@gmail.com)
 *
 * This file is part of SAFSlib.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <boost/format.hpp>

#include <limits.h>

#include "log.h"
#include "native_file.h"
#include "safs_file.h"
#include "RAID_config.h"
#include "io_interface.h"

namespace safs
{

safs_file::safs_file(const RAID_config &conf, const std::string &file_name)
{
	conf.get_disks(native_dirs);
	for (unsigned i = 0; i < native_dirs.size(); i++)
		native_dirs[i].name += "/" + file_name;
	this->name = file_name;
}

std::vector<std::string> safs_file::erase_header_file(
		const std::vector<std::string> &files)
{
	std::vector<std::string> ret;
	for (auto it = files.begin(); it != files.end(); it++)
		if (*it != "header")
			ret.push_back(*it);
	return ret;
}

bool safs_file::exist() const
{
	std::set<int> part_ids;
	for (unsigned i = 0; i < native_dirs.size(); i++) {
		native_dir dir(native_dirs[i].name);
		if (!dir.exist())
			return false;
		std::vector<std::string> files;
		dir.read_all_files(files);
		if (files.size() > 1)
			files = erase_header_file(files);
		if (files.size() != 1) {
			fprintf(stderr, "%s doesn't have exactly one file\n",
					dir.get_name().c_str());
			return false;
		}
		part_ids.insert(atoi(files[0].c_str()));
	}
	if (part_ids.size() < native_dirs.size()) {
		fprintf(stderr, "there are duplicated partition ids in %s.\n",
				name.c_str());
		return false;
	}
	return true;
}

ssize_t safs_file::get_size() const
{
	if (!exist())
		return -1;
	size_t ret = 0;
	for (unsigned i = 0; i < native_dirs.size(); i++) {
		native_dir dir(native_dirs[i].name);
		std::vector<std::string> local_files;
		dir.read_all_files(local_files);
		if (local_files.size() > 1)
			local_files = erase_header_file(local_files);
		assert(local_files.size() == 1);
		native_file f(dir.get_name() + "/" + local_files[0]);
		ret += f.get_size();
	}
	return ret;
}

bool safs_file::rename(const std::string &new_name)
{
	if (!exist())
		return false;

	for (unsigned i = 0; i < native_dirs.size(); i++) {
		native_file f(native_dirs[i].name);
		if (!f.rename(f.get_dir_name() + "/" + new_name))
			return false;
	}
	name = new_name;
	for (unsigned i = 0; i < native_dirs.size(); i++) {
		native_file f(native_dirs[i].name);
		native_dirs[i].name = f.get_dir_name() + "/" + new_name;
	}
	return true;
}

bool safs_file::create_file(size_t file_size, int block_size, int mapping_option)
{
	size_t size_per_disk = file_size / native_dirs.size();
	if (file_size % native_dirs.size() > 0)
		size_per_disk++;
	size_per_disk = ROUNDUP(size_per_disk, 512);

	safs_header header(block_size, mapping_option, true);
	for (unsigned i = 0; i < native_dirs.size(); i++) {
		native_dir dir(native_dirs[i].name);
		bool ret = dir.create_dir(true);
		if (!ret)
			return false;
		if (i == 0) {
			std::string header_file = dir.get_name() + "/header";
			FILE *f = fopen(header_file.c_str(), "w");
			if (f == NULL) {
				perror("fopen");
				return false;
			}
			size_t num_writes = fwrite(&header, sizeof(header), 1, f);
			if (num_writes != 1) {
				perror("fwrite");
				return false;
			}
			int ret = fclose(f);
			assert(ret == 0);
		}
		native_file f(dir.get_name() + "/" + itoa(i));
		ret = f.create_file(size_per_disk);
		if (!ret)
			return false;
	}
	return true;
}

bool safs_file::delete_file()
{
	for (unsigned i = 0; i < native_dirs.size(); i++) {
		native_dir dir(native_dirs[i].name);
		bool ret = dir.delete_dir(true);
		if (!ret)
			return false;
	}
	return true;
}

safs_header safs_file::get_header() const
{
	for (size_t i = 0; i < native_dirs.size(); i++) {
		std::string dir_str = native_dirs[i].name;
		if (!file_exist(dir_str) || !file_exist(dir_str + "/header"))
			continue;
		std::string file_name = dir_str + "/header";
		FILE *f = fopen(file_name.c_str(), "r");
		if (f == NULL) {
			perror("fopen");
			break;
		}
		safs_header header;
		size_t num_reads = fread(&header, sizeof(header), 1, f);
		if (num_reads != 1) {
			perror("fread");
			break;
		}
		int ret = fclose(f);
		assert(ret == 0);
		return header;
	}

	return safs_header();
}

size_t get_all_safs_files(std::set<std::string> &files)
{
	std::set<std::string> all_files;
	const RAID_config &conf = get_sys_RAID_conf();

	// First find all individual file names in the root directories.
	for (int i = 0; i < conf.get_num_disks(); i++) {
		std::string dir_name = conf.get_disk(i).name;
		native_dir dir(dir_name);
		std::vector<std::string> file_names;
		dir.read_all_files(file_names);
		all_files.insert(file_names.begin(), file_names.end());
	}

	for (std::set<std::string>::const_iterator it = all_files.begin();
			it != all_files.end(); it++) {
		safs_file file(conf, *it);
		if (file.exist()) {
			files.insert(*it);
		}
		else {
			BOOST_LOG_TRIVIAL(error) << boost::format("%1% is corrupted")
				% file.get_name();
		}
	}
	return 0;
}

}
<commit_msg>[SAFS]: store chunks of an SAFS file to disks in random order.<commit_after>/**
 * Copyright 2014 Open Connectome Project (http://openconnecto.me)
 * Written by Da Zheng (zhengda1936@gmail.com)
 *
 * This file is part of SAFSlib.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <boost/format.hpp>

#include <limits.h>

#include "log.h"
#include "native_file.h"
#include "safs_file.h"
#include "RAID_config.h"
#include "io_interface.h"

namespace safs
{

safs_file::safs_file(const RAID_config &conf, const std::string &file_name)
{
	conf.get_disks(native_dirs);
	for (unsigned i = 0; i < native_dirs.size(); i++)
		native_dirs[i].name += "/" + file_name;
	this->name = file_name;
}

std::vector<std::string> safs_file::erase_header_file(
		const std::vector<std::string> &files)
{
	std::vector<std::string> ret;
	for (auto it = files.begin(); it != files.end(); it++)
		if (*it != "header")
			ret.push_back(*it);
	return ret;
}

bool safs_file::exist() const
{
	std::set<int> part_ids;
	for (unsigned i = 0; i < native_dirs.size(); i++) {
		native_dir dir(native_dirs[i].name);
		if (!dir.exist())
			return false;
		std::vector<std::string> files;
		dir.read_all_files(files);
		if (files.size() > 1)
			files = erase_header_file(files);
		if (files.size() != 1) {
			fprintf(stderr, "%s doesn't have exactly one file\n",
					dir.get_name().c_str());
			return false;
		}
		part_ids.insert(atoi(files[0].c_str()));
	}
	if (part_ids.size() < native_dirs.size()) {
		fprintf(stderr, "there are duplicated partition ids in %s.\n",
				name.c_str());
		return false;
	}
	return true;
}

ssize_t safs_file::get_size() const
{
	if (!exist())
		return -1;
	size_t ret = 0;
	for (unsigned i = 0; i < native_dirs.size(); i++) {
		native_dir dir(native_dirs[i].name);
		std::vector<std::string> local_files;
		dir.read_all_files(local_files);
		if (local_files.size() > 1)
			local_files = erase_header_file(local_files);
		assert(local_files.size() == 1);
		native_file f(dir.get_name() + "/" + local_files[0]);
		ret += f.get_size();
	}
	return ret;
}

bool safs_file::rename(const std::string &new_name)
{
	if (!exist())
		return false;

	for (unsigned i = 0; i < native_dirs.size(); i++) {
		native_file f(native_dirs[i].name);
		if (!f.rename(f.get_dir_name() + "/" + new_name))
			return false;
	}
	name = new_name;
	for (unsigned i = 0; i < native_dirs.size(); i++) {
		native_file f(native_dirs[i].name);
		native_dirs[i].name = f.get_dir_name() + "/" + new_name;
	}
	return true;
}

bool safs_file::create_file(size_t file_size, int block_size, int mapping_option)
{
	size_t size_per_disk = file_size / native_dirs.size();
	if (file_size % native_dirs.size() > 0)
		size_per_disk++;
	size_per_disk = ROUNDUP(size_per_disk, 512);

	// We use the random index to reorder the native directories.
	// So different files map their data chunks to disks in different order.
	// The benefit is that when we access data in the same location but from
	// different files, the data is likely fetched from different disks.
	// Thus, this leads to better I/O utilization.
	std::vector<int> dir_idxs(native_dirs.size());
	for (size_t i = 0; i < dir_idxs.size(); i++)
		dir_idxs[i] = i;
	random_shuffle(dir_idxs.begin(), dir_idxs.end());

	safs_header header(block_size, mapping_option, true);
	for (unsigned i = 0; i < native_dirs.size(); i++) {
		native_dir dir(native_dirs[dir_idxs[i]].name);
		bool ret = dir.create_dir(true);
		if (!ret)
			return false;
		// We store the metadata of the SAFS in the directory that
		// stores the first part.
		if (i == 0) {
			printf("the first part is in %s\n", dir.get_name().c_str());
			std::string header_file = dir.get_name() + "/header";
			FILE *f = fopen(header_file.c_str(), "w");
			if (f == NULL) {
				perror("fopen");
				return false;
			}
			size_t num_writes = fwrite(&header, sizeof(header), 1, f);
			if (num_writes != 1) {
				perror("fwrite");
				return false;
			}
			int ret = fclose(f);
			assert(ret == 0);
		}
		native_file f(dir.get_name() + "/" + itoa(i));
		ret = f.create_file(size_per_disk);
		if (!ret)
			return false;
	}
	return true;
}

bool safs_file::delete_file()
{
	for (unsigned i = 0; i < native_dirs.size(); i++) {
		native_dir dir(native_dirs[i].name);
		bool ret = dir.delete_dir(true);
		if (!ret)
			return false;
	}
	return true;
}

safs_header safs_file::get_header() const
{
	for (size_t i = 0; i < native_dirs.size(); i++) {
		std::string dir_str = native_dirs[i].name;
		if (!file_exist(dir_str) || !file_exist(dir_str + "/header"))
			continue;
		std::string file_name = dir_str + "/header";
		FILE *f = fopen(file_name.c_str(), "r");
		if (f == NULL) {
			perror("fopen");
			break;
		}
		safs_header header;
		size_t num_reads = fread(&header, sizeof(header), 1, f);
		if (num_reads != 1) {
			perror("fread");
			break;
		}
		int ret = fclose(f);
		assert(ret == 0);
		return header;
	}

	return safs_header();
}

size_t get_all_safs_files(std::set<std::string> &files)
{
	std::set<std::string> all_files;
	const RAID_config &conf = get_sys_RAID_conf();

	// First find all individual file names in the root directories.
	for (int i = 0; i < conf.get_num_disks(); i++) {
		std::string dir_name = conf.get_disk(i).name;
		native_dir dir(dir_name);
		std::vector<std::string> file_names;
		dir.read_all_files(file_names);
		all_files.insert(file_names.begin(), file_names.end());
	}

	for (std::set<std::string>::const_iterator it = all_files.begin();
			it != all_files.end(); it++) {
		safs_file file(conf, *it);
		if (file.exist()) {
			files.insert(*it);
		}
		else {
			BOOST_LOG_TRIVIAL(error) << boost::format("%1% is corrupted")
				% file.get_name();
		}
	}
	return 0;
}

}
<|endoftext|>


<commit_before>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#include "vast/error.hpp"

#include "vast/detail/assert.hpp"

#include <caf/pec.hpp>
#include <caf/sec.hpp>

#include <sstream>
#include <string>

namespace vast {
namespace {

const char* descriptions[] = {
  "no_error",
  "unspecified",
  "no_such_file",
  "filesystem_error",
  "type_clash",
  "unsupported_operator",
  "parse_error",
  "print_error",
  "convert_error",
  "invalid_query",
  "format_error",
  "end_of_input",
  "version_error",
  "syntax_error",
  "invalid_table_slice_type",
  "invalid_synopsis_type",
  "remote_node_down",
  "invalid_result",
  "invalid_configuration",
  "unrecognized_option",
  "invalid_subcommand",
  "missing_subcommand",
  "missing_component",
  "unimplemented",
  "silent",
};

void render_default_ctx(std::ostringstream& oss, const caf::message& ctx) {
  size_t size = ctx.size();
  if (size > 0) {
    oss << ":";
    for (size_t i = 0; i < size; ++i)
      oss << ' ' << ctx.stringify(i);
  }
}

} // namespace

const char* to_string(ec x) {
  auto index = static_cast<size_t>(x);
  VAST_ASSERT(index < sizeof(descriptions));
  return descriptions[index];
}

std::string render(caf::error err) {
  using caf::atom_uint;
  std::ostringstream oss;
  auto category = err.category();
  if (atom_uint(category) == atom_uint("vast")
      && static_cast<vast::ec>(err.code()) == ec::silent)
    return "";
  oss << "!! ";
  switch (atom_uint(category)) {
    default:
      oss << to_string(category);
      render_default_ctx(oss, err.context());
      break;
    case atom_uint("vast"): {
      auto x = static_cast<vast::ec>(err.code());
      oss << to_string(x);
      switch (x) {
        default:
          render_default_ctx(oss, err.context());
      }
    } break;
    case atom_uint("parser"):
      oss << to_string(static_cast<caf::pec>(err.code()));
      render_default_ctx(oss, err.context());
      break;
    case atom_uint("system"):
      oss << to_string(static_cast<caf::sec>(err.code()));
      render_default_ctx(oss, err.context());
      break;
  }
  return oss.str();
}

} // namespace vast
<commit_msg>Simplify error code equality check<commit_after>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#include "vast/error.hpp"

#include "vast/detail/assert.hpp"

#include <caf/pec.hpp>
#include <caf/sec.hpp>

#include <sstream>
#include <string>

namespace vast {
namespace {

const char* descriptions[] = {
  "no_error",
  "unspecified",
  "no_such_file",
  "filesystem_error",
  "type_clash",
  "unsupported_operator",
  "parse_error",
  "print_error",
  "convert_error",
  "invalid_query",
  "format_error",
  "end_of_input",
  "version_error",
  "syntax_error",
  "invalid_table_slice_type",
  "invalid_synopsis_type",
  "remote_node_down",
  "invalid_result",
  "invalid_configuration",
  "unrecognized_option",
  "invalid_subcommand",
  "missing_subcommand",
  "missing_component",
  "unimplemented",
  "silent",
};

void render_default_ctx(std::ostringstream& oss, const caf::message& ctx) {
  size_t size = ctx.size();
  if (size > 0) {
    oss << ":";
    for (size_t i = 0; i < size; ++i)
      oss << ' ' << ctx.stringify(i);
  }
}

} // namespace

const char* to_string(ec x) {
  auto index = static_cast<size_t>(x);
  VAST_ASSERT(index < sizeof(descriptions));
  return descriptions[index];
}

std::string render(caf::error err) {
  using caf::atom_uint;
  std::ostringstream oss;
  auto category = err.category();
  if (atom_uint(category) == atom_uint("vast") && err == ec::silent)
    return "";
  oss << "!! ";
  switch (atom_uint(category)) {
    default:
      oss << to_string(category);
      render_default_ctx(oss, err.context());
      break;
    case atom_uint("vast"): {
      auto x = static_cast<vast::ec>(err.code());
      oss << to_string(x);
      switch (x) {
        default:
          render_default_ctx(oss, err.context());
      }
    } break;
    case atom_uint("parser"):
      oss << to_string(static_cast<caf::pec>(err.code()));
      render_default_ctx(oss, err.context());
      break;
    case atom_uint("system"):
      oss << to_string(static_cast<caf::sec>(err.code()));
      render_default_ctx(oss, err.context());
      break;
  }
  return oss.str();
}

} // namespace vast
<|endoftext|>


<commit_before>// Copyright 2017 Global Phasing Ltd.

#include "gemmi/mmread.hpp"
#include "gemmi/gz.hpp"

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

namespace py = pybind11;

void add_mmread(py::module& m) {
  m.def("read_structure", [](const std::string& path) {
          return std::move(gemmi::read_structure(gemmi::MaybeGzipped(path)));
        }, py::arg("path"), py::return_value_policy::move,
        "Reads a coordinate file into Structure.");
}
<commit_msg>clang suggested to remove std::move (-Wpessimizing-move)<commit_after>// Copyright 2017 Global Phasing Ltd.

#include "gemmi/mmread.hpp"
#include "gemmi/gz.hpp"

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

namespace py = pybind11;

void add_mmread(py::module& m) {
  m.def("read_structure", [](const std::string& path) {
          return gemmi::read_structure(gemmi::MaybeGzipped(path));
        }, py::arg("path"),
        "Reads a coordinate file into Structure.");
}
<|endoftext|>