<commit_before>//---------------------------------------------------------- -*- Mode: C++ -*-
// $Id$
//
// Created 2006/06/05
// Author: Sriram Rao
//         Mike Ovsiannikov implement multiple outstanding request processing,
//         and "client threads".
//
// Copyright 2008-2012 Quantcast Corp.
// Copyright 2006-2008 Kosmix Corp.
//
// This file is part of Kosmos File System (KFS).
//
// 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.
//
//
// \file ClientSM.cc
// \brief Kfs client protocol state machine implementation.
//
//----------------------------------------------------------------------------

#include "ClientSM.h"
#include "ChunkServer.h"
#include "NetDispatch.h"
#include "util.h"
#include "common/kfstypes.h"
#include "kfsio/Globals.h"
#include "qcdio/qcstutils.h"
#include "kfsio/IOBuffer.h"
#include "common/MsgLogger.h"
#include "common/Properties.h"
#include "AuditLog.h"

#include <string>
#include <sstream>
#include <algorithm>

namespace KFS
{

using std::max;
using std::string;
using std::ostringstream;

inline string
PeerName(const NetConnectionPtr& conn)
{
    return (conn ? conn->GetPeerName() : string("unknown"));
}

inline string
PeerIp(const NetConnectionPtr& conn)
{
    if (! conn) {
        return string();
    }
    const string peer = conn->GetPeerName();
    const size_t pos  = peer.rfind(':');
    if (pos == string::npos) {
        return peer;
    }
    return peer.substr(0, pos);
}

int  ClientSM::sMaxPendingOps             = 1;
int  ClientSM::sMaxPendingBytes           = 3 << 10;
int  ClientSM::sMaxReadAhead              = 3 << 10;
int  ClientSM::sInactivityTimeout         = 8 * 60;
int  ClientSM::sMaxWriteBehind            = 3 << 10;
int  ClientSM::sBufCompactionThreshold    = 1 << 10;
int  ClientSM::sOutBufCompactionThreshold = 8 << 10;
int  ClientSM::sClientCount               = 0;
bool ClientSM::sAuditLoggingFlag          = false;
ClientSM* ClientSM::sClientSMPtr[1]      = {0};
IOBuffer::WOStream ClientSM::sWOStream;

/* static */ void
ClientSM::SetParameters(const Properties& prop)
{
    const int maxPendingOps = prop.getValue(
        "metaServer.clientSM.maxPendingOps",
        -1);
    if (maxPendingOps > 0) {
        sMaxPendingOps = maxPendingOps;
    } else if (! gNetDispatch.IsRunning() &&
            prop.getValue("metaServer.clientThreadCount", -1) > 0) {
        sMaxPendingOps = 4;
    }
    sMaxPendingBytes = max(1, prop.getValue(
        "metaServer.clientSM.maxPendingBytes",
        sMaxPendingBytes));
    sMaxReadAhead = max(256, prop.getValue(
        "metaServer.clientSM.maxReadAhead",
        sMaxReadAhead));
    sInactivityTimeout = prop.getValue(
        "metaServer.clientSM.inactivityTimeout",
        sInactivityTimeout);
    sMaxWriteBehind = max(1, prop.getValue(
        "metaServer.clientSM.maxWriteBehind",
        sMaxWriteBehind));
    sBufCompactionThreshold = prop.getValue(
        "metaServer.clientSM.bufCompactionThreshold",
        sBufCompactionThreshold);
    sOutBufCompactionThreshold = prop.getValue(
        "metaServer.clientSM.outBufCompactionThreshold",
        sOutBufCompactionThreshold);
    sAuditLoggingFlag = prop.getValue(
        "metaServer.clientSM.auditLogging",
        sAuditLoggingFlag ? 1 : 0) != 0;
    AuditLog::SetParameters(prop);
}

ClientSM::ClientSM(
    const NetConnectionPtr&      conn,
    ClientManager::ClientThread* thread,
    IOBuffer::WOStream*          wostr,
    char*                        parseBuffer)
    : mNetConnection(conn),
      mClientIp(PeerIp(conn)),
      mPendingOpsCount(0),
      mOstream(wostr ? *wostr : sWOStream),
      mParseBuffer(parseBuffer),
      mRecursionCnt(0),
      mClientProtoVers(KFS_CLIENT_PROTO_VERS),
      mDisconnectFlag(false),
      mLastReadLeft(0),
      mClientThread(thread),
      mNext(0)
{
    assert(mNetConnection && mNetConnection->IsGood());

    ClientSMList::Init(*this);
    {
        QCStMutexLocker locker(gNetDispatch.GetClientManagerMutex());
        ClientSMList::PushBack(sClientSMPtr, *this);
        sClientCount++;
    }
    mNetConnection->SetInactivityTimeout(sInactivityTimeout);
    mNetConnection->SetMaxReadAhead(sMaxReadAhead);
    SET_HANDLER(this, &ClientSM::HandleRequest);
}

ClientSM::~ClientSM()
{
    QCStMutexLocker locker(gNetDispatch.GetClientManagerMutex());
    ClientSMList::Remove(sClientSMPtr, *this);
    sClientCount--;
}

///
/// Send out the response to the client request.  The response is
/// generated by MetaRequest as per the protocol.
/// @param[in] op The request for which we finished execution.
///
void
ClientSM::SendResponse(MetaRequest *op)
{
    if ((op->op == META_ALLOCATE && (op->status < 0 ||
            static_cast<const MetaAllocate*>(op)->logFlag)) ||
            MsgLogger::GetLogger()->IsLogLevelEnabled(
                MsgLogger::kLogLevelDEBUG)) {
        // for chunk allocations, for debugging purposes, need to know
        // where the chunk was placed.
        KFS_LOG_STREAM_INFO << PeerName(mNetConnection) <<
            " -seq: "   << op->opSeqno <<
            " status: " << op->status <<
            (op->statusMsg.empty() ?
                "" : " msg: ") << op->statusMsg <<
            " "         << op->Show() <<
        KFS_LOG_EOM;
    }
    if (! mNetConnection) {
        return;
    }
    if (op->op == META_DISCONNECT) {
        mDisconnectFlag = true;
    }
    op->response(
        mOstream.Set(mNetConnection->GetOutBuffer()),
        mNetConnection->GetOutBuffer());
    mOstream.Reset();
    if (mRecursionCnt <= 0) {
        mNetConnection->StartFlush();
    }
}

///
/// Generic event handler.  Decode the event that occurred and
/// appropriately extract out the data and deal with the event.
/// @param[in] code: The type of event that occurred
/// @param[in] data: Data being passed in relative to the event that
/// occurred.
/// @retval 0 to indicate successful event handling; -1 otherwise.
///
int
ClientSM::HandleRequest(int code, void *data)
{
    if (code == EVENT_CMD_DONE) {
        assert(data && mPendingOpsCount > 0);
        if (ClientManager::Enqueue(mClientThread,
                *reinterpret_cast<MetaRequest*>(data))) {
            return 0;
        }
    }

    assert(mRecursionCnt >= 0 && (mNetConnection ||
        (code == EVENT_CMD_DONE && data && mPendingOpsCount > 0)));
    mRecursionCnt++;

    switch (code) {
    case EVENT_NET_READ: {
        // We read something from the network. Run the RPC that
        // came in.
        mLastReadLeft = 0;
        IOBuffer& iobuf = mNetConnection->GetInBuffer();
        if (mDisconnectFlag) {
            iobuf.Clear(); // Discard
        }
        assert(data == &iobuf);
        // Do not start new op if response does not get unloaded by
        // the client to prevent out of buffers.
        bool overWriteBehindFlag = false;
        for (; ;) {
            while ((overWriteBehindFlag =
                    mNetConnection->GetNumBytesToWrite() >=
                        sMaxWriteBehind) &&
                    mRecursionCnt <= 1 &&
                    mNetConnection->CanStartFlush()) {
                mNetConnection->StartFlush();
            }
            int cmdLen;
            if (overWriteBehindFlag ||
                    IsOverPendingOpsLimit() ||
                    ! IsMsgAvail(&iobuf, &cmdLen)) {
                break;
            }
            HandleClientCmd(iobuf, cmdLen);
        }
        if (overWriteBehindFlag) {
            break;
        }
        if (! IsOverPendingOpsLimit() && ! mDisconnectFlag) {
            mLastReadLeft = iobuf.BytesConsumable();
            if (mLastReadLeft <= MAX_RPC_HEADER_LEN) {
                mNetConnection->SetMaxReadAhead(sMaxReadAhead);
                break;
            }
            KFS_LOG_STREAM_ERROR << PeerName(mNetConnection) <<
                " exceeded max request header size: " <<
                    mLastReadLeft <<
                " > " << MAX_RPC_HEADER_LEN <<
                " closing connection" <<
            KFS_LOG_EOM;
            mLastReadLeft = 0;
            iobuf.Clear();
            mNetConnection->Close();
            HandleRequest(EVENT_NET_ERROR, NULL);
        }
        break;
    }

    case EVENT_CMD_DONE: {
        assert(data && mPendingOpsCount > 0);
        MetaRequest* const op = reinterpret_cast<MetaRequest*>(data);
        if (sAuditLoggingFlag && ! op->reqHeaders.IsEmpty()) {
            AuditLog::Log(*op);
        }
        SendResponse(op);
        delete op;
        mPendingOpsCount--;
        if (! mNetConnection) {
            break;
        }
        if (mRecursionCnt <= 1 &&
                (mPendingOpsCount <= 0 ||
                ! ClientManager::Flush(
                    mClientThread, *this))) {
            mNetConnection->StartFlush();
        }
    }
        // Fall through.
    case EVENT_NET_WROTE:
        // Something went out on the network.
        // Process next command.
        if (! IsOverPendingOpsLimit() &&
                mRecursionCnt <= 1 &&
                (code == EVENT_CMD_DONE ||
                    ! mNetConnection->IsReadReady()) &&
                mNetConnection->GetNumBytesToWrite() <
                    sMaxWriteBehind) {
            if (mNetConnection->GetNumBytesToRead() >
                    mLastReadLeft ||
                    mDisconnectFlag) {
                HandleRequest(EVENT_NET_READ,
                    &mNetConnection->GetInBuffer());
            } else if (! mNetConnection->IsReadReady()) {
                mNetConnection->SetMaxReadAhead(sMaxReadAhead);
            }
        }
        break;

    case EVENT_NET_ERROR:
        if (mNetConnection->IsGood() &&
                (mPendingOpsCount > 0 ||
                mNetConnection->IsWriteReady())) {
            // Fin from the other side, flush and close connection.
            mDisconnectFlag = true;
            break;
        }
        // Fall through.
    case EVENT_INACTIVITY_TIMEOUT:
        KFS_LOG_STREAM_DEBUG << PeerName(mNetConnection) <<
            " closing connection" <<
        KFS_LOG_EOM;
        mNetConnection->Close();
        mNetConnection->GetInBuffer().Clear();
        break;

    default:
        assert(!"Unknown event");
        break;
    }

    if (mRecursionCnt <= 1) {
        bool goodFlag = mNetConnection && mNetConnection->IsGood();
        if (goodFlag && (mPendingOpsCount <= 0 ||
                ! ClientManager::Flush(
                    mClientThread, *this))) {
            mNetConnection->StartFlush();
            goodFlag = mNetConnection && mNetConnection->IsGood();
        }
        if (goodFlag && mDisconnectFlag) {
            if (mPendingOpsCount <= 0 &&
                    ! mNetConnection->IsWriteReady()) {
                mNetConnection->Close();
                goodFlag = false;
            } else {
                mNetConnection->SetMaxReadAhead(0);
            }
        }
        if (goodFlag) {
            IOBuffer& inbuf = mNetConnection->GetInBuffer();
            int numBytes = inbuf.BytesConsumable();
            if (numBytes <= sBufCompactionThreshold &&
                    numBytes > 0) {
                inbuf.MakeBuffersFull();
            }
            IOBuffer& outbuf = mNetConnection->GetOutBuffer();
            numBytes = outbuf.BytesConsumable();
            if (numBytes <= sOutBufCompactionThreshold &&
                    numBytes > 0) {
                outbuf.MakeBuffersFull();
            }
            if (mNetConnection->IsReadReady() &&
                    (IsOverPendingOpsLimit() ||
                    mNetConnection->GetNumBytesToWrite() >=
                        sMaxWriteBehind ||
                    mNetConnection->GetNumBytesToRead() >=
                        sMaxPendingBytes)) {
                mLastReadLeft = 0;
                mNetConnection->SetMaxReadAhead(0);
            }
        } else {
            if (mPendingOpsCount > 0) {
                mNetConnection.reset();
            } else {
                delete this;
                return 0;
            }
        }
    }
    assert(
        mRecursionCnt > 0 &&
        (mRecursionCnt > 1 || mPendingOpsCount > 0 ||
            (mNetConnection && mNetConnection->IsGood()))
    );
    mRecursionCnt--;
    return 0;
}

///
/// We have a command in a buffer. So, parse out the command and
/// execute it if possible.
/// @param[in] iobuf: Buffer containing the command
/// @param[in] cmdLen: Length of the command in the buffer
///
void
ClientSM::HandleClientCmd(IOBuffer& iobuf, int cmdLen)
{
    assert(! IsOverPendingOpsLimit() && mNetConnection);
    MetaRequest* op = 0;
    if (ParseCommand(iobuf, cmdLen, &op, mParseBuffer) != 0) {
        IOBuffer::IStream is(iobuf, cmdLen);
        char buf[128];
        int  maxLines = 16;
        while (maxLines-- > 0 && is.getline(buf, sizeof(buf))) {
            KFS_LOG_STREAM_ERROR << PeerName(mNetConnection) <<
                " invalid request: " << buf <<
            KFS_LOG_EOM;
        }
        iobuf.Clear();
        mNetConnection->Close();
        HandleRequest(EVENT_NET_ERROR, NULL);
        return;
    }
    if (op->clientProtoVers < mClientProtoVers) {
        mClientProtoVers = op->clientProtoVers;
        KFS_LOG_STREAM_WARN << PeerName(mNetConnection) <<
            " command with old protocol version: " <<
            op->clientProtoVers << ' ' << op->Show() <<
        KFS_LOG_EOM;
    }
    // Command is ready to be pushed down.  So remove the cmd from the buffer.
    if (sAuditLoggingFlag) {
        op->reqHeaders.Move(&iobuf, cmdLen);
    } else {
        iobuf.Consume(cmdLen);
    }
    KFS_LOG_STREAM_DEBUG << PeerName(mNetConnection) <<
        " +seq: " << op->opSeqno <<
        " "       << op->Show() <<
        " pending:"
        " rd: "   << mNetConnection->GetNumBytesToRead() <<
        " wr: "   << mNetConnection->GetNumBytesToWrite() <<
    KFS_LOG_EOM;
    op->clientIp = mClientIp;
    op->clnt     = this;
    mPendingOpsCount++;
    ClientManager::SubmitRequest(mClientThread, *op);
}

} // namespace KFS
<commit_msg>Meta sever: change default for max number of requests parsed and enqueued in one go with the client threads enabled to 16.<commit_after>//---------------------------------------------------------- -*- Mode: C++ -*-
// $Id$
//
// Created 2006/06/05
// Author: Sriram Rao
//         Mike Ovsiannikov implement multiple outstanding request processing,
//         and "client threads".
//
// Copyright 2008-2012 Quantcast Corp.
// Copyright 2006-2008 Kosmix Corp.
//
// This file is part of Kosmos File System (KFS).
//
// 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.
//
//
// \file ClientSM.cc
// \brief Kfs client protocol state machine implementation.
//
//----------------------------------------------------------------------------

#include "ClientSM.h"
#include "ChunkServer.h"
#include "NetDispatch.h"
#include "util.h"
#include "common/kfstypes.h"
#include "kfsio/Globals.h"
#include "qcdio/qcstutils.h"
#include "kfsio/IOBuffer.h"
#include "common/MsgLogger.h"
#include "common/Properties.h"
#include "AuditLog.h"

#include <string>
#include <sstream>
#include <algorithm>

namespace KFS
{

using std::max;
using std::string;
using std::ostringstream;

inline string
PeerName(const NetConnectionPtr& conn)
{
    return (conn ? conn->GetPeerName() : string("unknown"));
}

inline string
PeerIp(const NetConnectionPtr& conn)
{
    if (! conn) {
        return string();
    }
    const string peer = conn->GetPeerName();
    const size_t pos  = peer.rfind(':');
    if (pos == string::npos) {
        return peer;
    }
    return peer.substr(0, pos);
}

int  ClientSM::sMaxPendingOps             = 1;
int  ClientSM::sMaxPendingBytes           = 3 << 10;
int  ClientSM::sMaxReadAhead              = 3 << 10;
int  ClientSM::sInactivityTimeout         = 8 * 60;
int  ClientSM::sMaxWriteBehind            = 3 << 10;
int  ClientSM::sBufCompactionThreshold    = 1 << 10;
int  ClientSM::sOutBufCompactionThreshold = 8 << 10;
int  ClientSM::sClientCount               = 0;
bool ClientSM::sAuditLoggingFlag          = false;
ClientSM* ClientSM::sClientSMPtr[1]      = {0};
IOBuffer::WOStream ClientSM::sWOStream;

/* static */ void
ClientSM::SetParameters(const Properties& prop)
{
    const int maxPendingOps = prop.getValue(
        "metaServer.clientSM.maxPendingOps",
        -1);
    if (maxPendingOps > 0) {
        sMaxPendingOps = maxPendingOps;
    } else if (! gNetDispatch.IsRunning() &&
            prop.getValue("metaServer.clientThreadCount", -1) > 0) {
        sMaxPendingOps = 16;
    }
    sMaxPendingBytes = max(1, prop.getValue(
        "metaServer.clientSM.maxPendingBytes",
        sMaxPendingBytes));
    sMaxReadAhead = max(256, prop.getValue(
        "metaServer.clientSM.maxReadAhead",
        sMaxReadAhead));
    sInactivityTimeout = prop.getValue(
        "metaServer.clientSM.inactivityTimeout",
        sInactivityTimeout);
    sMaxWriteBehind = max(1, prop.getValue(
        "metaServer.clientSM.maxWriteBehind",
        sMaxWriteBehind));
    sBufCompactionThreshold = prop.getValue(
        "metaServer.clientSM.bufCompactionThreshold",
        sBufCompactionThreshold);
    sOutBufCompactionThreshold = prop.getValue(
        "metaServer.clientSM.outBufCompactionThreshold",
        sOutBufCompactionThreshold);
    sAuditLoggingFlag = prop.getValue(
        "metaServer.clientSM.auditLogging",
        sAuditLoggingFlag ? 1 : 0) != 0;
    AuditLog::SetParameters(prop);
}

ClientSM::ClientSM(
    const NetConnectionPtr&      conn,
    ClientManager::ClientThread* thread,
    IOBuffer::WOStream*          wostr,
    char*                        parseBuffer)
    : mNetConnection(conn),
      mClientIp(PeerIp(conn)),
      mPendingOpsCount(0),
      mOstream(wostr ? *wostr : sWOStream),
      mParseBuffer(parseBuffer),
      mRecursionCnt(0),
      mClientProtoVers(KFS_CLIENT_PROTO_VERS),
      mDisconnectFlag(false),
      mLastReadLeft(0),
      mClientThread(thread),
      mNext(0)
{
    assert(mNetConnection && mNetConnection->IsGood());

    ClientSMList::Init(*this);
    {
        QCStMutexLocker locker(gNetDispatch.GetClientManagerMutex());
        ClientSMList::PushBack(sClientSMPtr, *this);
        sClientCount++;
    }
    mNetConnection->SetInactivityTimeout(sInactivityTimeout);
    mNetConnection->SetMaxReadAhead(sMaxReadAhead);
    SET_HANDLER(this, &ClientSM::HandleRequest);
}

ClientSM::~ClientSM()
{
    QCStMutexLocker locker(gNetDispatch.GetClientManagerMutex());
    ClientSMList::Remove(sClientSMPtr, *this);
    sClientCount--;
}

///
/// Send out the response to the client request.  The response is
/// generated by MetaRequest as per the protocol.
/// @param[in] op The request for which we finished execution.
///
void
ClientSM::SendResponse(MetaRequest *op)
{
    if ((op->op == META_ALLOCATE && (op->status < 0 ||
            static_cast<const MetaAllocate*>(op)->logFlag)) ||
            MsgLogger::GetLogger()->IsLogLevelEnabled(
                MsgLogger::kLogLevelDEBUG)) {
        // for chunk allocations, for debugging purposes, need to know
        // where the chunk was placed.
        KFS_LOG_STREAM_INFO << PeerName(mNetConnection) <<
            " -seq: "   << op->opSeqno <<
            " status: " << op->status <<
            (op->statusMsg.empty() ?
                "" : " msg: ") << op->statusMsg <<
            " "         << op->Show() <<
        KFS_LOG_EOM;
    }
    if (! mNetConnection) {
        return;
    }
    if (op->op == META_DISCONNECT) {
        mDisconnectFlag = true;
    }
    op->response(
        mOstream.Set(mNetConnection->GetOutBuffer()),
        mNetConnection->GetOutBuffer());
    mOstream.Reset();
    if (mRecursionCnt <= 0) {
        mNetConnection->StartFlush();
    }
}

///
/// Generic event handler.  Decode the event that occurred and
/// appropriately extract out the data and deal with the event.
/// @param[in] code: The type of event that occurred
/// @param[in] data: Data being passed in relative to the event that
/// occurred.
/// @retval 0 to indicate successful event handling; -1 otherwise.
///
int
ClientSM::HandleRequest(int code, void *data)
{
    if (code == EVENT_CMD_DONE) {
        assert(data && mPendingOpsCount > 0);
        if (ClientManager::Enqueue(mClientThread,
                *reinterpret_cast<MetaRequest*>(data))) {
            return 0;
        }
    }

    assert(mRecursionCnt >= 0 && (mNetConnection ||
        (code == EVENT_CMD_DONE && data && mPendingOpsCount > 0)));
    mRecursionCnt++;

    switch (code) {
    case EVENT_NET_READ: {
        // We read something from the network. Run the RPC that
        // came in.
        mLastReadLeft = 0;
        IOBuffer& iobuf = mNetConnection->GetInBuffer();
        if (mDisconnectFlag) {
            iobuf.Clear(); // Discard
        }
        assert(data == &iobuf);
        // Do not start new op if response does not get unloaded by
        // the client to prevent out of buffers.
        bool overWriteBehindFlag = false;
        for (; ;) {
            while ((overWriteBehindFlag =
                    mNetConnection->GetNumBytesToWrite() >=
                        sMaxWriteBehind) &&
                    mRecursionCnt <= 1 &&
                    mNetConnection->CanStartFlush()) {
                mNetConnection->StartFlush();
            }
            int cmdLen;
            if (overWriteBehindFlag ||
                    IsOverPendingOpsLimit() ||
                    ! IsMsgAvail(&iobuf, &cmdLen)) {
                break;
            }
            HandleClientCmd(iobuf, cmdLen);
        }
        if (overWriteBehindFlag) {
            break;
        }
        if (! IsOverPendingOpsLimit() && ! mDisconnectFlag) {
            mLastReadLeft = iobuf.BytesConsumable();
            if (mLastReadLeft <= MAX_RPC_HEADER_LEN) {
                mNetConnection->SetMaxReadAhead(sMaxReadAhead);
                break;
            }
            KFS_LOG_STREAM_ERROR << PeerName(mNetConnection) <<
                " exceeded max request header size: " <<
                    mLastReadLeft <<
                " > " << MAX_RPC_HEADER_LEN <<
                " closing connection" <<
            KFS_LOG_EOM;
            mLastReadLeft = 0;
            iobuf.Clear();
            mNetConnection->Close();
            HandleRequest(EVENT_NET_ERROR, NULL);
        }
        break;
    }

    case EVENT_CMD_DONE: {
        assert(data && mPendingOpsCount > 0);
        MetaRequest* const op = reinterpret_cast<MetaRequest*>(data);
        if (sAuditLoggingFlag && ! op->reqHeaders.IsEmpty()) {
            AuditLog::Log(*op);
        }
        SendResponse(op);
        delete op;
        mPendingOpsCount--;
        if (! mNetConnection) {
            break;
        }
        if (mRecursionCnt <= 1 &&
                (mPendingOpsCount <= 0 ||
                ! ClientManager::Flush(
                    mClientThread, *this))) {
            mNetConnection->StartFlush();
        }
    }
        // Fall through.
    case EVENT_NET_WROTE:
        // Something went out on the network.
        // Process next command.
        if (! IsOverPendingOpsLimit() &&
                mRecursionCnt <= 1 &&
                (code == EVENT_CMD_DONE ||
                    ! mNetConnection->IsReadReady()) &&
                mNetConnection->GetNumBytesToWrite() <
                    sMaxWriteBehind) {
            if (mNetConnection->GetNumBytesToRead() >
                    mLastReadLeft ||
                    mDisconnectFlag) {
                HandleRequest(EVENT_NET_READ,
                    &mNetConnection->GetInBuffer());
            } else if (! mNetConnection->IsReadReady()) {
                mNetConnection->SetMaxReadAhead(sMaxReadAhead);
            }
        }
        break;

    case EVENT_NET_ERROR:
        if (mNetConnection->IsGood() &&
                (mPendingOpsCount > 0 ||
                mNetConnection->IsWriteReady())) {
            // Fin from the other side, flush and close connection.
            mDisconnectFlag = true;
            break;
        }
        // Fall through.
    case EVENT_INACTIVITY_TIMEOUT:
        KFS_LOG_STREAM_DEBUG << PeerName(mNetConnection) <<
            " closing connection" <<
        KFS_LOG_EOM;
        mNetConnection->Close();
        mNetConnection->GetInBuffer().Clear();
        break;

    default:
        assert(!"Unknown event");
        break;
    }

    if (mRecursionCnt <= 1) {
        bool goodFlag = mNetConnection && mNetConnection->IsGood();
        if (goodFlag && (mPendingOpsCount <= 0 ||
                ! ClientManager::Flush(
                    mClientThread, *this))) {
            mNetConnection->StartFlush();
            goodFlag = mNetConnection && mNetConnection->IsGood();
        }
        if (goodFlag && mDisconnectFlag) {
            if (mPendingOpsCount <= 0 &&
                    ! mNetConnection->IsWriteReady()) {
                mNetConnection->Close();
                goodFlag = false;
            } else {
                mNetConnection->SetMaxReadAhead(0);
            }
        }
        if (goodFlag) {
            IOBuffer& inbuf = mNetConnection->GetInBuffer();
            int numBytes = inbuf.BytesConsumable();
            if (numBytes <= sBufCompactionThreshold &&
                    numBytes > 0) {
                inbuf.MakeBuffersFull();
            }
            IOBuffer& outbuf = mNetConnection->GetOutBuffer();
            numBytes = outbuf.BytesConsumable();
            if (numBytes <= sOutBufCompactionThreshold &&
                    numBytes > 0) {
                outbuf.MakeBuffersFull();
            }
            if (mNetConnection->IsReadReady() &&
                    (IsOverPendingOpsLimit() ||
                    mNetConnection->GetNumBytesToWrite() >=
                        sMaxWriteBehind ||
                    mNetConnection->GetNumBytesToRead() >=
                        sMaxPendingBytes)) {
                mLastReadLeft = 0;
                mNetConnection->SetMaxReadAhead(0);
            }
        } else {
            if (mPendingOpsCount > 0) {
                mNetConnection.reset();
            } else {
                delete this;
                return 0;
            }
        }
    }
    assert(
        mRecursionCnt > 0 &&
        (mRecursionCnt > 1 || mPendingOpsCount > 0 ||
            (mNetConnection && mNetConnection->IsGood()))
    );
    mRecursionCnt--;
    return 0;
}

///
/// We have a command in a buffer. So, parse out the command and
/// execute it if possible.
/// @param[in] iobuf: Buffer containing the command
/// @param[in] cmdLen: Length of the command in the buffer
///
void
ClientSM::HandleClientCmd(IOBuffer& iobuf, int cmdLen)
{
    assert(! IsOverPendingOpsLimit() && mNetConnection);
    MetaRequest* op = 0;
    if (ParseCommand(iobuf, cmdLen, &op, mParseBuffer) != 0) {
        IOBuffer::IStream is(iobuf, cmdLen);
        char buf[128];
        int  maxLines = 16;
        while (maxLines-- > 0 && is.getline(buf, sizeof(buf))) {
            KFS_LOG_STREAM_ERROR << PeerName(mNetConnection) <<
                " invalid request: " << buf <<
            KFS_LOG_EOM;
        }
        iobuf.Clear();
        mNetConnection->Close();
        HandleRequest(EVENT_NET_ERROR, NULL);
        return;
    }
    if (op->clientProtoVers < mClientProtoVers) {
        mClientProtoVers = op->clientProtoVers;
        KFS_LOG_STREAM_WARN << PeerName(mNetConnection) <<
            " command with old protocol version: " <<
            op->clientProtoVers << ' ' << op->Show() <<
        KFS_LOG_EOM;
    }
    // Command is ready to be pushed down.  So remove the cmd from the buffer.
    if (sAuditLoggingFlag) {
        op->reqHeaders.Move(&iobuf, cmdLen);
    } else {
        iobuf.Consume(cmdLen);
    }
    KFS_LOG_STREAM_DEBUG << PeerName(mNetConnection) <<
        " +seq: " << op->opSeqno <<
        " "       << op->Show() <<
        " pending:"
        " rd: "   << mNetConnection->GetNumBytesToRead() <<
        " wr: "   << mNetConnection->GetNumBytesToWrite() <<
    KFS_LOG_EOM;
    op->clientIp = mClientIp;
    op->clnt     = this;
    mPendingOpsCount++;
    ClientManager::SubmitRequest(mClientThread, *op);
}

} // namespace KFS
<|endoftext|>


<commit_before>#include "client.h"

CLIENT::CLIENT (char *IP)
{
	struct sockaddr_in dest_addr;

        name_verified = false;

	sockfd = socket (AF_INET, SOCK_STREAM, 0);
	if(sockfd == -1){
		perror ("socket");
		exit (EXIT_FAILURE);	// v. pthread_exit
	}

	dest_addr.sin_family = AF_INET;
	dest_addr.sin_port = htons(PORT);
	dest_addr.sin_addr.s_addr = inet_addr(IP);
	memset(&(dest_addr.sin_zero), 0, 8);

	if (connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr)) == -1){
		if(write (STDERR_FILENO, "Couldn't connect to the server\n", 31) != 31){
                        perror ("write");
                        exit (EXIT_FAILURE);
                }
		if(close(sockfd) == -1){
			perror ("close");
			exit (EXIT_FAILURE);	// v. pthread_exit
		}
	}
}

CLIENT::~CLIENT ()
{

}

void CLIENT::Play ()
{
        server = exchangeCIandName ();

        std::thread (writeLoop, this).detach();

        std::thread (readLoop, this).detach();
}

SERVER CLIENT::exchangeCIandName ()
{
        std::string server_pk;
        std::string server_nonce;
        ssize_t br;
        char buf[64];
        char responce;

        server_pk = recvPK ();
        server_nonce =  recvNonce ();

        sendPK();
        sendNonce();

        while(!name_verified){
                if(write (STDOUT_FILENO, "Please select a username: ", 26) != 26){
                    perror ("write");
                    exit (EXIT_FAILURE);
                }

                memset (buf, 0, 64);

                if((br = read (STDIN_FILENO, buf, 64)) == -1){
                        perror ("read");
                        exit (EXIT_FAILURE);
                }

                if(!br){}   //EOF

                if(write (sockfd, buf, sizeof(buf)) != sizeof(buf)){
                        perror ("write");
                        exit (EXIT_FAILURE);
                }

                if(read (sockfd, &responce, 1) != 1){
                        perror ("read");
                        exit (EXIT_FAILURE);
                }

                if(responce == 'Y')
                        name_verified = true;
        }

        CRYPTO cryptinfo (server_pk, server_nonce);
        SERVER server (cryptinfo);

        return server;
}

void CLIENT::sendPK ()
{
        if(write (sockfd, cryptinfo.getPK().c_str(), crypto_box_PUBLICKEYBYTES ) != crypto_box_PUBLICKEYBYTES){
                perror ("write");
                exit (EXIT_FAILURE);
        }
}

void CLIENT::sendNonce ()
{
        if(write (sockfd, cryptinfo.getNonce().c_str(), crypto_box_NONCEBYTES) != crypto_box_NONCEBYTES){
                perror ("write");
                exit (EXIT_FAILURE);
        }
}

std::string CLIENT::recvPK ()
{
        std::string server_pk;
        char buf[crypto_box_PUBLICKEYBYTES];

        memset (buf, 0, crypto_box_PUBLICKEYBYTES);

        if(read (sockfd, buf, crypto_box_PUBLICKEYBYTES) != crypto_box_PUBLICKEYBYTES){
                perror ("read");
                exit (EXIT_FAILURE);
        }

        server_pk = buf;

        return server_pk;
}

std::string CLIENT::recvNonce ()
{
        std::string server_nonce;
        char buf[crypto_box_NONCEBYTES];

        memset (buf, 0, crypto_box_NONCEBYTES);

        if(read (sockfd, buf, crypto_box_NONCEBYTES) != crypto_box_NONCEBYTES){
                perror ("read");
                exit (EXIT_FAILURE);
        }

        server_nonce = buf;

        return server_nonce;
}

int CLIENT::getSFD ()
{
        return sockfd;
}

void readLoop (CLIENT *client_p)
{

}

void writeLoop (CLIENT *client_p)
{
        char buf[1024];
        ssize_t br;

        while(1){
                memset (buf, 0, 1024);

                if((br = read (STDIN_FILENO, buf, 1024)) == -1){
                        perror ("read");
                        exit (EXIT_FAILURE);
                }
                if(!br){
                        //EOF
                        close (client_p->getSFD());
                        return;
                }
                if(write (client_p->getSFD(), buf, br) != br){
                        perror ("write");
                        exit (EXIT_FAILURE);
                }

    }
}<commit_msg>implemented client read loop<commit_after>#include "client.h"

CLIENT::CLIENT (char *IP)
{
	struct sockaddr_in dest_addr;

        name_verified = false;

	sockfd = socket (AF_INET, SOCK_STREAM, 0);
	if(sockfd == -1){
		perror ("socket");
		exit (EXIT_FAILURE);	// v. pthread_exit
	}

	dest_addr.sin_family = AF_INET;
	dest_addr.sin_port = htons(PORT);
	dest_addr.sin_addr.s_addr = inet_addr(IP);
	memset(&(dest_addr.sin_zero), 0, 8);

	if (connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr)) == -1){
		if(write (STDERR_FILENO, "Couldn't connect to the server\n", 31) != 31){
                        perror ("write");
                        exit (EXIT_FAILURE);
                }
		if(close(sockfd) == -1){
			perror ("close");
			exit (EXIT_FAILURE);	// v. pthread_exit
		}
	}
}

CLIENT::~CLIENT ()
{

}

void CLIENT::Play ()
{
        server = exchangeCIandName ();

        std::thread (writeLoop, this).detach();

        std::thread (readLoop, this).detach();
}

SERVER CLIENT::exchangeCIandName ()
{
        std::string server_pk;
        std::string server_nonce;
        ssize_t br;
        char buf[64];
        char responce;

        server_pk = recvPK ();
        server_nonce =  recvNonce ();

        sendPK();
        sendNonce();

        while(!name_verified){
                if(write (STDOUT_FILENO, "Please select a username: ", 26) != 26){
                    perror ("write");
                    exit (EXIT_FAILURE);
                }

                memset (buf, 0, 64);

                if((br = read (STDIN_FILENO, buf, 64)) == -1){
                        perror ("read");
                        exit (EXIT_FAILURE);
                }

                if(!br){}   //EOF

                if(write (sockfd, buf, sizeof(buf)) != sizeof(buf)){
                        perror ("write");
                        exit (EXIT_FAILURE);
                }

                if(read (sockfd, &responce, 1) != 1){
                        perror ("read");
                        exit (EXIT_FAILURE);
                }

                if(responce == 'Y')
                        name_verified = true;
        }

        CRYPTO cryptinfo (server_pk, server_nonce);
        SERVER server (cryptinfo);

        return server;
}

void CLIENT::sendPK ()
{
        if(write (sockfd, cryptinfo.getPK().c_str(), crypto_box_PUBLICKEYBYTES ) != crypto_box_PUBLICKEYBYTES){
                perror ("write");
                exit (EXIT_FAILURE);
        }
}

void CLIENT::sendNonce ()
{
        if(write (sockfd, cryptinfo.getNonce().c_str(), crypto_box_NONCEBYTES) != crypto_box_NONCEBYTES){
                perror ("write");
                exit (EXIT_FAILURE);
        }
}

std::string CLIENT::recvPK ()
{
        std::string server_pk;
        char buf[crypto_box_PUBLICKEYBYTES];

        memset (buf, 0, crypto_box_PUBLICKEYBYTES);

        if(read (sockfd, buf, crypto_box_PUBLICKEYBYTES) != crypto_box_PUBLICKEYBYTES){
                perror ("read");
                exit (EXIT_FAILURE);
        }

        server_pk = buf;

        return server_pk;
}

std::string CLIENT::recvNonce ()
{
        std::string server_nonce;
        char buf[crypto_box_NONCEBYTES];

        memset (buf, 0, crypto_box_NONCEBYTES);

        if(read (sockfd, buf, crypto_box_NONCEBYTES) != crypto_box_NONCEBYTES){
                perror ("read");
                exit (EXIT_FAILURE);
        }

        server_nonce = buf;

        return server_nonce;
}

int CLIENT::getSFD ()
{
        return sockfd;
}

void readLoop (CLIENT *client_p)
{
        char buf[1024];
        ssize_t br;

        while(1){
                memset (buf, 0, 1024);

                if((br = read (client_p->getSFD(), buf, 1024)) == -1){
                        perror ("read");
                        exit (EXIT_FAILURE);
                }
                if(!br)
                        return;
                if(write(STDOUT_FILENO, buf, br) != br){
                        perror ("write");
                        exit (EXIT_FAILURE);
                }
        }
}

void writeLoop (CLIENT *client_p)
{
        char buf[1024];
        ssize_t br;

        while(1){
                memset (buf, 0, 1024);

                if((br = read (STDIN_FILENO, buf, 1024)) == -1){
                        perror ("read");
                        exit (EXIT_FAILURE);
                }
                if(!br){
                        //EOF
                        close (client_p->getSFD());
                        return;
                }
                if(write (client_p->getSFD(), buf, br) != br){
                        perror ("write");
                        exit (EXIT_FAILURE);
                }

        }
}<|endoftext|>


<commit_before>#include "player.h"
#include "subjectblock.h"
#include "types.h"
#include <iostream>
#include <algorithm>
#include <QDebug>
#include "board.h"
#include <QtGlobal>
#include <QPropertyAnimation>
#include <QSequentialAnimationGroup>
#include "localgame.h"
#include "sellpopup.h"
#include <QMediaPlayer>
#include <QFileInfo>
#include <QDir>
#define NUMBER_OF_BLOCKS 32
#define NEXT_POS(current_pos) ((current_pos + 1) % 32)

using namespace std;

Player::Player(QGameItem* parent,int _id) : QGameItem(parent)
{
    //randomly determine CharacterType
    switch(rand() % 5){
        case 0:
            character_type = CharacterType::LOL;
            break;
        case 1:
            character_type = CharacterType::GENIUS;
            break;
        case 2:
            character_type = CharacterType::HARD_WORKER;
            break;
        case 3:
            character_type = CharacterType::OUTSIDER;
            break;
        case 4:
            character_type = CharacterType::ALCOHOLIC;
    }

    id = _id;
    name = "";
    position = 0;

    energy = 1000;
    if(character_type == CharacterType::GENIUS)
        energy += 200;

    bankrupt = false;
    mobile = true;
    immobile_penalty = 0;
    plural = false;

    //initialize map
    using namespace SubjectType;
    registered[BIO] = 0;
    registered[CHEM] = 0;
    registered[CSED] = 0;
    registered[EE] = 0;
    registered[MATH] = 0;
    registered[ME] = 0;
    registered[IME] = 0;
    registered[PHYS] = 0;

    switch(_id){
    case 1:
        color = QString("red");
        break;
    case 2:
        color = QString("blue");
        break;
    case 3:
        color = QString("green");
        break;
    case 4:
        color = QString("yellow");
        break;
    }

    using namespace BlockCoords;

    for(int i =0; i < 32; i ++){
        player_coord[i] = block_coord[i];
    }

    for(int i=1; i< 24; i ++){
        player_coord[i] += QPointF(0,-40);
    }

    for(int i=17; i<24; i++){
        player_coord[i] += QPointF(40,0);
    }

    player_coord[8] = block_coord[8];

    setPos(player_coord[0]);

    // step sound load
    mediaplayer = new QMediaPlayer();
    mediaplayer->setMedia(QUrl::fromLocalFile(QFileInfo("sound/piece_move.wav").absoluteFilePath()));
    mediaplayer->setVolume(100);

    // end initialize
    qDebug() << "Player Created" << endl;
}

Player::~Player()
{

    qDebug() << "Player Destroyed" << endl;
}

void Player::setColor(QString color_str){
    color = color_str;
}

QString Player::getColor(){
    return color;
}

// Accessor Methods
int Player::getPosition() const
{
    return position;
}

QPointF Player::adjustCoord(QPointF &coord){
    return coord;
}

bool Player::isBankrupt() const
{
    return bankrupt;
}

bool Player::isMobile() const
{
    return mobile;
}

int Player::getEnergy() const
{
    return energy;
}

int Player::getPenalty() const
{
    return immobile_penalty;
}

bool Player::isPlural() const
{
    return plural;
}

CharacterType::Type Player::getType() const
{
    return character_type;
}

list<Block*> Player::getBlocks() const
{
    return own_blocks;
}

// Methods
void Player::setEnergy(int energy)
{
    this->energy = energy;
    emit energyChanged(this->energy);
}

void Player::setPlural(bool plural)
{
    this->plural = plural;
}

void Player::setBankrupt()
{
    setEnergy(0);
    bankrupt = true;

    for(list<Block*>::iterator itor = own_blocks.begin(); itor != own_blocks.end(); itor++)
       removeBlock(dynamic_cast<SubjectBlock*>(*itor));
}

// set player to stay mouindo
// parm: how long to stay in mouindo
void Player::setMouindo(int penalty)
{
    this->immobile_penalty = penalty;
    mobile = false;
}

void Player::setMobile(bool mobile){
    this->mobile = mobile;
    immobile_penalty = 0;
}

void Player::escapeAttempt(){
    immobile_penalty--;
    if(immobile_penalty==0)
        mobile = true;
}

//probably unused forever...
bool Player::escapeMouindo()
{
    if(mobile)
        return true;

    else {

        if(immobile_penalty == 0) {
            mobile = true;
            return true;
        }

        else {
            // roll a dice
            immobile_penalty--;
            return false;
        }
    }
}

void Player::walkBy(int steps)
{
    using namespace BlockCoords;
    LocalGame::getInst()->setGameState(LocalGameState::PLAYER_MOVING);
    const int step_interval = 300; //0.1 seconds
    int current_pos = position;
    int next_pos;

    QSequentialAnimationGroup * seq_animation_group
            = new QSequentialAnimationGroup;

    //add sleep animation
    QPropertyAnimation * sleep
            = new QPropertyAnimation(this,"pos");
    sleep->setDuration(1800);
    //don't move
    sleep->setStartValue(player_coord[current_pos]);
    sleep->setEndValue(player_coord[current_pos]);
    seq_animation_group->addAnimation(sleep);

    while(steps){
        next_pos = NEXT_POS(current_pos);
        QPropertyAnimation * step_animation
                = new QPropertyAnimation(this,"pos");
        step_animation->setDuration(step_interval);
        step_animation->setStartValue(player_coord[current_pos]);
        step_animation->setEndValue(player_coord[next_pos]);
        step_animation->setEasingCurve(QEasingCurve::InOutQuint);
        connect(step_animation,SIGNAL(finished()),this,SLOT(stepForward()));
        seq_animation_group->addAnimation(step_animation);
        steps--; //decrease one step
        current_pos = next_pos;

    }
    seq_animation_group->start(QAbstractAnimation::DeleteWhenStopped);

    connect(seq_animation_group,SIGNAL(finished()),this,SLOT(arrived()));
    //position = current_pos;
}

void Player::jumpTo(int block_num){
    using namespace BlockCoords;
    LocalGame::getInst()->setGameState(LocalGameState::PLAYER_MOVING);
    QPointF target = player_coord[block_num];
    QPropertyAnimation * step_animation
            = new QPropertyAnimation(this,"pos");
    step_animation->setDuration(2000);
    step_animation->setStartValue(player_coord[getPosition()]);
    step_animation->setEndValue(target);
    step_animation->setEasingCurve(QEasingCurve::InOutQuint);
    step_animation->start(QAbstractAnimation::DeleteWhenStopped);

    connect(step_animation,SIGNAL(finished()),this,SLOT(arrived()));
    position = block_num;
}

void Player::stepForward(){
    position = NEXT_POS(position);
    mediaplayer->play();
    if(position == 0){
        giveSalary();
    }
}

void Player::arrived(){
    qDebug() << "arrived at:"<<position;
    emit playerArrived(this);
}

bool Player::hasBlock(Block* block)
{
    // subject block check
    if(block->getType() != BlockType::SUBJECT) {
        qDebug() << "This is not a Subject Block!";
        return false;
    }

    list<Block*>::iterator finder = own_blocks.end();
    finder = find(own_blocks.begin(), own_blocks.end(), block);

    // no matching
    if(finder == own_blocks.end())
        return false;
    else
        return true;
}

void Player::addBlock(Block *block)
{
    SubjectBlock * subj_block = dynamic_cast<SubjectBlock*>(block);
    subj_block->setOwner(this);
    registered.find(((SubjectBlock*)block)->getDept())->second++;
    own_blocks.push_back(block);
}

void Player::removeBlock(Block *block)
{
    if(!hasBlock(block)) {
        qDebug() << "You don't have that block. Check Again!";
        return;
    }
    SubjectBlock * sblock = dynamic_cast<SubjectBlock*>(block);
    sblock->setGrade(SubjectBlock::NONE);
    sblock->setOwner(NULL);
    registered.find(((SubjectBlock*)block)->getDept())->second--;
    own_blocks.remove(block);
}

void Player::giveSalary()
{
    qDebug() << "Player " << id << " received salary";
    //maybe add animation for gaining energy

    QMediaPlayer* mediaplayer = new QMediaPlayer();
    mediaplayer->setMedia(QUrl::fromLocalFile(QFileInfo("sound/coinsprinkle.mp3").absoluteFilePath()));
    mediaplayer->setVolume(100);
    mediaplayer->play();

    if(character_type == CharacterType::HARD_WORKER)
        energy += 150;
    else
        energy += 100;

    emit energyChanged(this->energy);
}

bool Player::checkWinStatus()
{
    int majored = 0;

    for(map<SubjectType::Type, int>::iterator i = registered.begin(); i != registered.end(); i++) {
        if(i->second == 3)
            majored ++;
    }

    if(plural && majored >= 2)
        return true;
    else if (!plural && majored >= 1)
        return true;
    else
        return false;
}

void Player::payEnergy(int payenergy)
{
    if(energy >= payenergy)
    {
        QMediaPlayer* coinsound = new QMediaPlayer();
        coinsound->setMedia(QUrl::fromLocalFile(QFileInfo("sound/coinspread.mp3").absoluteFilePath()));
        coinsound->setVolume(100);
        coinsound->play();
        energy-=payenergy;
    }
    else{
        if(getAssetValue() >= payenergy){
            Sellpopup * popup = new Sellpopup(QGameItem::getWindow(), this, payenergy);
            popup->show();
        }
        else
            setBankrupt();
    }
    emit energyChanged(this->energy);
}
void Player::giveEnergy(int paidenergy){
    energy+=paidenergy;
    QMediaPlayer* coinsound = new QMediaPlayer();
    coinsound->setMedia(QUrl::fromLocalFile(QFileInfo("sound/coinspread.mp3").absoluteFilePath()));
    coinsound->setVolume(100);
    coinsound->play();
    emit energyChanged(this->energy);
}

int Player::getId() const {
    return id;
}

void Player::setType(CharacterType::Type type) {
    character_type = type;
}

int Player::getAssetValue() {

    int asset = 0;

    if(own_blocks.empty()) {
        qDebug() << "Player has nothing!";
        asset = 0;
    }
    else {
        for(list<Block*>::iterator itor = own_blocks.begin(); itor != own_blocks.end(); itor++) {
           asset += dynamic_cast<SubjectBlock*>(*itor)->getSellCost();
        }
    }
    return asset;
}

void Player::animatePlayerImage(int frame){
    QString filename = QString(":/images/ingame/character/");

    int zone = position /8 ;

    if(zone == 0){
        filename += QString("top_up_");
    }
    else if(zone ==1){
        filename += QString("top_right_");
    }
    else if(zone ==2){
        filename += QString("top_down_");
    }
    else {
        filename += QString("top_right_");
    }

    if(id == 1 || id ==3)
        filename += QString("io_");
    else if(id == 2 || id ==4)
        filename += QString("id_");

    filename += color + QString("_");

    LocalGame * game_inst = LocalGame::getInst();

    if(game_inst->getGameState() == LocalGameState::PLAYER_MOVING
            && game_inst->getCurrentPlayer() == this)
        filename += QString("walk_");
    else
        filename += QString("stand_");

    filename += QString::number(frame).rightJustified(3,'0') + QString(".png");

    //qDebug() << filename;

    QImage image(filename);

    QTransform rotate;
    rotate.rotate(180);

    if(zone == 3)
        image = image.mirrored(true,false);

    setPixmap(QPixmap::fromImage(image));
}
<commit_msg>Player: energy set to 500 / checkwinstatus update<commit_after>#include "player.h"
#include "subjectblock.h"
#include "types.h"
#include <iostream>
#include <algorithm>
#include <QDebug>
#include "board.h"
#include <QtGlobal>
#include <QPropertyAnimation>
#include <QSequentialAnimationGroup>
#include "localgame.h"
#include "sellpopup.h"
#include <QMediaPlayer>
#include <QFileInfo>
#include <QDir>
#define NUMBER_OF_BLOCKS 32
#define NEXT_POS(current_pos) ((current_pos + 1) % 32)

using namespace std;

Player::Player(QGameItem* parent,int _id) : QGameItem(parent)
{
    //randomly determine CharacterType
    switch(rand() % 5){
        case 0:
            character_type = CharacterType::LOL;
            break;
        case 1:
            character_type = CharacterType::GENIUS;
            break;
        case 2:
            character_type = CharacterType::HARD_WORKER;
            break;
        case 3:
            character_type = CharacterType::OUTSIDER;
            break;
        case 4:
            character_type = CharacterType::ALCOHOLIC;
    }

    id = _id;
    name = "";
    position = 0;

    energy = 500;
    if(character_type == CharacterType::GENIUS)
        energy += 200;

    bankrupt = false;
    mobile = true;
    immobile_penalty = 0;
    plural = false;

    //initialize map
    using namespace SubjectType;
    registered[BIO] = 0;
    registered[CHEM] = 0;
    registered[CSED] = 0;
    registered[EE] = 0;
    registered[MATH] = 0;
    registered[ME] = 0;
    registered[IME] = 0;
    registered[PHYS] = 0;

    switch(_id){
    case 1:
        color = QString("red");
        break;
    case 2:
        color = QString("blue");
        break;
    case 3:
        color = QString("green");
        break;
    case 4:
        color = QString("yellow");
        break;
    }

    using namespace BlockCoords;

    for(int i =0; i < 32; i ++){
        player_coord[i] = block_coord[i];
    }

    for(int i=1; i< 24; i ++){
        player_coord[i] += QPointF(0,-40);
    }

    for(int i=17; i<24; i++){
        player_coord[i] += QPointF(40,0);
    }

    player_coord[8] = block_coord[8];

    setPos(player_coord[0]);

    // step sound load
    mediaplayer = new QMediaPlayer();
    mediaplayer->setMedia(QUrl::fromLocalFile(QFileInfo("sound/piece_move.wav").absoluteFilePath()));
    mediaplayer->setVolume(100);

    // end initialize
    qDebug() << "Player Created" << endl;
}

Player::~Player()
{

    qDebug() << "Player Destroyed" << endl;
}

void Player::setColor(QString color_str){
    color = color_str;
}

QString Player::getColor(){
    return color;
}

// Accessor Methods
int Player::getPosition() const
{
    return position;
}

QPointF Player::adjustCoord(QPointF &coord){
    return coord;
}

bool Player::isBankrupt() const
{
    return bankrupt;
}

bool Player::isMobile() const
{
    return mobile;
}

int Player::getEnergy() const
{
    return energy;
}

int Player::getPenalty() const
{
    return immobile_penalty;
}

bool Player::isPlural() const
{
    return plural;
}

CharacterType::Type Player::getType() const
{
    return character_type;
}

list<Block*> Player::getBlocks() const
{
    return own_blocks;
}

// Methods
void Player::setEnergy(int energy)
{
    this->energy = energy;
    emit energyChanged(this->energy);
}

void Player::setPlural(bool plural)
{
    this->plural = plural;
}

void Player::setBankrupt()
{
    setEnergy(0);
    bankrupt = true;

    for(list<Block*>::iterator itor = own_blocks.begin(); itor != own_blocks.end(); itor++)
       removeBlock(dynamic_cast<SubjectBlock*>(*itor));
}

// set player to stay mouindo
// parm: how long to stay in mouindo
void Player::setMouindo(int penalty)
{
    this->immobile_penalty = penalty;
    mobile = false;
}

void Player::setMobile(bool mobile){
    this->mobile = mobile;
    immobile_penalty = 0;
}

void Player::escapeAttempt(){
    immobile_penalty--;
    if(immobile_penalty==0)
        mobile = true;
}

//probably unused forever...
bool Player::escapeMouindo()
{
    if(mobile)
        return true;

    else {

        if(immobile_penalty == 0) {
            mobile = true;
            return true;
        }

        else {
            // roll a dice
            immobile_penalty--;
            return false;
        }
    }
}

void Player::walkBy(int steps)
{
    using namespace BlockCoords;
    LocalGame::getInst()->setGameState(LocalGameState::PLAYER_MOVING);
    const int step_interval = 300; //0.1 seconds
    int current_pos = position;
    int next_pos;

    QSequentialAnimationGroup * seq_animation_group
            = new QSequentialAnimationGroup;

    //add sleep animation
    QPropertyAnimation * sleep
            = new QPropertyAnimation(this,"pos");
    sleep->setDuration(1800);
    //don't move
    sleep->setStartValue(player_coord[current_pos]);
    sleep->setEndValue(player_coord[current_pos]);
    seq_animation_group->addAnimation(sleep);

    while(steps){
        next_pos = NEXT_POS(current_pos);
        QPropertyAnimation * step_animation
                = new QPropertyAnimation(this,"pos");
        step_animation->setDuration(step_interval);
        step_animation->setStartValue(player_coord[current_pos]);
        step_animation->setEndValue(player_coord[next_pos]);
        step_animation->setEasingCurve(QEasingCurve::InOutQuint);
        connect(step_animation,SIGNAL(finished()),this,SLOT(stepForward()));
        seq_animation_group->addAnimation(step_animation);
        steps--; //decrease one step
        current_pos = next_pos;

    }
    seq_animation_group->start(QAbstractAnimation::DeleteWhenStopped);

    connect(seq_animation_group,SIGNAL(finished()),this,SLOT(arrived()));
    //position = current_pos;
}

void Player::jumpTo(int block_num){
    using namespace BlockCoords;
    LocalGame::getInst()->setGameState(LocalGameState::PLAYER_MOVING);
    QPointF target = player_coord[block_num];
    QPropertyAnimation * step_animation
            = new QPropertyAnimation(this,"pos");
    step_animation->setDuration(2000);
    step_animation->setStartValue(player_coord[getPosition()]);
    step_animation->setEndValue(target);
    step_animation->setEasingCurve(QEasingCurve::InOutQuint);
    step_animation->start(QAbstractAnimation::DeleteWhenStopped);

    connect(step_animation,SIGNAL(finished()),this,SLOT(arrived()));
    position = block_num;
}

void Player::stepForward(){
    position = NEXT_POS(position);
    mediaplayer->play();
    if(position == 0){
        giveSalary();
    }
}

void Player::arrived(){
    qDebug() << "arrived at:"<<position;
    emit playerArrived(this);
}

bool Player::hasBlock(Block* block)
{
    // subject block check
    if(block->getType() != BlockType::SUBJECT) {
        qDebug() << "This is not a Subject Block!";
        return false;
    }

    list<Block*>::iterator finder = own_blocks.end();
    finder = find(own_blocks.begin(), own_blocks.end(), block);

    // no matching
    if(finder == own_blocks.end())
        return false;
    else
        return true;
}

void Player::addBlock(Block *block)
{
    SubjectBlock * subj_block = dynamic_cast<SubjectBlock*>(block);
    subj_block->setOwner(this);
    registered.find(((SubjectBlock*)block)->getDept())->second++;
    own_blocks.push_back(block);
}

void Player::removeBlock(Block *block)
{
    if(!hasBlock(block)) {
        qDebug() << "You don't have that block. Check Again!";
        return;
    }
    SubjectBlock * sblock = dynamic_cast<SubjectBlock*>(block);
    sblock->setGrade(SubjectBlock::NONE);
    sblock->setOwner(NULL);
    registered.find(((SubjectBlock*)block)->getDept())->second--;
    own_blocks.remove(block);
}

void Player::giveSalary()
{
    qDebug() << "Player " << id << " received salary";
    //maybe add animation for gaining energy

    QMediaPlayer* mediaplayer = new QMediaPlayer();
    mediaplayer->setMedia(QUrl::fromLocalFile(QFileInfo("sound/coinsprinkle.mp3").absoluteFilePath()));
    mediaplayer->setVolume(100);
    mediaplayer->play();

    if(character_type == CharacterType::HARD_WORKER)
        energy += 150;
    else
        energy += 100;

    emit energyChanged(this->energy);
}

bool Player::checkWinStatus()
{
    int majored = 0;
    int majored_b = 0;

    map<SubjectType::Type, int> B_grades;

    B_grades[BIO] = 0;
    B_grades[CHEM] = 0;
    B_grades[CSED] = 0;
    B_grades[EE] = 0;
    B_grades[MATH] = 0;
    B_grades[ME] = 0;
    B_grades[IME] = 0;
    B_grades[PHYS] = 0;

    foreach(block,own_blocks){
        SubjectBlock* sblock = dynamic_cast<SubjectBlock*>(block);
        if(sblock->getGrade() == SubjectBlock::B ||
                sblock->getGrade() == SubjectBlock::A)
            B_grades[sblock->getDept()]++;
    }

    for(map<SubjectType::Type, int>::iterator i =registered.begin(); i != registered.end(); i++) {
        if(i->second == 3)
            majored ++;
    }

    for(map<SubjectType::Type, int>::iterator i = B_grades.begin(); i != B_grades.end(); i++) {
        if(i->second == 3)
            majored_b ++;
    }

    if(plural && majored ==2)
        return true;
    else if(!plural && majored_b == 1)
        return true;
    else
        false;

}

void Player::payEnergy(int payenergy)
{
    if(energy >= payenergy)
    {
        QMediaPlayer* coinsound = new QMediaPlayer();
        coinsound->setMedia(QUrl::fromLocalFile(QFileInfo("sound/coinspread.mp3").absoluteFilePath()));
        coinsound->setVolume(100);
        coinsound->play();
        energy-=payenergy;
    }
    else{
        if(getAssetValue() >= payenergy){
            Sellpopup * popup = new Sellpopup(QGameItem::getWindow(), this, payenergy);
            popup->show();
        }
        else
            setBankrupt();
    }
    emit energyChanged(this->energy);
}
void Player::giveEnergy(int paidenergy){
    energy+=paidenergy;
    QMediaPlayer* coinsound = new QMediaPlayer();
    coinsound->setMedia(QUrl::fromLocalFile(QFileInfo("sound/coinspread.mp3").absoluteFilePath()));
    coinsound->setVolume(100);
    coinsound->play();
    emit energyChanged(this->energy);
}

int Player::getId() const {
    return id;
}

void Player::setType(CharacterType::Type type) {
    character_type = type;
}

int Player::getAssetValue() {

    int asset = 0;

    if(own_blocks.empty()) {
        qDebug() << "Player has nothing!";
        asset = 0;
    }
    else {
        for(list<Block*>::iterator itor = own_blocks.begin(); itor != own_blocks.end(); itor++) {
           asset += dynamic_cast<SubjectBlock*>(*itor)->getSellCost();
        }
    }
    return asset;
}

void Player::animatePlayerImage(int frame){
    QString filename = QString(":/images/ingame/character/");

    int zone = position /8 ;

    if(zone == 0){
        filename += QString("top_up_");
    }
    else if(zone ==1){
        filename += QString("top_right_");
    }
    else if(zone ==2){
        filename += QString("top_down_");
    }
    else {
        filename += QString("top_right_");
    }

    if(id == 1 || id ==3)
        filename += QString("io_");
    else if(id == 2 || id ==4)
        filename += QString("id_");

    filename += color + QString("_");

    LocalGame * game_inst = LocalGame::getInst();

    if(game_inst->getGameState() == LocalGameState::PLAYER_MOVING
            && game_inst->getCurrentPlayer() == this)
        filename += QString("walk_");
    else
        filename += QString("stand_");

    filename += QString::number(frame).rightJustified(3,'0') + QString(".png");

    //qDebug() << filename;

    QImage image(filename);

    QTransform rotate;
    rotate.rotate(180);

    if(zone == 3)
        image = image.mirrored(true,false);

    setPixmap(QPixmap::fromImage(image));
}
<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_FUN_MULTIPLY_HPP
#define STAN_MATH_PRIM_FUN_MULTIPLY_HPP

#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/err.hpp>
#include <stan/math/prim/fun/Eigen.hpp>
#include <stan/math/prim/fun/dot_product.hpp>
#ifdef STAN_OPENCL
#include <stan/math/opencl/prim.hpp>
#endif
#include <type_traits>

namespace stan {
namespace math {

/**
 * Return specified matrix multiplied by specified scalar.
 *
 * @tparam Mat type of the matrix or expression
 * @tparam Scal type of the scalar
 *
 * @param m matrix
 * @param c scalar
 * @return product of matrix and scalar
 */
template <typename Mat, typename Scal, require_stan_scalar_t<Scal>* = nullptr,
          require_eigen_t<Mat>* = nullptr,
          require_all_not_st_var<Scal, Mat>* = nullptr>
inline auto multiply(const Mat& m, Scal c) {
  return c * m;
}

/**
 * Return specified scalar multiplied by specified matrix.
 *
 * @tparam Scal type of the scalar
 * @tparam Mat type of the matrix or expression
 *
 * @param c scalar
 * @param m matrix
 * @return product of scalar and matrix
 */
template <typename Scal, typename Mat, require_stan_scalar_t<Scal>* = nullptr,
          require_eigen_t<Mat>* = nullptr,
          require_all_not_st_var<Scal, Mat>* = nullptr>
inline auto multiply(Scal c, const Mat& m) {
  return c * m;
}

/**
 * Return the product of the specified matrices. The number of
 * columns in the first matrix must be the same as the number of rows
 * in the second matrix.
 *
 * @tparam Mat1 type of the first matrix or expression
 * @tparam Mat2 type of the second matrix or expression
 *
 * @param m1 first matrix or expression
 * @param m2 second matrix or expression
 * @return the product of the first and second matrices
 * @throw std::invalid_argument if the number of columns of m1 does
 * not match the number of rows of m2.
 */
template <typename Mat1, typename Mat2,
          require_all_eigen_vt<std::is_arithmetic, Mat1, Mat2>* = nullptr,
          require_any_not_same_t<double, value_type_t<Mat1>,
                                 value_type_t<Mat2>>* = nullptr,
          require_not_eigen_row_and_col_t<Mat1, Mat2>* = nullptr>
inline auto multiply(const Mat1& m1, const Mat2& m2) {
  check_size_match("multiply", "Columns of m1", m1.cols(), "Rows of m2",
                   m2.rows());
  return m1 * m2;
}

/**
 * Return the product of the specified matrices. The number of
 * columns in the first matrix must be the same as the number of rows
 * in the second matrix. If scalar of matrices is \c double OpenCL
 * implementation can be used.
 *
 * @tparam Mat1 type of the first matrix or expression
 * @tparam Mat2 type of the second matrix or expression
 *
 * @param m1 first matrix or expression
 * @param m2 second matrix or expression
 * @return the product of the first and second matrices
 * @throw std::invalid_argument if the number of columns of m1 does
 * not match the number of rows of m2.
 */
template <typename Mat1, typename Mat2,
          require_all_eigen_t<Mat1, Mat2>* = nullptr,
          require_all_same_t<double, value_type_t<Mat1>,
                             value_type_t<Mat2>>* = nullptr,
          require_not_eigen_row_and_col_t<Mat1, Mat2>* = nullptr>
inline auto multiply(const Mat1& m1, const Mat2& m2)
    -> decltype((m1 * m2).eval()) {
  check_multiplicable("multiply", "m1", m1, "m2", m2);

#ifdef STAN_OPENCL
  if (m1.rows() * m1.cols() * m2.cols()
      > opencl_context.tuning_opts().multiply_dim_prod_worth_transfer) {
    matrix_cl<double> m1_cl(m1);
    matrix_cl<double> m2_cl(m2);
    matrix_cl<double> m3_cl = m1_cl * m2_cl;
    return from_matrix_cl<Mat1::RowsAtCompileTime, Mat2::ColsAtCompileTime>(
        m3_cl);
  } else {
    return (m1 * m2).eval();
  }
#else
  return (m1 * m2).eval();
#endif
}

/**
 * Return the scalar product of the specified row vector and
 * specified column vector.  The return is the same as the dot
 * product.  The two vectors must be the same size.
 *
 * @tparam RowVec type of the row vector
 * @tparam ColVec type of the column vector
 *
 * @param rv row vector
 * @param v column vector
 * @return scalar result of multiplying row vector by column vector
 * @throw std::invalid_argument if rv and v are not the same size
 */
template <typename RowVec, typename ColVec,
          require_all_not_st_var<RowVec, ColVec>* = nullptr,
          require_eigen_row_and_col_t<RowVec, ColVec>* = nullptr>
inline auto multiply(const RowVec& rv, const ColVec& v) {
  check_multiplicable("multiply", "rv", rv, "v", v);
  return dot_product(rv, v);
}

/**
 * Return product of scalars.
 *
 * @tparam Scalar1 type of first scalar
 * @tparam Scalar2 type of second scalar
 * @param m scalar
 * @param c scalar
 * @return product
 */
template <typename Scalar1, typename Scalar2,
          require_all_stan_scalar_t<Scalar1, Scalar2>* = nullptr>
inline return_type_t<Scalar1, Scalar2> multiply(Scalar1 m, Scalar2 c) {
  return c * m;
}

}  // namespace math
}  // namespace stan

#endif
<commit_msg>remove OpenCL code from prim multiply.hpp<commit_after>#ifndef STAN_MATH_PRIM_FUN_MULTIPLY_HPP
#define STAN_MATH_PRIM_FUN_MULTIPLY_HPP

#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/err.hpp>
#include <stan/math/prim/fun/Eigen.hpp>
#include <stan/math/prim/fun/dot_product.hpp>
#include <type_traits>

namespace stan {
namespace math {

/**
 * Return specified matrix multiplied by specified scalar.
 *
 * @tparam Mat type of the matrix or expression
 * @tparam Scal type of the scalar
 *
 * @param m matrix
 * @param c scalar
 * @return product of matrix and scalar
 */
template <typename Mat, typename Scal, require_stan_scalar_t<Scal>* = nullptr,
          require_eigen_t<Mat>* = nullptr,
          require_all_not_st_var<Scal, Mat>* = nullptr>
inline auto multiply(const Mat& m, Scal c) {
  return c * m;
}

/**
 * Return specified scalar multiplied by specified matrix.
 *
 * @tparam Scal type of the scalar
 * @tparam Mat type of the matrix or expression
 *
 * @param c scalar
 * @param m matrix
 * @return product of scalar and matrix
 */
template <typename Scal, typename Mat, require_stan_scalar_t<Scal>* = nullptr,
          require_eigen_t<Mat>* = nullptr,
          require_all_not_st_var<Scal, Mat>* = nullptr>
inline auto multiply(Scal c, const Mat& m) {
  return c * m;
}

/**
 * Return the product of the specified matrices. The number of
 * columns in the first matrix must be the same as the number of rows
 * in the second matrix.
 *
 * @tparam Mat1 type of the first matrix or expression
 * @tparam Mat2 type of the second matrix or expression
 *
 * @param m1 first matrix or expression
 * @param m2 second matrix or expression
 * @return the product of the first and second matrices
 * @throw std::invalid_argument if the number of columns of m1 does
 * not match the number of rows of m2.
 */
template <typename Mat1, typename Mat2,
          require_all_eigen_vt<std::is_arithmetic, Mat1, Mat2>* = nullptr,
          require_not_eigen_row_and_col_t<Mat1, Mat2>* = nullptr>
inline auto multiply(const Mat1& m1, const Mat2& m2) {
  check_size_match("multiply", "Columns of m1", m1.cols(), "Rows of m2",
                   m2.rows());
  return m1 * m2;
}

/**
 * Return the scalar product of the specified row vector and
 * specified column vector.  The return is the same as the dot
 * product.  The two vectors must be the same size.
 *
 * @tparam RowVec type of the row vector
 * @tparam ColVec type of the column vector
 *
 * @param rv row vector
 * @param v column vector
 * @return scalar result of multiplying row vector by column vector
 * @throw std::invalid_argument if rv and v are not the same size
 */
template <typename RowVec, typename ColVec,
          require_all_not_st_var<RowVec, ColVec>* = nullptr,
          require_eigen_row_and_col_t<RowVec, ColVec>* = nullptr>
inline auto multiply(const RowVec& rv, const ColVec& v) {
  check_multiplicable("multiply", "rv", rv, "v", v);
  return dot_product(rv, v);
}

/**
 * Return product of scalars.
 *
 * @tparam Scalar1 type of first scalar
 * @tparam Scalar2 type of second scalar
 * @param m scalar
 * @param c scalar
 * @return product
 */
template <typename Scalar1, typename Scalar2,
          require_all_stan_scalar_t<Scalar1, Scalar2>* = nullptr>
inline return_type_t<Scalar1, Scalar2> multiply(Scalar1 m, Scalar2 c) {
  return c * m;
}

}  // namespace math
}  // namespace stan

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "chainparamsbase.h"

#include "util.h"

#include <assert.h>

#include <boost/assign/list_of.hpp>

using namespace boost::assign;

/**
 * Main network
 */
class CBaseMainParams : public CBaseChainParams
{
public:
    CBaseMainParams()
    {
        networkID = CBaseChainParams::MAIN;
        nRPCPort = 8372;
    }
};
static CBaseMainParams mainParams;

/**
 * Testnet (v3)
 */
class CBaseTestNetParams : public CBaseMainParams
{
public:
    CBaseTestNetParams()
    {
        networkID = CBaseChainParams::TESTNET;
        nRPCPort = 18372;
        strDataDir = "testnet3";
    }
};
static CBaseTestNetParams testNetParams;

/*
 * Regression test
 */
class CBaseRegTestParams : public CBaseTestNetParams
{
public:
    CBaseRegTestParams()
    {
        networkID = CBaseChainParams::REGTEST;
        strDataDir = "regtest";
    }
};
static CBaseRegTestParams regTestParams;

/*
 * Unit test
 */
class CBaseUnitTestParams : public CBaseMainParams
{
public:
    CBaseUnitTestParams()
    {
        networkID = CBaseChainParams::UNITTEST;
        strDataDir = "unittest";
    }
};
static CBaseUnitTestParams unitTestParams;

static CBaseChainParams* pCurrentBaseParams = 0;

const CBaseChainParams& BaseParams()
{
    assert(pCurrentBaseParams);
    return *pCurrentBaseParams;
}

void SelectBaseParams(CBaseChainParams::Network network)
{
    switch (network) {
    case CBaseChainParams::MAIN:
        pCurrentBaseParams = &mainParams;
        break;
    case CBaseChainParams::TESTNET:
        pCurrentBaseParams = &testNetParams;
        break;
    case CBaseChainParams::REGTEST:
        pCurrentBaseParams = &regTestParams;
        break;
    case CBaseChainParams::UNITTEST:
        pCurrentBaseParams = &unitTestParams;
        break;
    default:
        assert(false && "Unimplemented network");
        return;
    }
}

CBaseChainParams::Network NetworkIdFromCommandLine()
{
    bool fRegTest = GetBoolArg("-regtest", false);
    bool fTestNet = GetBoolArg("-testnet", false);

    if (fTestNet && fRegTest)
        return CBaseChainParams::MAX_NETWORK_TYPES;
    if (fRegTest)
        return CBaseChainParams::REGTEST;
    if (fTestNet)
        return CBaseChainParams::TESTNET;
    return CBaseChainParams::MAIN;
}

bool SelectBaseParamsFromCommandLine()
{
    CBaseChainParams::Network network = NetworkIdFromCommandLine();
    if (network == CBaseChainParams::MAX_NETWORK_TYPES)
        return false;

    SelectBaseParams(network);
    return true;
}

bool AreBaseParamsConfigured()
{
    return pCurrentBaseParams != NULL;
}
<commit_msg>Default testnet true<commit_after>// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "chainparamsbase.h"

#include "util.h"

#include <assert.h>

#include <boost/assign/list_of.hpp>

using namespace boost::assign;

/**
 * Main network
 */
class CBaseMainParams : public CBaseChainParams
{
public:
    CBaseMainParams()
    {
        networkID = CBaseChainParams::MAIN;
        nRPCPort = 8372;
    }
};
static CBaseMainParams mainParams;

/**
 * Testnet (v3)
 */
class CBaseTestNetParams : public CBaseMainParams
{
public:
    CBaseTestNetParams()
    {
        networkID = CBaseChainParams::TESTNET;
        nRPCPort = 18372;
        strDataDir = "testnet3";
    }
};
static CBaseTestNetParams testNetParams;

/*
 * Regression test
 */
class CBaseRegTestParams : public CBaseTestNetParams
{
public:
    CBaseRegTestParams()
    {
        networkID = CBaseChainParams::REGTEST;
        strDataDir = "regtest";
    }
};
static CBaseRegTestParams regTestParams;

/*
 * Unit test
 */
class CBaseUnitTestParams : public CBaseMainParams
{
public:
    CBaseUnitTestParams()
    {
        networkID = CBaseChainParams::UNITTEST;
        strDataDir = "unittest";
    }
};
static CBaseUnitTestParams unitTestParams;

static CBaseChainParams* pCurrentBaseParams = 0;

const CBaseChainParams& BaseParams()
{
    assert(pCurrentBaseParams);
    return *pCurrentBaseParams;
}

void SelectBaseParams(CBaseChainParams::Network network)
{
    switch (network) {
    case CBaseChainParams::MAIN:
        pCurrentBaseParams = &mainParams;
        break;
    case CBaseChainParams::TESTNET:
        pCurrentBaseParams = &testNetParams;
        break;
    case CBaseChainParams::REGTEST:
        pCurrentBaseParams = &regTestParams;
        break;
    case CBaseChainParams::UNITTEST:
        pCurrentBaseParams = &unitTestParams;
        break;
    default:
        assert(false && "Unimplemented network");
        return;
    }
}

CBaseChainParams::Network NetworkIdFromCommandLine()
{
    bool fRegTest = GetBoolArg("-regtest", false);
    bool fTestNet = GetBoolArg("-testnet", true);

    if (fTestNet && fRegTest)
        return CBaseChainParams::MAX_NETWORK_TYPES;
    if (fRegTest)
        return CBaseChainParams::REGTEST;
    if (fTestNet)
        return CBaseChainParams::TESTNET;
    return CBaseChainParams::MAIN;
}

bool SelectBaseParamsFromCommandLine()
{
    CBaseChainParams::Network network = NetworkIdFromCommandLine();
    if (network == CBaseChainParams::MAX_NETWORK_TYPES)
        return false;

    SelectBaseParams(network);
    return true;
}

bool AreBaseParamsConfigured()
{
    return pCurrentBaseParams != NULL;
}
<|endoftext|>


<commit_before>// Copyright (c) 2012-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "clientversion.h"

#include "tinyformat.h"

#include <string>

/**
 * Name of client reported in the 'version' message. Report the same name
 * for both bitcoind and bitcoin-core, to make it harder for attackers to
 * target servers or GUI users specifically.
 */
const std::string CLIENT_NAME("Satoshi");

/**
 * Client version number
 */
#define CLIENT_VERSION_SUFFIX "-rc1"

/**
 * The following part of the code determines the CLIENT_BUILD variable.
 * Several mechanisms are used for this:
 * * first, if HAVE_BUILD_INFO is defined, include build.h, a file that is
 *   generated by the build environment, possibly containing the output
 *   of git-describe in a macro called BUILD_DESC
 * * secondly, if this is an exported version of the code, GIT_ARCHIVE will
 *   be defined (automatically using the export-subst git attribute), and
 *   GIT_COMMIT will contain the commit id.
 * * then, three options exist for determining CLIENT_BUILD:
 *   * if BUILD_DESC is defined, use that literally (output of git-describe)
 *   * if not, but GIT_COMMIT is defined, use v[maj].[min].[rev].[build]-g[commit]
 *   * otherwise, use v[maj].[min].[rev].[build]-unk
 * finally CLIENT_VERSION_SUFFIX is added
 */

//! First, include build.h if requested
#ifdef HAVE_BUILD_INFO
#include "build.h"
#endif

//! git will put "#define GIT_ARCHIVE 1" on the next line inside archives. $Format:%n#define GIT_ARCHIVE 1$
#ifdef GIT_ARCHIVE
#define GIT_COMMIT_ID "$Format:%h$"
#define GIT_COMMIT_DATE "$Format:%cD$"
#endif

#define BUILD_DESC_WITH_SUFFIX(maj, min, rev, build, suffix) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-" DO_STRINGIZE(suffix)

#define BUILD_DESC_FROM_COMMIT(maj, min, rev, build, commit) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-g" commit

#define BUILD_DESC_FROM_UNKNOWN(maj, min, rev, build) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-unk"

#ifndef BUILD_DESC
#ifdef BUILD_SUFFIX
#define BUILD_DESC BUILD_DESC_WITH_SUFFIX(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, BUILD_SUFFIX)
#elif defined(GIT_COMMIT_ID)
#define BUILD_DESC BUILD_DESC_FROM_COMMIT(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, GIT_COMMIT_ID)
#else
#define BUILD_DESC BUILD_DESC_FROM_UNKNOWN(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD)
#endif
#endif

const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX);

static std::string FormatVersion(int nVersion)
{
    if (nVersion % 100 == 0)
        return strprintf("%d.%d.%d", nVersion / 1000000, (nVersion / 10000) % 100, (nVersion / 100) % 100);
    else
        return strprintf("%d.%d.%d.%d", nVersion / 1000000, (nVersion / 10000) % 100, (nVersion / 100) % 100, nVersion % 100);
}

std::string FormatFullVersion()
{
    return CLIENT_BUILD;
}

/**
 * Format the subversion field according to BIP 14 spec (https://github.com/bitcoin/bips/blob/master/bip-0014.mediawiki)
 */
std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector<std::string>& comments)
{
    std::ostringstream ss;
    ss << "/";
    ss << name << ":" << FormatVersion(nClientVersion);
    if (!comments.empty())
    {
        std::vector<std::string>::const_iterator it(comments.begin());
        ss << "(" << *it;
        for(++it; it != comments.end(); ++it)
            ss << "; " << *it;
        ss << ")";
    }
    ss << "/";
    return ss.str();
}
<commit_msg>no client version suffix for master branch<commit_after>// Copyright (c) 2012-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "clientversion.h"

#include "tinyformat.h"

#include <string>

/**
 * Name of client reported in the 'version' message. Report the same name
 * for both bitcoind and bitcoin-core, to make it harder for attackers to
 * target servers or GUI users specifically.
 */
const std::string CLIENT_NAME("Satoshi");

/**
 * Client version number
 */
#define CLIENT_VERSION_SUFFIX ""

/**
 * The following part of the code determines the CLIENT_BUILD variable.
 * Several mechanisms are used for this:
 * * first, if HAVE_BUILD_INFO is defined, include build.h, a file that is
 *   generated by the build environment, possibly containing the output
 *   of git-describe in a macro called BUILD_DESC
 * * secondly, if this is an exported version of the code, GIT_ARCHIVE will
 *   be defined (automatically using the export-subst git attribute), and
 *   GIT_COMMIT will contain the commit id.
 * * then, three options exist for determining CLIENT_BUILD:
 *   * if BUILD_DESC is defined, use that literally (output of git-describe)
 *   * if not, but GIT_COMMIT is defined, use v[maj].[min].[rev].[build]-g[commit]
 *   * otherwise, use v[maj].[min].[rev].[build]-unk
 * finally CLIENT_VERSION_SUFFIX is added
 */

//! First, include build.h if requested
#ifdef HAVE_BUILD_INFO
#include "build.h"
#endif

//! git will put "#define GIT_ARCHIVE 1" on the next line inside archives. $Format:%n#define GIT_ARCHIVE 1$
#ifdef GIT_ARCHIVE
#define GIT_COMMIT_ID "$Format:%h$"
#define GIT_COMMIT_DATE "$Format:%cD$"
#endif

#define BUILD_DESC_WITH_SUFFIX(maj, min, rev, build, suffix) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-" DO_STRINGIZE(suffix)

#define BUILD_DESC_FROM_COMMIT(maj, min, rev, build, commit) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-g" commit

#define BUILD_DESC_FROM_UNKNOWN(maj, min, rev, build) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-unk"

#ifndef BUILD_DESC
#ifdef BUILD_SUFFIX
#define BUILD_DESC BUILD_DESC_WITH_SUFFIX(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, BUILD_SUFFIX)
#elif defined(GIT_COMMIT_ID)
#define BUILD_DESC BUILD_DESC_FROM_COMMIT(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, GIT_COMMIT_ID)
#else
#define BUILD_DESC BUILD_DESC_FROM_UNKNOWN(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD)
#endif
#endif

const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX);

static std::string FormatVersion(int nVersion)
{
    if (nVersion % 100 == 0)
        return strprintf("%d.%d.%d", nVersion / 1000000, (nVersion / 10000) % 100, (nVersion / 100) % 100);
    else
        return strprintf("%d.%d.%d.%d", nVersion / 1000000, (nVersion / 10000) % 100, (nVersion / 100) % 100, nVersion % 100);
}

std::string FormatFullVersion()
{
    return CLIENT_BUILD;
}

/**
 * Format the subversion field according to BIP 14 spec (https://github.com/bitcoin/bips/blob/master/bip-0014.mediawiki)
 */
std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector<std::string>& comments)
{
    std::ostringstream ss;
    ss << "/";
    ss << name << ":" << FormatVersion(nClientVersion);
    if (!comments.empty())
    {
        std::vector<std::string>::const_iterator it(comments.begin());
        ss << "(" << *it;
        for(++it; it != comments.end(); ++it)
            ss << "; " << *it;
        ss << ")";
    }
    ss << "/";
    return ss.str();
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include "fnord-base/io/filerepository.h"
#include "fnord-base/io/fileutil.h"
#include "fnord-base/application.h"
#include "fnord-base/logging.h"
#include "fnord-base/random.h"
#include "fnord-base/thread/eventloop.h"
#include "fnord-base/thread/threadpool.h"
#include "fnord-base/thread/FixedSizeThreadPool.h"
#include "fnord-base/wallclock.h"
#include "fnord-base/VFS.h"
#include "fnord-rpc/ServerGroup.h"
#include "fnord-rpc/RPC.h"
#include "fnord-rpc/RPCClient.h"
#include "fnord-base/cli/flagparser.h"
#include "fnord-json/json.h"
#include "fnord-json/jsonrpc.h"
#include "fnord-http/httprouter.h"
#include "fnord-http/httpserver.h"
#include "fnord-http/VFSFileServlet.h"
#include "fnord-feeds/FeedService.h"
#include "fnord-feeds/RemoteFeedFactory.h"
#include "fnord-feeds/RemoteFeedReader.h"
#include "fnord-base/stats/statsdagent.h"
#include "fnord-sstable/SSTableServlet.h"
#include "fnord-logtable/LogTableServlet.h"
#include "fnord-logtable/TableRepository.h"
#include "fnord-logtable/TableJanitor.h"
#include "fnord-logtable/TableReplication.h"
#include "fnord-afx/ArtifactReplication.h"
#include "fnord-afx/ArtifactIndexReplication.h"
#include "fnord-logtable/NumericBoundsSummary.h"
#include "fnord-mdb/MDB.h"
#include "fnord-mdb/MDBUtil.h"
#include "fnord-tsdb/TSDBNode.h"
#include "fnord-tsdb/TSDBServlet.h"
#include "fnord-tsdb/CSTableIndex.h"
#include "common.h"
#include "schemas.h"
#include "ModelReplication.h"
#include "JoinedSessionViewer.h"

using namespace fnord;

std::atomic<bool> shutdown_sig;
fnord::thread::EventLoop ev;

void quit(int n) {
  shutdown_sig = true;
  fnord::logInfo("cm.chunkserver", "Shutting down...");
  // FIXPAUL: wait for http server stop...
  ev.shutdown();
}

int main(int argc, const char** argv) {
  fnord::Application::init();
  fnord::Application::logToStderr();

  /* shutdown hook */
  shutdown_sig = false;
  struct sigaction sa;
  memset(&sa, 0, sizeof(struct sigaction));
  sa.sa_handler = quit;
  sigaction(SIGTERM, &sa, NULL);
  sigaction(SIGQUIT, &sa, NULL);
  sigaction(SIGINT, &sa, NULL);

  fnord::cli::FlagParser flags;

  flags.defineFlag(
      "http_port",
      fnord::cli::FlagParser::T_INTEGER,
      false,
      NULL,
      "8000",
      "Start the public http server on this port",
      "<port>");

  flags.defineFlag(
      "datadir",
      cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "datadir path",
      "<path>");

  flags.defineFlag(
      "replicate_to",
      cli::FlagParser::T_STRING,
      false,
      NULL,
      NULL,
      "url",
      "<url>");

  flags.defineFlag(
      "loglevel",
      fnord::cli::FlagParser::T_STRING,
      false,
      NULL,
      "INFO",
      "loglevel",
      "<level>");

  flags.parseArgv(argc, argv);

  Logger::get()->setMinimumLogLevel(
      strToLogLevel(flags.getString("loglevel")));

  /* args */
  auto dir = flags.getString("datadir");
  auto repl_targets = flags.getStrings("replicate_to");

  /* start http server and worker pools */
  fnord::thread::ThreadPool tpool;
  http::HTTPConnectionPool http(&ev);
  fnord::http::HTTPRouter http_router;
  fnord::http::HTTPServer http_server(&http_router, &ev);
  http_server.listen(flags.getInt("http_port"));

  JoinedSessionViewer jsessviewer;
  http_router.addRouteByPrefixMatch("/sessviewer", &jsessviewer);

  auto repl_scheme = mkRef(new dht::FixedReplicationScheme());
  for (const auto& r : repl_targets) {
    repl_scheme->addHost(r);
  }

  tsdb::TSDBNode tsdb_node(dir + "/tsdb", repl_scheme.get(), &http);

  tsdb::StreamProperties config(new msg::MessageSchema(joinedSessionsSchema()));
  config.max_datafile_size = 1024 * 1024 * 512;
  config.chunk_size = Duration(3600 * 4 * kMicrosPerSecond);
  config.compaction_interval = Duration(1800 * kMicrosPerSecond);
  config.derived_datasets.emplace_back(new tsdb::CSTableIndex(config.schema));
  tsdb_node.configurePrefix("joined_sessions.", config);

  tsdb::TSDBServlet tsdb_servlet(&tsdb_node);
  http_router.addRouteByPrefixMatch("/tsdb", &tsdb_servlet, &tpool);

  tsdb_node.start();
  ev.run();

  tsdb_node.stop();
  fnord::logInfo("cm.chunkserver", "Exiting...");

  exit(0);
}

<commit_msg>remove cstable build as derived file/secondary index<commit_after>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include "fnord-base/io/filerepository.h"
#include "fnord-base/io/fileutil.h"
#include "fnord-base/application.h"
#include "fnord-base/logging.h"
#include "fnord-base/random.h"
#include "fnord-base/thread/eventloop.h"
#include "fnord-base/thread/threadpool.h"
#include "fnord-base/thread/FixedSizeThreadPool.h"
#include "fnord-base/wallclock.h"
#include "fnord-base/VFS.h"
#include "fnord-rpc/ServerGroup.h"
#include "fnord-rpc/RPC.h"
#include "fnord-rpc/RPCClient.h"
#include "fnord-base/cli/flagparser.h"
#include "fnord-json/json.h"
#include "fnord-json/jsonrpc.h"
#include "fnord-http/httprouter.h"
#include "fnord-http/httpserver.h"
#include "fnord-http/VFSFileServlet.h"
#include "fnord-feeds/FeedService.h"
#include "fnord-feeds/RemoteFeedFactory.h"
#include "fnord-feeds/RemoteFeedReader.h"
#include "fnord-base/stats/statsdagent.h"
#include "fnord-sstable/SSTableServlet.h"
#include "fnord-logtable/LogTableServlet.h"
#include "fnord-logtable/TableRepository.h"
#include "fnord-logtable/TableJanitor.h"
#include "fnord-logtable/TableReplication.h"
#include "fnord-afx/ArtifactReplication.h"
#include "fnord-afx/ArtifactIndexReplication.h"
#include "fnord-logtable/NumericBoundsSummary.h"
#include "fnord-mdb/MDB.h"
#include "fnord-mdb/MDBUtil.h"
#include "fnord-tsdb/TSDBNode.h"
#include "fnord-tsdb/TSDBServlet.h"
#include "common.h"
#include "schemas.h"
#include "ModelReplication.h"
#include "JoinedSessionViewer.h"

using namespace fnord;

std::atomic<bool> shutdown_sig;
fnord::thread::EventLoop ev;

void quit(int n) {
  shutdown_sig = true;
  fnord::logInfo("cm.chunkserver", "Shutting down...");
  // FIXPAUL: wait for http server stop...
  ev.shutdown();
}

int main(int argc, const char** argv) {
  fnord::Application::init();
  fnord::Application::logToStderr();

  /* shutdown hook */
  shutdown_sig = false;
  struct sigaction sa;
  memset(&sa, 0, sizeof(struct sigaction));
  sa.sa_handler = quit;
  sigaction(SIGTERM, &sa, NULL);
  sigaction(SIGQUIT, &sa, NULL);
  sigaction(SIGINT, &sa, NULL);

  fnord::cli::FlagParser flags;

  flags.defineFlag(
      "http_port",
      fnord::cli::FlagParser::T_INTEGER,
      false,
      NULL,
      "8000",
      "Start the public http server on this port",
      "<port>");

  flags.defineFlag(
      "datadir",
      cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "datadir path",
      "<path>");

  flags.defineFlag(
      "replicate_to",
      cli::FlagParser::T_STRING,
      false,
      NULL,
      NULL,
      "url",
      "<url>");

  flags.defineFlag(
      "loglevel",
      fnord::cli::FlagParser::T_STRING,
      false,
      NULL,
      "INFO",
      "loglevel",
      "<level>");

  flags.parseArgv(argc, argv);

  Logger::get()->setMinimumLogLevel(
      strToLogLevel(flags.getString("loglevel")));

  /* args */
  auto dir = flags.getString("datadir");
  auto repl_targets = flags.getStrings("replicate_to");

  /* start http server and worker pools */
  fnord::thread::ThreadPool tpool;
  http::HTTPConnectionPool http(&ev);
  fnord::http::HTTPRouter http_router;
  fnord::http::HTTPServer http_server(&http_router, &ev);
  http_server.listen(flags.getInt("http_port"));

  JoinedSessionViewer jsessviewer;
  http_router.addRouteByPrefixMatch("/sessviewer", &jsessviewer);

  auto repl_scheme = mkRef(new dht::FixedReplicationScheme());
  for (const auto& r : repl_targets) {
    repl_scheme->addHost(r);
  }

  tsdb::TSDBNode tsdb_node(dir + "/tsdb", repl_scheme.get(), &http);

  tsdb::StreamProperties config(new msg::MessageSchema(joinedSessionsSchema()));
  config.max_datafile_size = 1024 * 1024 * 512;
  config.chunk_size = Duration(3600 * 4 * kMicrosPerSecond);
  config.compaction_interval = Duration(1800 * kMicrosPerSecond);
  tsdb_node.configurePrefix("joined_sessions.", config);

  tsdb::TSDBServlet tsdb_servlet(&tsdb_node);
  http_router.addRouteByPrefixMatch("/tsdb", &tsdb_servlet, &tpool);

  tsdb_node.start();
  ev.run();

  tsdb_node.stop();
  fnord::logInfo("cm.chunkserver", "Exiting...");

  exit(0);
}

<|endoftext|>