text:
//******************************************************************************
// RCF - Remote Call Framework
//
// Copyright (c) 2005 - 2013, Delta V Software. All rights reserved.
// http://www.deltavsoft.com
//
// RCF is distributed under dual licenses - closed source or GPL.
// Consult your particular license for conditions of use.
//
// If you have not purchased a commercial license, you are using RCF
// under GPL terms.
//
// Version: 2.0
// Contact: support <at> deltavsoft.com
//
//******************************************************************************

#include <RCF/MethodInvocation.hpp>

#include <vector>

#include <boost/mpl/assert.hpp>

#include <RCF/CurrentSession.hpp>
#include <RCF/RcfServer.hpp>
#include <RCF/RcfSession.hpp>
#include <RCF/SerializationProtocol.hpp>
#include <RCF/Service.hpp>
#include <RCF/ThreadLocalData.hpp>

#include <SF/Encoding.hpp>

namespace RCF {

    void encodeServerError(RcfServer & server, ByteBuffer & byteBuffer, int error)
    {
        RCF_UNUSED_VARIABLE(server);

        const std::size_t Len = 4+1+1+4;

        if (byteBuffer.getLength() + byteBuffer.getLeftMargin() < Len)
        {
            byteBuffer = ByteBuffer(Len);
        }

        byteBuffer.setLeftMargin(4);

        std::size_t pos = 0;
        SF::encodeInt(Descriptor_Error, byteBuffer, pos);
        SF::encodeInt(0, byteBuffer, pos);
        SF::encodeInt(error, byteBuffer, pos);
    }

    void encodeServerError(RcfServer & server, ByteBuffer & byteBuffer, int error, int arg0, int arg1)
    {

        const std::size_t Len = 4+1+1+4+4;

        if (byteBuffer.getLength() + byteBuffer.getLeftMargin() < Len)
        {
            byteBuffer = ByteBuffer(Len);
        }

        byteBuffer.setLeftMargin(4);

        int ver = 0;
        if (server.getRuntimeVersion() >= 8)
        {
            ver = 1;
        }

        // without RCF:: qualifiers, borland chooses not to generate any code at all...
        std::size_t pos = 0;
        SF::encodeInt(Descriptor_Error, byteBuffer, pos);
        SF::encodeInt(ver, byteBuffer, pos);
        SF::encodeInt(error, byteBuffer, pos);
        SF::encodeInt(arg0, byteBuffer, pos);

        if (ver == 1)
        {
            SF::encodeInt(arg1, byteBuffer, pos);
        }
    }

    //*************************************
    // MethodInvocationRequest

    RemoteCallRequest::RemoteCallRequest(const MethodInvocationRequest & req) :
        mServantBindingName(req.mService),
        mInterfaceName(req.mSubInterface),
        mFnId(req.mFnId),
        mOneway(req.mOneway),
        mSerializationProtocol(req.mSerializationProtocol),
        mRuntimeVersion(req.mRuntimeVersion),
        mArchiveVersion(req.mArchiveVersion),
        mPingBackIntervalMs(req.mPingBackIntervalMs),
        mUseNativeWstringSerialization(req.mUseNativeWstringSerialization),
        mEnableSfPointerTracking(req.mEnableSfPointerTracking)
    {
    }

    MethodInvocationRequest::MethodInvocationRequest() :
        mToken(),
        mSubInterface(),
        mFnId(0),
        mSerializationProtocol(DefaultSerializationProtocol),
        mMarshalingProtocol(DefaultMarshalingProtocol),
        mOneway(false),
        mClose(false),
        mService(),
        mRuntimeVersion(0),
        mIgnoreRuntimeVersion(false),
        mPingBackIntervalMs(0),
        mArchiveVersion(0),
        mUseNativeWstringSerialization(false),
        mEnableSfPointerTracking(false)
    {
    }

    void MethodInvocationRequest::init(
        const Token &           token,
        const std::string &     service,
        const std::string &     subInterface,
        int                     fnId,
        SerializationProtocol   serializationProtocol,
        MarshalingProtocol      marshalingProtocol,
        bool                    oneway,
        bool                    close,
        int                     runtimeVersion,
        bool                    ignoreRuntimeVersion,
        boost::uint32_t         pingBackIntervalMs,
        int                     archiveVersion,
        bool                    useNativeWstringSerialization,
        bool                    enableSfPointerTracking)
    {
        mToken                      = token;
        mService                    = service;
        mSubInterface               = subInterface;
        mFnId                       = fnId;
        mSerializationProtocol      = serializationProtocol;
        mMarshalingProtocol         = marshalingProtocol;
        mOneway                     = oneway;
        mClose                      = close;
        mRuntimeVersion             = runtimeVersion;
        mIgnoreRuntimeVersion       = ignoreRuntimeVersion;
        mPingBackIntervalMs         = pingBackIntervalMs;
        mArchiveVersion             = archiveVersion;
        mUseNativeWstringSerialization = useNativeWstringSerialization;
        mEnableSfPointerTracking    = enableSfPointerTracking;
    }

    void MethodInvocationRequest::init(
        int                     runtimeVersion)
    {
        mRuntimeVersion             = runtimeVersion;
        mOneway                     = true;
    }

    void MethodInvocationRequest::init(
        const MethodInvocationRequest & rhs)
    {
        init(
            rhs.mToken,
            rhs.mService,
            rhs.mSubInterface,
            rhs.mFnId,
            rhs.mSerializationProtocol,
            rhs.mMarshalingProtocol,
            rhs.mOneway,
            rhs.mClose,
            rhs.mRuntimeVersion,
            rhs.mIgnoreRuntimeVersion,
            rhs.mPingBackIntervalMs,
            rhs.mArchiveVersion,
            rhs.mUseNativeWstringSerialization,
            rhs.mEnableSfPointerTracking);
    }

    Token MethodInvocationRequest::getToken() const
    {
        return mToken;
    }

    const std::string & MethodInvocationRequest::getSubInterface() const
    {
        return mSubInterface;
    }

    int MethodInvocationRequest::getFnId() const
    {
        return mFnId;
    }

    bool MethodInvocationRequest::getOneway() const
    {
        return mOneway;
    }

    bool MethodInvocationRequest::getClose() const
    {
        return mClose;
    }

    const std::string & MethodInvocationRequest::getService() const
    {
        return mService;
    }

    void MethodInvocationRequest::setService(const std::string &service)
    {
        mService = service;
    }

    int MethodInvocationRequest::getPingBackIntervalMs()
    {
        return mPingBackIntervalMs;
    }

    bool MethodInvocationRequest::decodeRequest(
        const ByteBuffer & message,
        ByteBuffer & messageBody,
        RcfSessionPtr rcfSessionPtr,
        RcfServer & rcfServer)
    {
        ByteBuffer buffer;

        ThreadLocalCached< std::vector<FilterPtr> > tlcNoFilters;
        std::vector<FilterPtr> &noFilters = tlcNoFilters.get();

        // Unfilter the message.
        decodeFromMessage(
            message,
            buffer,
            &rcfServer,
            rcfSessionPtr,
            noFilters);

        // Decode the request header.
        std::size_t pos = 0;
        mRuntimeVersion = 1;

        int tokenId = 0;
        int msgId = 0;
        int messageVersion = 0;

        bool ignoreRuntimeVersion = false;

        // For backwards compatibility.
        mEnableSfPointerTracking = true;

        SF::decodeInt(msgId, buffer, pos);
        RCF_VERIFY(msgId == Descriptor_Request, Exception(_RcfError_Decoding()))(msgId);
        SF::decodeInt(messageVersion, buffer, pos);

        if (messageVersion > 7)
        {
            return false;
        }

        SF::decodeString(mService, buffer, pos);
        SF::decodeInt(tokenId, buffer, pos);
        SF::decodeString(mSubInterface, buffer, pos);
        SF::decodeInt(mFnId, buffer, pos);

        int sp = 0;
        SF::decodeInt(sp, buffer, pos);
        mSerializationProtocol = SerializationProtocol(sp);

        SF::decodeBool(mOneway, buffer, pos);
        SF::decodeBool(mClose, buffer, pos);

        if (messageVersion == 1)
        {
            SF::decodeInt(mRuntimeVersion, buffer, pos);
            SF::decodeBool(ignoreRuntimeVersion, buffer, pos);
            mPingBackIntervalMs = 0;
        }
        else if (messageVersion == 2)
        {
            SF::decodeInt(mRuntimeVersion, buffer, pos);
            SF::decodeBool(ignoreRuntimeVersion, buffer, pos);
            SF::decodeInt(mPingBackIntervalMs, buffer, pos);
        }
        else if (messageVersion == 3)
        {
            SF::decodeInt(mRuntimeVersion, buffer, pos);
            SF::decodeBool(ignoreRuntimeVersion, buffer, pos);
            SF::decodeInt(mPingBackIntervalMs, buffer, pos);
            SF::decodeInt(mArchiveVersion, buffer, pos);
        }
        else if (messageVersion == 4)
        {
            SF::decodeInt(mRuntimeVersion, buffer, pos);
            SF::decodeBool(ignoreRuntimeVersion, buffer, pos);
            SF::decodeInt(mPingBackIntervalMs, buffer, pos);
            SF::decodeInt(mArchiveVersion, buffer, pos);
            SF::decodeByteBuffer(mRequestUserData, buffer, pos);
        }
        else if (messageVersion == 5)
        {
            SF::decodeInt(mRuntimeVersion, buffer, pos);
            SF::decodeBool(ignoreRuntimeVersion, buffer, pos);
            SF::decodeInt(mPingBackIntervalMs, buffer, pos);
            SF::decodeInt(mArchiveVersion, buffer, pos);
            SF::decodeByteBuffer(mRequestUserData, buffer, pos);
            SF::decodeBool(mUseNativeWstringSerialization, buffer, pos);
        }
        else if (messageVersion == 6)
        {
            SF::decodeInt(mRuntimeVersion, buffer, pos);
            SF::decodeBool(ignoreRuntimeVersion, buffer, pos);
            SF::decodeInt(mPingBackIntervalMs, buffer, pos);
            SF::decodeInt(mArchiveVersion, buffer, pos);
            SF::decodeByteBuffer(mRequestUserData, buffer, pos);
            SF::decodeBool(mUseNativeWstringSerialization, buffer, pos);
            SF::decodeBool(mEnableSfPointerTracking, buffer, pos);
        }
        else if (messageVersion == 7)
        {
            SF::decodeInt(mRuntimeVersion, buffer, pos);
            SF::decodeBool(ignoreRuntimeVersion, buffer, pos);
            SF::decodeInt(mPingBackIntervalMs, buffer, pos);
            SF::decodeInt(mArchiveVersion, buffer, pos);
            SF::decodeByteBuffer(mRequestUserData, buffer, pos);
            SF::decodeBool(mUseNativeWstringSerialization, buffer, pos);
            SF::decodeBool(mEnableSfPointerTracking, buffer, pos);
            SF::decodeByteBuffer(mOutOfBandRequest, buffer, pos);
        }

        mToken = Token(tokenId);

        if (mSubInterface.empty())
        {
            mSubInterface = mService;
        }

        // Check runtime version.
        if (mRuntimeVersion > rcfServer.getRuntimeVersion())
        {
            return false;
        }
        else
        {
            rcfSessionPtr->setRuntimeVersion(mRuntimeVersion);
        }

        // Check archive version.
        boost::uint32_t serverArchiveVersion = rcfServer.getArchiveVersion();
        if (serverArchiveVersion && mArchiveVersion > serverArchiveVersion)
        {
            return false;
        }
        else
        {
            rcfSessionPtr->setArchiveVersion(mArchiveVersion);
        }

        rcfSessionPtr->setNativeWstringSerialization(mUseNativeWstringSerialization);

        messageBody = ByteBuffer(buffer, pos);

        return true;
    }

    bool MethodInvocationRequest::encodeResponse(
        const RemoteException *         pRe,
        ByteBuffer &                    buffer,
        bool                            enableSfPointerTracking)
    {
        bool isException = pRe ? true : false;

        RCF_ASSERT(!mVecPtr || mVecPtr.unique());
        if (!mVecPtr)
        {
            mVecPtr.reset(new std::vector<char>(50));
        }

        int runtimeVersion = mRuntimeVersion;
        int messageVersion = 0;

        if (runtimeVersion < 7)
        {
            messageVersion = 0;
        }
        else if (runtimeVersion <= 9)
        {
            messageVersion = 1;
        }
        else if (runtimeVersion <= 11)
        {
            messageVersion = 2;
        }
        else
        {
            messageVersion = 3;
        }

        std::size_t pos = 0;
        BOOST_STATIC_ASSERT(0 <= Descriptor_Response && Descriptor_Response < 255);
        SF::encodeInt(Descriptor_Response, *mVecPtr, pos);
        SF::encodeInt(messageVersion, *mVecPtr, pos);
        SF::encodeBool(isException, *mVecPtr, pos);

        if (messageVersion == 1)
        {
            SF::encodeByteBuffer(mResponseUserData, *mVecPtr, pos);
        }
        else if (messageVersion == 2)
        {
            SF::encodeByteBuffer(mResponseUserData, *mVecPtr, pos);
            SF::encodeBool(enableSfPointerTracking, *mVecPtr, pos);
        }
        else if (messageVersion == 3)
        {
            SF::encodeByteBuffer(mResponseUserData, *mVecPtr, pos);
            SF::encodeBool(enableSfPointerTracking, *mVecPtr, pos);
            SF::encodeByteBuffer(mOutOfBandResponse, *mVecPtr, pos);
        }

        mVecPtr->resize(pos);

        buffer = ByteBuffer(mVecPtr);

        // If there was an exception, it still needs to be serialized.
        return true;
    }

    const std::string EmptyString;

    ByteBuffer MethodInvocationRequest::encodeRequestHeader()
    {
        RCF_ASSERT(!mVecPtr || mVecPtr.unique());
        if (!mVecPtr)
        {
            mVecPtr.reset(new std::vector<char>(50));
        }

        int runtimeVersion = mRuntimeVersion;
        int messageVersion = 0;

        if (runtimeVersion < 2)
        {
            messageVersion = 0;
        }
        else if (runtimeVersion < 5)
        {
            messageVersion = 1;
        }
        else if (runtimeVersion == 5)
        {
            messageVersion = 2;
        }
        else if (runtimeVersion == 6)
        {
            messageVersion = 3;
        }
        else if (runtimeVersion == 7)
        {
            messageVersion = 4;
        }
        else if (runtimeVersion <= 9)
        {
            messageVersion = 5;
        }
        else if (runtimeVersion <= 11)
        {
            messageVersion = 6;
        }
        else
        {
            messageVersion = 7;
        }

        std::size_t pos = 0;
        SF::encodeInt(Descriptor_Request, *mVecPtr, pos);
        SF::encodeInt(messageVersion, *mVecPtr, pos);
        SF::encodeString(mService, *mVecPtr, pos);
        SF::encodeInt(mToken.getId(), *mVecPtr, pos);

        mSubInterface == mService ?
            SF::encodeString(EmptyString, *mVecPtr, pos) :
            SF::encodeString(mSubInterface, *mVecPtr, pos);

        SF::encodeInt(mFnId, *mVecPtr, pos);
        SF::encodeInt(mSerializationProtocol, *mVecPtr, pos);
        SF::encodeBool(mOneway, *mVecPtr, pos);
        SF::encodeBool(mClose, *mVecPtr, pos);

        if (messageVersion == 1)
        {
            SF::encodeInt(mRuntimeVersion, *mVecPtr, pos);
            SF::encodeBool(mIgnoreRuntimeVersion, *mVecPtr, pos);
        }
        else if (messageVersion == 2)
        {
            SF::encodeInt(mRuntimeVersion, *mVecPtr, pos);
            SF::encodeBool(mIgnoreRuntimeVersion, *mVecPtr, pos);
            SF::encodeInt(mPingBackIntervalMs, *mVecPtr, pos);
        }
        else if (messageVersion == 3)
        {
            SF::encodeInt(mRuntimeVersion, *mVecPtr, pos);
            SF::encodeBool(mIgnoreRuntimeVersion, *mVecPtr, pos);
            SF::encodeInt(mPingBackIntervalMs, *mVecPtr, pos);
            SF::encodeInt(mArchiveVersion, *mVecPtr, pos);
        }
        else if (messageVersion == 4)
        {
            SF::encodeInt(mRuntimeVersion, *mVecPtr, pos);
            SF::encodeBool(mIgnoreRuntimeVersion, *mVecPtr, pos);
            SF::encodeInt(mPingBackIntervalMs, *mVecPtr, pos);
            SF::encodeInt(mArchiveVersion, *mVecPtr, pos);
            SF::encodeByteBuffer(mRequestUserData, *mVecPtr, pos);
        }
        else if (messageVersion == 5)
        {
            SF::encodeInt(mRuntimeVersion, *mVecPtr, pos);
            SF::encodeBool(mIgnoreRuntimeVersion, *mVecPtr, pos);
            SF::encodeInt(mPingBackIntervalMs, *mVecPtr, pos);
            SF::encodeInt(mArchiveVersion, *mVecPtr, pos);
            SF::encodeByteBuffer(mRequestUserData, *mVecPtr, pos);
            SF::encodeBool(mUseNativeWstringSerialization, *mVecPtr, pos);
        }
        else if (messageVersion == 6)
        {
            SF::encodeInt(mRuntimeVersion, *mVecPtr, pos);
            SF::encodeBool(mIgnoreRuntimeVersion, *mVecPtr, pos);
            SF::encodeInt(mPingBackIntervalMs, *mVecPtr, pos);
            SF::encodeInt(mArchiveVersion, *mVecPtr, pos);
            SF::encodeByteBuffer(mRequestUserData, *mVecPtr, pos);
            SF::encodeBool(mUseNativeWstringSerialization, *mVecPtr, pos);
            SF::encodeBool(mEnableSfPointerTracking, *mVecPtr, pos);
        }
        else if (messageVersion == 7)
        {
            SF::encodeInt(mRuntimeVersion, *mVecPtr, pos);
            SF::encodeBool(mIgnoreRuntimeVersion, *mVecPtr, pos);
            SF::encodeInt(mPingBackIntervalMs, *mVecPtr, pos);
            SF::encodeInt(mArchiveVersion, *mVecPtr, pos);
            SF::encodeByteBuffer(mRequestUserData, *mVecPtr, pos);
            SF::encodeBool(mUseNativeWstringSerialization, *mVecPtr, pos);
            SF::encodeBool(mEnableSfPointerTracking, *mVecPtr, pos);
            SF::encodeByteBuffer(mOutOfBandRequest, *mVecPtr, pos);
        }

        mVecPtr->resize(pos);

        return ByteBuffer(mVecPtr);
    }

    void MethodInvocationRequest::encodeRequest(
        const std::vector<ByteBuffer> &buffers,
        std::vector<ByteBuffer> &message,
        const std::vector<FilterPtr> &filters)
    {
        encodeToMessage(
            message,
            buffers,
            filters);
    }

    void MethodInvocationRequest::decodeResponse(const ByteBuffer &message,
        ByteBuffer &buffer,
        MethodInvocationResponse &response,
        const std::vector<FilterPtr> &filters)
    {
        decodeFromMessage(
            message,
            buffer,
            NULL,
            RcfSessionPtr(),
            filters);

        std::size_t pos = 0;

        // Decode response header.
        int msgId = 0;
        SF::decodeInt(msgId, buffer, pos);

        int ver = 0;
        SF::decodeInt(ver, buffer, pos);

        if (msgId == Descriptor_Error)
        {
            RCF_VERIFY(ver <= 1, Exception(_RcfError_Decoding()))(ver);

            int error = 0;
            SF::decodeInt(error, buffer, pos);
            response.mException = false;
            response.mError = true;
            response.mErrorCode = error;
            if (
                error == RcfError_VersionMismatch ||
                error == RcfError_PingBack)
            {
                SF::decodeInt(response.mArg0, buffer, pos);

                if (ver == 1)
                {
                    SF::decodeInt(response.mArg1, buffer, pos);
                }
            }
        }
        else
        {
            RCF_VERIFY(msgId == Descriptor_Response, Exception(_RcfError_Decoding()))(msgId);
            RCF_VERIFY(ver <= 3, Exception(_RcfError_Decoding()))(ver);

            // For backwards compatibility.
            response.mEnableSfPointerTracking = true;

            SF::decodeBool(response.mException, buffer, pos);

            if (ver == 1)
            {
                SF::decodeByteBuffer(mResponseUserData, buffer, pos);
            }
            else if (ver == 2)
            {
                SF::decodeByteBuffer(mResponseUserData, buffer, pos);
                SF::decodeBool(response.mEnableSfPointerTracking, buffer, pos);
            }
            else if (ver == 3)
            {
                SF::decodeByteBuffer(mResponseUserData, buffer, pos);
                SF::decodeBool(response.mEnableSfPointerTracking, buffer, pos);
                SF::decodeByteBuffer(mOutOfBandResponse, buffer, pos);
            }

            response.mError = false;
            response.mErrorCode = 0;
            response.mArg0 = 0;
            response.mArg1 = 0;
        }

        // Return the response body.
        buffer = ByteBuffer(buffer, pos);
    }

    StubEntryPtr MethodInvocationRequest::locateStubEntryPtr(
        RcfServer &rcfServer)
    {
        Token targetToken = getToken();
        const std::string & targetName = getService();
        StubEntryPtr stubEntryPtr;
        RcfSession * pRcfSession = getTlsRcfSessionPtr();

        if (targetToken != Token())
        {
            stubEntryPtr = rcfServer.findStubEntryForToken(targetToken);
        }
        else if (!targetName.empty())
        {
            ReadLock readLock(rcfServer.mStubMapMutex);
            const std::string & servantName = getService();
            RcfServer::StubMap::iterator iter = rcfServer.mStubMap.find(servantName);
            if (iter != rcfServer.mStubMap.end())
            {
                stubEntryPtr = (*iter).second;
            }
        }
        else
        {
            stubEntryPtr = pRcfSession->getDefaultStubEntryPtr();
        }

        return stubEntryPtr;
    }

    //*******************************************
    // MethodInvocationResponse

    MethodInvocationResponse::MethodInvocationResponse() :
        mException(),
        mError(),
        mErrorCode(),
        mArg0(),
        mArg1(),
        mEnableSfPointerTracking(false)
    {}

    bool MethodInvocationResponse::isException() const
    {
        return mException;
    }

    bool MethodInvocationResponse::isError() const
    {
        return mError;
    }

    int MethodInvocationResponse::getError() const
    {
        return mErrorCode;
    }

    int MethodInvocationResponse::getArg0() const
    {
        return mArg0;
    }

    int MethodInvocationResponse::getArg1() const
    {
        return mArg1;
    }

    std::auto_ptr<RemoteException> MethodInvocationResponse::getExceptionPtr()
    {
        return mExceptionPtr;
    }

    bool MethodInvocationResponse::getEnableSfPointerTracking() const
    {
        return mEnableSfPointerTracking;
    }

    //*******************************************

    void MethodInvocationRequest::encodeToMessage(
        std::vector<ByteBuffer> &message,
        const std::vector<ByteBuffer> &buffers,
        const std::vector<FilterPtr> &filters)
    {
        if (filters.empty())
        {
            // No filters, so nothing to do really.

            message.resize(0);

            std::copy(
                buffers.begin(),
                buffers.end(),
                std::back_inserter(message));
        }
        else
        {
            // Pass the buffers through the filters.

            ThreadLocalCached< std::vector<ByteBuffer> > tlcFilteredBuffers;
            std::vector<ByteBuffer> &filteredBuffers = tlcFilteredBuffers.get();

            std::size_t unfilteredLen = lengthByteBuffers(buffers);
            bool ok = filterData(buffers, filteredBuffers, filters);
            RCF_VERIFY(ok, Exception(_RcfError_FilterMessage()));

            message.resize(0);

            std::copy(
                filteredBuffers.begin(),
                filteredBuffers.end(),
                std::back_inserter(message));

            if (filteredBuffers.empty())
            {
                // Can happen if buffers has e.g. a single zero length buffer.
                RCF_ASSERT_EQ(lengthByteBuffers(buffers) , 0);
                RCF_ASSERT(!buffers.empty());
                RCF_ASSERT_EQ(buffers.front().getLength() , 0);
                message.push_back(buffers.front());
            }

            // Encode the filter header.
            const std::size_t BufferLen = (5+10)*4;
            char buffer[BufferLen];
            ByteBuffer byteBuffer(&buffer[0], BufferLen);

            std::size_t pos = 0;

            // Descriptor
            SF::encodeInt(Descriptor_FilteredPayload, byteBuffer, pos);

            // Version.
            SF::encodeInt(0, byteBuffer, pos);

            RCF_VERIFY(
                filters.size() <= 10,
                Exception(_RcfError_FilterCount(filters.size(), 10)));

            // Number of filters.
            SF::encodeInt(static_cast<int>(filters.size()), byteBuffer, pos);

            // Filter ids.
            for (std::size_t i=0; i<filters.size(); ++i)
            {
                int filterId = filters[i]->getFilterId();
                SF::encodeInt(filterId, byteBuffer, pos);
            }

            // Legacy, not used anymore.
            int filterHeaderLen = 0;
            SF::encodeInt(filterHeaderLen, byteBuffer, pos);

            // Length of the message when it is unfiltered.
            int len = static_cast<int>(unfilteredLen);
            SF::encodeInt(len, byteBuffer, pos);

            // Copy the filter header into the left margin of the first buffer.
            std::size_t headerLen = pos;

            RCF_ASSERT_LTEQ(headerLen, BufferLen);

            RCF_ASSERT(
                !message.empty() &&
                message.front().getLeftMargin() >= headerLen)
                (message.front().getLeftMargin())(headerLen);

            if ( headerLen > BufferLen )
            {
                RCF_THROW(_RcfError_MessageHeaderEncoding(BufferLen, headerLen));
            }

            ByteBuffer &front = message.front();
            front.expandIntoLeftMargin(headerLen);
            memcpy(front.getPtr(), &buffer[0], headerLen);
        }
    }

    struct FilterIdComparison
    {
        bool operator()(FilterPtr filterPtr, int filterId)
        {
            return filterPtr->getFilterId() == filterId;
        }
    };

#if RCF_FEATURE_PROTOBUF==1
    static const bool SupportProtobufs = true;
#else
    static const bool SupportProtobufs = false;
#endif

    void MethodInvocationRequest::decodeFromMessage(
        const ByteBuffer &message,
        ByteBuffer &buffer,
        RcfServer *pRcfServer,
        RcfSessionPtr rcfSessionPtr,
        const std::vector<FilterPtr> &existingFilters)
    {
        ThreadLocalCached< std::vector<int> > tlcFilterIds;
        std::vector<int> &filterIds = tlcFilterIds.get();

        // Decode the filter header, if there is one.
        std::size_t pos = 0;
        std::size_t unfilteredLen = 0;

        mMarshalingProtocol = Mp_Rcf;

        char * const pch = (char*) message.getPtr() ;
        if (pch[0] == Descriptor_FilteredPayload)
        {
            int descriptor = 0;
            SF::decodeInt(descriptor, message, pos);
            RCF_VERIFY(descriptor == Descriptor_FilteredPayload, Exception(_RcfError_Decoding()))(descriptor);

            int version = 0;
            SF::decodeInt(version, message, pos);
            RCF_VERIFY(version == 0, Exception(_RcfError_Decoding()))(version);

            int filterCount = 0;
            SF::decodeInt(filterCount, message, pos);
            RCF_VERIFY(0 < filterCount && filterCount <= 10, Exception(_RcfError_Decoding()))(filterCount);

            filterIds.resize(0);
            for (int i=0; i<filterCount; ++i)
            {
                int filterId = 0;
                SF::decodeInt(filterId, message, pos);
                filterIds.push_back(filterId);
            }

            int clearLen = 0;
            SF::decodeInt(clearLen, message, pos);
            RCF_VERIFY(0 <= clearLen, Exception(_RcfError_Decoding()))(clearLen);

            int unfilteredLen_ = 0;
            SF::decodeInt(unfilteredLen_, message, pos);
            RCF_VERIFY(0 <= unfilteredLen_, Exception(_RcfError_Decoding()))(unfilteredLen_);
            unfilteredLen = unfilteredLen_;
        }

        ByteBuffer filteredData(message, pos);

        if (pRcfServer)
        {
            // Server side decoding.

            if (filterIds.empty())
            {
                rcfSessionPtr->setFiltered(false);
                buffer = filteredData;
            }
            else
            {
                rcfSessionPtr->setFiltered(true);
                std::vector<FilterPtr> &filters = rcfSessionPtr->getFilters();

                if (    filters.size() != filterIds.size()
                    ||    !std::equal(
                            filters.begin(),
                            filters.end(),
                            filterIds.begin(),
                            FilterIdComparison()))
                {
                    filters.clear();

                    std::transform(
                        filterIds.begin(),
                        filterIds.end(),
                        std::back_inserter(filters),
                        boost::bind( &RcfServer::createFilter, pRcfServer, _1) );

                    if (
                        std::find_if(
                            filters.begin(),
                            filters.end(),
                            SharedPtrIsNull()) == filters.end())
                    {
                        connectFilters(filters);
                    }
                    else
                    {
                        // TODO: better not to throw exceptions here?
                        Exception e(_RcfError_UnknownFilter());
                        RCF_THROW(e);
                    }
                }

                bool bRet = unfilterData(
                    filteredData,
                    buffer,
                    unfilteredLen,
                    filters);

                RCF_ASSERT(bRet);
                RCF_UNUSED_VARIABLE(bRet);
            }
        }
        else
        {
            // Client side decoding.

            if (    existingFilters.size() == filterIds.size()
                &&    std::equal(
                        existingFilters.begin(),
                        existingFilters.end(),
                        filterIds.begin(),
                        FilterIdComparison()))
            {
                if (existingFilters.empty())
                {
                    buffer = filteredData;
                }
                else
                {
                    bool bRet = unfilterData(
                        filteredData,
                        buffer,
                        unfilteredLen,
                        existingFilters);

                    RCF_VERIFY(bRet, Exception(_RcfError_UnfilterMessage()));
                }
            }
            else
            {
                Exception e(_RcfError_PayloadFilterMismatch());
                RCF_THROW(e);
            }
        }
    }

    // Out of band messages.

    OobMessage::OobMessage(int runtimeVersion) :
        mRuntimeVersion(runtimeVersion),
        mResponseError(0)
    {
    }

    OobMessage::~OobMessage()
    {
    }

    void OobMessage::encodeResponse(ByteBuffer & buffer)
    {
        boost::shared_ptr< std::vector<char> > vecPtr( new std::vector<char>(50) );
        std::size_t pos = 0;
        encodeResponseCommon(vecPtr, pos);
        vecPtr->resize(pos);
        buffer = ByteBuffer(vecPtr);
    }

    void OobMessage::decodeResponse(const ByteBuffer & buffer)
    {
        std::size_t pos = 0;
        decodeResponseCommon(buffer, pos);
    }

    void OobMessage::encodeRequestCommon(VecPtr vecPtr, std::size_t & pos)
    {
        int magicNumber = 65;
        int msgType = getMessageType();
        int msgVersion = mRuntimeVersion;

        SF::encodeInt(magicNumber, *vecPtr, pos);
        SF::encodeInt(msgType, *vecPtr, pos);
        SF::encodeInt(msgVersion, *vecPtr, pos);
    }

    void OobMessage::encodeResponseCommon(VecPtr vecPtr, std::size_t & pos)
    {
        int magicNumber = 66;
        int msgType = getMessageType();
        int msgVersion = mRuntimeVersion;

        SF::encodeInt(magicNumber, *vecPtr, pos);
        SF::encodeInt(msgType, *vecPtr, pos);
        SF::encodeInt(msgVersion, *vecPtr, pos);
        SF::encodeInt(mResponseError, *vecPtr, pos);
        SF::encodeString(mResponseErrorString, *vecPtr, pos);
    }

    void OobMessage::decodeResponseCommon(const ByteBuffer & buffer, std::size_t & pos)
    {
        int magicNumber = 0;
        int msgType = 0;
        int msgVersion = 0;

        SF::decodeInt(magicNumber, buffer, pos);
        RCF_VERIFY(magicNumber == 66, Exception(_RcfError_Decoding()));

        SF::decodeInt(msgType, buffer, pos);
        RCF_VERIFY(msgType == getMessageType(), Exception(_RcfError_Decoding()));

        SF::decodeInt(msgVersion, buffer, pos);
        RCF_VERIFY(msgVersion == mRuntimeVersion, Exception(_RcfError_Decoding()));

        SF::decodeInt(mResponseError, buffer, pos);
        SF::decodeString(mResponseErrorString, buffer, pos);
    }

    OobMessagePtr OobMessage::decodeRequestCommon(const ByteBuffer & buffer)
    {
        std::size_t pos = 0;

        int magicNumber = 0;
        int msgType = 0;
        int msgVersion = 0;

        SF::decodeInt(magicNumber, buffer, pos);
        RCF_VERIFY(magicNumber == 65, Exception(_RcfError_Decoding()));

        SF::decodeInt(msgType, buffer, pos);
        SF::decodeInt(msgVersion, buffer, pos);

        OobMessagePtr msgPtr;
        switch (msgType)
        {
        case Omt_RequestTransportFilters:
            msgPtr.reset( new OobRequestTransportFilters(msgVersion) );
            break;

        case Omt_CreateCallbackConnection:
            msgPtr.reset( new OobCreateCallbackConnection(msgVersion) );
            break;

        case Omt_RequestSubscription:
            msgPtr.reset( new OobRequestSubscription(msgVersion) );
            break;

        default:
            RCF_THROW( Exception(_RcfError_Decoding()) );
        }

        msgPtr->decodeRequest(buffer, pos);

        return msgPtr;
    }

    // OobRequestTransportFilters

    OobRequestTransportFilters::OobRequestTransportFilters(int runtimeVersion) :
        OobMessage(runtimeVersion)
    {
    }

    OobRequestTransportFilters::OobRequestTransportFilters(
        int runtimeVersion,
        const std::vector<FilterPtr> &filters) :
            OobMessage(runtimeVersion)
    {
        for (std::size_t i=0; i<filters.size(); ++i)
        {
            mFilterIds.push_back( filters[i]->getFilterId() );
        }
    }

    OobMessageType OobRequestTransportFilters::getMessageType()
    {
        return Omt_RequestTransportFilters;
    }

    void OobRequestTransportFilters::encodeRequest(ByteBuffer & buffer)
    {
        boost::shared_ptr< std::vector<char> > vecPtr( new std::vector<char>(50) );
        std::size_t pos = 0;

        encodeRequestCommon(vecPtr, pos);

        if (mRuntimeVersion <= 12)
        {
            int filterCount = static_cast<int>(mFilterIds.size());
            SF::encodeInt(filterCount, *vecPtr, pos);
            for (std::size_t i=0; i<mFilterIds.size(); ++i)
            {
                SF::encodeInt(mFilterIds[i], *vecPtr, pos);
            }
        }

        vecPtr->resize(pos);
        buffer = ByteBuffer(vecPtr);
    }

    void OobRequestTransportFilters::decodeRequest(const ByteBuffer & buffer, std::size_t & pos)
    {
        if (mRuntimeVersion <= 12)
        {
            int filterCount = 0;
            SF::decodeInt(filterCount, buffer, pos);
            RCF_VERIFY(filterCount <= 10, Exception(_RcfError_Decoding()));

            mFilterIds.clear();
            for (int i=0; i<filterCount; ++i)
            {
                int filterId = 0;
                SF::decodeInt(filterId, buffer, pos);
                mFilterIds.push_back(filterId);
            }
        }
    }

    // OobCreateCallbackConnection

    OobCreateCallbackConnection::OobCreateCallbackConnection(int runtimeVersion) :
        OobMessage(runtimeVersion)
    {
    }

    OobMessageType OobCreateCallbackConnection::getMessageType()
    {
        return Omt_CreateCallbackConnection;
    }

    void OobCreateCallbackConnection::encodeRequest(ByteBuffer & buffer)
    {
        boost::shared_ptr< std::vector<char> > vecPtr( new std::vector<char>(50) );
        std::size_t pos = 0;
        encodeRequestCommon(vecPtr, pos);
        vecPtr->resize(pos);
        buffer = ByteBuffer(vecPtr);
    }

    void OobCreateCallbackConnection::decodeRequest(
        const ByteBuffer & buffer,
        std::size_t & pos)
    {
        RCF_UNUSED_VARIABLE(buffer);
        RCF_UNUSED_VARIABLE(pos);
    }

    // OobRequestSubscription

    OobRequestSubscription::OobRequestSubscription(int runtimeVersion) :
        OobMessage(runtimeVersion),
        mPublisherName(),
        mSubToPubPingIntervalMs(0),
        mPubToSubPingIntervalMs(0)
    {
    }

    OobRequestSubscription::OobRequestSubscription(
        int                     runtimeVersion,
        const std::string &     publisherName,
        boost::uint32_t         subToPubPingIntervalMs) :
            OobMessage(runtimeVersion),
            mPublisherName(publisherName),
            mSubToPubPingIntervalMs(subToPubPingIntervalMs),
            mPubToSubPingIntervalMs(0)
    {
    }

    OobMessageType OobRequestSubscription::getMessageType()
    {
        return Omt_RequestSubscription;
    }

    void OobRequestSubscription::encodeRequest(ByteBuffer & buffer)
    {
        boost::shared_ptr< std::vector<char> > vecPtr( new std::vector<char>(50) );
        std::size_t pos = 0;
        encodeRequestCommon(vecPtr, pos);

        SF::encodeString(mPublisherName, *vecPtr, pos);
        SF::encodeInt(mSubToPubPingIntervalMs, *vecPtr, pos);

        vecPtr->resize(pos);
        buffer = ByteBuffer(vecPtr);
    }

    void OobRequestSubscription::decodeRequest(
        const ByteBuffer & buffer,
        std::size_t & pos)
    {
        if (mRuntimeVersion <= 12)
        {
            SF::decodeString(mPublisherName, buffer, pos);
            SF::decodeInt(mSubToPubPingIntervalMs, buffer, pos);
        }
    }

    void OobRequestSubscription::encodeResponse(ByteBuffer & buffer)
    {
        boost::shared_ptr< std::vector<char> > vecPtr( new std::vector<char>(50) );
        std::size_t pos = 0;

        encodeResponseCommon(vecPtr, pos);
        SF::encodeInt(mPubToSubPingIntervalMs, *vecPtr, pos);

        vecPtr->resize(pos);
        buffer = ByteBuffer(vecPtr);
        }

    void OobRequestSubscription::decodeResponse(const ByteBuffer & buffer)
    {
        std::size_t pos = 0;
        decodeResponseCommon(buffer, pos);
        SF::decodeInt(mPubToSubPingIntervalMs, buffer, pos);
    }

} // namespace RCF

max_stars_repo_name: ASMlover/study

max_issues_repo_name: ASMlover/study

max_forks_repo_name: ASMlover/study


text:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <cstring>

#include <sstream>
#include <vector>
#include <string>
#include <set>
#include <iostream>
#include <fstream>
#include <time.h>
#include <limits.h>
//#include <atomic>
#include <chrono>

#include <stdint.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <functional>

#include <getopt.h>

#include "../common/Common.hpp"
//#include "utils.hpp"
#include "../utils/fastq.hpp"
#include "../kmer/Kmer.hpp"
#include "../hash/HashTables.hpp"

#include "../utils/alglib-3.15.0/src/statistics.h"
#include "../utils/alglib-3.15.0/src/ap.h"

#include "../kmer/kmc_api/kmc_file.h"
#include "../kmer/kmc_reader.hpp"

#include "../utils/threadpool.hpp"
#include <boost/bind.hpp>
//#include <boost/thread.hpp>
using namespace std;
//using namespace boost;
using namespace boost::threadpool;
using namespace std::chrono;

// structs for getopt
struct SA_ProgramOptions {
  size_t k;
  string input1;
  string input2;
  string output1;
  string output2;
  int mode;
  unsigned int num_threads;
  int max_memory;
  int count_min;
  bool verbose;
  bool kmc;
  bool bin;
  float kmer_vote; //ratio of unique kmers in a read to be claimed as unique read
  float pvalue_thresh;
  vector<string> files;

  SA_ProgramOptions() : k(0), mode(1), num_threads(8), max_memory(12), count_min(2), verbose(false), kmc(false), bin(true), kmer_vote(0.5), pvalue_thresh(0.005) {}
};

void SA_PrintUsage() {
  cerr << "SA " << SA_VERSION << endl << endl;
  cerr << "Compare frequencies of k-mers [from KMC library] and saves differential reads results for each metagenome in comparison" << endl << endl;
  cerr << "Usage: SA -k -a -b -o -p [options]";
  cerr << endl << endl <<
	"-k, --kmer-size=INT             Size of k-mers, at most " << (int) (Kmer::MAX_K-1)<< endl <<
	"-a, --input1=STRING             Input filename for metagenome group A" << endl <<
	"-b, --input2=STRING             Input filename for metagenome group B" << endl <<
	"-o, --output1=STRING            Prefix for output of metagenome A" << endl <<
	"-p, --output2=STRING            Prefix for output of metagenome B" << endl <<
	"-v, --kmer-vote=FLOAT           Percentage threshold of differential k-mers in distinctive reads <default 0.5>" << endl <<
	"-t, --number-threads=INT        Number of threads for running KMC etc. <default 8>" << endl <<
	"-m, --max-memory=INT            Max memory for running KMC <default 12>" << endl <<
	"-c, --count-min=INT            Min threshold of k-mer count for running KMC <default 2>" << endl <<
	"-q, --pvalue-thresh=FLOAT       For U-test <default 0.005>" << endl <<
	"-M, --mode=INT                  1 or 2 <default 1>" << endl <<
	"    --kmc                       Call KMC (if you do not have kmc output; make sure kmc is available in the current environment)" << endl <<
	"    --no-bin                    Do not generate kmer_count.bin (already existed)" << endl <<
    "    --verbose                   Print messages during run" << endl << endl
    ;
}

void SA_ParseOptions(int argc, char **argv, SA_ProgramOptions &opt) {
  int verbose_flag = 0;
  int kmc_flag = 0;
  int bin_flag = 0;
  const char* opt_string = "k:o:p:a:b:v:q:m:c:t:M:";
  static struct option long_options[] =
  {
    {"verbose", no_argument,  &verbose_flag, 1},
	{"kmc", no_argument, &kmc_flag, 1},
	{"no-bin", no_argument, &bin_flag, 1},
	{"kmer-size", required_argument, 0, 'k'},
    {"output1", required_argument, 0, 'o'},
	{"output2", required_argument, 0, 'p'},
	{"input1", required_argument, 0, 'a'},
	{"input2", required_argument, 0, 'b'},
	{"kmer-vote", required_argument, 0, 'v'},
	{"pvalue-thresh", required_argument, 0, 'q'},
	{"max-memory", required_argument, 0, 'm'},
	{"count-min", required_argument, 0, 'c'},
	{"num-threads", required_argument, 0, 't'},
    {"mode", required_argument, 0, 'M'},
	{0,0,0,0}
  };

  int option_index = 0;
  int c;
  stringstream ss;
  while (true) {
    c = getopt_long(argc,argv,opt_string, long_options, &option_index);

    if (c == -1) {
      break;
    }

    switch (c) {
	case 'k':
	  opt.k = atoi(optarg);
	  break;
	case 'o':
      opt.output1 = optarg;
      break;
	case 'p':
	  opt.output2 = optarg;
	  break;
	case 'a':
	  opt.input1 = optarg;
	  break;
	case 'b':
	  opt.input2 = optarg;
	  break;
	case 'v':
	  opt.kmer_vote = atof(optarg);
	  break;
	case 'q':
	  opt.pvalue_thresh = atof(optarg);
	  break;
	case 'M':
	  opt.mode = atoi(optarg);
	  break;
    	case 't':
	  opt.num_threads = atoi(optarg);
	  break;
	case 'm':
	  opt.max_memory = atoi(optarg);
	  break;
	case 'c':
          opt.count_min = atoi(optarg);
          break;
	default: break;
    }
  }

  if (verbose_flag) {
	  opt.verbose = true;
  }

  if (kmc_flag) {
	  opt.kmc = true;
  }

  if (bin_flag) {
	  opt.bin = false;
  }
}

bool SA_CheckOptions(SA_ProgramOptions &opt) {
  bool ret = true;

  if (opt.k <= 0 || opt.k >= MAX_KMER_SIZE) {
	  cerr << "Error, invalid value for kmer-size: " << opt.k << endl;
	  cerr << "Values must be between 1 and " << (MAX_KMER_SIZE-1) << endl;
	  ret = false;
  }

  /*
  if (opt.files1.size() == 0 || opt.files2.size() == 0) {
    cerr << "Need to specify files for input" << endl;
    ret = false;
  } else {
    struct stat stFileInfo;
    vector<string>::const_iterator it;
    int intStat;
    for(it = opt.files1.begin(); it != opt.files1.end(); ++it) {
      intStat = stat(it->c_str(), &stFileInfo);
      if (intStat != 0) {
	cerr << "Error: file not found, " << *it << endl;
	ret = false;
      }
    }
	for(it = opt.files2.begin(); it != opt.files2.end(); ++it) {
      intStat = stat(it->c_str(), &stFileInfo);
      if (intStat != 0) {
	cerr << "Error: file not found, " << *it << endl;
	ret = false;
      }
    }

  }
  */

  //TODO: check if we have permission to write to outputfile

  return ret;

}

void SA_PrintSummary(const SA_ProgramOptions &opt) {
  cout << "Mode: " << opt.mode << endl;
  cout << "kmer size: " << Kmer::k << endl;
  cout << "Using kmer_vote: " << opt.kmer_vote << endl;
  cout << "Using pvalue_thresh: " << opt.pvalue_thresh << endl;
  cout << "Writing kmer_count.bin? " << std::boolalpha << opt.bin << endl;
}

//added by Mingjie on 02/12/2015
//test kmer count in batches
void BatchTest(uint16_t **ary_count, int tot_sample, uint64_t batch_size, streamoff batch_offset, int num_sample1, int num_sample2, vector<uint64_t> &v_kmers, float pvalue_thresh, const vector<Kmer> &kvec, uset_t *g_kmer1_ptr, uset_t *g_kmer2_ptr, uset_t *large_kmer_count_ptr) {
	double freq_array1[num_sample1], freq_array2[num_sample2];
	double bothtails, lefttail, righttail, freq;
	int numZero;
	uint16_t cnt;
	uint64_t tot_cnt;
	uint64_t num_kmers;
	alglib::real_1d_array array_s1, array_s2;

	bothtails = 0;
	lefttail  = 0;
	righttail = 0;

	Kmer km;
	for(uint64_t i=0; i<batch_size; i++) {
		km = kvec[batch_offset+i];
		tot_cnt = 0;
		numZero = 0;
		for(int j=0; j<tot_sample; j++){
			cnt = ary_count[j][i];
			//cout << cnt << endl;
			tot_cnt += cnt;
			if (cnt == 0){
				numZero++;
			}
			num_kmers = v_kmers[j];
			freq = double(cnt)*1000000/num_kmers;

			if(j<num_sample1) {
				freq_array1[j] = freq;
			} else {
				freq_array2[j-num_sample1] = freq;
			}
		}
		//char tmp[1024];
		//km.toString(tmp);
		//cout << tmp << endl;
		//exit(1);
		//if (tot_cnt > tot_sample) {
		array_s1.setcontent(num_sample1, freq_array1);
		array_s2.setcontent(num_sample2, freq_array2);
		alglib::mannwhitneyutest(array_s1, num_sample1, array_s2, num_sample2, bothtails, lefttail, righttail);
		if(numZero < tot_sample * 0.7 ){
			if(lefttail <= pvalue_thresh) {
				g_kmer2_ptr->insert(km);
			} else if (righttail <= pvalue_thresh) {
				g_kmer1_ptr->insert(km);
			}
			if (tot_cnt > tot_sample*2  ){
				large_kmer_count_ptr->insert(km);
			}
		}
	}
}

void SA(int argc, char **argv) {

	SA_ProgramOptions opt;
	SA_ParseOptions(argc,argv,opt);
	ckhmap_t kmap, *kmap_ptr;
	kmap_ptr = &kmap;
  uset_t large_kmer_count, *large_kmer_count_ptr;
  large_kmer_count_ptr = &large_kmer_count;
	size_t kmer_coverage;
	size_t kmap_size;
	std::string filename;
	vector<string> samples1, samples2, samples;
	vector<string> kmc_names1, kmc_names2, kmc_names;
	vector<size_t> v_kmers; //kmer_cov for each sample
	int num_sample1, num_sample2, tot_sample;
	uset_t g_kmer1, g_kmer2, *g_kmer1_ptr, *g_kmer2_ptr;  //differential kmers for two groups in comparison
	g_kmer1_ptr = &g_kmer1;
	g_kmer2_ptr = &g_kmer2;
	vector<Kmer> kvec;

	alglib::real_1d_array array_s1, array_s2;

	int cap_threads = 6;
	steady_clock::time_point t1, t2, t3, t4, t5, t6;

	if (argc < 2) {
		SA_PrintUsage();
		exit(1);
	}

	/*
	if (!SA_CheckOptions(opt)) {
	CountBF_PrintUsage();
	exit(1);
	} */

	// set static global k-value
	Kmer::set_k(opt.k);

	if (opt.verbose) {
		SA_PrintSummary(opt);
	}

	int act_threads;
	act_threads = opt.num_threads > cap_threads ? cap_threads:opt.num_threads;

	GetInput(opt.input1, samples1, kmc_names1);
	GetInput(opt.input2, samples2, kmc_names2);

	samples = samples1;
	samples.insert(samples.end(), samples2.begin(), samples2.end());
	kmc_names = kmc_names1;
	kmc_names.insert(kmc_names.end(), kmc_names2.begin(), kmc_names2.end());

	num_sample1 = samples1.size();
	num_sample2 = samples2.size();
	tot_sample = samples.size();
	if (opt.verbose) {
		cout << endl << "# samples in group 1: " << num_sample1 << endl << "# samples in group 2: " << num_sample2 << endl;
	}
  if (opt.bin){
		pool tp(opt.num_threads);
		buildKHtable();

  }
	else {
		//read in total number of kmers in each sample
		ifstream logStream("kmer_count.log");
		string line;
		getline(logStream, line);
		istringstream ss(line);
		ss >> kmap_size;
		for (int i = 0; i < tot_sample; i++) {
			ss >> kmer_coverage;
			v_kmers.push_back(kmer_coverage);
		}
	}

	//read kmers in kvec to restore the original kmer order in kmap
	ifstream kmer_file("kmer_set.hex");
	kvec.resize(kmap_size);
	uint8_t bytes[(Kmer::MAX_K)/4];
	size_t idx_k = 0;
	for (size_t i = 0; i < kmap_size; i++) {
		kmer_file.read(reinterpret_cast<char*> (&bytes[0]), sizeof(bytes[0])*(Kmer::MAX_K)/4);
		Kmer km(bytes);
		kvec[idx_k] = km;
		idx_k ++;
	}
	t4 = steady_clock::now();

	ifstream inStream("kmer_count.bin", ios::binary);

	const uint64_t batch_thresh = 10000000; //if changed, remember to change 2D array parameter vec_count in readHT and batchTest
	uint64_t batch_size;

	//initialize 2D array
	uint16_t** ary_count = new uint16_t*[tot_sample];
	for (int i=0; i < tot_sample; i++) {
		ary_count[i] = new uint16_t[batch_thresh];
	}

	if (opt.verbose) {
	  cout << "\n...Loading and testing in batches..." << endl;
	}

	//load and test kmer count info in batches
	uint64_t kcnt_rem = kmap_size;
	streamoff batch_offset = 0;
	while(kcnt_rem >= batch_thresh) {
	  batch_size = batch_thresh;

	  ReadHT(inStream, tot_sample, kmap_size, ary_count, batch_size, batch_offset);
	  BatchTest(ary_count, tot_sample, batch_size, batch_offset, num_sample1, num_sample2, v_kmers, opt.pvalue_thresh, kvec, g_kmer1_ptr, g_kmer2_ptr, large_kmer_count_ptr);

	  //cout << g_kmer1.size() << "\t" << g_kmer2.size() <<endl;

	  batch_offset += batch_size;
	  kcnt_rem -= batch_size;
	  if (opt.verbose) {
		  cout << "# loaded kmers: " << batch_offset << endl;
	  }

	}
	if(kcnt_rem > 0 && kcnt_rem < batch_thresh) {
	  batch_size = kcnt_rem;
	  ReadHT(inStream, tot_sample, kmap_size, ary_count, batch_size, batch_offset);
	  BatchTest(ary_count, tot_sample, batch_size, batch_offset, num_sample1, num_sample2, v_kmers, opt.pvalue_thresh, kvec, g_kmer1_ptr, g_kmer2_ptr, large_kmer_count_ptr);
	}

	for (int i = 0; i < tot_sample; ++i) {
		delete [] ary_count[i];
	}
	delete [] ary_count;
	inStream.close();

	t5 = steady_clock::now();
	auto duration45 = duration_cast<std::chrono::minutes>(t5 - t4).count();
	cout << "BatchTesting takes " << duration45 << " minutes\n";

	if (opt.verbose) {
	  cout << "\n# differential kmers in group 1: " << g_kmer1.size() << endl;
	  cout << "# differential kmers in group 2: " << g_kmer2.size() << endl;
	}

	//deallocate the memory of kvec
	vector<Kmer>().swap(kvec);

	if (opt.verbose) {
	  cout << "\n...Writing distinctive reads..."  << endl;
	}

	//unsigned int write_threads;
	//write_threads = opt.num_threads > cap_threads ? opt.num_threads : act_threads;
	pool tp(opt.num_threads);

	if (opt.verbose) {
		cout << "start " << tp.size() << " threads" << endl;
	}

	for(vector<string>::iterator it=samples1.begin(); it!=samples1.end(); ++it) {
	  vector<string> tmp;
	  tmp.push_back(*it);

	  const char * basep = (*it).c_str();
	  std::string base(basename(basep));

		filename = std::string(opt.output1) + ("_" + base);
		if (opt.verbose) {
			cout << "writing to " << filename << endl;
		}
		ReadExtract(g_kmer1_ptr, tmp, filename, opt.kmer_vote, opt.verbose, tp, opt.num_threads, large_kmer_count_ptr);
	  tmp.clear();
	}

	for(vector<string>::iterator it=samples2.begin(); it!=samples2.end(); ++it) {
	  vector<string> tmp;
	  tmp.push_back(*it);

	  const char * basep = (*it).c_str();
	  std::string base(basename(basep));
		filename = std::string(opt.output2) + ("_" + base);
		if (opt.verbose) {
			cout << "writing to " << filename << endl;
		}
		ReadExtract(g_kmer2_ptr, tmp, filename, opt.kmer_vote, opt.verbose, tp, opt.num_threads, large_kmer_count_ptr);
	  tmp.clear();
	}

	t6 = steady_clock::now();
	auto duration56 = duration_cast<std::chrono::minutes>(t6 - t5).count();
	cout << "ReadExtract takes " << duration56 << " minutes\n";

}

ext: cc

max_stars_repo_name: mgtools/kmerLSHSA

max_stars_repo_licenses: Intel MIT

max_issues_repo_name: mgtools/kmerLSHSA

max_issues_repo_licenses: Intel MIT

max_forks_repo_name: mgtools/kmerLSHSA

max_forks_repo_licenses: Intel MIT


text:
///////////////////////////////////////////////////////////////////////////////////
// distribution::toolkit::distributions::normal::normalizing_constant.hpp         //
//                                                                               //
//  (C) Copyright 2009 Erwann Rogard                                             //
//  Use, modification and distribution are subject to the                        //
//  Boost Software License, Version 1.0. (See accompanying file                  //
//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)             //
///////////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_STATISTICS_DETAIL_DISTRIBUTION_TOOLKIT_NORMAL_NORMALIZING_CONSTANT_HPP_ER_2009
#define BOOST_STATISTICS_DETAIL_DISTRIBUTION_TOOLKIT_NORMAL_NORMALIZING_CONSTANT_HPP_ER_2009
#include <cmath>
#include <boost/math/constants/constants.hpp>
#include <boost/math/distributions/normal.hpp>

namespace boost{
namespace math{

template<typename T,typename P>
T normalizing_constant(const boost::math::normal_distribution<T,P>& d){
    static T pi = boost::math::constants::pi<T>;
    static T two = static_cast<T>(2);
    return sqrt(two * pi) * d.scale();
}

}// math
}// boost

#endif

ext: hpp


text:
// Copyright (c) 2013, Noe Casas (noe.casas@gmail.com).
// Distributed under New BSD License.
// (see accompanying file COPYING)

#ifndef BITSTRING_GENOTIPE_HEADER_SEEN___
#define BITSTRING_GENOTIPE_HEADER_SEEN___

#include <memory>
#include <vector>
#include <string>
#include <stdexcept>
#include <boost/noncopyable.hpp>
#include "gene/policies.hpp"

namespace gene { namespace bitstring {

/******************************************************************************
 * PoD representing a chromosome.
 * Immutable sequence of encoded genes.
 *****************************************************************************/
struct Chromosome : boost::noncopyable
{
  const std::vector<uint8_t> encodedGenes;
};

/******************************************************************************
 * PoD representing the genotype of an individual.
 * Immutable sequence of chromosomes.
 *****************************************************************************/
struct Genotype : boost::noncopyable
{
  const std::vector<std::unique_ptr<Chromosome>> chromosomes;
};

/****************************************************************************
 * Implementation of mutation with a fixed probability.
 ***************************************************************************/
struct BitFlipMutation : public gene::MutationStrategy<Genotype>,
                         boost::noncopyable
{
  BitFlipMutation (float bitMutationProbability);

  std::unique_ptr<Genotype> mutate(const Genotype&);

  private: const float percentageOfMutation_;
};

/****************************************************************************
 * Implementation of Combination that performs N point crossover.
 ***************************************************************************/
struct OnePointCrossover : public CombinationStrategy<Genotype>,
                           boost::noncopyable
{
  OnePointCrossover ();
  std::unique_ptr<Genotype> combine(const Genotype&, const Genotype&);
  private: const std::size_t numberOfPoints_;
};

}}

#include "gene/bitstring_impl.hpp"

#endif

max_stars_repo_name: noe/gene

max_issues_repo_name: noe/gene

max_forks_repo_name: noe/gene


text:
#include <catch.hpp>

#include "board.hpp"

#include <numeric_range.hpp>

#include <boost/optional/optional_io.hpp>

using Aronda::Board;

TEST_CASE("Testing placing a stone on en empty board", "[board]")
{
    Board g;

    SECTION("Playing 1 stone on an empty 3 capacity square")
    {
        Aronda::Square s{18};
        CHECK(g.squareState(s) == Aronda::SquareState{{0, 0}, {}});

        const auto res = g.placeStone({s, Aronda::black, 1});
        REQUIRE(res.has_value());
        CHECK(res->squareState(s) == Aronda::SquareState{{1, 0}, {}});
    }

    SECTION("Playing 2 stone on an empty 3 capacity square")
    {
        Aronda::Square s{18};
        CHECK(g.squareState(s) == Aronda::SquareState{{0, 0}, {}});

        const auto res = g.placeStone({s, Aronda::black, 2});
        REQUIRE(res.has_value());
        CHECK(res->squareState(s) == Aronda::SquareState{{2, 0}, {}});
    }

    SECTION("Playing a third stone on an empty 3 capacity square locks it")
    {
        Aronda::Square s{18};
        CHECK(g.squareState(s) == Aronda::SquareState{{0, 0}, {}});

        const auto res1 = g.placeStone({s, Aronda::black, 2});
        REQUIRE(res1.has_value());
        CHECK(res1->squareState(s) == Aronda::SquareState{{2, 0}, {}});

        const auto res2 = res1->placeStone({s, Aronda::black, 1});
        REQUIRE(res2.has_value());
        CHECK(res2->squareState(s) == Aronda::SquareState{{3, 0}, {Aronda::black}});
    }

    SECTION("Trying to place a fourth stone on an 3 capacity square is forbidden")
    {
        Aronda::Square s{18};
        CHECK(g.squareState(s) == Aronda::SquareState{{0, 0}, {}});

        const auto res1 = g.placeStone({s, Aronda::black, 2});
        REQUIRE(res1.has_value());
        CHECK(res1->squareState(s) == Aronda::SquareState{{2, 0}, {}});

        const auto res2 = res1->placeStone({s, Aronda::black, 2});
        REQUIRE(!res2.has_value());
        CHECK(res2.error() == Aronda::InvalidMove::TooManyStones);
    }

    SECTION("Playing 1 stone on an empty 2 capacity square")
    {
        Aronda::Square s{19};
        CHECK(g.squareState(s) == Aronda::SquareState{{0, 0}, {}});

        const auto res = g.placeStone({s, Aronda::black, 1});
        REQUIRE(res.has_value());
        CHECK(res->squareState(s) == Aronda::SquareState{{1, 0}, {}});
    }

    SECTION("Playing 2 stone on an empty 2 capacity square locks it")
    {
        Aronda::Square s{19};
        CHECK(g.squareState(s) == Aronda::SquareState{{0, 0}, {}});

        const auto res = g.placeStone({s, Aronda::black, 2});
        REQUIRE(res.has_value());
        CHECK(res->squareState(s) == Aronda::SquareState{{2, 0}, {Aronda::black}});
    }

    SECTION("Trying to place a third stone on a 2 capacity square is forbidden")
    {
        Aronda::Square s{19};
        CHECK(g.squareState(s) == Aronda::SquareState{{0, 0}, {}});

        const auto res1 = g.placeStone({s, Aronda::black, 2});
        REQUIRE(res1.has_value());
        CHECK(res1->squareState(s) == Aronda::SquareState{{2, 0}, {Aronda::black}});

        const auto res2 = res1->placeStone({s, Aronda::black, 1});
        REQUIRE(!res2.has_value());
        CHECK(res2.error() == Aronda::InvalidMove::SquareLocked);
    }

    SECTION("Trying to place four stones on a 2 capacity square is forbidden")
    {
        Aronda::Square s{19};
        CHECK(g.squareState(s) == Aronda::SquareState{{0, 0}, {}});

        const auto res1 = g.placeStone({s, Aronda::black, 2});
        REQUIRE(res1.has_value());
        CHECK(res1->squareState(s) == Aronda::SquareState{{2, 0}, {Aronda::black}});

        const auto res2 = res1->placeStone({s, Aronda::black, 2});
        REQUIRE(!res2.has_value());
        CHECK(res2.error() == Aronda::InvalidMove::SquareLocked);
    }

    SECTION("Trying to place a stone on the fourth ring on an empty board should be possible")
    {
        for(const auto square : range<std::size_t>(17, 25))
        {
            const auto res = g.placeStone({Aronda::Square{square}, Aronda::black, 1});
            REQUIRE(res.has_value());
        }
    }

    SECTION("Trying to place a stone on the second ring on an empty board should fail")
    {
        for(const auto square : range<std::size_t>(9, 17))
        {
            const auto res = g.placeStone({Aronda::Square{square}, Aronda::black, 1});
            REQUIRE(!res.has_value());
            CHECK(res.error() == Aronda::InvalidMove::SquareUnreachable);
        }
    }

    SECTION("Trying to place a stone on the third ring on an empty board should fail")
    {
        for(const auto square : range<std::size_t>(1, 9))
        {
            const auto res = g.placeStone({Aronda::Square{square}, Aronda::black, 1});
            REQUIRE(!res.has_value());
            CHECK(res.error() == Aronda::InvalidMove::SquareUnreachable);
        }
    }

    SECTION("Trying to place a stone on the central square on an empty board should fail")
    {
        const auto res = g.placeStone({Aronda::Square{0}, Aronda::black, 1});
        REQUIRE(!res.has_value());
        CHECK(res.error() == Aronda::InvalidMove::SquareUnreachable);
    }
}

ext: cpp

max_stars_repo_name: julienlopez/Aronda

max_issues_repo_name: julienlopez/Aronda

max_forks_repo_name: julienlopez/Aronda


text:
/*
 * test.cpp
 *
 *  Created on: Jul 31, 2015
 *      Author: sontd
 */

#include <GL/glut.h>
#include <limits>
#include <set>
#include <ctime>
#include <cstdlib>
#include <stdlib.h>
#include <boost/next_prior.hpp>
#include <sstream>
#include <fstream>
#include "../include/environment/map.hpp"
#include "../include/plans/boustrophedon/boustrophedon.hpp"

#define R_SIZE 0.5 // robot size
#define E_SIZE 6.0 // default environment size
#define WORLD_INSERT_OBSTACLE "<!-- INSERT: Boundary and Obstacles here -->" // flag at original world file to insert bound and obstacles into

using namespace wandrian::environment;
using namespace wandrian::plans::boustrophedon;

double e_size = 0;

MapPtr map;
PointPtr starting_point;
std::list<PointPtr> tmp_path;
/**
 * Linked libraries to compile: -lglut -lGL (g++)
 */

void draw(std::list<PointPtr> points, int type) {
  glBegin(type);
  for (std::list<PointPtr>::iterator p = points.begin(); p != points.end();
      p++) {
    glVertex2d((*p)->x, (*p)->y);
  }
  glVertex2d((*points.begin())->x, (*points.begin())->y);
  glEnd();
}

void draw_path(std::list<PointPtr> points, int type) {
  glBegin(type);
  for (std::list<PointPtr>::iterator p = points.begin(); p != points.end();
      p++) {
    glVertex2d((*p)->x, (*p)->y);
  }
  glEnd();
}

void display() {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(-6, 6, -6, 6, -1, 1);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  glScalef(0.5, 0.5, 0);

  // Center point
  glPointSize(4);
  glColor3ub(255, 255, 0);
  glBegin(GL_POINTS);
  glVertex2i(0, 0);
  glEnd();

  // Coordinate
  glPointSize(1);
  glColor3ub(255, 255, 255);
  glBegin(GL_POINTS);
  for (int i = -e_size; i <= e_size; i++) {
    for (int j = -e_size; j <= e_size; j++) {
      if ((i != 0 || j != 0) && i % 2 == 0 && j % 2 == 0)
        glVertex2i((double) i / 2, (double) j / 2);
    }
  }
  glEnd();

  // Environment
  glColor3ub(255, 0, 0);
  draw(map->get_boundary()->get_boundary(), GL_LINE_STRIP);
  std::list<RectanglePtr> obstacles = map->get_obstacles();
  for (std::list<RectanglePtr>::iterator obstacle = obstacles.begin();
      obstacle != obstacles.end(); obstacle++) {
    draw((*obstacle)->get_boundary(), GL_POLYGON);
  }

  // Starting point
  glPointSize(4);
  glColor3ub(0, 255, 0);
  glBegin(GL_POINTS);
  glVertex2d(starting_point->x, starting_point->y);
  glEnd();

  // Boustrophedon covering path
  glColor3ub(0, 255, 0);
  draw_path(tmp_path, GL_LINE_STRIP);

  glRasterPos2i(0, -11);
  std::stringstream ss;
  ss << starting_point->x << ", " << starting_point->y;
  for (int i = 0; i < ss.str().length(); i++)
    glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, ss.str()[i]);

  glutSwapBuffers();
}

int run(int argc, char **argv) {
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
  glutInitWindowSize(600, 600);
  glutCreateWindow("Environment");
  glutDisplayFunc(display);
  glutMainLoop();
  return 0;
}

bool test_go_to(PointPtr position, bool flexibly) {
  tmp_path.insert(tmp_path.end(), position);
  return true;
}

bool test_see_obstacle(VectorPtr direction, double step) {
  // Simulator check obstacle
  PointPtr last_position = *(--tmp_path.end());
  PointPtr new_position = PointPtr(
      new Point(last_position + direction * step * R_SIZE / 2));
  if (map) {
    CellPtr space = boost::static_pointer_cast<Cell>(map->get_boundary());
    if (new_position->x >= space->get_center()->x + space->get_size() / 2
        || new_position->x <= space->get_center()->x - space->get_size() / 2
        || new_position->y >= space->get_center()->y + space->get_size() / 2
        || new_position->y <= space->get_center()->y - space->get_size() / 2) {
      return true;
    }
    std::list<RectanglePtr> obstacles = map->get_obstacles();
    for (std::list<RectanglePtr>::iterator o = obstacles.begin();
        o != obstacles.end(); o++) {
      CellPtr obstacle = boost::static_pointer_cast<Cell>(*o);
      if (new_position->x
          >= obstacle->get_center()->x - obstacle->get_size() / 2
          && new_position->x
              <= obstacle->get_center()->x + obstacle->get_size() / 2
          && new_position->y
              >= obstacle->get_center()->y - obstacle->get_size() / 2
          && new_position->y
              <= obstacle->get_center()->y + obstacle->get_size() / 2) {
        return true;
      }
    }
  }
  return false;
}

int main(int argc, char **argv) {
  if (argc >= 2) {
    std::istringstream iss(argv[1]);
    if (!(iss >> e_size)
        || !(4 <= e_size && e_size <= 20 && (int) e_size % 2 == 0)) {
      e_size = E_SIZE;
    }
  } else {
    e_size = E_SIZE;
  }
  BoustrophedonPtr boustrophedon = BoustrophedonPtr(new Boustrophedon());
  boustrophedon->initialize(starting_point, R_SIZE,
      "../../worlds/prefered_boustrophedon.map");
  map = boustrophedon->get_map();

  CellPtr space = CellPtr(new Cell(PointPtr(new Point(0, 0)), e_size));
  std::list<RectanglePtr> obstacles;
  std::srand(std::time(0));
  starting_point = PointPtr(
      new Point(-(e_size - R_SIZE) / 2, -(e_size - R_SIZE) / 2));
  int r = std::rand() % (int) (e_size * e_size / 16) + e_size * e_size / 8;

  std::ifstream world_in("../../worlds/empty.world");
  std::ofstream world_out("../../worlds/tmp.world");
  std::string line;

  obstacles = map->get_obstacles();

  while (std::getline(world_in, line, '\n')) {
    world_out << line << '\n';
    if (line.find(WORLD_INSERT_OBSTACLE) != std::string::npos) {
      int n;
      n = 1;
      // Upper bound
      for (double i = -e_size / 2 + R_SIZE / 2; i <= e_size / 2 - R_SIZE / 2;
          i += R_SIZE) {
        world_out << "    <model name='cinder_block_bound_" << n << "'>\n";
        world_out << "      <include>\n";
        world_out << "        <uri>model://cinder_block</uri>\n";
        world_out << "      </include>\n";
        world_out << "      <pose>" << i << " " << (e_size / 2 + R_SIZE / 4)
            << " 0 0 0 0</pose>\n";
        world_out << "      <static>1</static>\n";
        world_out << "    </model>\n";
        n++;
      }

      // Right bound
      for (double i = -e_size / 2 + R_SIZE / 2; i <= e_size / 2 - R_SIZE / 2;
          i += R_SIZE) {
        world_out << "    <model name='cinder_block_bound_" << n << "'>\n";
        world_out << "      <include>\n";
        world_out << "        <uri>model://cinder_block</uri>\n";
        world_out << "      </include>\n";
        world_out << "      <pose>" << (e_size / 2 + R_SIZE / 4) << " " << -i
            << " 0 0 0 " << M_PI_2 << "</pose>\n";
        world_out << "      <static>1</static>\n";
        world_out << "    </model>\n";
        n++;
      }

      // Lower bound
      for (double i = -e_size / 2 + R_SIZE / 2; i <= e_size / 2 - R_SIZE / 2;
          i += R_SIZE) {
        world_out << "    <model name='cinder_block_bound_" << n << "'>\n";
        world_out << "      <include>\n";
        world_out << "        <uri>model://cinder_block</uri>\n";
        world_out << "      </include>\n";
        world_out << "      <pose>" << -i << " " << -(e_size / 2 + R_SIZE / 4)
            << " 0 0 0 0</pose>\n";
        world_out << "      <static>1</static>\n";
        world_out << "    </model>\n";
        n++;
      }

      // Left bound
      for (double i = -e_size / 2 + R_SIZE / 2; i <= e_size / 2 - R_SIZE / 2;
          i += R_SIZE) {
        world_out << "    <model name='cinder_block_bound_" << n << "'>\n";
        world_out << "      <include>\n";
        world_out << "        <uri>model://cinder_block</uri>\n";
        world_out << "      </include>\n";
        world_out << "      <pose>" << -(e_size / 2 + R_SIZE / 4) << " " << i
            << " 0 0 0 " << M_PI_2 << "</pose>\n";
        world_out << "      <static>1</static>\n";
        world_out << "    </model>\n";
        n++;
      }

      n = 1;
//      double o_size = 4 * R_SIZE;
      // Obstacles
      for (std::list<RectanglePtr>::iterator o = obstacles.begin();
          o != obstacles.end(); o++) {

        PointPtr p = (boost::static_pointer_cast<Rectangle>(*o))->get_center();
        double h = (boost::static_pointer_cast<Rectangle>(*o))->get_height();
        double w = (boost::static_pointer_cast<Rectangle>(*o))->get_width();
        int c = 1;

        // double x = p->x - R_SIZE * (w / R_SIZE / 2.0 - 1.0 / 2.0);
        double x = p->x - w / 2 + R_SIZE / 2;

        for (int i = 1; i <= (int) (w / R_SIZE); i++) {

          for (double y = p->y - R_SIZE * (h / R_SIZE / 2.0 - 1.0 / 4.0);
              y <= p->y + R_SIZE * (h / R_SIZE / 2.0 - 1.0 / 4.0);
              y += R_SIZE / 2.0) {

            world_out << "    <model name='cinder_block_obstacle_" << n << "_"
                << c << "'>\n";
            world_out << "      <include>\n";
            world_out << "        <uri>model://cinder_block</uri>\n";
            world_out << "      </include>\n";
            world_out << "      <pose>" << x << " " << y << " 0 0 0 0</pose>\n";
            world_out << "      <static>1</static>\n";
            world_out << "    </model>\n";
            c++;

          }
          x += R_SIZE;
        }
        n++;
      }
    }
  }
  world_in.close();
  world_out.close();

  tmp_path.insert(tmp_path.end(), starting_point);
  boustrophedon->set_behavior_go_to(boost::bind(&test_go_to, _1, _2));

  boustrophedon->cover();

  run(argc, argv);
  return 0;
}