<commit_before>#include <iostream>
#include <ctime>

#include "search.hpp"
#include "movegen.hpp"
#include "perft.hpp"
#include "rollout.hpp"
#include "eval.hpp"
#include "makemove.hpp"
#include "score.hpp"
#include "other.hpp"

void messageLoop()
{
    Position pos;
    setBoard(pos, "startpos");

    Hashtable tt;
    tableInit(&tt);
    create(&tt, 128);

    bool quit = false;
    while(quit == false)
    {
        std::string input;
        getline(std::cin, input);

        std::vector<std::string> tokens = split(input, ' ');

        for(unsigned int n = 0; n < tokens.size(); ++n)
        {
            if(tokens[n] == "isready")
            {
                std::cout << "readyok" << std::endl;
            }
            else if(tokens[n] == "go")
            {
                // Default subcommands
                int depth = 5;
                int movetime = 0;

                // Subcommands
                for(unsigned int i = n+1; i < tokens.size(); ++i)
                {
                    if(tokens[i] == "infinite")
                    {
                        depth = 20;
                        n += 1;
                    }
                    else if(tokens[i] == "depth")
                    {
                        depth = stoi(tokens[i+1]);
                        movetime = 0;
                        n += 2;
                        i += 1;
                    }
                    else if(tokens[i] == "movetime")
                    {
                        depth = 0;
                        movetime = stoi(tokens[i+1]);
                        n += 2;
                        i += 1;
                    }
                }

                search(&tt, pos, depth, movetime);
            }
            else if(tokens[n] == "mcts")
            {
                // Default subcommands
                int numSimulations = 100000;
                int movetime = 0;
                int searchType = 1;

                // Subcommands
                for(unsigned int i = n+1; i < tokens.size(); ++i)
                {
                    if(tokens[i] == "pure")
                    {
                        searchType = 0;
                        n += 1;
                    }
                    else if(tokens[i] == "uct")
                    {
                        searchType = 1;
                        n += 1;
                    }
                    else if(tokens[i] == "movetime")
                    {
                        numSimulations = 0;
                        movetime = stoi(tokens[i+1]);
                        n += 2;
                        i += 1;
                    }
                    else if(tokens[i] == "simulations")
                    {
                        numSimulations = stoi(tokens[i+1]);
                        movetime = 0;
                        n += 2;
                        i += 1;
                    }
                }

                if(searchType == 0)
                {
                    mctsPure(pos, numSimulations, movetime);
                }
                else if(searchType == 1)
                {
                    mctsUct(pos, numSimulations, movetime);
                }
            }
            else if(tokens[n] == "perft")
            {
                int depth = 5;

                // Subcommands
                if(n+1 < tokens.size())
                {
                    depth = stoi(tokens[n+1]);
                    n += 1;
                }

                // Subcommand checking
                if(depth < 1)
                {
                    depth = 1;
                }
                else if(depth > 12)
                {
                    std::cout << "WARNING: perft(" << depth << ") may take a long time to finish" << std::endl;
                }

                perft(&tt, pos, depth);
            }
            else if(tokens[n] == "result")
            {
                Move moves[256];
                int numMoves = movegen(pos, moves);

                if(numMoves > 0)
                {
                    std::cout << "result none" << std::endl;
                }
                else
                {
                    int r = score(pos);

                    if(r == 0) {std::cout << "result draw" << std::endl; continue;}

                    if(pos.turn == SIDE::CROSS)
                    {
                        if(r > 0) {std::cout << "result X" << std::endl;}
                        else      {std::cout << "result O" << std::endl;}
                    }
                    else
                    {
                        if(r > 0) {std::cout << "result O" << std::endl;}
                        else      {std::cout << "result X" << std::endl;}
                    }
                }
            }
            else if(tokens[n] == "split")
            {
                int depth = 5;

                // Subcommands
                if(n+1 < tokens.size())
                {
                    depth = stoi(tokens[n+1]);
                    n += 1;
                }

                // Subcommand checking
                if(depth < 1)
                {
                    depth = 1;
                }
                else if(depth > 12)
                {
                    std::cout << "WARNING: split perft(" << depth << ") may take a long time to finish" << std::endl;
                }

                splitPerft(&tt, pos, depth);
            }
            else if(tokens[n] == "rollout")
            {
                if(n+1 >= tokens.size()) {continue;}

                // Subcommands
                int numGames = stoi(tokens[n+1]);
                n += 1;

                // Subcommand checking
                if(numGames <= 1)
                {
                    numGames = 1;
                }

                int wins = 0;
                int losses = 0;
                int draws = 0;

                clock_t start = clock();
                for(int g = 0; g < numGames; ++g)
                {
                    int r = rollout(pos, 300);
                         if(r == 1)  {wins++;}
                    else if(r == -1) {losses++;}
                    else             {draws++;}

                    if((g+1) % 100 == 0)
                    {
                        std::cout << "info"
                                  << " wins " << wins
                                  << " draws " << draws
                                  << " losses " << losses
                                  << " winrate " << 100.0*(double)wins/(wins + draws + losses) << "%"
                                  << " time " << 1000.0*(double)(clock() - start)/CLOCKS_PER_SEC
                                  << std::endl;
                    }
                }

                std::cout << "winrate "
                          << 100.0*(double)wins/(wins + draws + losses) << "%"
                          << std::endl;
            }
            else if(tokens[n] == "hashtable")
            {
                if(n+1 >= tokens.size()) {continue;}

                if(tokens[n+1] == "clear")
                {
                    n += 1;
                    clear(&tt);
                }
                else if(tokens[n+1] == "print")
                {
                    n += 1;
                    printDetails(&tt);
                }
            }
            else if(tokens[n] == "print")
            {
                print(pos);
            }
            else if(tokens[n] == "setpos")
            {
                if(n+2 < tokens.size())
                {
                    int r = setBoard(pos, tokens[n+1] + " " + tokens[n+2]);
                    if(r != 0)
                    {
                        std::cout << "WARNING: set position error (" << r << ")" << std::endl;
                    }

                    n += 2;
                }
                else if(n+1 < tokens.size())
                {
                    if(tokens[n+1] != "startpos") {tokens[n+1] += " X";}

                    int r = setBoard(pos, tokens[n+1]);
                    if(r != 0)
                    {
                        std::cout << "WARNING: set position error (" << r << ")" << std::endl;
                    }

                    n += 1;
                }
            }
            else if(tokens[n] == "eval")
            {
                splitEval(pos);
            }
            else if(tokens[n] == "movegen")
            {
                printMoves(pos);
            }
            else if(tokens[n] == "moves")
            {
                for(unsigned int i = n+1; i < tokens.size(); ++i)
                {
                    if(legalMove(pos, tokens[i]) == false) {break;}

                    makemove(pos, tokens[i]);
                    n += 1;
                }
            }
            else if(tokens[n] == "help")
            {
                std::cout << "Commands:" << std::endl;
                std::cout << "-- go [depth] [movetime]" << std::endl;
                std::cout << "-- perft [depth]" << std::endl;
                std::cout << "-- split [depth]" << std::endl;
                std::cout << "-- rollout [games]" << std::endl;
                std::cout << "-- hashtable [clear/print]" << std::endl;
                std::cout << "-- print" << std::endl;
                std::cout << "-- setpos [position]" << std::endl;
                std::cout << "-- eval" << std::endl;
                std::cout << "-- movegen" << std::endl;
                std::cout << "-- moves [moves]" << std::endl;
                std::cout << "-- isready" << std::endl;
                std::cout << "-- help" << std::endl;
                std::cout << "-- about" << std::endl;
                std::cout << "-- quit" << std::endl;
            }
            else if(tokens[n] == "about")
            {
                std::cout << "An Ataxx engine written in C++" << std::endl;
                std::cout << "https://github.com/kz04px/ataxx-engine" << std::endl;
            }
            else if(tokens[n] == "quit")
            {
                quit = true;
                break;
            }
            else
            {
                std::cout << "Unknown token (" << tokens[n] << ")" << std::endl;
            }
        }
    }

    clear(&tt);
    tableRemove(&tt);
}
<commit_msg>Added "newgame" command<commit_after>#include <iostream>
#include <ctime>

#include "search.hpp"
#include "movegen.hpp"
#include "perft.hpp"
#include "rollout.hpp"
#include "eval.hpp"
#include "makemove.hpp"
#include "score.hpp"
#include "other.hpp"

void messageLoop()
{
    Position pos;
    setBoard(pos, "startpos");

    Hashtable tt;
    tableInit(&tt);
    create(&tt, 128);

    bool quit = false;
    while(quit == false)
    {
        std::string input;
        getline(std::cin, input);

        std::vector<std::string> tokens = split(input, ' ');

        for(unsigned int n = 0; n < tokens.size(); ++n)
        {
            if(tokens[n] == "isready")
            {
                std::cout << "readyok" << std::endl;
            }
            else if(tokens[n] == "newgame")
            {
                setBoard(pos, "startpos");
                clear(&tt);
            }
            else if(tokens[n] == "go")
            {
                // Default subcommands
                int depth = 5;
                int movetime = 0;

                // Subcommands
                for(unsigned int i = n+1; i < tokens.size(); ++i)
                {
                    if(tokens[i] == "infinite")
                    {
                        depth = 20;
                        n += 1;
                    }
                    else if(tokens[i] == "depth")
                    {
                        depth = stoi(tokens[i+1]);
                        movetime = 0;
                        n += 2;
                        i += 1;
                    }
                    else if(tokens[i] == "movetime")
                    {
                        depth = 0;
                        movetime = stoi(tokens[i+1]);
                        n += 2;
                        i += 1;
                    }
                }

                search(&tt, pos, depth, movetime);
            }
            else if(tokens[n] == "mcts")
            {
                // Default subcommands
                int numSimulations = 100000;
                int movetime = 0;
                int searchType = 1;

                // Subcommands
                for(unsigned int i = n+1; i < tokens.size(); ++i)
                {
                    if(tokens[i] == "pure")
                    {
                        searchType = 0;
                        n += 1;
                    }
                    else if(tokens[i] == "uct")
                    {
                        searchType = 1;
                        n += 1;
                    }
                    else if(tokens[i] == "movetime")
                    {
                        numSimulations = 0;
                        movetime = stoi(tokens[i+1]);
                        n += 2;
                        i += 1;
                    }
                    else if(tokens[i] == "simulations")
                    {
                        numSimulations = stoi(tokens[i+1]);
                        movetime = 0;
                        n += 2;
                        i += 1;
                    }
                }

                if(searchType == 0)
                {
                    mctsPure(pos, numSimulations, movetime);
                }
                else if(searchType == 1)
                {
                    mctsUct(pos, numSimulations, movetime);
                }
            }
            else if(tokens[n] == "perft")
            {
                int depth = 5;

                // Subcommands
                if(n+1 < tokens.size())
                {
                    depth = stoi(tokens[n+1]);
                    n += 1;
                }

                // Subcommand checking
                if(depth < 1)
                {
                    depth = 1;
                }
                else if(depth > 12)
                {
                    std::cout << "WARNING: perft(" << depth << ") may take a long time to finish" << std::endl;
                }

                perft(&tt, pos, depth);
            }
            else if(tokens[n] == "result")
            {
                Move moves[256];
                int numMoves = movegen(pos, moves);

                if(numMoves > 0)
                {
                    std::cout << "result none" << std::endl;
                }
                else
                {
                    int r = score(pos);

                    if(r == 0) {std::cout << "result draw" << std::endl; continue;}

                    if(pos.turn == SIDE::CROSS)
                    {
                        if(r > 0) {std::cout << "result X" << std::endl;}
                        else      {std::cout << "result O" << std::endl;}
                    }
                    else
                    {
                        if(r > 0) {std::cout << "result O" << std::endl;}
                        else      {std::cout << "result X" << std::endl;}
                    }
                }
            }
            else if(tokens[n] == "split")
            {
                int depth = 5;

                // Subcommands
                if(n+1 < tokens.size())
                {
                    depth = stoi(tokens[n+1]);
                    n += 1;
                }

                // Subcommand checking
                if(depth < 1)
                {
                    depth = 1;
                }
                else if(depth > 12)
                {
                    std::cout << "WARNING: split perft(" << depth << ") may take a long time to finish" << std::endl;
                }

                splitPerft(&tt, pos, depth);
            }
            else if(tokens[n] == "rollout")
            {
                if(n+1 >= tokens.size()) {continue;}

                // Subcommands
                int numGames = stoi(tokens[n+1]);
                n += 1;

                // Subcommand checking
                if(numGames <= 1)
                {
                    numGames = 1;
                }

                int wins = 0;
                int losses = 0;
                int draws = 0;

                clock_t start = clock();
                for(int g = 0; g < numGames; ++g)
                {
                    int r = rollout(pos, 300);
                         if(r == 1)  {wins++;}
                    else if(r == -1) {losses++;}
                    else             {draws++;}

                    if((g+1) % 100 == 0)
                    {
                        std::cout << "info"
                                  << " wins " << wins
                                  << " draws " << draws
                                  << " losses " << losses
                                  << " winrate " << 100.0*(double)wins/(wins + draws + losses) << "%"
                                  << " time " << 1000.0*(double)(clock() - start)/CLOCKS_PER_SEC
                                  << std::endl;
                    }
                }

                std::cout << "winrate "
                          << 100.0*(double)wins/(wins + draws + losses) << "%"
                          << std::endl;
            }
            else if(tokens[n] == "hashtable")
            {
                if(n+1 >= tokens.size()) {continue;}

                if(tokens[n+1] == "clear")
                {
                    n += 1;
                    clear(&tt);
                }
                else if(tokens[n+1] == "print")
                {
                    n += 1;
                    printDetails(&tt);
                }
            }
            else if(tokens[n] == "print")
            {
                print(pos);
            }
            else if(tokens[n] == "setpos")
            {
                if(n+2 < tokens.size())
                {
                    int r = setBoard(pos, tokens[n+1] + " " + tokens[n+2]);
                    if(r != 0)
                    {
                        std::cout << "WARNING: set position error (" << r << ")" << std::endl;
                    }

                    n += 2;
                }
                else if(n+1 < tokens.size())
                {
                    if(tokens[n+1] != "startpos") {tokens[n+1] += " X";}

                    int r = setBoard(pos, tokens[n+1]);
                    if(r != 0)
                    {
                        std::cout << "WARNING: set position error (" << r << ")" << std::endl;
                    }

                    n += 1;
                }
            }
            else if(tokens[n] == "eval")
            {
                splitEval(pos);
            }
            else if(tokens[n] == "movegen")
            {
                printMoves(pos);
            }
            else if(tokens[n] == "moves")
            {
                for(unsigned int i = n+1; i < tokens.size(); ++i)
                {
                    if(legalMove(pos, tokens[i]) == false) {break;}

                    makemove(pos, tokens[i]);
                    n += 1;
                }
            }
            else if(tokens[n] == "help")
            {
                std::cout << "Commands:" << std::endl;
                std::cout << "-- go [depth] [movetime]" << std::endl;
                std::cout << "-- perft [depth]" << std::endl;
                std::cout << "-- split [depth]" << std::endl;
                std::cout << "-- rollout [games]" << std::endl;
                std::cout << "-- hashtable [clear/print]" << std::endl;
                std::cout << "-- print" << std::endl;
                std::cout << "-- setpos [position]" << std::endl;
                std::cout << "-- eval" << std::endl;
                std::cout << "-- movegen" << std::endl;
                std::cout << "-- moves [moves]" << std::endl;
                std::cout << "-- isready" << std::endl;
                std::cout << "-- help" << std::endl;
                std::cout << "-- about" << std::endl;
                std::cout << "-- quit" << std::endl;
            }
            else if(tokens[n] == "about")
            {
                std::cout << "An Ataxx engine written in C++" << std::endl;
                std::cout << "https://github.com/kz04px/ataxx-engine" << std::endl;
            }
            else if(tokens[n] == "quit")
            {
                quit = true;
                break;
            }
            else
            {
                std::cout << "Unknown token (" << tokens[n] << ")" << std::endl;
            }
        }
    }

    clear(&tt);
    tableRemove(&tt);
}
<|endoftext|>


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

#include "protocol.h"
#include "util.h"
#include "netbase.h"

#ifndef WIN32
# include <arpa/inet.h>
#endif

static const char* ppszTypeName[] =
{
    "ERROR",
    "tx",
    "dstx",
    "block",
    "filtered block",
    "tx lock request",
    "tx lock vote",
    "spork",
    "masternode winner",
    "unknown",
    "unknown",
    "unknown",
    "unknown",
    "unknown",
    "unknown"
};

CMessageHeader::CMessageHeader()
{
    memcpy(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE);
    memset(pchCommand, 0, sizeof(pchCommand));
    pchCommand[1] = 1;
    nMessageSize = -1;
    nChecksum = 0;
}

CMessageHeader::CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn)
{
    memcpy(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE);
    memset(pchCommand, 0, sizeof(pchCommand));
    strncpy(pchCommand, pszCommand, COMMAND_SIZE);
    nMessageSize = nMessageSizeIn;
    nChecksum = 0;
}

std::string CMessageHeader::GetCommand() const
{
    return std::string(pchCommand, pchCommand + strnlen(pchCommand, COMMAND_SIZE));
}

bool CMessageHeader::IsValid() const
{
    // Check start string
    if (memcmp(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE) != 0)
        return false;

    // Check the command string for errors
    for (const char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; p1++)
    {
        if (*p1 == 0)
        {
            // Must be all zeros after the first zero
            for (; p1 < pchCommand + COMMAND_SIZE; p1++)
                if (*p1 != 0)
                    return false;
        }
        else if (*p1 < ' ' || *p1 > 0x7E)
            return false;
    }

    // Message size
    if (nMessageSize > MAX_SIZE)
    {
        LogPrintf("CMessageHeader::IsValid() : (%s, %u bytes) nMessageSize > MAX_SIZE\n", GetCommand(), nMessageSize);
        return false;
    }

    return true;
}

CAddress::CAddress() : CService()
{
    Init();
}

CAddress::CAddress(CService ipIn, uint64_t nServicesIn) : CService(ipIn)
{
    Init();
    nServices = nServicesIn;
}

void CAddress::Init()
{
    nServices = NODE_NETWORK;
    nTime = 100000000;
    nLastTry = 0;
}

CInv::CInv()
{
    type = 0;
    hash = 0;
}

CInv::CInv(int typeIn, const uint256& hashIn)
{
    type = typeIn;
    hash = hashIn;
}

CInv::CInv(const std::string& strType, const uint256& hashIn)
{
    unsigned int i;
    for (i = 1; i < ARRAYLEN(ppszTypeName); i++)
    {
        if (strType == ppszTypeName[i])
        {
            type = i;
            break;
        }
    }
    if (i == ARRAYLEN(ppszTypeName))
        throw std::out_of_range(strprintf("CInv::CInv(string, uint256) : unknown type '%s'", strType));
    hash = hashIn;
}

bool operator<(const CInv& a, const CInv& b)
{
    return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
}

bool CInv::IsKnownType() const
{
    return (type >= 1 && type < (int)ARRAYLEN(ppszTypeName));
}

const char* CInv::GetCommand() const
{
    if (!IsKnownType())
        throw std::out_of_range(strprintf("CInv::GetCommand() : type=%d unknown type", type));
    return ppszTypeName[type];
}

std::string CInv::ToString() const
{
    return strprintf("%s %s", GetCommand(), hash.ToString());
}
<commit_msg>MessageHeader correction<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "protocol.h"
#include "util.h"
#include "netbase.h"

#ifndef WIN32
# include <arpa/inet.h>
#endif

static const char* ppszTypeName[] =
{
    "ERROR",
    "tx",
    "dstx",
    "block",
    "filtered block",
    "tx lock request",
    "tx lock vote",
    "spork",
    "masternode winner",
    "unknown",
    "unknown",
    "unknown",
    "unknown",
    "unknown",
    "unknown"
};

CMessageHeader::CMessageHeader()
{
    memcpy(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE);
    pchCommand[1] = 1;
    nMessageSize = -1;
    nChecksum = 0;
}

CMessageHeader::CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn)
{
    memcpy(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE);
    memset(pchCommand, 0, sizeof(pchCommand));
    strncpy(pchCommand, pszCommand, COMMAND_SIZE);
    nMessageSize = nMessageSizeIn;
    nChecksum = 0;
}

std::string CMessageHeader::GetCommand() const
{
    return std::string(pchCommand, pchCommand + strnlen(pchCommand, COMMAND_SIZE));
}

bool CMessageHeader::IsValid() const
{
    // Check start string
    if (memcmp(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE) != 0)
        return false;

    // Check the command string for errors
    for (const char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; p1++)
    {
        if (*p1 == 0)
        {
            // Must be all zeros after the first zero
            for (; p1 < pchCommand + COMMAND_SIZE; p1++)
                if (*p1 != 0)
                    return false;
        }
        else if (*p1 < ' ' || *p1 > 0x7E)
            return false;
    }

    // Message size
    if (nMessageSize > MAX_SIZE)
    {
        LogPrintf("CMessageHeader::IsValid() : (%s, %u bytes) nMessageSize > MAX_SIZE\n", GetCommand(), nMessageSize);
        return false;
    }

    return true;
}

CAddress::CAddress() : CService()
{
    Init();
}

CAddress::CAddress(CService ipIn, uint64_t nServicesIn) : CService(ipIn)
{
    Init();
    nServices = nServicesIn;
}

void CAddress::Init()
{
    nServices = NODE_NETWORK;
    nTime = 100000000;
    nLastTry = 0;
}

CInv::CInv()
{
    type = 0;
    hash = 0;
}

CInv::CInv(int typeIn, const uint256& hashIn)
{
    type = typeIn;
    hash = hashIn;
}

CInv::CInv(const std::string& strType, const uint256& hashIn)
{
    unsigned int i;
    for (i = 1; i < ARRAYLEN(ppszTypeName); i++)
    {
        if (strType == ppszTypeName[i])
        {
            type = i;
            break;
        }
    }
    if (i == ARRAYLEN(ppszTypeName))
        throw std::out_of_range(strprintf("CInv::CInv(string, uint256) : unknown type '%s'", strType));
    hash = hashIn;
}

bool operator<(const CInv& a, const CInv& b)
{
    return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
}

bool CInv::IsKnownType() const
{
    return (type >= 1 && type < (int)ARRAYLEN(ppszTypeName));
}

const char* CInv::GetCommand() const
{
    if (!IsKnownType())
        throw std::out_of_range(strprintf("CInv::GetCommand() : type=%d unknown type", type));
    return ppszTypeName[type];
}

std::string CInv::ToString() const
{
    return strprintf("%s %s", GetCommand(), hash.ToString());
}
<|endoftext|>


<commit_before>// Copyright (c) 2015-2016 Nathan Bass "IngCr3at1on"
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "base58.h"
#include "util.h"
#include "reactors.h"

using namespace std;

int CURRENT_REACTOR_VERSION = -2; // Test version

bool maybeWipeReactorDB(string strFileName) {
    int dbversion;
    if (CReactorDB(strFileName).CheckReactorDBVersion(dbversion)) {
        if (dbversion == CURRENT_REACTOR_VERSION)
            return false;
    }

    // No version set or version is invalid, wipe the DB.
    printf("maybeWipeReactorDB() : reactor databse is outdated, removing for recreation\n");
    CReactorDB(strFileName).Close();
    bitdb.CloseDb("reactors.dat");
    boost::filesystem::remove(strFileName);
    // Return true so we know to re-inflate the DB.
    return true;
}

/* This function should not be called by tests (is not currently required for
 * them) as it will use the reactor.dat found in the datadir instead of the
 * mockdb. */
void InitReactors() {
    bool inflatedb = false;
    // Check if the reactor database exists and check the version if it does.
    string reactordbfile = GetReactorDBFile();
    if (boost::filesystem::exists(boost::filesystem::path(reactordbfile))) {
        if (maybeWipeReactorDB(reactordbfile))
            inflatedb = true;

        if (!inflatedb) {
            // TODO Replace with correct first and last reactor addresses.
            if (!fTestNet && (!CReactorDB(reactordbfile).CheckReactorAddr(string("dMajkjpXzy2KTk21JkFx8aDtUVoaXmeMEZ"))
                || !CReactorDB(reactordbfile).CheckReactorAddr(string("dK8Sh1R81YxaFrwwMmYEH1QET6ejhUw3pQ"))))
                inflatedb = true;
            else if (fTestNet && (!CReactorDB(reactordbfile).CheckReactorAddr(string("muLhTBAfaS2ro2fhDFh6D7MArg6qGv1j1i"))
                || !CReactorDB(reactordbfile).CheckReactorAddr(string("mkB4XAhFZmG5rNuhs4mnnBFWN3jKD2rXw2"))))
                inflatedb = true;
        }
    } else {
        inflatedb = true;
    }

    if (inflatedb)
        InflateReactorDB(reactordbfile);
}

bool CTransaction::IsReactorStake(string strFileName, CScript scriptPubKeyType, CScript scriptPubKeyAddress, unsigned int nTime, int64 nValueIn, int64 nValueOut, uint64 nCoinAge, unsigned int nBits, int nHeight) {
    int64 nStakeReward = nValueOut - nValueIn;

    // Should never be anything else.
    if (scriptPubKeyType[0] == OP_REACTOR) {
        unsigned int valid_starting;
        unsigned int valid_until;
        int64 reactorStakeValue;

        /* Destination address is stored in the CScript for vout[1] of the input
         * so extract it against our database. */
        if (!CReactorDB(strFileName).IsReactor(strFileName, scriptPubKeyAddress, reactorStakeValue, valid_starting, valid_until))
            return DoS(100, error("IsReactorStake() : invalid reactor address, HAXORS!!!"));

        if (nTime < valid_starting)
            return DoS(100, error("IsReactorStake() : reactor is not valid yet"));

        if (nTime >= valid_until && valid_until != (unsigned int)-1)
            return DoS(100, error("IsReactorStake() : reactor is expired"));

        /* If this is a reactor check that the size of the stake matches the
         * requirements of the given reactor.*/
        if (reactorStakeValue == 3000 || reactorStakeValue == 15000) {
            if (nValueIn < (reactorStakeValue * COIN))
                return DoS(100, error("IsReactorStake() : nValueIn doesn't meet requirement for reactor stake; credit %" PRI64d "; reactor size %d or %d", nValueIn, 3000, 15000));

            if (nValueIn > (reactorStakeValue * COIN))
                return DoS(100, error("IsReactorStake() : nValueIn exceeds value of reactor; credit %" PRI64d "; reactor size %d or %d", nValueIn, 3000, 15000));
        } else {
            if (nValueIn < (reactorStakeValue * COIN))
                return DoS(100, error("IsReactorStake() : credit doesn't meet requirement for reactor stake; credit %" PRI64d "; reactor size %" PRI64d "", nValueIn, reactorStakeValue));

            if (nValueIn > (reactorStakeValue * COIN))
                return DoS(100, error("IsReactorStake() : credit exceeds value of reactor; credit %" PRI64d "; reactor size %" PRI64d "", nValueIn, reactorStakeValue));
        }

        if (nStakeReward > GetProofOfStakeReward(nCoinAge, nBits, nTime, nHeight, GetReactorRate(reactorStakeValue, nValueIn)) - GetMinFee() + MIN_TX_FEE)
            return DoS(100, error("IsReactorStake() : %s stake reward exceeded", GetHash().ToString().substr(0, 10).c_str()));

        return true;
    }

    return false;
}

// Inflate the reactor table in the reactorDB
void InflateReactorDB(string strFileName) {
    printf("InflateReactorDB() : inflating reactor database.\n");

    fTestNet ? CReactorDB(strFileName, "cw+").WriteTestReactorDB() : CReactorDB(strFileName, "cw+").WriteReactorDB();
}

int GetReactorRate(int64 reactorStakeValue, int64 nValueIn) {
    if (reactorStakeValue == 1000 || reactorStakeValue == 10000)
        return 2;

    /* We store the max value of the Legendaries in the database and override
     * the rate for 3000 coin stakes here. */
    if (reactorStakeValue == 15000 && nValueIn == 3000)
        return 2;

    if (reactorStakeValue == 15000 && nValueIn == 15000)
        return 1.5;

    return 0;
}

bool CReactorDB::WriteReactorDBVersion(int version)
{
    return Write(string("dbversion"), version);
}

bool CReactorDB::WriteReactorAddr(const string address, unsigned int valid_starting, unsigned int valid_until, int64 reactorStakeValue)
{
    return Write(make_pair(string("reactor"), address), boost::make_tuple(valid_starting, valid_until, reactorStakeValue));
}

bool CReactorDB::CheckReactorDBVersion(int &version)
{
    if (!Exists(string("dbversion")))
        return false;

    Read(string("dbversion"), version);
    return true;
}

bool CReactorDB::CheckReactorAddr(const string address)
{
    return Exists(make_pair(string("reactor"), address));
}

bool CReactorDB::IsReactor(std::string strFileName, CScript scriptPubKeyAddress, int64 &reactorStakeValue, unsigned int &valid_starting, unsigned int &valid_until)
{
    CTxDestination address;
    ExtractDestination(scriptPubKeyAddress, address);
    CBitcoinAddress addr(address);

    // Check if the address exists in the reactor database.
    if (!CReactorDB(strFileName).CheckReactorAddr(addr.ToString()))
        return false;

    boost::tuple<unsigned int, unsigned int, int64> t;
    Read(make_pair(string("reactor"), addr.ToString()), t);

    valid_starting = t.get<0>();
    valid_until = t.get<1>();

    reactorStakeValue = t.get<2>();
    return true;
}
<commit_msg>Fix legendary reactor rate and add staisybit rate<commit_after>// Copyright (c) 2015-2016 Nathan Bass "IngCr3at1on"
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "base58.h"
#include "util.h"
#include "reactors.h"

using namespace std;

int CURRENT_REACTOR_VERSION = -2; // Test version

bool maybeWipeReactorDB(string strFileName) {
    int dbversion;
    if (CReactorDB(strFileName).CheckReactorDBVersion(dbversion)) {
        if (dbversion == CURRENT_REACTOR_VERSION)
            return false;
    }

    // No version set or version is invalid, wipe the DB.
    printf("maybeWipeReactorDB() : reactor databse is outdated, removing for recreation\n");
    CReactorDB(strFileName).Close();
    bitdb.CloseDb("reactors.dat");
    boost::filesystem::remove(strFileName);
    // Return true so we know to re-inflate the DB.
    return true;
}

/* This function should not be called by tests (is not currently required for
 * them) as it will use the reactor.dat found in the datadir instead of the
 * mockdb. */
void InitReactors() {
    bool inflatedb = false;
    // Check if the reactor database exists and check the version if it does.
    string reactordbfile = GetReactorDBFile();
    if (boost::filesystem::exists(boost::filesystem::path(reactordbfile))) {
        if (maybeWipeReactorDB(reactordbfile))
            inflatedb = true;

        if (!inflatedb) {
            // TODO Replace with correct first and last reactor addresses.
            if (!fTestNet && (!CReactorDB(reactordbfile).CheckReactorAddr(string("dMajkjpXzy2KTk21JkFx8aDtUVoaXmeMEZ"))
                || !CReactorDB(reactordbfile).CheckReactorAddr(string("dK8Sh1R81YxaFrwwMmYEH1QET6ejhUw3pQ"))))
                inflatedb = true;
            else if (fTestNet && (!CReactorDB(reactordbfile).CheckReactorAddr(string("muLhTBAfaS2ro2fhDFh6D7MArg6qGv1j1i"))
                || !CReactorDB(reactordbfile).CheckReactorAddr(string("mkB4XAhFZmG5rNuhs4mnnBFWN3jKD2rXw2"))))
                inflatedb = true;
        }
    } else {
        inflatedb = true;
    }

    if (inflatedb)
        InflateReactorDB(reactordbfile);
}

bool CTransaction::IsReactorStake(string strFileName, CScript scriptPubKeyType, CScript scriptPubKeyAddress, unsigned int nTime, int64 nValueIn, int64 nValueOut, uint64 nCoinAge, unsigned int nBits, int nHeight) {
    int64 nStakeReward = nValueOut - nValueIn;

    // Should never be anything else.
    if (scriptPubKeyType[0] == OP_REACTOR) {
        unsigned int valid_starting;
        unsigned int valid_until;
        int64 reactorStakeValue;

        /* Destination address is stored in the CScript for vout[1] of the input
         * so extract it against our database. */
        if (!CReactorDB(strFileName).IsReactor(strFileName, scriptPubKeyAddress, reactorStakeValue, valid_starting, valid_until))
            return DoS(100, error("IsReactorStake() : invalid reactor address, HAXORS!!!"));

        if (nTime < valid_starting)
            return DoS(100, error("IsReactorStake() : reactor is not valid yet"));

        if (nTime >= valid_until && valid_until != (unsigned int)-1)
            return DoS(100, error("IsReactorStake() : reactor is expired"));

        /* If this is a reactor check that the size of the stake matches the
         * requirements of the given reactor.*/
        if (reactorStakeValue == 3000 || reactorStakeValue == 15000) {
            if (nValueIn < (reactorStakeValue * COIN))
                return DoS(100, error("IsReactorStake() : nValueIn doesn't meet requirement for reactor stake; credit %" PRI64d "; reactor size %d or %d", nValueIn, 3000, 15000));

            if (nValueIn > (reactorStakeValue * COIN))
                return DoS(100, error("IsReactorStake() : nValueIn exceeds value of reactor; credit %" PRI64d "; reactor size %d or %d", nValueIn, 3000, 15000));
        } else {
            if (nValueIn < (reactorStakeValue * COIN))
                return DoS(100, error("IsReactorStake() : credit doesn't meet requirement for reactor stake; credit %" PRI64d "; reactor size %" PRI64d "", nValueIn, reactorStakeValue));

            if (nValueIn > (reactorStakeValue * COIN))
                return DoS(100, error("IsReactorStake() : credit exceeds value of reactor; credit %" PRI64d "; reactor size %" PRI64d "", nValueIn, reactorStakeValue));
        }

        if (nStakeReward > GetProofOfStakeReward(nCoinAge, nBits, nTime, nHeight, GetReactorRate(reactorStakeValue, nValueIn)) - GetMinFee() + MIN_TX_FEE)
            return DoS(100, error("IsReactorStake() : %s stake reward exceeded", GetHash().ToString().substr(0, 10).c_str()));

        return true;
    }

    return false;
}

// Inflate the reactor table in the reactorDB
void InflateReactorDB(string strFileName) {
    printf("InflateReactorDB() : inflating reactor database.\n");

    fTestNet ? CReactorDB(strFileName, "cw+").WriteTestReactorDB() : CReactorDB(strFileName, "cw+").WriteReactorDB();
}

int GetReactorRate(int64 reactorStakeValue, int64 nValueIn) {
    if (reactorStakeValue == 100)
        return 1.05;

    if (reactorStakeValue == 1000 || reactorStakeValue == 10000)
        return 2;

    /* We store the max value of the Legendaries in the database and override
     * the rate for 3000 coin stakes here. */
    if (reactorStakeValue == 15000 && nValueIn == 3000 * COIN)
        return 2;

    if (reactorStakeValue == 15000 && nValueIn == 15000 * COIN)
        return 1.25;

    return 0;
}

bool CReactorDB::WriteReactorDBVersion(int version)
{
    return Write(string("dbversion"), version);
}

bool CReactorDB::WriteReactorAddr(const string address, unsigned int valid_starting, unsigned int valid_until, int64 reactorStakeValue)
{
    return Write(make_pair(string("reactor"), address), boost::make_tuple(valid_starting, valid_until, reactorStakeValue));
}

bool CReactorDB::CheckReactorDBVersion(int &version)
{
    if (!Exists(string("dbversion")))
        return false;

    Read(string("dbversion"), version);
    return true;
}

bool CReactorDB::CheckReactorAddr(const string address)
{
    return Exists(make_pair(string("reactor"), address));
}

bool CReactorDB::IsReactor(std::string strFileName, CScript scriptPubKeyAddress, int64 &reactorStakeValue, unsigned int &valid_starting, unsigned int &valid_until)
{
    CTxDestination address;
    ExtractDestination(scriptPubKeyAddress, address);
    CBitcoinAddress addr(address);

    // Check if the address exists in the reactor database.
    if (!CReactorDB(strFileName).CheckReactorAddr(addr.ToString()))
        return false;

    boost::tuple<unsigned int, unsigned int, int64> t;
    Read(make_pair(string("reactor"), addr.ToString()), t);

    valid_starting = t.get<0>();
    valid_until = t.get<1>();

    reactorStakeValue = t.get<2>();
    return true;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <thread>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#include "dcomm.h"
#include "frame.cpp"
#include "crc32.h"
using namespace std;

struct sockaddr_in myaddr;
struct sockaddr_in remaddr;
socklen_t addrlen = sizeof(remaddr);
int s;
int msgcnt = 0;
char sent_frame[DATASIZE + 15];
frame frame_buffer[RXQSIZE];

void receiveMessage(){
	printf("waiting on port 9999\n");
	for (;;) {
		int recvlen = recvfrom(s, sent_frame, sizeof(sent_frame), 0, (struct sockaddr *)&remaddr, &addrlen);
		if (recvlen > 0) {

			frame f(sent_frame);
			frame_buffer[f.getFrameNumber() % WINDOWSIZE] = f;
		}

	}
}

void consumeMessage(){
	int j = 0;
	for (;;){
		j++;
		for (int i = 0; i < RXQSIZE; i++) {
			if (frame_buffer[i].getFrameNumber() != -1){

				CRC32 crc32;
				string tmp;

				if (1) { // jika checksum sama
					cout << frame_buffer[i].getData() << endl;

					int frameNumber = frame_buffer[i].getFrameNumber();
					char buf[10];
					sprintf(buf, "%d", frameNumber);
					if (sendto(s, buf, sizeof(buf), 0, (struct sockaddr *)&remaddr, addrlen)==-1) {
					    perror("sendto");
					    exit(1);
					}

					usleep(50);
					frame_buffer[i].empty();
				}
			}
		}
	}
}

#define BUFSIZE 32

int main(int argc, char const *argv[]) {

	// Create UDP socket
	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		perror("cannot create socket\n");
		return 0;
	}

	// Bind the socket to any valid IP address and a specific port
	memset((char *)&myaddr, 0, sizeof(myaddr));
	myaddr.sin_family = AF_INET;
	myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	myaddr.sin_port = htons(atoi(argv[1]));

	if (bind(s, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
		perror("bind failed");
		return 0;
	}
	thread receive_t(receiveMessage);
	thread consume_t(consumeMessage);
	consume_t.join();
	receive_t.join();
	// Everything is configured and ready to receive message

}
<commit_msg>Add to do<commit_after>#include <iostream>
#include <thread>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#include "dcomm.h"
#include "frame.cpp"
#include "crc32.h"
using namespace std;

struct sockaddr_in myaddr;
struct sockaddr_in remaddr;
socklen_t addrlen = sizeof(remaddr);
int s;
int msgcnt = 0;
char sent_frame[DATASIZE + 15];
frame frame_buffer[RXQSIZE];

void receiveMessage(){
	printf("waiting on port 9999\n");
	for (;;) {
		int recvlen = recvfrom(s, sent_frame, sizeof(sent_frame), 0, (struct sockaddr *)&remaddr, &addrlen);
		if (recvlen > 0) {

			frame f(sent_frame);
			frame_buffer[f.getFrameNumber() % WINDOWSIZE] = f;
		}

	}
}

void consumeMessage(){
	for (;;){
		for (int i = 0; i < RXQSIZE; i++) {
			if (frame_buffer[i].getFrameNumber() != -1) { // jika frame buffer tidak kosong
				if (1) { // jika checksum sama

					// kirim ACK
					cout << frame_buffer[i].getData() << endl;
					int frameNumber = frame_buffer[i].getFrameNumber();
					char buf[10];
					sprintf(buf, "%d", frameNumber);
					if (sendto(s, buf, sizeof(buf), 0, (struct sockaddr *)&remaddr, addrlen)==-1) {
					    perror("sendto");
					    exit(1);
					}

				} else { // checksum tidak sama
					// kirim NAK
				}

				// Hapus frame yang sudah diproses
				usleep(50);
				frame_buffer[i].empty();
			}
		}
	}
}

#define BUFSIZE 32

int main(int argc, char const *argv[]) {

	// Create UDP socket
	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		perror("cannot create socket\n");
		return 0;
	}

	// Bind the socket to any valid IP address and a specific port
	memset((char *)&myaddr, 0, sizeof(myaddr));
	myaddr.sin_family = AF_INET;
	myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	myaddr.sin_port = htons(atoi(argv[1]));

	if (bind(s, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
		perror("bind failed");
		return 0;
	}
	thread receive_t(receiveMessage);
	thread consume_t(consumeMessage);
	consume_t.join();
	receive_t.join();
	// Everything is configured and ready to receive message

}
<|endoftext|>


<commit_before>/*
 * Copyright 2020-2021 INRIA
 */

#include "eigenpy/register.hpp"

namespace eigenpy
{

  PyArray_Descr * Register::getPyArrayDescr(PyTypeObject * py_type_ptr)
  {
    MapDescr::iterator it = instance().py_array_descr_bindings.find(py_type_ptr);
    if(it != instance().py_array_descr_bindings.end())
      return it->second;
    else
      return NULL;
  }

  bool Register::isRegistered(PyTypeObject * py_type_ptr)
  {
    if(getPyArrayDescr(py_type_ptr) != NULL)
      return true;
    else
      return false;
  }

  int Register::getTypeCode(PyTypeObject * py_type_ptr)
  {
    MapCode::iterator it = instance().py_array_code_bindings.find(py_type_ptr);
    if(it != instance().py_array_code_bindings.end())
      return it->second;
    else
      return PyArray_TypeNum(py_type_ptr);
  }

  int Register::registerNewType(PyTypeObject * py_type_ptr,
                                const std::type_info * type_info_ptr,
                                const int type_size,
                                const int alignement,
                                PyArray_GetItemFunc * getitem,
                                PyArray_SetItemFunc * setitem,
                                PyArray_NonzeroFunc * nonzero,
                                PyArray_CopySwapFunc * copyswap,
                                PyArray_CopySwapNFunc * copyswapn,
                                PyArray_DotFunc * dotfunc,
                                PyArray_FillWithScalarFunc * fillwithscalar)
  {
    namespace bp = boost::python;
    bp::list bases(bp::handle<>(bp::borrowed(py_type_ptr->tp_bases)));
    bases.append((bp::handle<>(bp::borrowed(&PyGenericArrType_Type))));

    bp::tuple tp_bases_extended(bases);
    Py_INCREF(tp_bases_extended.ptr());
    py_type_ptr->tp_bases = tp_bases_extended.ptr();

    py_type_ptr->tp_flags &= ~Py_TPFLAGS_READY; // to force the rebuild
    if(PyType_Ready(py_type_ptr) < 0) // Force rebuilding of the __bases__ and mro
    {
      throw std::invalid_argument("PyType_Ready fails to initialize input type.");
    }

    PyArray_Descr * descr_ptr = new PyArray_Descr(*call_PyArray_DescrFromType(NPY_OBJECT));
    PyArray_Descr & descr = *descr_ptr;
    descr.typeobj = py_type_ptr;
    descr.kind = 'V';
    descr.byteorder = '=';
    descr.type = 'r';
    descr.elsize = type_size;
    descr.flags = NPY_NEEDS_PYAPI | NPY_USE_GETITEM | NPY_USE_SETITEM;
    descr.type_num = 0;
    descr.names = 0;
    descr.fields = 0;
    descr.alignment = alignement; //call_PyArray_DescrFromType(NPY_OBJECT)->alignment;

    PyArray_ArrFuncs * funcs_ptr = new PyArray_ArrFuncs;
    PyArray_ArrFuncs & funcs = *funcs_ptr;
    descr.f = funcs_ptr;
    call_PyArray_InitArrFuncs(funcs_ptr);
    funcs.getitem = getitem;
    funcs.setitem = setitem;
    funcs.nonzero = nonzero;
    funcs.copyswap = copyswap;
    funcs.copyswapn = copyswapn;
    funcs.dotfunc = dotfunc;
    funcs.fillwithscalar = fillwithscalar;
    //      f->cast = cast;

    const int code = call_PyArray_RegisterDataType(descr_ptr);
    assert(code >= 0 && "The return code should be positive");
    PyArray_Descr * new_descr = call_PyArray_DescrFromType(code);

    if(PyDict_SetItemString(py_type_ptr->tp_dict,"dtype",(PyObject*)descr_ptr) < 0)
    {
      throw std::invalid_argument("PyDict_SetItemString fails.");
    }

    instance().type_to_py_type_bindings.insert(std::make_pair(type_info_ptr,py_type_ptr));
    instance().py_array_descr_bindings[py_type_ptr] = new_descr;
    instance().py_array_code_bindings[py_type_ptr] = code;

    //      PyArray_RegisterCanCast(descr,NPY_OBJECT,NPY_NOSCALAR);
    return code;
  }

  Register & Register::instance()
  {
    static Register self;
    return self;
  }

} // namespace eigenpy
<commit_msg>register: handle fill<commit_after>/*
 * Copyright 2020-2021 INRIA
 */

#include "eigenpy/register.hpp"

namespace eigenpy
{

  PyArray_Descr * Register::getPyArrayDescr(PyTypeObject * py_type_ptr)
  {
    MapDescr::iterator it = instance().py_array_descr_bindings.find(py_type_ptr);
    if(it != instance().py_array_descr_bindings.end())
      return it->second;
    else
      return NULL;
  }

  bool Register::isRegistered(PyTypeObject * py_type_ptr)
  {
    if(getPyArrayDescr(py_type_ptr) != NULL)
      return true;
    else
      return false;
  }

  int Register::getTypeCode(PyTypeObject * py_type_ptr)
  {
    MapCode::iterator it = instance().py_array_code_bindings.find(py_type_ptr);
    if(it != instance().py_array_code_bindings.end())
      return it->second;
    else
      return PyArray_TypeNum(py_type_ptr);
  }

  int Register::registerNewType(PyTypeObject * py_type_ptr,
                                const std::type_info * type_info_ptr,
                                const int type_size,
                                const int alignement,
                                PyArray_GetItemFunc * getitem,
                                PyArray_SetItemFunc * setitem,
                                PyArray_NonzeroFunc * nonzero,
                                PyArray_CopySwapFunc * copyswap,
                                PyArray_CopySwapNFunc * copyswapn,
                                PyArray_DotFunc * dotfunc,
                                PyArray_FillFunc * fill,
                                PyArray_FillWithScalarFunc * fillwithscalar)
  {
    namespace bp = boost::python;
    bp::list bases(bp::handle<>(bp::borrowed(py_type_ptr->tp_bases)));
    bases.append((bp::handle<>(bp::borrowed(&PyGenericArrType_Type))));

    bp::tuple tp_bases_extended(bases);
    Py_INCREF(tp_bases_extended.ptr());
    py_type_ptr->tp_bases = tp_bases_extended.ptr();

    py_type_ptr->tp_flags &= ~Py_TPFLAGS_READY; // to force the rebuild
    if(PyType_Ready(py_type_ptr) < 0) // Force rebuilding of the __bases__ and mro
    {
      throw std::invalid_argument("PyType_Ready fails to initialize input type.");
    }

    PyArray_Descr * descr_ptr = new PyArray_Descr(*call_PyArray_DescrFromType(NPY_OBJECT));
    PyArray_Descr & descr = *descr_ptr;
    descr.typeobj = py_type_ptr;
    descr.kind = 'V';
    descr.byteorder = '=';
    descr.type = 'r';
    descr.elsize = type_size;
    descr.flags = NPY_NEEDS_PYAPI | NPY_USE_GETITEM | NPY_USE_SETITEM;
    descr.type_num = 0;
    descr.names = 0;
    descr.fields = 0;
    descr.alignment = alignement; //call_PyArray_DescrFromType(NPY_OBJECT)->alignment;

    PyArray_ArrFuncs * funcs_ptr = new PyArray_ArrFuncs;
    PyArray_ArrFuncs & funcs = *funcs_ptr;
    descr.f = funcs_ptr;
    call_PyArray_InitArrFuncs(funcs_ptr);
    funcs.getitem = getitem;
    funcs.setitem = setitem;
    funcs.nonzero = nonzero;
    funcs.copyswap = copyswap;
    funcs.copyswapn = copyswapn;
    funcs.dotfunc = dotfunc;
    funcs.fill = fill;
    funcs.fillwithscalar = fillwithscalar;
    //      f->cast = cast;

    const int code = call_PyArray_RegisterDataType(descr_ptr);
    assert(code >= 0 && "The return code should be positive");
    PyArray_Descr * new_descr = call_PyArray_DescrFromType(code);

    if(PyDict_SetItemString(py_type_ptr->tp_dict,"dtype",(PyObject*)descr_ptr) < 0)
    {
      throw std::invalid_argument("PyDict_SetItemString fails.");
    }

    instance().type_to_py_type_bindings.insert(std::make_pair(type_info_ptr,py_type_ptr));
    instance().py_array_descr_bindings[py_type_ptr] = new_descr;
    instance().py_array_code_bindings[py_type_ptr] = code;

    //      PyArray_RegisterCanCast(descr,NPY_OBJECT,NPY_NOSCALAR);
    return code;
  }

  Register & Register::instance()
  {
    static Register self;
    return self;
  }

} // namespace eigenpy
<|endoftext|>


<commit_before>// ======================================================================== //
// Copyright 2009-2018 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#include "regression.h"

namespace embree
{
  static std::unique_ptr<std::vector<RegressionTest*>> regression_tests;

  void registerRegressionTest(RegressionTest* test)
  {
    if (!regression_tests)
      regression_tests = std::unique_ptr<std::vector<RegressionTest*>>(new std::vector<RegressionTest*>);

    regression_tests->push_back(test);
  }

  RegressionTest* getRegressionTest(size_t index)
  {
    if (!regression_tests)
      return nullptr;

    if (index >= regression_tests->size())
      return nullptr;

    return (*regression_tests)[index];
  }
}
<commit_msg>fixed issues with static variable initialization order causing a memory leak in regression.cpp<commit_after>// ======================================================================== //
// Copyright 2009-2018 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#include "regression.h"

namespace embree
{
  /* registerRegressionTest is invoked from static initializers, thus
   * we cannot have the regression_tests variable as global static
   * variable due to issues with static variable initialization
   * order. */
  std::vector<RegressionTest*>& get_regression_tests()
  {
    static std::vector<RegressionTest*> regression_tests;
    return regression_tests;
  }

  void registerRegressionTest(RegressionTest* test)
  {
    get_regression_tests().push_back(test);
  }

  RegressionTest* getRegressionTest(size_t index)
  {
    if (index >= get_regression_tests().size())
      return nullptr;

    return get_regression_tests()[index];
  }
}
<|endoftext|>


<commit_before>#include "CUDADenseGraphBFSolver.h"
#include "CUDAFormulas.h"
#include "Device.h"
#include <cmath>
#include <float.h>
#include <algorithm>
#include <limits>

using namespace sqaod_cuda;
namespace sq = sqaod;

template<class real>
CUDADenseGraphBFSolver<real>::CUDADenseGraphBFSolver() {
    tileSize_ = 16384; /* FIXME: give a correct size */
}

template<class real>
CUDADenseGraphBFSolver<real>::CUDADenseGraphBFSolver(Device &device) {
    tileSize_ = 16384; /* FIXME: give a correct size */
    assignDevice(device);
}

template<class real>
CUDADenseGraphBFSolver<real>::~CUDADenseGraphBFSolver() {
}

template<class real>
void CUDADenseGraphBFSolver<real>::assignDevice(Device &device) {
    batchSearch_.assignDevice(device);
    devCopy_.assignDevice(device);
}

template<class real>
void CUDADenseGraphBFSolver<real>::getProblemSize(sqaod::SizeType *N) const {
    *N = N_;
}

template<class real>
void CUDADenseGraphBFSolver<real>::setProblem(const Matrix &W, sq::OptimizeMethod om) {
    throwErrorIf(!isSymmetric(W), "W is not symmetric.");
    N_ = W.rows;
    W_ = W;
    om_ = om;
    if (om_ == sq::optMaximize)
        W_ *= real(-1.);
}

template<class real>
void CUDADenseGraphBFSolver<real>::setTileSize(sqaod::SizeType tileSize) {
    tileSize_ = tileSize;
}

template<class real>
const sq::BitsArray &CUDADenseGraphBFSolver<real>::get_x() const {
    return xList_;
}

template<class real>
const sq::VectorType<real> &CUDADenseGraphBFSolver<real>::get_E() const {
    return E_;
}

template<class real>
void CUDADenseGraphBFSolver<real>::initSearch() {
    batchSearch_.setProblem(W_, tileSize_);
    HostObjectAllocator().allocate(&h_packedXmin_, tileSize_);

    Emin_ = std::numeric_limits<real>::max();
    xList_.clear();
    xMax_ = 1ull << N_;
}

template<class real>
void CUDADenseGraphBFSolver<real>::finSearch() {
    batchSearch_.synchronize();
    const DevicePackedBitsArray &dPackedXmin = batchSearch_.get_xMins();
    sqaod::SizeType nXMin = std::min(tileSize_, dPackedXmin.size);
    devCopy_(&h_packedXmin_, dPackedXmin);
    devCopy_.synchronize();

    xList_.clear();
    E_.resize(nXMin);
    if (om_ == sq::optMaximize)
        E_ *= real(-1.);
    for (sqaod::IdxType idx = 0; idx < (sqaod::IdxType)nXMin; ++idx) {
        sq::Bits bits;
        unpackBits(&bits, h_packedXmin_[idx], N_);
        xList_.pushBack(bits); // FIXME: apply move
    }
}

template<class real>
void CUDADenseGraphBFSolver<real>::searchRange(sq::PackedBits xBegin, sq::PackedBits xEnd) {
    /* FIXME: Use multiple searchers, multi GPU */
    throwErrorIf(xBegin > xEnd, "xBegin should be larger than xEnd");
    xBegin = std::min(std::max(0ULL, xBegin), xMax_);
    xEnd = std::min(std::max(0ULL, xEnd), xMax_);
    if (xBegin == xEnd)
        return; /* Nothing to do */

    batchSearch_.calculate_E(xBegin, xEnd);
    batchSearch_.synchronize();

    real newEmin = batchSearch_.get_Emin();
    if (newEmin < Emin_) {
        batchSearch_.partition_xMins(false);
        Emin_ = newEmin;
    }
    else if (newEmin == Emin_) {
        batchSearch_.partition_xMins(true);
    }
}

template<class real>
void CUDADenseGraphBFSolver<real>::search() {
    initSearch();
    int iStep = (int)std::min((unsigned long long)tileSize_, xMax_);
    for (sq::PackedBits iTile = 0; iTile < xMax_; iTile += iStep) {
        searchRange(iTile, iTile + iStep);
    }
    finSearch();
}

template class sqaod_cuda::CUDADenseGraphBFSolver<float>;
template class sqaod_cuda::CUDADenseGraphBFSolver<double>;
<commit_msg>Fix: Emin_ is not copied to E_.<commit_after>#include "CUDADenseGraphBFSolver.h"
#include "CUDAFormulas.h"
#include "Device.h"
#include <cmath>
#include <float.h>
#include <algorithm>
#include <limits>

using namespace sqaod_cuda;
namespace sq = sqaod;

template<class real>
CUDADenseGraphBFSolver<real>::CUDADenseGraphBFSolver() {
    tileSize_ = 16384; /* FIXME: give a correct size */
}

template<class real>
CUDADenseGraphBFSolver<real>::CUDADenseGraphBFSolver(Device &device) {
    tileSize_ = 16384; /* FIXME: give a correct size */
    assignDevice(device);
}

template<class real>
CUDADenseGraphBFSolver<real>::~CUDADenseGraphBFSolver() {
}

template<class real>
void CUDADenseGraphBFSolver<real>::assignDevice(Device &device) {
    batchSearch_.assignDevice(device);
    devCopy_.assignDevice(device);
}

template<class real>
void CUDADenseGraphBFSolver<real>::getProblemSize(sqaod::SizeType *N) const {
    *N = N_;
}

template<class real>
void CUDADenseGraphBFSolver<real>::setProblem(const Matrix &W, sq::OptimizeMethod om) {
    throwErrorIf(!isSymmetric(W), "W is not symmetric.");
    N_ = W.rows;
    W_ = W;
    om_ = om;
    if (om_ == sq::optMaximize)
        W_ *= real(-1.);
}

template<class real>
void CUDADenseGraphBFSolver<real>::setTileSize(sqaod::SizeType tileSize) {
    tileSize_ = tileSize;
}

template<class real>
const sq::BitsArray &CUDADenseGraphBFSolver<real>::get_x() const {
    return xList_;
}

template<class real>
const sq::VectorType<real> &CUDADenseGraphBFSolver<real>::get_E() const {
    return E_;
}

template<class real>
void CUDADenseGraphBFSolver<real>::initSearch() {
    batchSearch_.setProblem(W_, tileSize_);
    HostObjectAllocator().allocate(&h_packedXmin_, tileSize_);

    Emin_ = std::numeric_limits<real>::max();
    xList_.clear();
    xMax_ = 1ull << N_;
}

template<class real>
void CUDADenseGraphBFSolver<real>::finSearch() {
    batchSearch_.synchronize();
    const DevicePackedBitsArray &dPackedXmin = batchSearch_.get_xMins();
    sqaod::SizeType nXMin = std::min(tileSize_, dPackedXmin.size);
    devCopy_(&h_packedXmin_, dPackedXmin);
    devCopy_.synchronize();

    xList_.clear();
    E_.resize(nXMin);
    E_ = Emin_;
    if (om_ == sq::optMaximize)
        E_ *= real(-1.);
    for (sqaod::IdxType idx = 0; idx < (sqaod::IdxType)nXMin; ++idx) {
        sq::Bits bits;
        unpackBits(&bits, h_packedXmin_[idx], N_);
        xList_.pushBack(bits); // FIXME: apply move
    }
}

template<class real>
void CUDADenseGraphBFSolver<real>::searchRange(sq::PackedBits xBegin, sq::PackedBits xEnd) {
    /* FIXME: Use multiple searchers, multi GPU */
    throwErrorIf(xBegin > xEnd, "xBegin should be larger than xEnd");
    xBegin = std::min(std::max(0ULL, xBegin), xMax_);
    xEnd = std::min(std::max(0ULL, xEnd), xMax_);
    if (xBegin == xEnd)
        return; /* Nothing to do */

    batchSearch_.calculate_E(xBegin, xEnd);
    batchSearch_.synchronize();

    real newEmin = batchSearch_.get_Emin();
    if (newEmin < Emin_) {
        batchSearch_.partition_xMins(false);
        Emin_ = newEmin;
    }
    else if (newEmin == Emin_) {
        batchSearch_.partition_xMins(true);
    }
}

template<class real>
void CUDADenseGraphBFSolver<real>::search() {
    initSearch();
    int iStep = (int)std::min((unsigned long long)tileSize_, xMax_);
    for (sq::PackedBits iTile = 0; iTile < xMax_; iTile += iStep) {
        searchRange(iTile, iTile + iStep);
    }
    finSearch();
}

template class sqaod_cuda::CUDADenseGraphBFSolver<float>;
template class sqaod_cuda::CUDADenseGraphBFSolver<double>;
<|endoftext|>


<commit_before>// -*- C++ -*-
//
// ----------------------------------------------------------------------
//
// Brad T. Aagaard, U.S. Geological Survey
//
// This code was developed as part of the Computational Infrastructure
// for Geodynamics (http://geodynamics.org).
//
// Copyright (c) 2010-2015 University of California, Davis
//
// See COPYING for license information.
//
// ----------------------------------------------------------------------
//

#include <portinfo>

#include "SpatialDB.hh" // ISA SpatialDB object
#include "SimpleDB.hh" // Implementation of class methods

#include "SimpleIO.hh" // USES SimpleIO
#include "SimpleDBData.hh" // USES SimpleDBData
#include "SimpleDBQuery.hh" // USES SimpleDBQuery

#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys

#include <stdexcept> // USES std::runtime_error
#include "Exception.hh" // USES OutOfBounds

#include <sstream> // USES std::ostringsgream
#include <assert.h> // USES assert()

// ----------------------------------------------------------------------
/// Default constructor
spatialdata::spatialdb::SimpleDB::SimpleDB(void) :
  _data(0),
  _iohandler(0),
  _query(0),
  _cs(0)
{ // constructor
} // constructor

// ----------------------------------------------------------------------
/// Constructor with label
spatialdata::spatialdb::SimpleDB::SimpleDB(const char* label) :
  SpatialDB(label),
  _data(0),
  _iohandler(0),
  _query(0),
  _cs(0)
{ // constructor
} // constructor

// ----------------------------------------------------------------------
/// Default destructor
spatialdata::spatialdb::SimpleDB::~SimpleDB(void)
{ // destructor
  delete _data; _data = 0;
  delete _iohandler; _iohandler = 0;
  delete _query; _query = 0;
  delete _cs; _cs = 0;
} // destructor

// ----------------------------------------------------------------------
/// Open the database and prepare for querying.
void
spatialdata::spatialdb::SimpleDB::open(void)
{ // open
  assert(_iohandler);

  // Read data
  if (!_data) {
    _data = new SimpleDBData;
    _iohandler->read(_data, &_cs);
  } // if

  // Create query object
  if (!_query)
    _query = new SimpleDBQuery(*this);
} // open

// ----------------------------------------------------------------------
/// Close the database.
void
spatialdata::spatialdb::SimpleDB::close(void)
{ // close
  delete _data; _data = 0;

  assert(_query);
  _query->deallocate();
} // close

// ----------------------------------------------------------------------
// Set query type.
void
spatialdata::spatialdb::SimpleDB::queryType(const SimpleDB::QueryEnum queryType)
{ // queryType
  if (0 == _query)
    _query = new SimpleDBQuery(*this);
  _query->queryType(queryType);
} // QueryType

// ----------------------------------------------------------------------
// Set values to be returned by queries.
void
spatialdata::spatialdb::SimpleDB::queryVals(const char* const* names,
					    const int numVals)
{ // queryVals
  if (0 == _query) {
    std::ostringstream msg;
    msg
      << "Spatial database " << label() << " has not been opened.\n"
      << "Please call Open() before calling QueryVals().";
    throw std::runtime_error(msg.str());
  } // if
  _query->queryVals(names, numVals);
} // queryVals

// ----------------------------------------------------------------------
// Set the I/O handler.
void
spatialdata::spatialdb::SimpleDB::ioHandler(const SimpleIO* iohandler)
{ // ioHandler
  delete _iohandler; _iohandler = (0 != iohandler) ? iohandler->clone() : 0;
} // ioHandler

// ----------------------------------------------------------------------
// Query the database.
int
spatialdata::spatialdb::SimpleDB::query(double* vals,
					const int numVals,
					const double* coords,
					const int numDims,
			      const spatialdata::geocoords::CoordSys* pCSQuery)
{ // query
  try {
    if (0 == _query) {
      std::ostringstream msg;
      msg
	<< "Spatial database " << label() << " has not been opened.\n"
	<< "Please call open() before calling query().";
      throw std::runtime_error(msg.str());
    } // if
    else if (0 == _data) {
      std::ostringstream msg;
      msg
	<< "Spatial database " << label() << " does not contain any data.\n"
	<< "Database query aborted.";
      throw std::runtime_error(msg.str());
    } // if
    _query->query(vals, numVals, coords, numDims, pCSQuery);
  } catch(const OutOfBounds& err) {
    std::fill(vals, vals+numVals, 0);
    return 1;
  } catch(const std::exception& err) {
    throw std::runtime_error(err.what());
  } catch(...) {
    throw std::runtime_error("Unknown error in SpatialDB query");
  } // catch
  return 0;
} // query

// End of file
<commit_msg>Made SimpleDB::close() more robust. Don't insist on query being non-null.<commit_after>// -*- C++ -*-
//
// ----------------------------------------------------------------------
//
// Brad T. Aagaard, U.S. Geological Survey
//
// This code was developed as part of the Computational Infrastructure
// for Geodynamics (http://geodynamics.org).
//
// Copyright (c) 2010-2015 University of California, Davis
//
// See COPYING for license information.
//
// ----------------------------------------------------------------------
//

#include <portinfo>

#include "SpatialDB.hh" // ISA SpatialDB object
#include "SimpleDB.hh" // Implementation of class methods

#include "SimpleIO.hh" // USES SimpleIO
#include "SimpleDBData.hh" // USES SimpleDBData
#include "SimpleDBQuery.hh" // USES SimpleDBQuery

#include "spatialdata/geocoords/CoordSys.hh" // USES CoordSys

#include <stdexcept> // USES std::runtime_error
#include "Exception.hh" // USES OutOfBounds

#include <sstream> // USES std::ostringsgream
#include <assert.h> // USES assert()

// ----------------------------------------------------------------------
/// Default constructor
spatialdata::spatialdb::SimpleDB::SimpleDB(void) :
  _data(0),
  _iohandler(0),
  _query(0),
  _cs(0)
{ // constructor
} // constructor

// ----------------------------------------------------------------------
/// Constructor with label
spatialdata::spatialdb::SimpleDB::SimpleDB(const char* label) :
  SpatialDB(label),
  _data(0),
  _iohandler(0),
  _query(0),
  _cs(0)
{ // constructor
} // constructor

// ----------------------------------------------------------------------
/// Default destructor
spatialdata::spatialdb::SimpleDB::~SimpleDB(void)
{ // destructor
  delete _data; _data = 0;
  delete _iohandler; _iohandler = 0;
  delete _query; _query = 0;
  delete _cs; _cs = 0;
} // destructor

// ----------------------------------------------------------------------
/// Open the database and prepare for querying.
void
spatialdata::spatialdb::SimpleDB::open(void)
{ // open
  assert(_iohandler);

  // Read data
  if (!_data) {
    _data = new SimpleDBData;
    _iohandler->read(_data, &_cs);
  } // if

  // Create query object
  if (!_query)
    _query = new SimpleDBQuery(*this);
} // open

// ----------------------------------------------------------------------
/// Close the database.
void
spatialdata::spatialdb::SimpleDB::close(void)
{ // close
  delete _data; _data = 0;

  if (_query) {
    _query->deallocate();
  } // if
} // close

// ----------------------------------------------------------------------
// Set query type.
void
spatialdata::spatialdb::SimpleDB::queryType(const SimpleDB::QueryEnum queryType)
{ // queryType
  if (0 == _query)
    _query = new SimpleDBQuery(*this);
  _query->queryType(queryType);
} // QueryType

// ----------------------------------------------------------------------
// Set values to be returned by queries.
void
spatialdata::spatialdb::SimpleDB::queryVals(const char* const* names,
					    const int numVals)
{ // queryVals
  if (0 == _query) {
    std::ostringstream msg;
    msg
      << "Spatial database " << label() << " has not been opened.\n"
      << "Please call Open() before calling QueryVals().";
    throw std::runtime_error(msg.str());
  } // if
  _query->queryVals(names, numVals);
} // queryVals

// ----------------------------------------------------------------------
// Set the I/O handler.
void
spatialdata::spatialdb::SimpleDB::ioHandler(const SimpleIO* iohandler)
{ // ioHandler
  delete _iohandler; _iohandler = (0 != iohandler) ? iohandler->clone() : 0;
} // ioHandler

// ----------------------------------------------------------------------
// Query the database.
int
spatialdata::spatialdb::SimpleDB::query(double* vals,
					const int numVals,
					const double* coords,
					const int numDims,
			      const spatialdata::geocoords::CoordSys* pCSQuery)
{ // query
  try {
    if (0 == _query) {
      std::ostringstream msg;
      msg
	<< "Spatial database " << label() << " has not been opened.\n"
	<< "Please call open() before calling query().";
      throw std::runtime_error(msg.str());
    } // if
    else if (0 == _data) {
      std::ostringstream msg;
      msg
	<< "Spatial database " << label() << " does not contain any data.\n"
	<< "Database query aborted.";
      throw std::runtime_error(msg.str());
    } // if
    _query->query(vals, numVals, coords, numDims, pCSQuery);
  } catch(const OutOfBounds& err) {
    std::fill(vals, vals+numVals, 0);
    return 1;
  } catch(const std::exception& err) {
    throw std::runtime_error(err.what());
  } catch(...) {
    throw std::runtime_error("Unknown error in SpatialDB query");
  } // catch
  return 0;
} // query

// End of file
<|endoftext|>


<commit_before>#include "reloader.h"

#include <algorithm>
#include <cinttypes>
#include <iostream>
#include <ncurses.h>
#include <thread>

#include "controller.h"
#include "curlhandle.h"
#include "dbexception.h"
#include "downloadthread.h"
#include "fmtstrformatter.h"
#include "reloadrangethread.h"
#include "reloadthread.h"
#include "rss/exception.h"
#include "rssfeed.h"
#include "rssparser.h"
#include "scopemeasure.h"
#include "utils.h"
#include "view.h"

namespace newsboat {

Reloader::Reloader(Controller* c, Cache* cc, ConfigContainer* cfg)
	: ctrl(c)
	, rsscache(cc)
	, cfg(cfg)
{
}

void Reloader::spawn_reloadthread()
{
	std::thread t{ReloadThread(ctrl, cfg)};
	t.detach();
}

void Reloader::start_reload_all_thread(std::vector<int>* indexes)
{
	LOG(Level::INFO, "starting reload all thread");
	std::thread t(DownloadThread(*this, indexes));
	t.detach();
}

bool Reloader::trylock_reload_mutex()
{
	if (reload_mutex.try_lock()) {
		LOG(Level::DEBUG, "Reloader::trylock_reload_mutex succeeded");
		return true;
	}
	LOG(Level::DEBUG, "Reloader::trylock_reload_mutex failed");
	return false;
}

void Reloader::reload(unsigned int pos,
	unsigned int max,
	bool unattended,
	CurlHandle* easyhandle)
{
	LOG(Level::DEBUG, "Reloader::reload: pos = %u max = %u", pos, max);
	if (pos < ctrl->get_feedcontainer()->feeds.size()) {
		std::shared_ptr<RssFeed> oldfeed =
			ctrl->get_feedcontainer()->feeds[pos];
		std::string errmsg;
		if (!unattended) {
			ctrl->get_view()->set_status(
				strprintf::fmt(_("%sLoading %s..."),
					prepare_message(pos + 1, max),
					utils::censor_url(oldfeed->rssurl())));
		}

		bool ignore_dl =
			(cfg->get_configvalue("ignore-mode") == "download");

		RssParser parser(oldfeed->rssurl(),
			rsscache,
			cfg,
			ignore_dl ? ctrl->get_ignores() : nullptr,
			ctrl->get_api());
		parser.set_easyhandle(easyhandle);
		LOG(Level::DEBUG, "Reloader::reload: created parser");
		try {
			oldfeed->set_status(DlStatus::DURING_DOWNLOAD);
			std::shared_ptr<RssFeed> newfeed = parser.parse();
			ctrl->replace_feed(
				oldfeed, newfeed, pos, unattended);
			if (newfeed->total_item_count() == 0) {
				LOG(Level::DEBUG,
					"Reloader::reload: feed is empty");
			}
			oldfeed->set_status(DlStatus::SUCCESS);
			ctrl->get_view()->set_status("");
		} catch (const DbException& e) {
			errmsg = strprintf::fmt(
					_("Error while retrieving %s: %s"),
					utils::censor_url(oldfeed->rssurl()),
					e.what());
		} catch (const std::string& emsg) {
			errmsg = strprintf::fmt(
					_("Error while retrieving %s: %s"),
					utils::censor_url(oldfeed->rssurl()),
					emsg);
		} catch (rsspp::Exception& e) {
			errmsg = strprintf::fmt(
					_("Error while retrieving %s: %s"),
					utils::censor_url(oldfeed->rssurl()),
					e.what());
		}
		if (errmsg != "") {
			oldfeed->set_status(DlStatus::DL_ERROR);
			ctrl->get_view()->set_status(errmsg);
			LOG(Level::USERERROR, "%s", errmsg);
		}
	} else {
		ctrl->get_view()->show_error(_("Error: invalid feed!"));
	}
}

std::string Reloader::prepare_message(unsigned int pos, unsigned int max)
{
	if (max > 0) {
		return strprintf::fmt("(%u/%u) ", pos, max);
	}
	return "";
}

void Reloader::reload_all(bool unattended)
{
	const auto unread_feeds =
		ctrl->get_feedcontainer()->unread_feed_count();
	const auto unread_articles =
		ctrl->get_feedcontainer()->unread_item_count();
	int num_threads = cfg->get_configvalue_as_int("reload-threads");
	time_t t1, t2, dt;

	ctrl->get_feedcontainer()->reset_feeds_status();
	const auto num_feeds = ctrl->get_feedcontainer()->feeds_size();

	// TODO: change to std::clamp in C++17
	const int min_threads = 1;
	const int max_threads = num_feeds;
	num_threads = std::max(min_threads, std::min(num_threads, max_threads));

	t1 = time(nullptr);

	LOG(Level::DEBUG, "Reloader::reload_all: starting with reload all...");
	if (num_threads == 1) {
		reload_range(0, num_feeds - 1, num_feeds, unattended);
	} else {
		std::vector<std::pair<unsigned int, unsigned int>> partitions =
				utils::partition_indexes(0, num_feeds - 1, num_threads);
		std::vector<std::thread> threads;
		LOG(Level::DEBUG,
			"Reloader::reload_all: starting reload threads...");
		for (int i = 0; i < num_threads - 1; i++) {
			threads.push_back(std::thread(ReloadRangeThread(*this,
						partitions[i].first,
						partitions[i].second,
						num_feeds,
						unattended)));
		}
		LOG(Level::DEBUG,
			"Reloader::reload_all: starting my own reload...");
		reload_range(partitions[num_threads - 1].first,
			partitions[num_threads - 1].second,
			num_feeds,
			unattended);
		LOG(Level::DEBUG,
			"Reloader::reload_all: joining other threads...");
		for (size_t i = 0; i < threads.size(); i++) {
			threads[i].join();
		}
	}

	// refresh query feeds (update and sort)
	LOG(Level::DEBUG, "Reloader::reload_all: refresh query feeds");
	for (const auto& feed : ctrl->get_feedcontainer()->feeds) {
		ctrl->get_view()->prepare_query_feed(feed);
	}
	ctrl->get_view()->force_redraw();

	ctrl->get_feedcontainer()->sort_feeds(cfg->get_feed_sort_strategy());
	ctrl->update_feedlist();

	t2 = time(nullptr);
	dt = t2 - t1;
	// On GCC, `time_t` is `long int`, which is at least 32 bits. On x86_64,
	// it's 64 bits. Thus, this cast is either a no-op, or an up-cast which are
	// always safe.
	LOG(Level::INFO,
		"Reloader::reload_all: reload took %" PRId64 " seconds",
		static_cast<int64_t>(dt));

	const auto unread_feeds2 =
		ctrl->get_feedcontainer()->unread_feed_count();
	const auto unread_articles2 =
		ctrl->get_feedcontainer()->unread_item_count();
	bool notify_always = cfg->get_configvalue_as_bool("notify-always");
	if (notify_always || unread_feeds2 > unread_feeds ||
		unread_articles2 > unread_articles) {
		int article_count = unread_articles2 - unread_articles;
		int feed_count = unread_feeds2 - unread_feeds;

		LOG(Level::DEBUG, "unread article count: %d", article_count);
		LOG(Level::DEBUG, "unread feed count: %d", feed_count);

		FmtStrFormatter fmt;
		fmt.register_fmt('f', std::to_string(unread_feeds2));
		fmt.register_fmt('n', std::to_string(unread_articles2));
		fmt.register_fmt('d',
			std::to_string(article_count >= 0 ? article_count : 0));
		fmt.register_fmt(
			'D', std::to_string(feed_count >= 0 ? feed_count : 0));
		notify(fmt.do_format(cfg->get_configvalue("notify-format")));
	}
}

void Reloader::reload_indexes(const std::vector<int>& indexes, bool unattended)
{
	ScopeMeasure m1("Reloader::reload_indexes");
	const auto unread_feeds =
		ctrl->get_feedcontainer()->unread_feed_count();
	const auto unread_articles =
		ctrl->get_feedcontainer()->unread_item_count();
	const auto size = ctrl->get_feedcontainer()->feeds_size();

	for (const auto& idx : indexes) {
		reload(idx, size, unattended);
	}

	const auto unread_feeds2 =
		ctrl->get_feedcontainer()->unread_feed_count();
	const auto unread_articles2 =
		ctrl->get_feedcontainer()->unread_item_count();
	bool notify_always = cfg->get_configvalue_as_bool("notify-always");
	if (notify_always || unread_feeds2 != unread_feeds ||
		unread_articles2 != unread_articles) {
		FmtStrFormatter fmt;
		fmt.register_fmt('f', std::to_string(unread_feeds2));
		fmt.register_fmt('n', std::to_string(unread_articles2));
		fmt.register_fmt('d',
			std::to_string(unread_articles2 - unread_articles));
		fmt.register_fmt(
			'D', std::to_string(unread_feeds2 - unread_feeds));
		notify(fmt.do_format(cfg->get_configvalue("notify-format")));
	}
	if (!unattended) {
		ctrl->get_view()->set_status("");
	}
}

void Reloader::reload_range(unsigned int start,
	unsigned int end,
	unsigned int size,
	bool unattended)
{
	std::vector<unsigned int> v;
	for (unsigned int i = start; i <= end; ++i) {
		v.push_back(i);
	}

	auto extract = [](std::string& s, const std::string& url) {
		size_t p = url.find("//");
		p = (p == std::string::npos) ? 0 : p + 2;
		std::string suff(url.substr(p));
		p = suff.find('/');
		s = suff.substr(0, p);
	};

	std::sort(v.begin(), v.end(), [&](unsigned int a, unsigned int b) {
		std::string domain1, domain2;
		extract(domain1, ctrl->get_feedcontainer()->feeds[a]->rssurl());
		extract(domain2, ctrl->get_feedcontainer()->feeds[b]->rssurl());
		std::reverse(domain1.begin(), domain1.end());
		std::reverse(domain2.begin(), domain2.end());
		return domain1 < domain2;
	});

	CurlHandle easyhandle;

	for (const auto& i : v) {
		LOG(Level::DEBUG,
			"Reloader::reload_range: reloading feed #%u",
			i);
		reload(i, size, unattended, &easyhandle);
	}
}

void Reloader::notify(const std::string& msg)
{
	if (cfg->get_configvalue_as_bool("notify-screen")) {
		LOG(Level::DEBUG, "reloader:notify: notifying screen");
		std::cout << "\033^" << msg << "\033\\";
		std::cout.flush();
	}
	if (cfg->get_configvalue_as_bool("notify-xterm")) {
		LOG(Level::DEBUG, "reloader:notify: notifying xterm");
		std::cout << "\033]2;" << msg << "\033\\";
		std::cout.flush();
	}
	if (cfg->get_configvalue_as_bool("notify-beep")) {
		LOG(Level::DEBUG, "reloader:notify: notifying beep");
		::beep();
	}
	if (cfg->get_configvalue("notify-program").length() > 0) {
		std::string prog = cfg->get_configvalue("notify-program");
		LOG(Level::DEBUG,
			"reloader:notify: notifying external program `%s'",
			prog);
		utils::run_command(prog, msg);
	}
}

} // namespace newsboat
<commit_msg>Don't replace_feed for query feeds during reload<commit_after>#include "reloader.h"

#include <algorithm>
#include <cinttypes>
#include <iostream>
#include <ncurses.h>
#include <thread>

#include "controller.h"
#include "curlhandle.h"
#include "dbexception.h"
#include "downloadthread.h"
#include "fmtstrformatter.h"
#include "reloadrangethread.h"
#include "reloadthread.h"
#include "rss/exception.h"
#include "rssfeed.h"
#include "rssparser.h"
#include "scopemeasure.h"
#include "utils.h"
#include "view.h"

namespace newsboat {

Reloader::Reloader(Controller* c, Cache* cc, ConfigContainer* cfg)
	: ctrl(c)
	, rsscache(cc)
	, cfg(cfg)
{
}

void Reloader::spawn_reloadthread()
{
	std::thread t{ReloadThread(ctrl, cfg)};
	t.detach();
}

void Reloader::start_reload_all_thread(std::vector<int>* indexes)
{
	LOG(Level::INFO, "starting reload all thread");
	std::thread t(DownloadThread(*this, indexes));
	t.detach();
}

bool Reloader::trylock_reload_mutex()
{
	if (reload_mutex.try_lock()) {
		LOG(Level::DEBUG, "Reloader::trylock_reload_mutex succeeded");
		return true;
	}
	LOG(Level::DEBUG, "Reloader::trylock_reload_mutex failed");
	return false;
}

void Reloader::reload(unsigned int pos,
	unsigned int max,
	bool unattended,
	CurlHandle* easyhandle)
{
	LOG(Level::DEBUG, "Reloader::reload: pos = %u max = %u", pos, max);
	if (pos < ctrl->get_feedcontainer()->feeds.size()) {
		std::shared_ptr<RssFeed> oldfeed =
			ctrl->get_feedcontainer()->feeds[pos];
		std::string errmsg;
		if (!unattended) {
			ctrl->get_view()->set_status(
				strprintf::fmt(_("%sLoading %s..."),
					prepare_message(pos + 1, max),
					utils::censor_url(oldfeed->rssurl())));
		}

		bool ignore_dl =
			(cfg->get_configvalue("ignore-mode") == "download");

		RssParser parser(oldfeed->rssurl(),
			rsscache,
			cfg,
			ignore_dl ? ctrl->get_ignores() : nullptr,
			ctrl->get_api());
		parser.set_easyhandle(easyhandle);
		LOG(Level::DEBUG, "Reloader::reload: created parser");
		try {
			oldfeed->set_status(DlStatus::DURING_DOWNLOAD);
			std::shared_ptr<RssFeed> newfeed = parser.parse();
			if (!newfeed->is_query_feed()) {
				ctrl->replace_feed(
					oldfeed, newfeed, pos, unattended);
			}
			if (newfeed->total_item_count() == 0) {
				LOG(Level::DEBUG,
					"Reloader::reload: feed is empty");
			}
			oldfeed->set_status(DlStatus::SUCCESS);
			ctrl->get_view()->set_status("");
		} catch (const DbException& e) {
			errmsg = strprintf::fmt(
					_("Error while retrieving %s: %s"),
					utils::censor_url(oldfeed->rssurl()),
					e.what());
		} catch (const std::string& emsg) {
			errmsg = strprintf::fmt(
					_("Error while retrieving %s: %s"),
					utils::censor_url(oldfeed->rssurl()),
					emsg);
		} catch (rsspp::Exception& e) {
			errmsg = strprintf::fmt(
					_("Error while retrieving %s: %s"),
					utils::censor_url(oldfeed->rssurl()),
					e.what());
		}
		if (errmsg != "") {
			oldfeed->set_status(DlStatus::DL_ERROR);
			ctrl->get_view()->set_status(errmsg);
			LOG(Level::USERERROR, "%s", errmsg);
		}
	} else {
		ctrl->get_view()->show_error(_("Error: invalid feed!"));
	}
}

std::string Reloader::prepare_message(unsigned int pos, unsigned int max)
{
	if (max > 0) {
		return strprintf::fmt("(%u/%u) ", pos, max);
	}
	return "";
}

void Reloader::reload_all(bool unattended)
{
	const auto unread_feeds =
		ctrl->get_feedcontainer()->unread_feed_count();
	const auto unread_articles =
		ctrl->get_feedcontainer()->unread_item_count();
	int num_threads = cfg->get_configvalue_as_int("reload-threads");
	time_t t1, t2, dt;

	ctrl->get_feedcontainer()->reset_feeds_status();
	const auto num_feeds = ctrl->get_feedcontainer()->feeds_size();

	// TODO: change to std::clamp in C++17
	const int min_threads = 1;
	const int max_threads = num_feeds;
	num_threads = std::max(min_threads, std::min(num_threads, max_threads));

	t1 = time(nullptr);

	LOG(Level::DEBUG, "Reloader::reload_all: starting with reload all...");
	if (num_threads == 1) {
		reload_range(0, num_feeds - 1, num_feeds, unattended);
	} else {
		std::vector<std::pair<unsigned int, unsigned int>> partitions =
				utils::partition_indexes(0, num_feeds - 1, num_threads);
		std::vector<std::thread> threads;
		LOG(Level::DEBUG,
			"Reloader::reload_all: starting reload threads...");
		for (int i = 0; i < num_threads - 1; i++) {
			threads.push_back(std::thread(ReloadRangeThread(*this,
						partitions[i].first,
						partitions[i].second,
						num_feeds,
						unattended)));
		}
		LOG(Level::DEBUG,
			"Reloader::reload_all: starting my own reload...");
		reload_range(partitions[num_threads - 1].first,
			partitions[num_threads - 1].second,
			num_feeds,
			unattended);
		LOG(Level::DEBUG,
			"Reloader::reload_all: joining other threads...");
		for (size_t i = 0; i < threads.size(); i++) {
			threads[i].join();
		}
	}

	// refresh query feeds (update and sort)
	LOG(Level::DEBUG, "Reloader::reload_all: refresh query feeds");
	for (const auto& feed : ctrl->get_feedcontainer()->feeds) {
		ctrl->get_view()->prepare_query_feed(feed);
	}
	ctrl->get_view()->force_redraw();

	ctrl->get_feedcontainer()->sort_feeds(cfg->get_feed_sort_strategy());
	ctrl->update_feedlist();

	t2 = time(nullptr);
	dt = t2 - t1;
	// On GCC, `time_t` is `long int`, which is at least 32 bits. On x86_64,
	// it's 64 bits. Thus, this cast is either a no-op, or an up-cast which are
	// always safe.
	LOG(Level::INFO,
		"Reloader::reload_all: reload took %" PRId64 " seconds",
		static_cast<int64_t>(dt));

	const auto unread_feeds2 =
		ctrl->get_feedcontainer()->unread_feed_count();
	const auto unread_articles2 =
		ctrl->get_feedcontainer()->unread_item_count();
	bool notify_always = cfg->get_configvalue_as_bool("notify-always");
	if (notify_always || unread_feeds2 > unread_feeds ||
		unread_articles2 > unread_articles) {
		int article_count = unread_articles2 - unread_articles;
		int feed_count = unread_feeds2 - unread_feeds;

		LOG(Level::DEBUG, "unread article count: %d", article_count);
		LOG(Level::DEBUG, "unread feed count: %d", feed_count);

		FmtStrFormatter fmt;
		fmt.register_fmt('f', std::to_string(unread_feeds2));
		fmt.register_fmt('n', std::to_string(unread_articles2));
		fmt.register_fmt('d',
			std::to_string(article_count >= 0 ? article_count : 0));
		fmt.register_fmt(
			'D', std::to_string(feed_count >= 0 ? feed_count : 0));
		notify(fmt.do_format(cfg->get_configvalue("notify-format")));
	}
}

void Reloader::reload_indexes(const std::vector<int>& indexes, bool unattended)
{
	ScopeMeasure m1("Reloader::reload_indexes");
	const auto unread_feeds =
		ctrl->get_feedcontainer()->unread_feed_count();
	const auto unread_articles =
		ctrl->get_feedcontainer()->unread_item_count();
	const auto size = ctrl->get_feedcontainer()->feeds_size();

	for (const auto& idx : indexes) {
		reload(idx, size, unattended);
	}

	const auto unread_feeds2 =
		ctrl->get_feedcontainer()->unread_feed_count();
	const auto unread_articles2 =
		ctrl->get_feedcontainer()->unread_item_count();
	bool notify_always = cfg->get_configvalue_as_bool("notify-always");
	if (notify_always || unread_feeds2 != unread_feeds ||
		unread_articles2 != unread_articles) {
		FmtStrFormatter fmt;
		fmt.register_fmt('f', std::to_string(unread_feeds2));
		fmt.register_fmt('n', std::to_string(unread_articles2));
		fmt.register_fmt('d',
			std::to_string(unread_articles2 - unread_articles));
		fmt.register_fmt(
			'D', std::to_string(unread_feeds2 - unread_feeds));
		notify(fmt.do_format(cfg->get_configvalue("notify-format")));
	}
	if (!unattended) {
		ctrl->get_view()->set_status("");
	}
}

void Reloader::reload_range(unsigned int start,
	unsigned int end,
	unsigned int size,
	bool unattended)
{
	std::vector<unsigned int> v;
	for (unsigned int i = start; i <= end; ++i) {
		v.push_back(i);
	}

	auto extract = [](std::string& s, const std::string& url) {
		size_t p = url.find("//");
		p = (p == std::string::npos) ? 0 : p + 2;
		std::string suff(url.substr(p));
		p = suff.find('/');
		s = suff.substr(0, p);
	};

	std::sort(v.begin(), v.end(), [&](unsigned int a, unsigned int b) {
		std::string domain1, domain2;
		extract(domain1, ctrl->get_feedcontainer()->feeds[a]->rssurl());
		extract(domain2, ctrl->get_feedcontainer()->feeds[b]->rssurl());
		std::reverse(domain1.begin(), domain1.end());
		std::reverse(domain2.begin(), domain2.end());
		return domain1 < domain2;
	});

	CurlHandle easyhandle;

	for (const auto& i : v) {
		LOG(Level::DEBUG,
			"Reloader::reload_range: reloading feed #%u",
			i);
		reload(i, size, unattended, &easyhandle);
	}
}

void Reloader::notify(const std::string& msg)
{
	if (cfg->get_configvalue_as_bool("notify-screen")) {
		LOG(Level::DEBUG, "reloader:notify: notifying screen");
		std::cout << "\033^" << msg << "\033\\";
		std::cout.flush();
	}
	if (cfg->get_configvalue_as_bool("notify-xterm")) {
		LOG(Level::DEBUG, "reloader:notify: notifying xterm");
		std::cout << "\033]2;" << msg << "\033\\";
		std::cout.flush();
	}
	if (cfg->get_configvalue_as_bool("notify-beep")) {
		LOG(Level::DEBUG, "reloader:notify: notifying beep");
		::beep();
	}
	if (cfg->get_configvalue("notify-program").length() > 0) {
		std::string prog = cfg->get_configvalue("notify-program");
		LOG(Level::DEBUG,
			"reloader:notify: notifying external program `%s'",
			prog);
		utils::run_command(prog, msg);
	}
}

} // namespace newsboat
<|endoftext|>