<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2021.  All rights reserved
 */
#ifndef _Stroika_Foundation_Debug_AssertExternallySynchronizedMutex_inl_
#define _Stroika_Foundation_Debug_AssertExternallySynchronizedMutex_inl_ 1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
#include <algorithm>

#include "Sanitizer.h"

namespace Stroika::Foundation::Debug {

    /*
     ********************************************************************************
     **************** Debug::AssertExternallySynchronizedMutex **********************
     ********************************************************************************
     */
#if qDebug
    inline AssertExternallySynchronizedMutex::AssertExternallySynchronizedMutex (const shared_ptr<SharedContext>& sharedContext) noexcept
        // https://stroika.atlassian.net/browse/STK-500
        // NOTE - this will generate a throw and std::unexpected violation if there is no memory and multiset CTOR
        // throws. There is no good answer in this case. We declare the constructors noexcept so the footprint of
        // AssertExternallySynchronizedMutex is as light as possible and the same (API/constraints) between debug and release
        // builds. And if we run out of memory here, there isn't much we can do to continue -- LGP 2018-10-02
        : _fSharedContext{sharedContext ? sharedContext : make_shared<SharedContext> ()}
    {
    }
    inline AssertExternallySynchronizedMutex::AssertExternallySynchronizedMutex (const shared_ptr<SharedContext>& sharedContext, const AssertExternallySynchronizedMutex& src) noexcept
        : AssertExternallySynchronizedMutex{sharedContext}
    {
        shared_lock<const AssertExternallySynchronizedMutex> critSec1{src}; // to copy, the src can have shared_locks, but no (write) locks
    }
    inline AssertExternallySynchronizedMutex::AssertExternallySynchronizedMutex (const AssertExternallySynchronizedMutex& src) noexcept
        : AssertExternallySynchronizedMutex{}
    {
        shared_lock<const AssertExternallySynchronizedMutex> critSec1{src}; // to copy, the src can have shared_locks, but no (write) locks
    }
    inline AssertExternallySynchronizedMutex::AssertExternallySynchronizedMutex (const shared_ptr<SharedContext>& sharedContext, [[maybe_unused]] AssertExternallySynchronizedMutex&& src) noexcept
        : AssertExternallySynchronizedMutex{sharedContext}
    {
        try {
            Require (src._fSharedContext->fLocks_ == 0 and src._fSharedContext->GetSharedLockEmpty_ ()); // to move, the src can have no locks of any kind (since we change src)
        }
        catch (...) {
            AssertNotReached ();
        }
    }
    inline AssertExternallySynchronizedMutex::AssertExternallySynchronizedMutex ([[maybe_unused]] AssertExternallySynchronizedMutex&& src) noexcept
        : AssertExternallySynchronizedMutex{}
    {
        try {
            Require (src._fSharedContext->fLocks_ == 0 and src._fSharedContext->GetSharedLockEmpty_ ()); // to move, the src can have no locks of any kind (since we change src)
        }
        catch (...) {
            AssertNotReached ();
        }
    }
#endif
    inline AssertExternallySynchronizedMutex& AssertExternallySynchronizedMutex::operator= ([[maybe_unused]] const AssertExternallySynchronizedMutex& rhs) noexcept
    {
#if qDebug
        try {
            DISABLE_COMPILER_MSC_WARNING_START (26110);                         // to copy, the src can have shared_locks, but no (write) locks
            shared_lock<const AssertExternallySynchronizedMutex> critSec1{rhs}; // ""
            if (this == &rhs) {
                Require (_fSharedContext->fLocks_ == 0 and _fSharedContext->GetSharedLockThreadsCount_ () == 1); // we locked ourselves above
            }
            else {
                // @todo This logic SB same as for MOVE, but for some reason this hasn't been triggered yet...
                // https://stroika.atlassian.net/browse/STK-752
                Require (_fSharedContext->fLocks_ == 0 and _fSharedContext->GetSharedLockEmpty_ ()); // We must not have any locks going to replace this
            }
            DISABLE_COMPILER_MSC_WARNING_END (26110);
        }
        catch (...) {
            AssertNotReached ();
        }
#endif
        return *this;
    }
    inline AssertExternallySynchronizedMutex& AssertExternallySynchronizedMutex::operator= ([[maybe_unused]] AssertExternallySynchronizedMutex&& rhs) noexcept
    {
#if qDebug
        try {
            Require (rhs._fSharedContext->fLocks_ == 0 and rhs._fSharedContext->GetSharedLockEmpty_ ()); // to move, the rhs can have no locks of any kind (since we change rhs)
            // NOTE - we also should check if fLocks_ != 0 -= thats OK if WE are the locker.
            // BUT - I think I need todo work here to TRANSFER the locks (and thats not done here/yet)
            //
            //Require (_fSharedContext->fLocks_ == 0 and _fSharedContext->GetSharedLockEmpty_ ());         // ditto for thing being assigned to
            // https://stroika.atlassian.net/browse/STK-752
            if (_fSharedContext->fLocks_ != 0) {
                // must do some sanity check and then transfer locks
                Assert (false); // NYI
            }
            if (not _fSharedContext->GetSharedLockEmpty_ ()) {
                auto tmp = _fSharedContext->CountSharedLockThreads_ ();
                Assert (tmp.second == 0); // not good enuf - must transer lock to RHS
                // UNCLEAR if should transfer rhs._fSharedContext making this increment irrelevant
                for (size_t i = 0; i < tmp.second; ++i) {
                    //  rhs.lock_shared ();
                }
            }
            //  _fSharedContext = move (rhs._fSharedContext);
        }
        catch (...) {
            AssertNotReached ();
        }
#endif
        return *this;
    }
#if qDebug
    inline void AssertExternallySynchronizedMutex::SetAssertExternallySynchronizedMutexContext (const shared_ptr<SharedContext>& sharedContext)
    {
        Require (sharedContext != nullptr);
        _fSharedContext = sharedContext;
    }
#endif
    inline void AssertExternallySynchronizedMutex::lock () const noexcept
    {
#if qDebug
        lock_ ();
#endif
    }
    inline void AssertExternallySynchronizedMutex::unlock () const noexcept
    {
#if qDebug
        unlock_ ();
#endif
    }
    inline void AssertExternallySynchronizedMutex::lock_shared () const noexcept
    {
#if qDebug
        lock_shared_ ();
#endif
    }
    inline void AssertExternallySynchronizedMutex::unlock_shared () const noexcept
    {
#if qDebug
        unlock_shared_ ();
#endif
    }

}

#endif /*_Stroika_Foundation_Debug_AssertExternallySynchronizedMutex_inl_*/
<commit_msg>slight cleanups of Debug/AssertExternallySynchronizedMutex.<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2021.  All rights reserved
 */
#ifndef _Stroika_Foundation_Debug_AssertExternallySynchronizedMutex_inl_
#define _Stroika_Foundation_Debug_AssertExternallySynchronizedMutex_inl_ 1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
#include <algorithm>

#include "Sanitizer.h"

namespace Stroika::Foundation::Debug {

    /*
     ********************************************************************************
     **************** Debug::AssertExternallySynchronizedMutex **********************
     ********************************************************************************
     */
#if qDebug
    inline AssertExternallySynchronizedMutex::AssertExternallySynchronizedMutex (const shared_ptr<SharedContext>& sharedContext) noexcept
        // https://stroika.atlassian.net/browse/STK-500
        // NOTE - this will generate a throw and std::unexpected violation if there is no memory and multiset CTOR
        // throws. There is no good answer in this case. We declare the constructors noexcept so the footprint of
        // AssertExternallySynchronizedMutex is as light as possible and the same (API/constraints) between debug and release
        // builds. And if we run out of memory here, there isn't much we can do to continue -- LGP 2018-10-02
        : _fSharedContext{sharedContext ? sharedContext : make_shared<SharedContext> ()}
    {
    }
    inline AssertExternallySynchronizedMutex::AssertExternallySynchronizedMutex (const shared_ptr<SharedContext>& sharedContext, const AssertExternallySynchronizedMutex& src) noexcept
        : AssertExternallySynchronizedMutex{sharedContext}
    {
        shared_lock<const AssertExternallySynchronizedMutex> critSec1{src}; // to copy, the src can have shared_locks, but no (write) locks
    }
    inline AssertExternallySynchronizedMutex::AssertExternallySynchronizedMutex (const AssertExternallySynchronizedMutex& src) noexcept
        : AssertExternallySynchronizedMutex{}
    {
        shared_lock<const AssertExternallySynchronizedMutex> critSec1{src}; // to copy, the src can have shared_locks, but no (write) locks
    }
    inline AssertExternallySynchronizedMutex::AssertExternallySynchronizedMutex (const shared_ptr<SharedContext>& sharedContext, [[maybe_unused]] AssertExternallySynchronizedMutex&& src) noexcept
        : AssertExternallySynchronizedMutex{sharedContext}
    {
        try {
            Require (src._fSharedContext->fLocks_ == 0 and src._fSharedContext->GetSharedLockEmpty_ ()); // to move, the src can have no locks of any kind (since we change src)
        }
        catch (...) {
            AssertNotReached ();
        }
    }
    inline AssertExternallySynchronizedMutex::AssertExternallySynchronizedMutex ([[maybe_unused]] AssertExternallySynchronizedMutex&& src) noexcept
        : AssertExternallySynchronizedMutex{}
    {
        try {
            Require (src._fSharedContext->fLocks_ == 0 and src._fSharedContext->GetSharedLockEmpty_ ()); // to move, the src can have no locks of any kind (since we change src)
        }
        catch (...) {
            AssertNotReached ();
        }
    }
#endif
    inline AssertExternallySynchronizedMutex& AssertExternallySynchronizedMutex::operator= ([[maybe_unused]] const AssertExternallySynchronizedMutex& rhs) noexcept
    {
#if qDebug
        try {
            DISABLE_COMPILER_MSC_WARNING_START (26110);                         // to copy, the src can have shared_locks, but no (write) locks
            shared_lock<const AssertExternallySynchronizedMutex> critSec1{rhs}; // ""
            if (this == &rhs) {
                Require (_fSharedContext->fLocks_ == 0 and _fSharedContext->GetSharedLockThreadsCount_ () == 1); // we locked ourselves above
            }
            else {
                // @todo This logic SB same as for MOVE, but for some reason this hasn't been triggered yet...
                // https://stroika.atlassian.net/browse/STK-752
                Require (_fSharedContext->fLocks_ == 0 and _fSharedContext->GetSharedLockEmpty_ ()); // We must not have any locks going to replace this
            }
            DISABLE_COMPILER_MSC_WARNING_END (26110);
        }
        catch (...) {
            AssertNotReached ();
        }
#endif
        return *this;
    }
    inline AssertExternallySynchronizedMutex& AssertExternallySynchronizedMutex::operator= ([[maybe_unused]] AssertExternallySynchronizedMutex&& rhs) noexcept
    {
#if qDebug
        try {
            Require (rhs._fSharedContext->fLocks_ == 0 and rhs._fSharedContext->GetSharedLockEmpty_ ()); // to move, the rhs can have no locks of any kind (since we change rhs)
            // https://stroika.atlassian.net/browse/STK-752
            // review - SB OK to assign over this with locks if the locks are all from this thread
            if (_fSharedContext->fLocks_ != 0) {
                Assert (false); // NYI
            }
            if (not _fSharedContext->GetSharedLockEmpty_ ()) {
                Assert (_fSharedContext->CountSharedLockThreads_ ().second == 0); // not good enuf - must transer lock to RHS
            }
        }
        catch (...) {
            AssertNotReached ();
        }
#endif
        return *this;
    }
#if qDebug
    inline void AssertExternallySynchronizedMutex::SetAssertExternallySynchronizedMutexContext (const shared_ptr<SharedContext>& sharedContext)
    {
        Require (sharedContext != nullptr);
        _fSharedContext = sharedContext;
    }
#endif
    inline void AssertExternallySynchronizedMutex::lock () const noexcept
    {
#if qDebug
        lock_ ();
#endif
    }
    inline void AssertExternallySynchronizedMutex::unlock () const noexcept
    {
#if qDebug
        unlock_ ();
#endif
    }
    inline void AssertExternallySynchronizedMutex::lock_shared () const noexcept
    {
#if qDebug
        lock_shared_ ();
#endif
    }
    inline void AssertExternallySynchronizedMutex::unlock_shared () const noexcept
    {
#if qDebug
        unlock_shared_ ();
#endif
    }

}

#endif /*_Stroika_Foundation_Debug_AssertExternallySynchronizedMutex_inl_*/
<|endoftext|>


<commit_before>// Copyright (c) 2003 Daniel Wallin and Arvid Norberg

// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
// OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef LUABIND_CALL_FUNCTION_HPP_INCLUDED
#define LUABIND_CALL_FUNCTION_HPP_INCLUDED

#include <luabind/config.hpp>

#include <luabind/error.hpp>
#include <luabind/detail/convert_to_lua.hpp>
#include <luabind/detail/pcall.hpp>
#include <luabind/detail/call_shared.hpp>
#include <luabind/detail/stack_utils.hpp>

namespace luabind
{
	namespace adl {
		class object;
	}

	using adl::object;

	namespace detail {

		template< typename PolicyList, unsigned int pos >
        void push_arguments(lua_State* /*L*/) {};

		template< typename PolicyList, unsigned int Pos, typename Arg0, typename... Args >
		void push_arguments(lua_State* L, Arg0&& arg0, Args&&... args)
		{
			using converter_type = specialized_converter_policy< fetched_converter_policy<Pos, PolicyList>, Arg0, cpp_to_lua >;
			converter_type().to_lua(L, unwrapped<Arg0>::get(std::forward<Arg0>(arg0)));
                    push_arguments<PolicyList, Pos+1>(L, std::forward<Args>(args)...);
                }

#ifndef LUABIND_NO_INTERNAL_TAG_ARGUMENTS
		template<typename Ret, typename PolicyList, typename... Args, unsigned int... Indices, typename Fn>
		void call_function_impl(lua_State* L, int m_params, Fn fn, std::true_type /* void */, meta::index_list<Indices...>, Args&&... args)
		{
			int top = lua_gettop(L);

			push_arguments<PolicyList, 1>(L, std::forward<Args>(args)...);

			if (fn(L, sizeof...(Args), 0)) {
				assert(lua_gettop(L) == top - m_params + 1);
				call_error(L);
			}
			// pops the return values from the function call
			stack_pop pop(L, lua_gettop(L) - top + m_params);
		}

		template<typename Ret, typename PolicyList, typename... Args, unsigned int... Indices, typename Fn>
		Ret call_function_impl(lua_State* L, int m_params, Fn fn, std::false_type /* void */ , meta::index_list<Indices...>, Args&&... args)
		{
			int top = lua_gettop(L);

			push_arguments<PolicyList, 1>(L, std::forward<Args>(args)...);

			if (fn(L, sizeof...(Args), 1)) {
				assert(lua_gettop(L) == top - m_params + 1);
				call_error(L);
			}
			// pops the return values from the function call
			stack_pop pop(L, lua_gettop(L) - top + m_params);

			specialized_converter_policy_n<0, PolicyList, Ret, lua_to_cpp> converter;
			if (converter.match(L, decorated_type<Ret>(), -1) < 0) {
				cast_error<Ret>(L);
			}

			return converter.to_cpp(L, decorated_type<Ret>(), -1);
		}
#else
		template<typename Ret, typename PolicyList, typename IndexList, unsigned int NumParams, int(*Function)(lua_State*, int, int), bool IsVoid = std::is_void<Ret>::value>
		struct call_function_struct;

		template<typename Ret, typename PolicyList, unsigned int NumParams, int(*Function)(lua_State*, int, int), unsigned int... Indices >
		struct call_function_struct< Ret, PolicyList, meta::index_list<Indices...>, NumParams, Function, true /* void */ >
		{
			template< typename... Args >
			static void call(lua_State* L, Args&&... args) {
				int top = lua_gettop(L);

				push_arguments<PolicyList, 1>(L, std::forward<Args>(args)...);

				if(Function(L, sizeof...(Args), 0)) {
					assert(lua_gettop(L)==top-NumParams+1);
					call_error(L);
				}
				// pops the return values from the function call
				stack_pop pop(L, lua_gettop(L)-top+NumParams);
			}
		};

		template<typename Ret, typename PolicyList, unsigned int NumParams, int(*Function)(lua_State*, int, int), unsigned int... Indices >
		struct call_function_struct< Ret, PolicyList, meta::index_list<Indices...>, NumParams, Function, false /* void */ >
		{
			template< typename... Args >
			static Ret call(lua_State* L, Args&&... args) {
				int top = lua_gettop(L);

				push_arguments<PolicyList, 1>(L, std::forward<Args>(args)...);

				if(Function(L, sizeof...(Args), 1)) {
					assert(lua_gettop(L)==top-NumParams+1);
					call_error(L);
				}
				// pops the return values from the function call
				stack_pop pop(L, lua_gettop(L)-top+NumParams);

				specialized_converter_policy_n<0, PolicyList, Ret, lua_to_cpp> converter;
				if(converter.match(L, decorated_type<Ret>(), -1)<0) {
					cast_error<Ret>(L);
				}

				return converter.to_cpp(L, decorated_type<Ret>(), -1);
			}
		};
#endif
	}

	template<class R, typename PolicyList = no_policies, typename... Args>
	R call_pushed_function(lua_State* L, Args&&... args)
	{
#ifndef LUABIND_NO_INTERNAL_TAG_ARGUMENTS
		return detail::call_function_impl<R, PolicyList>(L, 1, &detail::pcall, std::is_void<R>(), meta::index_range<1, sizeof...(Args) +1>(), std::forward<Args>(args)...);
#else
		return detail::call_function_struct<R, PolicyList, meta::index_range<1, sizeof...(Args)+1>, 1, &detail::pcall >::call(L, std::forward<Args>(args)...);
#endif
	}

	template<class R, typename PolicyList = no_policies, typename... Args>
	R call_function(lua_State* L, const char* name, Args&&... args )
	{
		assert(name && "luabind::call_function() expects a function name");
		lua_getglobal(L, name);
		return call_pushed_function<R, PolicyList>(L, std::forward<Args>(args)...);
	}

	template<class R, typename PolicyList = no_policies, typename... Args>
	R resume_pushed_function(lua_State* L, Args&&... args)
	{
#ifndef LUABIND_NO_INTERNAL_TAG_ARGUMENTS
		return detail::call_function_impl<R, PolicyList>(L, 1, &detail::resume_impl, std::is_void<R>(), meta::index_range<1, sizeof...(Args) +1>(), std::forward<Args>(args)...);
#else
		return detail::call_function_struct<R, PolicyList, meta::index_range<1, sizeof...(Args)+1>, 1, &detail::resume_impl >::call(L, std::forward<Args>(args)...);
#endif
	}

	template<class R, typename PolicyList = no_policies, typename... Args>
	R resume_function(lua_State* L, const char* name, Args&&... args)
	{
		assert(name && "luabind::resume_function() expects a function name");
		lua_getglobal(L, name);
		return resume_pushed_function<R, PolicyList>(L, std::forward<Args>(args)...);
	}

	template<class R, typename PolicyList = no_policies, typename... Args>
	R resume(lua_State* L, Args&&... args)
	{
#ifndef LUABIND_NO_INTERNAL_TAG_ARGUMENTS
		return detail::call_function_impl<R, PolicyList>(L, 0, &detail::resume_impl, std::is_void<R>(), meta::index_range<1, sizeof...(Args) +1>(), std::forward<Args>(args)...);
#else
		return detail::call_function_struct<R, PolicyList, meta::index_range<1, sizeof...(Args)+1>, 0, &detail::resume_impl >::call(L, std::forward<Args>(args)...);
#endif
	}

}

#endif // LUABIND_CALL_FUNCTION_HPP_INCLUDED

<commit_msg>Tiny change<commit_after>// Copyright (c) 2003 Daniel Wallin and Arvid Norberg

// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
// OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef LUABIND_CALL_FUNCTION_HPP_INCLUDED
#define LUABIND_CALL_FUNCTION_HPP_INCLUDED

#include <luabind/config.hpp>

#include <luabind/error.hpp>
#include <luabind/detail/convert_to_lua.hpp>
#include <luabind/detail/pcall.hpp>
#include <luabind/detail/call_shared.hpp>
#include <luabind/detail/stack_utils.hpp>

namespace luabind
{
	namespace adl {
		class object;
	}

	using adl::object;

	namespace detail {

		template< typename PolicyList, unsigned int pos >
        void push_arguments(lua_State* /*L*/) {};

		template< typename PolicyList, unsigned int Pos, typename Arg0, typename... Args >
		void push_arguments(lua_State* L, Arg0&& arg0, Args&&... args)
		{
			using converter_type = specialized_converter_policy< fetched_converter_policy<Pos, PolicyList>, Arg0, cpp_to_lua >;
			converter_type().to_lua(L, unwrapped<Arg0>::get(std::forward<Arg0>(arg0)));
                        push_arguments<PolicyList, Pos+1>(L, std::forward<Args>(args)...);
                }

#ifndef LUABIND_NO_INTERNAL_TAG_ARGUMENTS
		template<typename Ret, typename PolicyList, typename... Args, unsigned int... Indices, typename Fn>
		void call_function_impl(lua_State* L, int m_params, Fn fn, std::true_type /* void */, meta::index_list<Indices...>, Args&&... args)
		{
			int top = lua_gettop(L);

			push_arguments<PolicyList, 1>(L, std::forward<Args>(args)...);

			if (fn(L, sizeof...(Args), 0)) {
				assert(lua_gettop(L) == top - m_params + 1);
				call_error(L);
			}
			// pops the return values from the function call
			stack_pop pop(L, lua_gettop(L) - top + m_params);
		}

		template<typename Ret, typename PolicyList, typename... Args, unsigned int... Indices, typename Fn>
		Ret call_function_impl(lua_State* L, int m_params, Fn fn, std::false_type /* void */ , meta::index_list<Indices...>, Args&&... args)
		{
			int top = lua_gettop(L);

			push_arguments<PolicyList, 1>(L, std::forward<Args>(args)...);

			if (fn(L, sizeof...(Args), 1)) {
				assert(lua_gettop(L) == top - m_params + 1);
				call_error(L);
			}
			// pops the return values from the function call
			stack_pop pop(L, lua_gettop(L) - top + m_params);

			specialized_converter_policy_n<0, PolicyList, Ret, lua_to_cpp> converter;
			if (converter.match(L, decorated_type<Ret>(), -1) < 0) {
				cast_error<Ret>(L);
			}

			return converter.to_cpp(L, decorated_type<Ret>(), -1);
		}
#else
		template<typename Ret, typename PolicyList, typename IndexList, unsigned int NumParams, int(*Function)(lua_State*, int, int), bool IsVoid = std::is_void<Ret>::value>
		struct call_function_struct;

		template<typename Ret, typename PolicyList, unsigned int NumParams, int(*Function)(lua_State*, int, int), unsigned int... Indices >
		struct call_function_struct< Ret, PolicyList, meta::index_list<Indices...>, NumParams, Function, true /* void */ >
		{
			template< typename... Args >
			static void call(lua_State* L, Args&&... args) {
				int top = lua_gettop(L);

				push_arguments<PolicyList, 1>(L, std::forward<Args>(args)...);

				if(Function(L, sizeof...(Args), 0)) {
					assert(lua_gettop(L)==top-NumParams+1);
					call_error(L);
				}
				// pops the return values from the function call
				stack_pop pop(L, lua_gettop(L)-top+NumParams);
			}
		};

		template<typename Ret, typename PolicyList, unsigned int NumParams, int(*Function)(lua_State*, int, int), unsigned int... Indices >
		struct call_function_struct< Ret, PolicyList, meta::index_list<Indices...>, NumParams, Function, false /* void */ >
		{
			template< typename... Args >
			static Ret call(lua_State* L, Args&&... args) {
				int top = lua_gettop(L);

				push_arguments<PolicyList, 1>(L, std::forward<Args>(args)...);

				if(Function(L, sizeof...(Args), 1)) {
					assert(lua_gettop(L)==top-NumParams+1);
					call_error(L);
				}
				// pops the return values from the function call
				stack_pop pop(L, lua_gettop(L)-top+NumParams);

				specialized_converter_policy_n<0, PolicyList, Ret, lua_to_cpp> converter;
				if(converter.match(L, decorated_type<Ret>(), -1)<0) {
					cast_error<Ret>(L);
				}

				return converter.to_cpp(L, decorated_type<Ret>(), -1);
			}
		};
#endif
	}

	template<class R, typename PolicyList = no_policies, typename... Args>
	R call_pushed_function(lua_State* L, Args&&... args)
	{
#ifndef LUABIND_NO_INTERNAL_TAG_ARGUMENTS
		return detail::call_function_impl<R, PolicyList>(L, 1, &detail::pcall, std::is_void<R>(), meta::index_range<1, sizeof...(Args) +1>(), std::forward<Args>(args)...);
#else
		return detail::call_function_struct<R, PolicyList, meta::index_range<1, sizeof...(Args)+1>, 1, &detail::pcall >::call(L, std::forward<Args>(args)...);
#endif
	}

	template<class R, typename PolicyList = no_policies, typename... Args>
	R call_function(lua_State* L, const char* name, Args&&... args )
	{
		assert(name && "luabind::call_function() expects a function name");
		lua_getglobal(L, name);
		return call_pushed_function<R, PolicyList>(L, std::forward<Args>(args)...);
	}

	template<class R, typename PolicyList = no_policies, typename... Args>
	R resume_pushed_function(lua_State* L, Args&&... args)
	{
#ifndef LUABIND_NO_INTERNAL_TAG_ARGUMENTS
		return detail::call_function_impl<R, PolicyList>(L, 1, &detail::resume_impl, std::is_void<R>(), meta::index_range<1, sizeof...(Args) +1>(), std::forward<Args>(args)...);
#else
		return detail::call_function_struct<R, PolicyList, meta::index_range<1, sizeof...(Args)+1>, 1, &detail::resume_impl >::call(L, std::forward<Args>(args)...);
#endif
	}

	template<class R, typename PolicyList = no_policies, typename... Args>
	R resume_function(lua_State* L, const char* name, Args&&... args)
	{
		assert(name && "luabind::resume_function() expects a function name");
		lua_getglobal(L, name);
		return resume_pushed_function<R, PolicyList>(L, std::forward<Args>(args)...);
	}

	template<class R, typename PolicyList = no_policies, typename... Args>
	R resume(lua_State* L, Args&&... args)
	{
#ifndef LUABIND_NO_INTERNAL_TAG_ARGUMENTS
		return detail::call_function_impl<R, PolicyList>(L, 0, &detail::resume_impl, std::is_void<R>(), meta::index_range<1, sizeof...(Args) +1>(), std::forward<Args>(args)...);
#else
		return detail::call_function_struct<R, PolicyList, meta::index_range<1, sizeof...(Args)+1>, 0, &detail::resume_impl >::call(L, std::forward<Args>(args)...);
#endif
	}

}

#endif // LUABIND_CALL_FUNCTION_HPP_INCLUDED

<|endoftext|>


<commit_before>/*
    spellcheckplugin.cpp

    Kopete Spell Checking plugin

    Copyright (c) 2003 by Jason Keirstead   <jason@keirstead.org>

    Kopete    (c) 2002 by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This program 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 2 of the License, or     *
    * (at your option) any later version.                                   *
    *                                                                       *
    *************************************************************************
*/
#include <qtextedit.h>
#include <kpopupmenu.h>

#include <kdebug.h>
#include <kspell.h>
#include <klocale.h>

#include "kopeteviewmanager.h"
#include "singlespellinstance.h"
#include "spellcheckpreferences.h"

SingleSpellInstance::SingleSpellInstance( KopeteView *myView, SpellCheckPreferences *mPrefs ) : QObject( 0L )
{
	mView = myView;

	//If this object was created, we know we have a QTextEdit, so this is safe
	t = static_cast<QTextEdit*>( mView->editWidget() );
	t->installEventFilter( this );
	t->viewport()->installEventFilter( this );

	words = 0L;
	spellCheckerReady = false;

	//Define our word seperator regexp
	//We can't use \b because QT barfs when trying to split on it
	mBound = QRegExp( QString::fromLatin1("[\\s\\W]") );

	mSpell = new KSpell(0L, i18n("Spellcheck - Kopete"), this, SLOT( slotSpellCheckerReady( KSpell * )), mPrefs->spellConfig() );
	connect( mSpell, SIGNAL( misspelling( const QString&, const QStringList&, unsigned int ) ), this, SLOT( slotMisspelling( const QString&, const QStringList&, unsigned int ) ) );
	connect( dynamic_cast<QObject*>(mView), SIGNAL( destroyed() ), this, SLOT( slotViewDestroyed() ) );
}

SingleSpellInstance::~SingleSpellInstance()
{
	kdDebug() << k_funcinfo << "Destroying single speller instance" << endl;
	spellCheckerReady = false;
	mSpell->cleanUp();
	delete mSpell;
	delete words;
}

void SingleSpellInstance::slotViewDestroyed()
{
	delete this;
}

void SingleSpellInstance::slotSpellCheckerReady( KSpell * )
{
	//kdDebug() << k_funcinfo << "Single spell checker prepared!" << endl;
	spellCheckerReady = true;
}

void SingleSpellInstance::slotUpdateTextEdit()
{
	QString plainTextContents = t->text();

	//Save the selection and cursor positions
	int parIdx = 1, txtIdx = 1;
	int selParFrom = 1, selTxtFrom = 1, selParTo = 1, selTxtTo = 1;
	t->getSelection(&selParFrom, &selTxtFrom, &selParTo, &selTxtTo);
	t->getCursorPosition(&parIdx, &txtIdx);

	//Don't use red if the current color is too red
	QString highlightColor;
	if( t->paletteForegroundColor().red() < 250 )
		highlightColor = QString::fromLatin1("red");
	else
		highlightColor = QString::fromLatin1("blue");

	QStringList words = QStringList::split( mBound, plainTextContents );
	if( words.count() > 0 )
	{
		for( QStringList::Iterator it = words.begin(); it != words.end(); ++it )
		{
			if( mReplacements.contains(*it) )
			{
				plainTextContents.replace( QRegExp( QString::fromLatin1("\\b(%1)\\b").arg( *it ) ),
					QString::fromLatin1("") + *it +
					QString::fromLatin1("") );
			}
		}
	}

	//Update the highlighting
	t->setTextFormat( QTextEdit::RichText );
	t->setText( plainTextContents );
	t->setTextFormat( QTextEdit::PlainText );

	//Restore the selection and cursor positions
	t->setCursorPosition( parIdx, txtIdx );
	if( selParFrom > -1 )
		t->setSelection( selParFrom, selTxtFrom, selParTo, selTxtTo );
}

void SingleSpellInstance::slotMisspelling( const QString &originalword, const QStringList &suggestions, unsigned int )
{
	//kdDebug() << k_funcinfo << originalword << "IS MISSPELLED!" << endl;

	if( !mReplacements.contains( originalword ) )
		mReplacements[originalword] = suggestions;

	slotUpdateTextEdit();
}

bool SingleSpellInstance::eventFilter(QObject *o, QEvent *e)
{
	QWidget *w = static_cast<QWidget*>( o );

	switch( e->type() )
	{
		//Keypress event, to do the actual checking
		case QEvent::KeyPress:
		{
			if( spellCheckerReady )
			{
				QKeyEvent *event = (QKeyEvent*) e;

				//Only spellcheck when we hit a word delimiter
				if( !QChar( event->ascii() ).isLetterOrNumber() )
				{
					//We need to use an actual pointer for this, not just pass in the address of a veriable,
					//because KSpell is async and the variable will be deleted before KSpell completes
					delete words;
					words = new QStringList( QStringList::split( mBound, t->text() ) );
					if( words->count() > 0 )
						mSpell->checkList( words, false );
				}

				//Update highlighting
				slotUpdateTextEdit();
			}
			break;
		}

		//ContextMenu, to enable right click replace menu
		case QEvent::ContextMenu:
		{
			if ( spellCheckerReady )
			{
				QContextMenuEvent *event = (QContextMenuEvent*) e;

				int para = 0, charPos, firstSpace, lastSpace;

				//Get the character at the position of the click
				QString paraText = t->text( para );
				charPos = t->charAt( event->pos(), &para );

				if( !paraText.at(charPos).isSpace() )
				{
					//Get word right clicked on
					firstSpace = paraText.findRev( mBound, charPos ) + 1;
					lastSpace = paraText.find( mBound, charPos );
					if( lastSpace == -1 )
						lastSpace = paraText.length();
					QString word = paraText.mid( firstSpace, lastSpace - firstSpace );

					//Continue if this word was misspelled
					if( !word.isEmpty() && mReplacements.contains( word ) )
					{
						KPopupMenu p;
						p.insertTitle( i18n("Suggestions") );

						//Add the suggesitons to the popup menu
						QStringList reps = mReplacements[word];
						if( reps.count() > 0 )
						{
							int listPos = 0;
							for ( QStringList::Iterator it = reps.begin(); it != reps.end(); ++it ) {
								p.insertItem( *it, listPos );
								listPos++;
							}
						}
						else
						{
							p.insertItem( QString::fromLatin1("No Suggestions"), -2 );
						}

						//Execute the popup inline
						int id = p.exec( w->mapToGlobal( event->pos() ) );

						if( id > -1 )
						{
							//Save the cursor position
							int parIdx = 1, txtIdx = 1;
							t->getCursorPosition(&parIdx, &txtIdx);

							//Put in our replacement
							QString txtContents = t->text();
							QString newContents = txtContents.left(firstSpace) + mReplacements[word][id] +
								txtContents.right( txtContents.length() - lastSpace );
							t->setText( newContents );

							//Restore the cursor position
							if( txtIdx > lastSpace )
								txtIdx += newContents.length() - txtContents.length();
							t->setCursorPosition(parIdx, txtIdx);

							//Update highlighting
							slotUpdateTextEdit();
						}

						//Cancel original event
						return true;
					}
				}
			}

			break;
		}
		default:
			break;
	}

	//Return false so events keep propegating
	return false;
}

<commit_msg>Fixed a minor bug involving multiple paragraphs<commit_after>/*
    spellcheckplugin.cpp

    Kopete Spell Checking plugin

    Copyright (c) 2003 by Jason Keirstead   <jason@keirstead.org>

    Kopete    (c) 2002 by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This program 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 2 of the License, or     *
    * (at your option) any later version.                                   *
    *                                                                       *
    *************************************************************************
*/
#include <qtextedit.h>
#include <kpopupmenu.h>

#include <kdebug.h>
#include <kspell.h>
#include <klocale.h>

#include "kopeteviewmanager.h"
#include "singlespellinstance.h"
#include "spellcheckpreferences.h"

SingleSpellInstance::SingleSpellInstance( KopeteView *myView, SpellCheckPreferences *mPrefs ) : QObject( 0L )
{
	mView = myView;

	//If this object was created, we know we have a QTextEdit, so this is safe
	t = static_cast<QTextEdit*>( mView->editWidget() );
	t->installEventFilter( this );
	t->viewport()->installEventFilter( this );

	words = 0L;
	spellCheckerReady = false;

	//Define our word seperator regexp
	//We can't use \b because QT barfs when trying to split on it
	mBound = QRegExp( QString::fromLatin1("[\\s\\W]") );

	mSpell = new KSpell(0L, i18n("Spellcheck - Kopete"), this, SLOT( slotSpellCheckerReady( KSpell * )), mPrefs->spellConfig() );
	connect( mSpell, SIGNAL( misspelling( const QString&, const QStringList&, unsigned int ) ), this, SLOT( slotMisspelling( const QString&, const QStringList&, unsigned int ) ) );
	connect( dynamic_cast<QObject*>(mView), SIGNAL( destroyed() ), this, SLOT( slotViewDestroyed() ) );
}

SingleSpellInstance::~SingleSpellInstance()
{
	kdDebug() << k_funcinfo << "Destroying single speller instance" << endl;
	spellCheckerReady = false;
	mSpell->cleanUp();
	delete mSpell;
	delete words;
}

void SingleSpellInstance::slotViewDestroyed()
{
	delete this;
}

void SingleSpellInstance::slotSpellCheckerReady( KSpell * )
{
	//kdDebug() << k_funcinfo << "Single spell checker prepared!" << endl;
	spellCheckerReady = true;
}

void SingleSpellInstance::slotUpdateTextEdit()
{
	QString plainTextContents = t->text();

	//Save the selection and cursor positions
	int parIdx = 1, txtIdx = 1;
	int selParFrom = 1, selTxtFrom = 1, selParTo = 1, selTxtTo = 1;
	t->getSelection(&selParFrom, &selTxtFrom, &selParTo, &selTxtTo);
	t->getCursorPosition(&parIdx, &txtIdx);

	//Don't use red if the current color is too red
	QString highlightColor;
	if( t->paletteForegroundColor().red() < 250 )
		highlightColor = QString::fromLatin1("red");
	else
		highlightColor = QString::fromLatin1("blue");

	QStringList words = QStringList::split( mBound, plainTextContents );
	if( words.count() > 0 )
	{
		for( QStringList::Iterator it = words.begin(); it != words.end(); ++it )
		{
			if( mReplacements.contains(*it) )
			{
				plainTextContents.replace( QRegExp( QString::fromLatin1("\\b(%1)\\b").arg( *it ) ),
					QString::fromLatin1("") + *it +
					QString::fromLatin1("") );
			}
		}
	}

	//Update the highlighting
	t->setTextFormat( QTextEdit::RichText );
	t->setText( plainTextContents );
	t->setTextFormat( QTextEdit::PlainText );

	//Restore the selection and cursor positions
	t->setCursorPosition( parIdx, txtIdx );
	if( selParFrom > -1 )
		t->setSelection( selParFrom, selTxtFrom, selParTo, selTxtTo );
}

void SingleSpellInstance::slotMisspelling( const QString &originalword, const QStringList &suggestions, unsigned int )
{
	//kdDebug() << k_funcinfo << originalword << "IS MISSPELLED!" << endl;

	if( !mReplacements.contains( originalword ) )
		mReplacements[originalword] = suggestions;

	slotUpdateTextEdit();
}

bool SingleSpellInstance::eventFilter(QObject *o, QEvent *e)
{
	QWidget *w = static_cast<QWidget*>( o );

	switch( e->type() )
	{
		//Keypress event, to do the actual checking
		case QEvent::KeyPress:
		{
			if( spellCheckerReady )
			{
				QKeyEvent *event = (QKeyEvent*) e;

				//Only spellcheck when we hit a word delimiter
				if( !QChar( event->ascii() ).isLetterOrNumber() )
				{
					//We need to use an actual pointer for this, not just pass in the address of a veriable,
					//because KSpell is async and the variable will be deleted before KSpell completes
					delete words;
					words = new QStringList( QStringList::split( mBound, t->text() ) );
					if( words->count() > 0 )
						mSpell->checkList( words, false );
				}

				//Update highlighting
				slotUpdateTextEdit();
			}
			break;
		}

		//ContextMenu, to enable right click replace menu
		case QEvent::ContextMenu:
		{
			if ( spellCheckerReady )
			{
				QContextMenuEvent *event = (QContextMenuEvent*) e;

				int para = 1, charPos, firstSpace, lastSpace;

				//Get the character at the position of the click
				charPos = t->charAt( event->pos(), &para );
				QString paraText = t->text( para );

				if( !paraText.at(charPos).isSpace() )
				{
					//Get word right clicked on
					firstSpace = paraText.findRev( mBound, charPos ) + 1;
					lastSpace = paraText.find( mBound, charPos );
					if( lastSpace == -1 )
						lastSpace = paraText.length();
					QString word = paraText.mid( firstSpace, lastSpace - firstSpace );

					//Continue if this word was misspelled
					if( !word.isEmpty() && mReplacements.contains( word ) )
					{
						KPopupMenu p;
						p.insertTitle( i18n("Suggestions") );

						//Add the suggestions to the popup menu
						QStringList reps = mReplacements[word];
						if( reps.count() > 0 )
						{
							int listPos = 0;
							for ( QStringList::Iterator it = reps.begin(); it != reps.end(); ++it ) {
								p.insertItem( *it, listPos );
								listPos++;
							}
						}
						else
						{
							p.insertItem( QString::fromLatin1("No Suggestions"), -2 );
						}

						//Execute the popup inline
						int id = p.exec( w->mapToGlobal( event->pos() ) );

						if( id > -1 )
						{
							//Save the cursor position
							int parIdx = 1, txtIdx = 1;
							t->getCursorPosition(&parIdx, &txtIdx);

							//Put in our replacement
							QString txtContents = t->text();
							QString newContents = txtContents.left(firstSpace) + mReplacements[word][id] +
								txtContents.right( txtContents.length() - lastSpace );
							t->setText( newContents );

							//Restore the cursor position
							if( txtIdx > lastSpace )
								txtIdx += newContents.length() - txtContents.length();
							t->setCursorPosition(parIdx, txtIdx);

							//Update highlighting
							slotUpdateTextEdit();
						}

						//Cancel original event
						return true;
					}
				}
			}

			break;
		}
		default:
			break;
	}

	//Return false so events keep propegating
	return false;
}

<|endoftext|>


<commit_before>/* ****************************************************************************
*
* FILE                     main_samsonWorker.cpp
*
* AUTHOR                   Ken Zangelin
*
* CREATION DATE            Dec 14 2010
*
*/
#include "parseArgs/parseArgs.h"
#include "logMsg/logMsg.h"
#include "logMsg/traceLevels.h"

#include "au/LockDebugger.h"            // au::LockDebugger

#include "engine/MemoryManager.h"
#include "engine/Engine.h"
#include "engine/DiskManager.h"
#include "engine/ProcessManager.h"

#include "samson/network/Network2.h"
#include "samson/network/Endpoint2.h"
#include "samson/network/EndpointManager.h"
#include "samson/worker/SamsonWorker.h"
#include "samson/common/SamsonSetup.h"
#include "samson/isolated/SharedMemoryManager.h"
#include "samson/stream/BlockManager.h"
#include "samson/module/ModulesManager.h"

/* ****************************************************************************
*
* Option variables
*/
bool             noLog;
bool             local;
char             workingDir[1024];

#define NOLS    _i "no log server"
#define DEF_WD  _i SAMSON_DEFAULT_WORKING_DIRECTORY
/* ****************************************************************************
*
* parse arguments
*/
PaArgument paArgs[] =
{
	{ "-nolog",      &noLog,       "NO_LOG",      PaBool,    PaOpt,  false,  false,   true,  "no logging"            },
	{ "-local",      &local,       "LOCAL",       PaBool,    PaOpt,  false,  false,   true,  "local execution"       },
	{ "-working",     workingDir,  "WORKING",     PaString,  PaOpt, DEF_WD,   PaNL,   PaNL,  "working directory"     },

	PA_END_OF_ARGS
};

/* ****************************************************************************
*
* logFd - file descriptor for log file used in all libraries
*/
int                   logFd  = -1;
samson::SamsonWorker* worker = NULL;

/* ****************************************************************************
*
* exitFunction -
*/
void exitFunction(void)
{
	if (worker)
		delete worker;

	if (progName)
		free(progName);
}

/* ****************************************************************************
*
* man texts -
*/
static const char* manSynopsis         = " [OPTION]";
static const char* manShortDescription = "samsonWorker is the worker process of the samson platform, ...\n\n"
   "Complete list of options:\n";
static const char* manDescription      =
   "samsonWorker is the worker process in the samson cluster,\n"
   "which consists of one or more workers and ONE controller ...\n";

static const char* manExitStatus    = "0      if OK\n 1-255  error\n";
static const char* manAuthor        = "Written by Andreu Urruela, Ken Zangelin and J.Gregorio Escalada.";
static const char* manReportingBugs = "bugs to samson-bug-report@tid.es\nSamson home page: <http://www.tid.es/products/samson>";
static const char* manCopyright     = "Copyright (C) 2011 Telefonica Investigacion y Desarrollo";
static const char* manVersion       = "0.6-1";

void captureSIGPIPE( int s )
{
    LM_M(("Capturing SIGPIPE"));
}

/* ****************************************************************************
*
* main -
*/
int main(int argC, const char *argV[])
{
	paConfig("prefix",                        (void*) "SSW_");
	paConfig("usage and exit on any warning", (void*) true);
	paConfig("log to screen",                 (void*) "only errors");
	paConfig("log file line format",          (void*) "TYPE:DATE:EXEC-AUX/FILE[LINE](p.PID) FUNC: TEXT");
	paConfig("screen line format",            (void*) "TYPE@TIME  EXEC: TEXT");
	paConfig("log to file",                   (void*) true);

	paConfig("man synopsis",                  (void*) manSynopsis);
	paConfig("man shortdescription",          (void*) manShortDescription);
	paConfig("man description",               (void*) manDescription);
	paConfig("man exitstatus",                (void*) manExitStatus);
	paConfig("man author",                    (void*) manAuthor);
	paConfig("man reportingbugs",             (void*) manReportingBugs);
	paConfig("man copyright",                 (void*) manCopyright);
	paConfig("man version",                   (void*) manVersion);

	paParse(paArgs, argC, (char**) argV, 1, false);

	lmAux((char*) "father");

	atexit(google::protobuf::ShutdownProtobufLibrary);
	atexit(exitFunction);

	LM_T(LmtInit, ("Started with arguments:"));
	for (int ix = 0; ix < argC; ix++)
		LM_T(LmtInit, ("  %02d: '%s'", ix, argV[ix]));

	logFd = lmFirstDiskFileDescriptor();

    // Capturing SIGPIPE
    if( signal( SIGPIPE , captureSIGPIPE ) == SIG_ERR )
        LM_W(("SIGPIPE cannot be handled"));

    // Make sure this singlelton is created just once
    au::LockDebugger::shared();

	samson::SamsonSetup::init();  // Load setup and create default directories
    samson::SamsonSetup::shared()->setWorkingDirectory(workingDir);

	engine::SharedMemoryManager::init(samson::SamsonSetup::getInt("general.num_processess") , samson::SamsonSetup::getUInt64("general.shared_memory_size_per_buffer"));
	engine::Engine::init();
	engine::DiskManager::init(1);
	engine::ProcessManager::init(samson::SamsonSetup::getInt("general.num_processess"));
	engine::MemoryManager::init(samson::SamsonSetup::getUInt64("general.memory"));
	samson::ModulesManager::init();
    samson::stream::BlockManager::init();

	// Instance of network object and initialization
	// --------------------------------------------------------------------
	samson::EndpointManager* epMgr     = new samson::EndpointManager(samson::Endpoint2::Worker);
	samson::Network2*        networkP  = new samson::Network2(epMgr);

	LM_T(LmtInit, ("Waiting for network connection ..."));
	networkP->runInBackground();

	while (!networkP->ready())
		sleep(1);

	LM_T(LmtInit, ("Network Ready"));

	// Instance of SamsonWorker object (network contains at least the number of wokers)
	// -----------------------------------------------------------------------------------

	worker = new samson::SamsonWorker(networkP);

	// Not necessary anymore. Engine automatically starts with "init" call
	// engine::Engine::run();

    while( true )
        sleep(10);
}
<commit_msg>Fix broken compilation undex linux<commit_after>/* ****************************************************************************
*
* FILE                     main_samsonWorker.cpp
*
* AUTHOR                   Ken Zangelin
*
* CREATION DATE            Dec 14 2010
*
*/
#include "parseArgs/parseArgs.h"
#include "logMsg/logMsg.h"
#include "logMsg/traceLevels.h"

#include <signal.h>

#include "au/LockDebugger.h"            // au::LockDebugger

#include "engine/MemoryManager.h"
#include "engine/Engine.h"
#include "engine/DiskManager.h"
#include "engine/ProcessManager.h"

#include "samson/network/Network2.h"
#include "samson/network/Endpoint2.h"
#include "samson/network/EndpointManager.h"
#include "samson/worker/SamsonWorker.h"
#include "samson/common/SamsonSetup.h"
#include "samson/isolated/SharedMemoryManager.h"
#include "samson/stream/BlockManager.h"
#include "samson/module/ModulesManager.h"

/* ****************************************************************************
*
* Option variables
*/
bool             noLog;
bool             local;
char             workingDir[1024];

#define NOLS    _i "no log server"
#define DEF_WD  _i SAMSON_DEFAULT_WORKING_DIRECTORY
/* ****************************************************************************
*
* parse arguments
*/
PaArgument paArgs[] =
{
	{ "-nolog",      &noLog,       "NO_LOG",      PaBool,    PaOpt,  false,  false,   true,  "no logging"            },
	{ "-local",      &local,       "LOCAL",       PaBool,    PaOpt,  false,  false,   true,  "local execution"       },
	{ "-working",     workingDir,  "WORKING",     PaString,  PaOpt, DEF_WD,   PaNL,   PaNL,  "working directory"     },

	PA_END_OF_ARGS
};

/* ****************************************************************************
*
* logFd - file descriptor for log file used in all libraries
*/
int                   logFd  = -1;
samson::SamsonWorker* worker = NULL;

/* ****************************************************************************
*
* exitFunction -
*/
void exitFunction(void)
{
	if (worker)
		delete worker;

	if (progName)
		free(progName);
}

/* ****************************************************************************
*
* man texts -
*/
static const char* manSynopsis         = " [OPTION]";
static const char* manShortDescription = "samsonWorker is the worker process of the samson platform, ...\n\n"
   "Complete list of options:\n";
static const char* manDescription      =
   "samsonWorker is the worker process in the samson cluster,\n"
   "which consists of one or more workers and ONE controller ...\n";

static const char* manExitStatus    = "0      if OK\n 1-255  error\n";
static const char* manAuthor        = "Written by Andreu Urruela, Ken Zangelin and J.Gregorio Escalada.";
static const char* manReportingBugs = "bugs to samson-bug-report@tid.es\nSamson home page: <http://www.tid.es/products/samson>";
static const char* manCopyright     = "Copyright (C) 2011 Telefonica Investigacion y Desarrollo";
static const char* manVersion       = "0.6-1";

void captureSIGPIPE( int s )
{
    LM_M(("Capturing SIGPIPE"));
}

/* ****************************************************************************
*
* main -
*/
int main(int argC, const char *argV[])
{
	paConfig("prefix",                        (void*) "SSW_");
	paConfig("usage and exit on any warning", (void*) true);
	paConfig("log to screen",                 (void*) "only errors");
	paConfig("log file line format",          (void*) "TYPE:DATE:EXEC-AUX/FILE[LINE](p.PID) FUNC: TEXT");
	paConfig("screen line format",            (void*) "TYPE@TIME  EXEC: TEXT");
	paConfig("log to file",                   (void*) true);

	paConfig("man synopsis",                  (void*) manSynopsis);
	paConfig("man shortdescription",          (void*) manShortDescription);
	paConfig("man description",               (void*) manDescription);
	paConfig("man exitstatus",                (void*) manExitStatus);
	paConfig("man author",                    (void*) manAuthor);
	paConfig("man reportingbugs",             (void*) manReportingBugs);
	paConfig("man copyright",                 (void*) manCopyright);
	paConfig("man version",                   (void*) manVersion);

	paParse(paArgs, argC, (char**) argV, 1, false);

	lmAux((char*) "father");

	atexit(google::protobuf::ShutdownProtobufLibrary);
	atexit(exitFunction);

	LM_T(LmtInit, ("Started with arguments:"));
	for (int ix = 0; ix < argC; ix++)
		LM_T(LmtInit, ("  %02d: '%s'", ix, argV[ix]));

	logFd = lmFirstDiskFileDescriptor();

    // Capturing SIGPIPE
    if( signal( SIGPIPE , captureSIGPIPE ) == SIG_ERR )
        LM_W(("SIGPIPE cannot be handled"));

    // Make sure this singlelton is created just once
    au::LockDebugger::shared();

	samson::SamsonSetup::init();  // Load setup and create default directories
    samson::SamsonSetup::shared()->setWorkingDirectory(workingDir);

	engine::SharedMemoryManager::init(samson::SamsonSetup::getInt("general.num_processess") , samson::SamsonSetup::getUInt64("general.shared_memory_size_per_buffer"));
	engine::Engine::init();
	engine::DiskManager::init(1);
	engine::ProcessManager::init(samson::SamsonSetup::getInt("general.num_processess"));
	engine::MemoryManager::init(samson::SamsonSetup::getUInt64("general.memory"));
	samson::ModulesManager::init();
    samson::stream::BlockManager::init();

	// Instance of network object and initialization
	// --------------------------------------------------------------------
	samson::EndpointManager* epMgr     = new samson::EndpointManager(samson::Endpoint2::Worker);
	samson::Network2*        networkP  = new samson::Network2(epMgr);

	LM_T(LmtInit, ("Waiting for network connection ..."));
	networkP->runInBackground();

	while (!networkP->ready())
		sleep(1);

	LM_T(LmtInit, ("Network Ready"));

	// Instance of SamsonWorker object (network contains at least the number of wokers)
	// -----------------------------------------------------------------------------------

	worker = new samson::SamsonWorker(networkP);

	// Not necessary anymore. Engine automatically starts with "init" call
	// engine::Engine::run();

    while( true )
        sleep(10);
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief document request handler
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2013 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2010-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "RestEdgeHandler.h"

#include "Basics/StringUtils.h"
#include "BasicsC/conversions.h"
#include "BasicsC/tri-strings.h"
#include "Rest/HttpRequest.h"
#include "VocBase/document-collection.h"
#include "VocBase/edge-collection.h"
#include "Utilities/ResourceHolder.h"

using namespace std;
using namespace triagens::basics;
using namespace triagens::rest;
using namespace triagens::arango;

// -----------------------------------------------------------------------------
// --SECTION--                                      constructors and destructors
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup ArangoDB
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief constructor
////////////////////////////////////////////////////////////////////////////////

RestEdgeHandler::RestEdgeHandler (HttpRequest* request, TRI_vocbase_t* vocbase)
  : RestDocumentHandler(request, vocbase) {
}

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

// -----------------------------------------------------------------------------
// --SECTION--                                                 protected methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup ArangoDB
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief creates an edge
///
/// @RESTHEADER{POST /_api/edge,creates an edge}
///
/// @REST{POST /_api/edge?collection=`collection-name`&from=`from-handle`&to=`to-handle`}
///
/// Creates a new edge in the collection identified by `collection-name`.
/// A JSON representation of the edge document must be passed as the body of
/// the POST request. This JSON object may contain the edge's document key in
/// the `_key` attribute if needed.
/// The document handle of the start point must be passed in `from-handle`.
/// The document handle of the end point must be passed in `to-handle`.
///
/// `from-handle` and `to-handle` are immutable once the edge has been
/// created.
///
/// In all other respects the method works like `POST /document`, see
/// @ref RestDocument for details.
///
/// @EXAMPLES
///
/// Create an edge:
///
/// @verbinclude rest-edge-create-edge
///
/// Read an edge:
///
/// @verbinclude rest-edge-read-edge
////////////////////////////////////////////////////////////////////////////////

bool RestEdgeHandler::createDocument () {
  vector<string> const& suffix = _request->suffix();

  if (suffix.size() != 0) {
    generateError(HttpResponse::BAD,
                  TRI_ERROR_HTTP_SUPERFLUOUS_SUFFICES,
                  "superfluous suffix, expecting " + EDGE_PATH + "?collection=<identifier>");
    return false;
  }

  // edge
  TRI_document_edge_t edge;

  // extract the from
  bool found;
  char const* from = _request->value("from", found);

  if (! found || *from == '\0') {
    generateError(HttpResponse::BAD,
                  TRI_ERROR_HTTP_BAD_PARAMETER,
                  "'from' is missing, expecting " + EDGE_PATH + "?collection=<identifier>&from=<from-handle>&to=<to-handle>");
    return false;
  }

  // extract the to
  char const* to = _request->value("to", found);

  if (! found || *to == '\0') {
    generateError(HttpResponse::BAD,
                  TRI_ERROR_HTTP_BAD_PARAMETER,
                  "'to' is missing, expecting " + EDGE_PATH + "?collection=<identifier>&from=<from-handle>&to=<to-handle>");
    return false;
  }

  // extract the cid
  const string& collection = _request->value("collection", found);

  if (! found || collection.empty()) {
    generateError(HttpResponse::BAD,
                  TRI_ERROR_ARANGO_COLLECTION_PARAMETER_MISSING,
                  "'collection' is missing, expecting " + DOCUMENT_PATH + "?collection=<identifier>");
    return false;
  }

  const bool waitForSync = extractWaitForSync();

  // auto-ptr that will free JSON data when scope is left
  ResourceHolder holder;

  TRI_json_t* json = parseJsonBody();
  if (! holder.registerJson(TRI_UNKNOWN_MEM_ZONE, json)) {
    return false;
  }

  if (json->_type != TRI_JSON_ARRAY) {
    generateTransactionError(collection, TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID);
    return false;
  }

  if (! checkCreateCollection(collection, getCollectionType())) {
    return false;
  }

  // find and load collection given by name or identifier
  SingleCollectionWriteTransaction<StandaloneTransaction<RestTransactionContext>, 1> trx(_vocbase, _resolver, collection);

  // .............................................................................
  // inside write transaction
  // .............................................................................

  int res = trx.begin();
  if (res != TRI_ERROR_NO_ERROR) {
    generateTransactionError(collection, res);
    return false;
  }

  const TRI_voc_cid_t cid = trx.cid();

  edge._fromCid = cid;
  edge._toCid = cid;
  edge._fromKey = 0;
  edge._toKey = 0;

  res = parseDocumentId(from, edge._fromCid, edge._fromKey);
  holder.registerString(TRI_CORE_MEM_ZONE, edge._fromKey);

  if (res != TRI_ERROR_NO_ERROR) {
    if (res == TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND) {
      generateError(HttpResponse::NOT_FOUND, res, "'from' does not point to a valid collection");
    }
    else {
      generateError(HttpResponse::BAD, res, "'from' is not a document handle");
    }
    return false;
  }

  res = parseDocumentId(to, edge._toCid, edge._toKey);
  holder.registerString(TRI_CORE_MEM_ZONE, edge._toKey);

  if (res != TRI_ERROR_NO_ERROR) {
    if (res == TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND) {
      generateError(HttpResponse::NOT_FOUND, res, "'to' does not point to a valid collection");
    }
    else {
      generateError(HttpResponse::BAD, res, "'to' is not a document handle");
    }
    return false;
  }

  // .............................................................................
  // inside write transaction
  // .............................................................................

  // will hold the result
  TRI_doc_mptr_t document;
  res = trx.createEdge(&document, json, waitForSync, &edge);
  const bool wasSynchronous = trx.synchronous();
  res = trx.finish(res);

  // .............................................................................
  // outside write transaction
  // .............................................................................

  if (res != TRI_ERROR_NO_ERROR) {
    generateTransactionError(collection, res);
    return false;
  }

  assert(document._key != 0);

  // generate result
  if (wasSynchronous) {
    generateCreated(cid, document._key, document._rid);
  }
  else {
    generateAccepted(cid, document._key, document._rid);
  }

  return true;
}

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<commit_msg>minor changes<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief document request handler
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2013 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2010-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "RestEdgeHandler.h"

#include "Basics/StringUtils.h"
#include "BasicsC/conversions.h"
#include "BasicsC/tri-strings.h"
#include "Rest/HttpRequest.h"
#include "VocBase/document-collection.h"
#include "VocBase/edge-collection.h"
#include "Utilities/ResourceHolder.h"

using namespace std;
using namespace triagens::basics;
using namespace triagens::rest;
using namespace triagens::arango;

// -----------------------------------------------------------------------------
// --SECTION--                                      constructors and destructors
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup ArangoDB
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief constructor
////////////////////////////////////////////////////////////////////////////////

RestEdgeHandler::RestEdgeHandler (HttpRequest* request, TRI_vocbase_t* vocbase)
  : RestDocumentHandler(request, vocbase) {
}

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

// -----------------------------------------------------------------------------
// --SECTION--                                                 protected methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup ArangoDB
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief creates an edge
///
/// @RESTHEADER{POST /_api/edge,creates an edge}
///
/// @RESTQUERYPARAMETERS
///
/// @RESTQUERYPARAM{collection,string,required}
/// Creates a new edge in the collection identified by `collection` name.
///
/// @RESTQUERYPARAM{from,string,required}
/// The document handle of the start point must be passed in `from` handle.
///
/// @RESTQUERYPARAM{to,string,required}
/// The document handle of the end point must be passed in `to` handle.
///
/// @RESTBODYPARAM{edge-document,json,required}
/// A JSON representation of the edge document must be passed as the body of
/// the POST request. This JSON object may contain the edge's document key in
/// the `_key` attribute if needed.
///
/// @RESTDESCRIPTION
/// `from` handle and `to` handle are immutable once the edge has been
/// created.
///
/// In all other respects the method works like `POST /document`, see
/// @ref RestDocument for details.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{202}
/// is returned if the edge was created successfully.
///
/// @RESTRETURNCODE{404}
/// is returned if the edge collection was not found.
///
/// @EXAMPLES
///
/// Create an edge and reads it back:
///
/// @EXAMPLE_ARANGOSH_RUN{RestEdgeCreateEdge}
///     db._drop("edges");
///     db._drop("vertices");
///     var Graph = require("org/arangodb/graph").Graph;
///     var g = new Graph("graph", "vertices", "edges");
///     g.addVertex(1);
///     g.addVertex(2);
///     var url = "/_api/edge/?collection=edges&from=vertices/1&to=vertices/2";
///
///     var response = logCurlRequest("POST", url, { "name": "Emil" });
///
///     assert(response.code === 202);
///
///     logJsonResponse(response);
///     var body = response.body.replace(/\\/g, '');
///     var edge_id = JSON.parse(body)._id;
///     var response2 = logCurlRequest("GET", "/_api/edge/" + edge_id);
///
///     assert(response2.code === 200);
///
///     logJsonResponse(response2);
/// @END_EXAMPLE_ARANGOSH_RUN
////////////////////////////////////////////////////////////////////////////////

bool RestEdgeHandler::createDocument () {
  vector<string> const& suffix = _request->suffix();

  if (suffix.size() != 0) {
    generateError(HttpResponse::BAD,
                  TRI_ERROR_HTTP_SUPERFLUOUS_SUFFICES,
                  "superfluous suffix, expecting " + EDGE_PATH + "?collection=<identifier>");
    return false;
  }

  // edge
  TRI_document_edge_t edge;

  // extract the from
  bool found;
  char const* from = _request->value("from", found);

  if (! found || *from == '\0') {
    generateError(HttpResponse::BAD,
                  TRI_ERROR_HTTP_BAD_PARAMETER,
                  "'from' is missing, expecting " + EDGE_PATH + "?collection=<identifier>&from=<from-handle>&to=<to-handle>");
    return false;
  }

  // extract the to
  char const* to = _request->value("to", found);

  if (! found || *to == '\0') {
    generateError(HttpResponse::BAD,
                  TRI_ERROR_HTTP_BAD_PARAMETER,
                  "'to' is missing, expecting " + EDGE_PATH + "?collection=<identifier>&from=<from-handle>&to=<to-handle>");
    return false;
  }

  // extract the cid
  const string& collection = _request->value("collection", found);

  if (! found || collection.empty()) {
    generateError(HttpResponse::BAD,
                  TRI_ERROR_ARANGO_COLLECTION_PARAMETER_MISSING,
                  "'collection' is missing, expecting " + DOCUMENT_PATH + "?collection=<identifier>");
    return false;
  }

  const bool waitForSync = extractWaitForSync();

  // auto-ptr that will free JSON data when scope is left
  ResourceHolder holder;

  TRI_json_t* json = parseJsonBody();
  if (! holder.registerJson(TRI_UNKNOWN_MEM_ZONE, json)) {
    return false;
  }

  if (json->_type != TRI_JSON_ARRAY) {
    generateTransactionError(collection, TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID);
    return false;
  }

  if (! checkCreateCollection(collection, getCollectionType())) {
    return false;
  }

  // find and load collection given by name or identifier
  SingleCollectionWriteTransaction<StandaloneTransaction<RestTransactionContext>, 1> trx(_vocbase, _resolver, collection);

  // .............................................................................
  // inside write transaction
  // .............................................................................

  int res = trx.begin();
  if (res != TRI_ERROR_NO_ERROR) {
    generateTransactionError(collection, res);
    return false;
  }

  const TRI_voc_cid_t cid = trx.cid();

  edge._fromCid = cid;
  edge._toCid = cid;
  edge._fromKey = 0;
  edge._toKey = 0;

  res = parseDocumentId(from, edge._fromCid, edge._fromKey);
  holder.registerString(TRI_CORE_MEM_ZONE, edge._fromKey);

  if (res != TRI_ERROR_NO_ERROR) {
    if (res == TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND) {
      generateError(HttpResponse::NOT_FOUND, res, "'from' does not point to a valid collection");
    }
    else {
      generateError(HttpResponse::BAD, res, "'from' is not a document handle");
    }
    return false;
  }

  res = parseDocumentId(to, edge._toCid, edge._toKey);
  holder.registerString(TRI_CORE_MEM_ZONE, edge._toKey);

  if (res != TRI_ERROR_NO_ERROR) {
    if (res == TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND) {
      generateError(HttpResponse::NOT_FOUND, res, "'to' does not point to a valid collection");
    }
    else {
      generateError(HttpResponse::BAD, res, "'to' is not a document handle");
    }
    return false;
  }

  // .............................................................................
  // inside write transaction
  // .............................................................................

  // will hold the result
  TRI_doc_mptr_t document;
  res = trx.createEdge(&document, json, waitForSync, &edge);
  const bool wasSynchronous = trx.synchronous();
  res = trx.finish(res);

  // .............................................................................
  // outside write transaction
  // .............................................................................

  if (res != TRI_ERROR_NO_ERROR) {
    generateTransactionError(collection, res);
    return false;
  }

  assert(document._key != 0);

  // generate result
  if (wasSynchronous) {
    generateCreated(cid, document._key, document._rid);
  }
  else {
    generateAccepted(cid, document._key, document._rid);
  }

  return true;
}

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<|endoftext|>