text:
#define BOOST_TEST_DYN_LINK
#include <canard/net/ofp/v10/message/flow_delete.hpp>
#include <boost/test/unit_test.hpp>

#include "../../test_utility.hpp"
#include "../fixture.hpp"

namespace ofp = canard::net::ofp;
namespace v10 = ofp::v10;
namespace msg = v10::messages;
namespace act = v10::actions;
namespace protocol = v10::protocol;

namespace {
struct parameters : match_fixture, action_fixture {
  v10::match match{
    in_port, eth_src, vlan_vid, eth_type, ip_proto, ipv4_dst, tcp_src
  };
  std::uint16_t priority = 0x4321;
  std::uint16_t out_port = 0x1234;
  std::uint32_t xid = 0x12345678;
};
struct flow_delete_fixture : parameters {
  msg::flow_delete sut{match, out_port, xid};
  std::vector<unsigned char> bin
    = "\x01\x0e\x00\x48\x12\x34\x56\x78"
      "\x00\x31\x3f\x88\x00\x01\x01\x02""\x03\x04\x05\x06\x00\x00\x00\x00"
      "\x00\x00\x01\x23\x00\x00\x08\x00""\x00\x07\x00\x00\x00\x00\x00\x00"
      "\xc0\xa8\x01\x00\x18\x23\x00\x00"
      "\x00\x00\x00\x00\x00\x00\x00\x00""\x00\x03\x00\x00\x00\x00\x00\x00"
      "\x00\x00\x00\x00\x12\x34\x00\x00"
      ""_bin;
};
struct flow_delete_strict_fixture : parameters {
  msg::flow_delete_strict sut{match, priority, out_port, xid};
  std::vector<unsigned char> bin
    = "\x01\x0e\x00\x48\x12\x34\x56\x78"
      "\x00\x31\x3f\x88\x00\x01\x01\x02""\x03\x04\x05\x06\x00\x00\x00\x00"
      "\x00\x00\x01\x23\x00\x00\x08\x00""\x00\x07\x00\x00\x00\x00\x00\x00"
      "\xc0\xa8\x01\x00\x18\x23\x00\x00"
      "\x00\x00\x00\x00\x00\x00\x00\x00""\x00\x04\x00\x00\x00\x00\x43\x21"
      "\x00\x00\x00\x00\x12\x34\x00\x00"
      ""_bin;
};
}

BOOST_AUTO_TEST_SUITE(message_test)

BOOST_AUTO_TEST_SUITE(flow_delete)

  BOOST_AUTO_TEST_SUITE(constructor)
    BOOST_FIXTURE_TEST_CASE(is_constructible_from_match, parameters)
    {
      msg::flow_delete sut{match};

      BOOST_TEST(sut.length() == sizeof(protocol::ofp_flow_mod));
      BOOST_TEST((sut.match() == match));
      BOOST_TEST(sut.out_port() == protocol::OFPP_NONE);
    }
    BOOST_FIXTURE_TEST_CASE(
        is_constructible_from_match_and_out_port, parameters)
    {
      msg::flow_delete sut{match, out_port};

      BOOST_TEST(sut.length() == sizeof(protocol::ofp_flow_mod));
      BOOST_TEST((sut.match() == match));
      BOOST_TEST(sut.out_port() == out_port);
    }
    BOOST_FIXTURE_TEST_CASE(
        is_constructible_from_match_and_out_port_and_xid, parameters)
    {
      msg::flow_delete sut{match, out_port, xid};

      BOOST_TEST(sut.length() == sizeof(protocol::ofp_flow_mod));
      BOOST_TEST(sut.xid() == xid);
      BOOST_TEST((sut.match() == match));
      BOOST_TEST(sut.out_port() == out_port);
    }
    BOOST_FIXTURE_TEST_CASE(
        is_copy_constructible_from_non_const_lvalue, flow_delete_fixture)
    {
      auto const copy = sut;

      BOOST_TEST((copy == sut));
    }
    BOOST_FIXTURE_TEST_CASE(
        is_copy_constructible_from_const_lvalue, flow_delete_fixture)
    {
      auto const& const_flow_delete = sut;

      auto const copy = const_flow_delete;

      BOOST_TEST((copy == sut));
    }
    BOOST_FIXTURE_TEST_CASE(is_move_constructible, flow_delete_fixture)
    {
      auto moved = sut;

      auto const copy = std::move(moved);

      BOOST_TEST((copy == sut));
      BOOST_TEST(moved.length() == sizeof(protocol::ofp_flow_mod));
      BOOST_TEST((moved.actions() == v10::action_list{}));
    }
  BOOST_AUTO_TEST_SUITE_END() // constructor

  BOOST_FIXTURE_TEST_SUITE(encode, flow_delete_fixture)
    BOOST_AUTO_TEST_CASE(generates_binary)
    {
      auto buf = std::vector<unsigned char>{};

      sut.encode(buf);

      BOOST_TEST(buf.size() == sut.length());
      BOOST_TEST(buf == bin, boost::test_tools::per_element{});
    }
  BOOST_AUTO_TEST_SUITE_END() // encode

  BOOST_FIXTURE_TEST_SUITE(decode, flow_delete_fixture)
    BOOST_AUTO_TEST_CASE(constructs_flow_delete_from_binary)
    {
      auto it = bin.begin();

      auto const flow_delete = msg::flow_delete::decode(it, bin.end());

      BOOST_TEST((it == bin.end()));
      BOOST_TEST((flow_delete == sut));
    }
  BOOST_AUTO_TEST_SUITE_END() // decode

BOOST_AUTO_TEST_SUITE_END() // flow_delete

BOOST_AUTO_TEST_SUITE(flow_delete_strict)

  BOOST_AUTO_TEST_SUITE(constructor)
    BOOST_FIXTURE_TEST_CASE(
        is_constructible_from_match_and_priority, parameters)
    {
      msg::flow_delete_strict sut{match, priority};

      BOOST_TEST(sut.length() == sizeof(protocol::ofp_flow_mod));
      BOOST_TEST((sut.match() == match));
      BOOST_TEST(sut.priority() == priority);
      BOOST_TEST(sut.out_port() == protocol::OFPP_NONE);
    }
    BOOST_FIXTURE_TEST_CASE(
        is_constructible_from_match_and_priority_and_out_port, parameters)
    {
      msg::flow_delete_strict sut{match, priority, out_port};

      BOOST_TEST(sut.length() == sizeof(protocol::ofp_flow_mod));
      BOOST_TEST((sut.match() == match));
      BOOST_TEST(sut.priority() == priority);
      BOOST_TEST(sut.out_port() == out_port);
    }
    BOOST_FIXTURE_TEST_CASE(
          is_constructible_from_match_and_priority_and_out_port_and_xid
        , parameters)
    {
      msg::flow_delete_strict sut{match, priority, out_port, xid};

      BOOST_TEST(sut.length() == sizeof(protocol::ofp_flow_mod));
      BOOST_TEST(sut.xid() == xid);
      BOOST_TEST((sut.match() == match));
      BOOST_TEST(sut.priority() == priority);
      BOOST_TEST(sut.out_port() == out_port);
    }
    BOOST_FIXTURE_TEST_CASE(
        is_copy_constructible_from_non_const_lvalue, flow_delete_strict_fixture)
    {
      auto const copy = sut;

      BOOST_TEST((copy == sut));
    }
    BOOST_FIXTURE_TEST_CASE(
        is_copy_constructible_from_const_lvalue, flow_delete_strict_fixture)
    {
      auto const& const_flow_delete = sut;

      auto const copy = const_flow_delete;

      BOOST_TEST((copy == sut));
    }
    BOOST_FIXTURE_TEST_CASE(is_move_constructible, flow_delete_strict_fixture)
    {
      auto moved = sut;

      auto const copy = std::move(moved);

      BOOST_TEST((copy == sut));
      BOOST_TEST(moved.length() == sizeof(protocol::ofp_flow_mod));
      BOOST_TEST((moved.actions() == v10::action_list{}));
    }
  BOOST_AUTO_TEST_SUITE_END() // constructor

  BOOST_FIXTURE_TEST_SUITE(encode, flow_delete_strict_fixture)
    BOOST_AUTO_TEST_CASE(generates_binary)
    {
      auto buf = std::vector<unsigned char>{};

      sut.encode(buf);

      BOOST_TEST(buf.size() == sut.length());
      BOOST_TEST(buf == bin, boost::test_tools::per_element{});
    }
  BOOST_AUTO_TEST_SUITE_END() // encode

  BOOST_FIXTURE_TEST_SUITE(decode, flow_delete_strict_fixture)
    BOOST_AUTO_TEST_CASE(constructs_flow_delete_from_binary)
    {
      auto it = bin.begin();

      auto const flow_delete_strict
        = msg::flow_delete_strict::decode(it, bin.end());

      BOOST_TEST((it == bin.end()));
      BOOST_TEST((flow_delete_strict == sut));
    }
    BOOST_AUTO_TEST_CASE(constructs_flow_delete_with_actions_from_binary)
    {
      bin.insert(bin.end(), output_bin.begin(), output_bin.end());
      bin[3] += output_bin.size();
      auto it = bin.begin();

      auto const flow_delete_strict
        = msg::flow_delete_strict::decode(it, bin.end());

      BOOST_TEST((it == bin.end()));
      BOOST_TEST((flow_delete_strict.actions() == v10::action_list{output}));
    }
  BOOST_AUTO_TEST_SUITE_END() // decode

BOOST_AUTO_TEST_SUITE_END() // flow_delete_strict

BOOST_AUTO_TEST_SUITE_END() // message_test


text:
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>

#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/program_options.hpp>
#include <boost/regex.hpp>
#include <boost/algorithm/string/regex.hpp>

#include "s2s/dynet/dict.h"
#include "s2s/corpus/comp.hpp"
#include "s2s/corpus/utils.hpp"

#ifndef INCLUDE_GUARD_S2S_DICT_SET_HPP
#define INCLUDE_GUARD_S2S_DICT_SET_HPP

namespace s2s {

class dict_set_token {

public:

    dynet::Dict d_word;
    dynet::Dict d_char;
    std::vector<dynet::Dict> d_feat;

    unsigned int start_id_word;
    unsigned int end_id_word;
    unsigned int unk_id_word;
    unsigned int pad_id_word;

    unsigned int start_id_char;
    unsigned int end_id_char;
    unsigned int unk_id_char;
    unsigned int pad_id_char;

    std::vector<unsigned int> start_id_feat;
    std::vector<unsigned int> end_id_feat;
    std::vector<unsigned int> unk_id_feat;
    std::vector<unsigned int> pad_id_feat;

    std::vector<unsigned int> word_freq;
    std::vector<unsigned int> char_freq;
    std::vector<std::vector<unsigned int>> feat_freq;

    void init(const unsigned int feature_size){ // opts.enc_feature_vocab_size.size()
        /* resize vectors */
        d_feat.resize(feature_size);
        start_id_feat.resize(feature_size);
        end_id_feat.resize(feature_size);
        unk_id_feat.resize(feature_size);
        pad_id_feat.resize(feature_size);
    }

    /* set start and end of sentence id */
    void set_id(const s2s_options &opts){
        // word
        start_id_word = d_word.convert(opts.start_symbol);
        end_id_word = d_word.convert(opts.end_symbol);
        pad_id_word = d_word.convert(opts.pad_symbol);
        // char
        start_id_char = d_char.convert(opts.start_symbol);
        end_id_char = d_char.convert(opts.end_symbol);
        pad_id_char = d_char.convert(opts.pad_symbol);
        // feat
        for(unsigned int feat_id = 0; feat_id < d_feat.size(); feat_id++){
            start_id_feat[feat_id] = d_feat[feat_id].convert(opts.start_symbol);
            end_id_feat[feat_id] = d_feat[feat_id].convert(opts.end_symbol);
            pad_id_feat[feat_id] = d_feat[feat_id].convert(opts.pad_symbol);
        }
    }

    void set_unk_id(const s2s_options &opts){
        unk_id_word = d_word.convert(opts.unk_symbol);
        unk_id_char = d_char.convert(opts.unk_symbol);
        for(unsigned int feat_id = 0; feat_id < d_feat.size(); feat_id++){
            unk_id_feat[feat_id] = d_feat[feat_id].convert(opts.unk_symbol);
        }
    }

    std::string fname_d_word(const s2s_options &opts, std::string file_prefix){
        std::string file_name = file_prefix + "word.txt";
        return file_name;
    }

    std::string fname_d_char(const s2s_options &opts, std::string file_prefix){
        std::string file_name = file_prefix + "char.txt";
        return file_name;
    }

    std::string fname_d_feat(const s2s_options &opts, const unsigned int feat_id, std::string file_prefix){
        std::string file_name = file_prefix + "feat_" + std::to_string(feat_id) + ".txt";
        return file_name;
    }

    void load(const s2s_options &opts, std::string file_prefix){
        {
            std::string file_name = fname_d_word(opts, file_prefix);
            std::cerr << "Loading word dictionary from " << file_name << "...\n";
            std::ifstream in(file_name);
            boost::archive::text_iarchive ia(in);
            ia >> d_word;
            in.close();
        }
        {
            std::string file_name = fname_d_char(opts, file_prefix);
            std::cerr << "Loading character dictionary from " << file_name << "...\n";
            std::ifstream in(file_name);
            boost::archive::text_iarchive ia(in);
            ia >> d_char;
            in.close();
        }
        for(unsigned int feat_id=0; feat_id < d_feat.size(); feat_id++){
            // std::string file_name = opts.rootdir + "/" + opts.dict_prefix + "src_" + std::to_string(i) + ".txt";
            std::string file_name = fname_d_feat(opts, feat_id, file_prefix);
            std::cerr << "Loading feature dictionary from " << file_name << "...\n";
            std::ifstream in(file_name);
            boost::archive::text_iarchive ia(in);
            ia >> d_feat[feat_id];
            in.close();
        }
        set_id(opts);
        set_unk_id(opts);
    }

    void save(const s2s_options &opts, std::string file_prefix){
        {
            std::string file_name = fname_d_word(opts, file_prefix);
            std::cerr << "Saving word dictionary from " << file_name << "...\n";
            std::ofstream out(file_name);
            boost::archive::text_oarchive oa(out);
            oa << d_word;
            out.close();
        }
        {
            std::string file_name = fname_d_char(opts, file_prefix);
            std::cerr << "Saving character dictionary from " << file_name << "...\n";
            std::ofstream out(file_name);
            boost::archive::text_oarchive oa(out);
            oa << d_char;
            out.close();
        }
        for(unsigned int feat_id=0; feat_id < d_feat.size(); feat_id++){
            std::string file_name = fname_d_feat(opts, feat_id, file_prefix);
            std::cerr << "Saving feature dictionary to " << file_name << "...\n";
            std::ofstream out(file_name);
            boost::archive::text_oarchive oa(out);
            oa << d_feat[feat_id];
            out.close();
        }
    }

    void freq_cut(const s2s_options &opts, const std::string file_path, const int word_vocab_size, const int char_vocab_size, const std::vector<int>& feature_vocab_size){
        std::ifstream in(file_path);
        assert(in);
        set_id(opts);
        std::vector<std::map<std::string, unsigned int> > vec_str_freq;
        std::map<std::string, unsigned int>  str_char_freq;
        std::string line;
        // count frequencies
        while(getline(in, line)) {
            std::vector<std::string>  tokens;
            boost::algorithm::split_regex(tokens, line, boost::regex(" "));
            for(const std::string token : tokens){
                std::vector<std::string> col;
                boost::algorithm::split_regex(col, token, boost::regex("-\\|-"));
                assert(col.size() == d_feat.size() + 1);
                if(col.size() != vec_str_freq.size()){
                    vec_str_freq.resize(col.size());
                }
                for(unsigned int col_id = 0; col_id < col.size(); col_id++){
                    vec_str_freq[col_id][col.at(col_id)]++;
                }
                std::vector<std::string> chars = split_to_char(col.at(0));
                for(auto elem : chars){
                    str_char_freq[elem]++;
                }
            }
        }
        in.close();
        // cutting words and features
        for(unsigned int col_id = 0; col_id < d_feat.size() + 1; col_id++){
            std::vector<std::pair<std::string, unsigned int> > str_vec;
            for(auto& p1: vec_str_freq.at(col_id)){
                str_vec.push_back(std::pair<std::string, unsigned int>(p1.first, p1.second));
            }
            CompareString comp;
            sort(str_vec.begin(), str_vec.end(), comp);
            if(col_id > 0){
                for(auto& p1 : str_vec){
                    if(feature_vocab_size.at(col_id-1) >= 0 && d_feat[col_id-1].size() + 1 >= (unsigned int)(feature_vocab_size.at(col_id-1))){ // -1 for <UNK>
                        break;
                    }
                    d_feat[col_id-1].convert(p1.first);
                }
            }else{
                for(auto& p1 : str_vec){
                    if(word_vocab_size >= 0 && d_word.size() + 1 >= (unsigned int)(word_vocab_size)){ // -1 for <UNK>
                        break;
                    }
                    d_word.convert(p1.first);
                }
            }
        }
        // cutting chars
        {
            std::vector<std::pair<std::string, unsigned int> > str_vec;
            for(auto& p1: str_char_freq){
                str_vec.push_back(std::pair<std::string, unsigned int>(p1.first, p1.second));
            }
            CompareString comp;
            sort(str_vec.begin(), str_vec.end(), comp);
            for(auto& p1 : str_vec){
                if(char_vocab_size >= 0 && d_char.size() + 1 >= (unsigned int)(char_vocab_size)){ // -1 for <UNK>
                    break;
                }
                d_char.convert(p1.first);
            }
        }
        // fix the vocabulary sizes
        d_word.freeze();
        d_word.set_unk(opts.unk_symbol);
        d_char.freeze();
        d_char.set_unk(opts.unk_symbol);
        for(unsigned int feat_id = 0; feat_id < d_feat.size(); feat_id++){
            d_feat[feat_id].freeze(); // no new word types allowed
            d_feat[feat_id].set_unk(opts.unk_symbol);
        }
        set_unk_id(opts);
        // set freq
        word_freq.resize(d_word.size());
        for(auto& p1: vec_str_freq.at(0)){
            word_freq[d_word.convert(p1.first)] = p1.second;
        }
        char_freq.resize(d_char.size());
        for(auto& p1: str_char_freq){
            char_freq[d_char.convert(p1.first)] = p1.second;
        }
        feat_freq.resize(d_feat.size());
        for(unsigned int feat_id = 0; feat_id < d_feat.size(); feat_id++){
            feat_freq[feat_id].resize(d_feat.at(feat_id).size());
            for(auto& p1: vec_str_freq.at(feat_id + 1)){
                feat_freq[feat_id][d_feat[feat_id].convert(p1.first)] = p1.second;
            }
        }
    }
};

class dict_set_label {

public:

    dynet::Dict d_word;

    unsigned int start_id_word;
    unsigned int keep_id_word;
    unsigned int delete_id_word;
    unsigned int end_id_word;

    /* set start and end of sentence id */
    void set_id(const s2s_options &opts){
        // word
        start_id_word = d_word.convert(opts.start_symbol);
        keep_id_word = d_word.convert(opts.keep_symbol);
        delete_id_word = d_word.convert(opts.delete_symbol);
        end_id_word = d_word.convert(opts.end_symbol);
        d_word.freeze();
    }

};

};
#endif

ext: hpp

max_stars_repo_name: kamigaito/SLAHAN

max_issues_repo_name: kamigaito/SLAHAN

max_forks_repo_name: kamigaito/SLAHAN


text:
/*
Copyright (c) 2020 Naomasa Matsubayashi

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

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

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <iostream>
#include <string>
#include <exception>
#include <boost/program_options.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/at_c.hpp>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
extern "C" {
#include <mpool/mpool.h>
}
#include "common.h"

int main( int argc, char* argv[] ) {
  boost::program_options::options_description options("options");
  bool delete_log = false;
  options.add_options()
    ("help,h",    "display this message")
    ("pool,p", boost::program_options::value<std::string>(),  "pool name")
    ("message,m", boost::program_options::value< std::vector< std::string > >()->multitoken(), "message" )
    ("compact,c", boost::program_options::value< std::vector< std::string > >()->multitoken(), "compact" )
    ("object,o", boost::program_options::value<std::string>(),  "object id")
    ("delete,d", boost::program_options::bool_switch( &delete_log ),  "delete");
  boost::program_options::variables_map params;
  boost::program_options::store( boost::program_options::parse_command_line( argc, argv, options ), params );
  boost::program_options::notify( params );
  if( params.count("help") ) {
    std::cout << options << std::endl;
    return 0;
  }
  if( !params.count( "pool" ) ) {
    std::cerr << "pool is required." << std::endl;
    std::cerr << options << std::endl;
    return 1;
  }
  mpool *raw_pool = nullptr;
  SAFE_CALL( mpool_open( params[ "pool" ].as< std::string >().c_str(), O_RDWR|O_EXCL, &raw_pool, nullptr ) );
  std::shared_ptr< mpool > pool( raw_pool, []( mpool *p ) { if( p ) mpool_close( p ); } );
  uint64_t log1 = 0;
  uint64_t log2 = 0;
  if( !params.count( "object" ) ) {
    mdc_capacity cap;
    memset( reinterpret_cast< void* >( &cap ), 0, sizeof( cap ) );
    cap.mdt_captgt = 4 * 1024 * 1024;
    SAFE_CALL( mpool_mdc_alloc( pool.get(), &log1, &log2, MP_MED_CAPACITY, &cap, nullptr ) );
    std::cout << "object id: " << log1 << ":" << log2 << std::endl;
    SAFE_CALL( mpool_mdc_commit( pool.get(), log1, log2 ) )
  }
  else {
    auto v = params[ "object" ].as< std::string >();
    boost::fusion::vector< uint64_t, uint64_t > parsed;
    namespace qi = boost::spirit::qi;
    if( !qi::parse( v.begin(), v.end(), qi::ulong_long >> ':' >> qi::ulong_long, parsed ) ) {
      std::cerr << "invalid object id" << std::endl;
      return 1;
    }
    log1 = boost::fusion::at_c< 0 >( parsed );
    log2 = boost::fusion::at_c< 1 >( parsed );
  }
  mpool_mdc *raw_log = nullptr;
  SAFE_CALL( mpool_mdc_open( pool.get(), log1, log2, 0, &raw_log ) );
  std::shared_ptr< mpool_mdc > log( raw_log, [pool]( mpool_mdc *p ) { if( p ) mpool_mdc_close( p ); } );
  if( params.count( "message" ) )
    for( const auto &a: params[ "message" ].as< std::vector< std::string > >() )
      SAFE_CALL( mpool_mdc_append( log.get(), const_cast< void* >( static_cast< const void* >( a.data() ) ), a.size(), 1 ) )
  if( params.count( "compact" ) ) {
    auto v = params[ "compact" ].as< std::vector< std::string > >();
    std::sort( v.begin(), v.end() );
    std::vector< std::vector< char > > bufs;
    SAFE_CALL( mpool_mdc_rewind( log.get() ) )
    while( 1 ) {
      std::vector< char > buf( 4096, 0 );
      size_t size = 0;
      auto e = mpool_mdc_read( log.get(), buf.data(), buf.size() - 1, &size );
      if( mpool_errno( e ) == EOVERFLOW && size > buf.size() ) {
        buf.resize( size + 1, 0 );
        SAFE_CALL( mpool_mdc_read( log.get(), buf.data(), buf.size() - 1, &size ) );
      }
      else SAFE_CALL( e )
      if( !size ) break;
      if( std::binary_search( v.begin(), v.end(), std::string( buf.data() ) ) ) {
        buf.resize( size );
        bufs.emplace_back( std::move( buf ) );
      }
    }
    SAFE_CALL( mpool_mdc_cstart( log.get() ) )
    for( const auto &buf: bufs ) {
      SAFE_CALL( mpool_mdc_append( log.get(), const_cast< void* >( static_cast< const void* >( buf.data() ) ), buf.size(), 0 ) )
    }
    SAFE_CALL( mpool_mdc_cend( log.get() ) )
  }
  SAFE_CALL( mpool_mdc_rewind( log.get() ) )
  while( 1 ) {
    std::vector< char > buf( 4096, 0 );
    size_t size = 0;
    auto e = mpool_mdc_read( log.get(), buf.data(), buf.size() - 1, &size );
    if( mpool_errno( e ) == EOVERFLOW && size > buf.size() ) {
      buf.resize( size + 1, 0 );
      SAFE_CALL( mpool_mdc_read( log.get(), buf.data(), buf.size() - 1, &size ) );
    }
    else SAFE_CALL( e )
    if( !size ) break;
    std::cout << "data: " << buf.data() << std::endl;
  }
  if( delete_log ) {
    log.reset();
    SAFE_CALL( mpool_mdc_destroy( pool.get(), log1, log2 ) )
  }
}

ext: cpp


text:
//==================================================================================================
/*!
  @file

  @copyright 2016 NumScale SAS
  @copyright 2016 J.T. Lapreste

  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
//==================================================================================================
#ifndef BOOST_SIMD_FUNCTION_COMPARE_LE_HPP_INCLUDED
#define BOOST_SIMD_FUNCTION_COMPARE_LE_HPP_INCLUDED

#if defined(DOXYGEN_ONLY)
namespace boost { namespace simd
{

 /*!

    @ingroup group-reduction
    Function object implementing compare_le capabilities

    Returns a logical scalar that is the result of the lexicographic
    test for <= on all elements of the entries

    It is probably not what you wish. Have a look to @ref is_less_equal

    This is a convenient alias of @ref compare_less_equal
  **/
  const boost::dispatch::functor<tag::compare_le_> compare_le = {};
} }
#endif

#include <boost/simd/function/scalar/compare_less_equal.hpp>
#include <boost/simd/function/simd/compare_le.hpp>

#endif


text: #include <boost/typeof/std/iostream.hpp>

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
#include "gil_io.h"

#include <iostream>

#include <boost/gil.hpp>
#include <boost/gil/extension/io/bmp.hpp>
#include <boost/gil/extension/io/jpeg.hpp>
#include <boost/gil/extension/io/png.hpp>
#include <boost/gil/extension/io/targa.hpp>
#include <boost/gil/extension/io/tiff.hpp>

namespace gil  = boost::gil;

bool read_image (const std::string& file, monster_image_t& image, ext_type type)
{
  try {
    switch (type) {
    case type_png:  { gil::read_image(file, image, gil::png_tag{});  break;}
    case type_jpeg: { gil::read_image(file, image, gil::jpeg_tag{}); break;}
    case type_tiff: { gil::read_image(file, image, gil::tiff_tag{}); break;}
    case type_targa:{ gil::read_image(file, image, gil::targa_tag{});break;}
    case type_bmp:  { gil::read_image(file, image, gil::bmp_tag{});  break;}
    case type_unsupported: assert(false); break;
    }
  }
  catch (...) {
    std::cout << "gil: error: " << file << ":GIL I/O error thrown while reading image.\n";
    return false;
  }
  return true;
}
bool write_image(const std::string& file, monster_image_t& image, ext_type type)
{

  try {
    switch (type) {
    case type_png:  { gil::write_view(file, gil::const_view(image), gil::png_tag{});  break;}
    case type_jpeg: { gil::write_view(file, gil::const_view(image), gil::jpeg_tag{}); break;}
    case type_tiff: { gil::write_view(file, gil::const_view(image), gil::tiff_tag{}); break;}
    case type_targa:{ gil::write_view(file, gil::const_view(image), gil::targa_tag{});break;}
    case type_bmp:  { gil::write_view(file, gil::const_view(image), gil::bmp_tag{});  break;}
    case type_unsupported: assert(false); break;
    }
  }
  catch (...) {
    std::cout << "gil: error: " << file << ": GIL I/O error thrown while writing output image.\n";
    return false;
  }

  return true;
}

ext: cc

max_stars_repo_name: stanzabird/gil

max_issues_repo_name: stanzabird/gil

max_forks_repo_name: stanzabird/gil


text:
/*
Copyright 2020 Glen Joseph Fernandes
(glenjofe@gmail.com)

Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/core/allocator_access.hpp>
#include <boost/core/lightweight_test.hpp>

template<class T>
struct A1 {
    typedef T value_type;
    A1(int n)
        : value(n) { }
    int value;
};

#if !defined(BOOST_NO_CXX11_ALLOCATOR)
template<class T>
struct A2 {
    typedef T value_type;
    A2(int n)
        : value(n) { }
    A2 select_on_container_copy_construction() const {
        return A2(value + 1);
    }
    int value;
};
#endif

int main()
{
    BOOST_TEST_EQ(1, boost::
        allocator_select_on_container_copy_construction(A1<int>(1)).value);
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
    BOOST_TEST_EQ(2, boost::
        allocator_select_on_container_copy_construction(A2<int>(1)).value);
#endif
    return boost::report_errors();
}


text: #include <boost/units/systems/si/codata/electromagnetic_constants.hpp>


text:
// Boost Graph library

//  Copyright Douglas Gregor 2004. Use, modification and
//  distribution is subject to the Boost Software License, Version
//  1.0. (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

#include <boost/core/lightweight_test.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/adjacency_matrix.hpp>
#include <boost/graph/filtered_graph.hpp>
#include <boost/graph/subgraph.hpp>
#include <string>
#include <vector>
#include <boost/graph/adjacency_list_io.hpp>
#include <sstream>
#include <boost/graph/iteration_macros.hpp>
#include <algorithm>
#include <iterator>

using namespace std;
using namespace boost;

struct City
{
    City() {}
    City(const std::string& name, int pop, int zipcode)
    : name(name), population(pop)
    {
        zipcodes.push_back(zipcode);
    }

    string name;
    int population;
    vector< int > zipcodes;
};

std::ostream& operator<<(std::ostream& out, const City& city)
{
    out << city.name << ' ' << city.population << ' ';
    copy(city.zipcodes.begin(), city.zipcodes.end(),
        ostream_iterator< int >(out, " "));
    out << -1;
    return out;
}

std::istream& operator>>(std::istream& in, City& city)
{
    if (in >> city.name >> city.population)
    {
        int zip;
        city.zipcodes.clear();
        while (in >> zip && zip != -1)
            city.zipcodes.push_back(zip);
    }
    return in;
}

bool operator==(const City& c1, const City& c2)
{
    return (c1.name == c2.name && c1.population == c2.population
        && c1.zipcodes == c2.zipcodes);
}

struct Highway
{
    Highway() {}
    Highway(const string& name, double miles, int speed_limit = 65,
        int lanes = 4, bool divided = true)
    : name(name)
    , miles(miles)
    , speed_limit(speed_limit)
    , lanes(lanes)
    , divided(divided)
    {
    }

    string name;
    double miles;
    int speed_limit;
    int lanes;
    bool divided;
};

std::ostream& operator<<(std::ostream& out, const Highway& highway)
{
    return out << highway.name << ' ' << highway.miles << ' ' << highway.miles
               << ' ' << highway.speed_limit << ' ' << highway.lanes << ' '
               << highway.divided;
}

std::istream& operator>>(std::istream& in, Highway& highway)
{
    return in >> highway.name >> highway.miles >> highway.miles
        >> highway.speed_limit >> highway.lanes >> highway.divided;
}

bool operator==(const Highway& h1, const Highway& h2)
{
    return (h1.name == h2.name && h1.miles == h2.miles
        && h1.speed_limit == h2.speed_limit && h1.lanes == h2.lanes
        && h1.divided == h2.divided);
}

template < bool > struct truth
{
};

template < typename Map, typename VertexIterator, typename Bundle >
typename boost::graph_traits< Map >::vertex_descriptor do_add_vertex(
    Map& map, VertexIterator, const Bundle& bundle, truth< true >)
{
    return add_vertex(bundle, map);
}

template < typename Map, typename VertexIterator, typename Bundle >
typename boost::graph_traits< Map >::vertex_descriptor do_add_vertex(
    Map& map, VertexIterator& vi, const Bundle& bundle, truth< false >)
{
    get(boost::vertex_bundle, map)[*vi] = bundle;
    return *vi++;
}

template < class EL, class VL, class D, class VP, class EP, class GP >
void test_io(adjacency_list< EL, VL, D, VP, EP, GP >& map, int)
{
    typedef adjacency_list< EL, VL, D, VP, EP, GP > Map;

    ostringstream out;
    cout << write(map);
    out << write(map);

    istringstream in(out.str());
    adjacency_list< EL, VL, D, VP, EP, GP > map2;
    in >> read(map2);
    typename graph_traits<
        adjacency_list< EL, VL, D, VP, EP, GP > >::vertex_iterator v2
        = vertices(map2).first;
    BGL_FORALL_VERTICES_T(v, map, Map)
    {
        BOOST_TEST(map[v] == map2[*v2]);
        typename graph_traits<
            adjacency_list< EL, VL, D, VP, EP, GP > >::out_edge_iterator e2
            = out_edges(*v2, map2).first;
        BGL_FORALL_OUTEDGES_T(v, e, map, Map)
        {
            BOOST_TEST(map[e] == map[*e2]);
            ++e2;
        }
        ++v2;
    }
}

template < typename Map > void test_io(const Map&, long)
{
    // Nothing to test
}

template < typename Map, bool CanAddVertex >
void test_bundled_properties(Map*, truth< CanAddVertex > can_add_vertex)
{
    typedef
        typename boost::graph_traits< Map >::vertex_iterator vertex_iterator;
    typedef typename boost::graph_traits< Map >::vertex_descriptor
        vertex_descriptor;
    typedef
        typename boost::graph_traits< Map >::edge_descriptor edge_descriptor;

    Map map(CanAddVertex ? 2 : 3);

    vertex_iterator vi = vertices(map).first;
    vertex_descriptor v = *vi;
    map[v].name = "Troy";
    map[v].population = 49170;
    map[v].zipcodes.push_back(12180);

    ++vi;
    vertex_descriptor u = *vi++;
    map[u].name = "Albany";
    map[u].population = 95658;
    map[u].zipcodes.push_back(12201);

    // Try adding a vertex with a property value
    vertex_descriptor bloomington = do_add_vertex(
        map, vi, City("Bloomington", 39000, 47401), can_add_vertex);
    BOOST_TEST(
        get(boost::vertex_bundle, map)[bloomington].zipcodes[0] == 47401);

    edge_descriptor e = add_edge(v, u, map).first;
    map[e].name = "I-87";
    map[e].miles = 10;
    map[e].speed_limit = 65;
    map[e].lanes = 4;
    map[e].divided = true;

    edge_descriptor our_trip
        = add_edge(v, bloomington, Highway("Long", 1000), map).first;
    BOOST_TEST(get(boost::edge_bundle, map, our_trip).miles == 1000);

    BOOST_TEST(get(get(&City::name, map), v) == "Troy");
    BOOST_TEST(get(get(&Highway::name, map), e) == "I-87");
    BOOST_TEST(get(&City::name, map, u) == "Albany");
    BOOST_TEST(get(&Highway::name, map, e) == "I-87");
    put(&City::population, map, v, 49168);
    BOOST_TEST(get(&City::population, map)[v] == 49168);

    boost::filtered_graph< Map, boost::keep_all > fmap(map, boost::keep_all());
    BOOST_TEST(get(boost::edge_bundle, map, our_trip).miles == 1000);

    BOOST_TEST(get(get(&City::name, fmap), v) == "Troy");
    BOOST_TEST(get(get(&Highway::name, fmap), e) == "I-87");
    BOOST_TEST(get(&City::name, fmap, u) == "Albany");
    BOOST_TEST(get(&Highway::name, fmap, e) == "I-87");
    put(&City::population, fmap, v, 49169);
    BOOST_TEST(get(&City::population, fmap)[v] == 49169);

    test_io(map, 0);
}

void test_subgraph_bundled_properties()
{
    typedef boost::subgraph<
        boost::adjacency_list< boost::vecS, boost::vecS, boost::bidirectionalS,
            City, boost::property< boost::edge_index_t, int, Highway > > >
        SubMap;
    typedef boost::graph_traits< SubMap >::vertex_descriptor Vertex;
    typedef boost::graph_traits< SubMap >::vertex_iterator vertex_iterator;

    SubMap map(3);
    vertex_iterator vi = vertices(map).first;
    Vertex troy = *vi++;
    map[troy].name = "Troy";
    map[*vi++].name = "Bloomington";
    map[*vi++].name = "Endicott";

    SubMap& g1 = map.create_subgraph();
    Vertex troy1 = add_vertex(*vertices(map).first, g1);
    BOOST_TEST(map[troy1].name == g1[troy1].name);
}

int main(int, char*[])
{
    typedef boost::adjacency_list< boost::listS, boost::vecS,
        boost::bidirectionalS, City, Highway >
        Map1;
    typedef boost::adjacency_matrix< boost::directedS, City, Highway > Map2;

    test_bundled_properties(static_cast< Map1* >(0), truth< true >());
    test_bundled_properties(static_cast< Map2* >(0), truth< false >());
    test_subgraph_bundled_properties();
    return boost::report_errors();
}

max_issues_repo_name: qingkouwei/mediaones


text:
/*
 * test_export.cpp
 *
 *  Created on: 2013-4-29
 *      Author: fasiondog
 */

#include "doctest/doctest.h"
#include <hikyuu/config.h>

#include <fstream>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <hikyuu/StockManager.h>
#include <hikyuu/trade_manage/TradeManager.h>
#include <hikyuu/trade_manage/crt/crtTM.h>
#include <hikyuu/trade_manage/crt/TC_FixedA.h>

using namespace hku;

#if HKU_SUPPORT_SERIALIZATION

/**
 * @defgroup test_trade_manage_export test_trade_manage_export
 * @ingroup test_hikyuu_trade_manage_suite
 * @{
 */

/** @par 检测点 */
TEST_CASE("test_CostRecord_export") {
    string filename(StockManager::instance().tmpdir());
    filename += "/CostRecord.xml";

    CostRecord cost(10.1, 5.3, 1.0, 0.7, 17.1);
    {
        std::ofstream ofs(filename);
        boost::archive::xml_oarchive oa(ofs);
        oa << BOOST_SERIALIZATION_NVP(cost);
    }

    CostRecord cost2;
    {
        std::ifstream ifs(filename);
        boost::archive::xml_iarchive ia(ifs);
        ia >> BOOST_SERIALIZATION_NVP(cost2);
    }

    CHECK_EQ(cost, cost2);
    CHECK_EQ(cost.commission, doctest::Approx(cost2.commission).epsilon(0.00001));
    CHECK_EQ(cost.stamptax, doctest::Approx(cost2.stamptax).epsilon(0.00001));
    CHECK_EQ(cost.transferfee, doctest::Approx(cost2.transferfee).epsilon(0.00001));
    CHECK_EQ(cost.others, doctest::Approx(cost2.others).epsilon(0.00001));
    CHECK_EQ(cost.total, doctest::Approx(cost2.total).epsilon(0.00001));
}

/** @par 检测点 */
TEST_CASE("test_TradeRecord_export") {
    StockManager& sm = StockManager::instance();
    string filename(sm.tmpdir());
    filename += "/TradeRecord.xml";

    Stock stock = sm.getStock("sh600000");

    TradeRecord record1;
    record1.stock = stock;
    record1.datetime = Datetime(201305011935);
    record1.business = BUSINESS_BUY;
    record1.planPrice = 10.0;
    record1.realPrice = 10.13;
    record1.goalPrice = 20.15;
    record1.number = 1000;
    record1.stoploss = 9.77;
    record1.cash = 99998.1;
    record1.from = PART_SIGNAL;
    {
        std::ofstream ofs(filename);
        boost::archive::xml_oarchive oa(ofs);
        oa << BOOST_SERIALIZATION_NVP(record1);
    }

    TradeRecord record2;
    {
        std::ifstream ifs(filename);
        boost::archive::xml_iarchive ia(ifs);
        ia >> BOOST_SERIALIZATION_NVP(record2);
    }

    CHECK_EQ(record1, record2);
}

/** @par 检测点 */
TEST_CASE("test_PositionRecord_export") {
    StockManager& sm = StockManager::instance();
    string filename(sm.tmpdir());
    filename += "/PositionRecord.xml";

    Stock stock = sm.getStock("sh600000");

    PositionRecord record1;
    record1.stock = stock;
    record1.takeDatetime = Datetime(200101010000);
    record1.cleanDatetime = Datetime(200101210000);
    record1.number = 1000;
    record1.stoploss = 10.11;
    record1.goalPrice = 11.13;
    record1.totalNumber = 2000;
    record1.buyMoney = 22000;
    record1.totalCost = 23.1;
    record1.totalRisk = 9.77;
    record1.sellMoney = 9180.1;
    {
        std::ofstream ofs(filename);
        boost::archive::xml_oarchive oa(ofs);
        oa << BOOST_SERIALIZATION_NVP(record1);
    }

    PositionRecord record2;
    {
        std::ifstream ifs(filename);
        boost::archive::xml_iarchive ia(ifs);
        ia >> BOOST_SERIALIZATION_NVP(record2);
    }

    CHECK_EQ(record1, record2);
}

/** @par 检测点 */
TEST_CASE("test_TradeManager_export") {
    StockManager& sm = StockManager::instance();
    string filename(sm.tmpdir());
    filename += "/TradeManager.xml";

    Stock stock = sm.getStock("sh600000");
    TradeCostPtr costfunc = TC_FixedA(0.0018, 5, 0.001, 0.001, 1.0);

    TradeManagerPtr tm1 = crtTM(Datetime(199901010000), 100000, costfunc);
    tm1->buy(Datetime(199911170000), stock, 27.18, 100, 27.18, 27.18, 0);
    {
        std::ofstream ofs(filename);
        boost::archive::xml_oarchive oa(ofs);
        oa << BOOST_SERIALIZATION_NVP(tm1);
    }

    TradeManagerPtr tm2;
    {
        std::ifstream ifs(filename);
        boost::archive::xml_iarchive ia(ifs);
        ia >> BOOST_SERIALIZATION_NVP(tm2);
    }

    CHECK_EQ(tm1->name(), tm2->name());
    CHECK_EQ(tm1->initCash(), tm2->initCash());
    CHECK_EQ(tm1->initDatetime(), tm2->initDatetime());
    CHECK_EQ(tm1->firstDatetime(), tm2->firstDatetime());
    CHECK_EQ(tm1->lastDatetime(), tm2->lastDatetime());
    CHECK_EQ(tm1->precision(), tm2->precision());

    const TradeRecordList& trade_list_1 = tm1->getTradeList();
    const TradeRecordList& trade_list_2 = tm2->getTradeList();
    CHECK_EQ(trade_list_1.size(), trade_list_2.size());
    size_t total = trade_list_1.size();
    for (size_t i = 0; i < total; i++) {
        CHECK_EQ(trade_list_1[i], trade_list_2[i]);
    }

    PositionRecordList position1 = tm1->getPositionList();
    PositionRecordList position2 = tm2->getPositionList();
    CHECK_EQ(position1.size(), position2.size());
    total = position1.size();
    for (size_t i = 0; i < total; ++i) {
        CHECK_EQ(position1[i], position2[i]);
    }

    position1 = tm1->getHistoryPositionList();
    position2 = tm2->getHistoryPositionList();
    CHECK_EQ(position1.size(), position2.size());
    total = position1.size();
    for (size_t i = 0; i < total; ++i) {
        CHECK_EQ(position1[i], position2[i]);
    }
}

/** @par 检测点 */
TEST_CASE("test_FundsRecord_export") {
    string filename(StockManager::instance().tmpdir());
    filename += "/FundsRecord.xml";

    FundsRecord funds1;
    funds1.cash = 1.0;
    funds1.market_value = 2.0;
    funds1.short_market_value = 2.5;
    funds1.base_cash = 3.0;
    funds1.base_asset = 4.0;
    funds1.borrow_cash = 5.0;
    funds1.borrow_asset = 6.0;
    {
        std::ofstream ofs(filename);
        boost::archive::xml_oarchive oa(ofs);
        oa << BOOST_SERIALIZATION_NVP(funds1);
    }

    FundsRecord funds2;
    {
        std::ifstream ifs(filename);
        boost::archive::xml_iarchive ia(ifs);
        ia >> BOOST_SERIALIZATION_NVP(funds2);
    }

    CHECK_EQ(funds1, funds2);
}

/** @par 检测点 */
TEST_CASE("test_BorrowRecord_export") {
    StockManager& sm = StockManager::instance();
    string filename(sm.tmpdir());
    filename += "/BorrowRecord.xml";

    Stock stock = sm.getStock("sh000001");
    BorrowRecord bor1;
    bor1.stock = stock;
    bor1.number = 2000;
    bor1.value = 22000;
    {
        std::ofstream ofs(filename);
        boost::archive::xml_oarchive oa(ofs);
        oa << BOOST_SERIALIZATION_NVP(bor1);
    }

    BorrowRecord bor2;
    {
        std::ifstream ifs(filename);
        boost::archive::xml_iarchive ia(ifs);
        ia >> BOOST_SERIALIZATION_NVP(bor2);
    }

    CHECK_EQ(bor1.stock, bor2.stock);
    CHECK_EQ(bor1.number, bor2.number);
    CHECK_EQ(bor1.value, bor2.value);
}

/** @} */

#endif /* HKU_SUPPORT_SERIALIZATION */

max_stars_repo_name: kknet/hikyuu

max_issues_repo_name: kknet/hikyuu

max_forks_repo_name: kknet/hikyuu


text:
//==================================================================================================
/*!
  @file

  @copyright 2015 NumScale SAS

  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
//==================================================================================================
#ifndef BOOST_SIMD_ARCH_COMMON_SIMD_FUNCTION_ALIGNED_STORE_HPP_INCLUDED
#define BOOST_SIMD_ARCH_COMMON_SIMD_FUNCTION_ALIGNED_STORE_HPP_INCLUDED
#include <boost/simd/meta/hierarchy/simd.hpp>
#include <boost/simd/detail/overload.hpp>
#include <boost/dispatch/function/overload.hpp>
#include <boost/dispatch/adapted/common/pointer.hpp>
#include <boost/simd/function/store.hpp>
#include <boost/align/is_aligned.hpp>
#include <boost/config.hpp>
#include <tuple>

namespace boost { namespace simd { namespace ext
{
  namespace bd = ::boost::dispatch;
  namespace bs = ::boost::simd;

  //------------------------------------------------------------------------------------------------
  /// INTERNAL ONLY - SIMD aligned_store in simd emulation without offset
  BOOST_DISPATCH_OVERLOAD ( aligned_store_
                          , (typename A0, typename A1)
                          , bs::simd_
                          , bs::pack_<bd::unspecified_<A0>,bs::simd_emulation_>
                          , bd::pointer_<bd::scalar_<bd::unspecified_<A1>>,1u>
                          )
  {

    BOOST_FORCEINLINE void operator()(const A0& a0, A1  a1) const BOOST_NOEXCEPT
    {
      BOOST_ASSERT_MSG( boost::alignment::is_aligned(A0::alignment, a1)
                      , "boost::simd::aligned_load was performed on an unaligned pointer of integer"
                      );
      bs::store(a0, a1);
    }
  };

} } }

#endif


text:
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX Developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include "config/divi-config.h"
#endif

#include "init.h"

#include "amount.h"
#include "BlockFileOpener.h"
#include <chainparams.h>
#include "checkpoints.h"
#include "compat/sanity.h"
#include <defaultValues.h>
#include "key.h"
#include "main.h"
#include "obfuscation.h"
#include <WalletBackupFeatureContainer.h>
#include "miner.h"
#include "net.h"
#include "rpcserver.h"
#include "script/standard.h"
#include "spork.h"
#include "sporkdb.h"
#include "txdb.h"
#include "torcontrol.h"
#include "ui_interface.h"
#include "util.h"
#include "utilmoneystr.h"
#include "NotificationInterface.h"
#include "FeeAndPriorityCalculator.h"
#include <Settings.h>
#include <MasternodeModule.h>
#include <functional>
#include <uiMessenger.h>
#include <ActiveChainManager.h>
#include <BlockDiskAccessor.h>
#include <TransactionInputChecker.h>
#include <txmempool.h>

#ifdef ENABLE_WALLET
#include "db.h"
#include "wallet.h"
#include "walletdb.h"
#include <WalletTx.h>
#endif

#include <fstream>
#include <stdint.h>
#include <stdio.h>

#ifndef WIN32
#include <signal.h>
#endif

#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/filesystem.hpp>
#include <boost/interprocess/sync/file_lock.hpp>
#include <boost/thread.hpp>
#include <openssl/crypto.h>

#if ENABLE_ZMQ
#include "zmq/zmqnotificationinterface.h"
#endif

#include <ValidationState.h>
#include <verifyDb.h>

#ifdef ENABLE_WALLET
CWallet* pwalletMain = NULL;
constexpr int nWalletBackups = 20;

/**
 * Wallet Settings
 */
extern CAmount maxTxFee;
#endif
extern CCriticalSection cs_main;
extern Settings& settings;
extern bool fReindex;
extern bool fImporting;
extern bool fCheckBlockIndex;
extern int nScriptCheckThreads;
extern int nCoinCacheSize;
extern bool fTxIndex;
extern bool fVerifyingBlocks;
extern bool fLiteMode;
extern BlockMap mapBlockIndex;
extern CTxMemPool mempool;
extern Settings& settings;
extern NotificationInterfaceRegistry registry;
extern CBlockTreeDB* pblocktree;
extern CCoinsViewCache* pcoinsTip;
#if ENABLE_ZMQ
static CZMQNotificationInterface* pzmqNotificationInterface = NULL;
#endif

//! -paytxfee will warn if called with a higher fee than this amount (in satoshis) per KB
static const CAmount nHighTransactionFeeWarning = 0.1 * COIN;
//! -maxtxfee will warn if called with a higher fee than this amount (in satoshis)
static const CAmount nHighTransactionMaxFeeWarning = 100 * nHighTransactionFeeWarning;

constexpr char FEE_ESTIMATES_FILENAME[] = "fee_estimates.dat";
CClientUIInterface uiInterface;
extern bool fAddressIndex;

bool static InitError(const std::string& str)
{
    uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_ERROR);
    return false;
}

bool static InitWarning(const std::string& str)
{
    uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_WARNING);
    return true;
}

//////////////////////////////////////////////////////////////////////////////
//
// Shutdown
//

//
// Thread management and startup/shutdown:
//
// The network-processing threads are all part of a thread group
// created by AppInit() or the Qt main() function.
//
// A clean exit happens when StartShutdown() or the SIGTERM
// signal handler sets fRequestShutdown, which triggers
// the DetectShutdownThread(), which interrupts the main thread group.
// DetectShutdownThread() then exits, which causes AppInit() to
// continue (it .joins the shutdown thread).
// Shutdown() is then
// called to clean up database connections, and stop other
// threads that should only be stopped after the main network-processing
// threads have exited.
//
// Note that if running -daemon the parent process returns from InitializeDivi
// before adding any threads to the threadGroup, so .join_all() returns
// immediately and the parent exits from main().
//
// Shutdown for Qt is very similar, only it uses a QTimer to detect
// fRequestShutdown getting set, and then does the normal Qt
// shutdown thing.
//

volatile bool fRequestShutdown = false;
volatile bool fRestartRequested = false; // if true then restart, else shutdown
void MainStartShutdown()
{
    fRequestShutdown = true;
}
bool MainShutdownRequested()
{
    return fRequestShutdown || fRestartRequested;
}

class CCoinsViewErrorCatcher : public CCoinsViewBacked
{
public:
    CCoinsViewErrorCatcher(CCoinsView* view) : CCoinsViewBacked(view) {}
    bool GetCoins(const uint256& txid, CCoins& coins) const override
    {
        try {
            return CCoinsViewBacked::GetCoins(txid, coins);
        } catch (const std::runtime_error& e) {
            uiInterface.ThreadSafeMessageBox(translate("Error reading from database, shutting down."), "", CClientUIInterface::MSG_ERROR);
            LogPrintf("Error reading from database: %s\n", e.what());
            // Starting the shutdown sequence and returning false to the caller would be
            // interpreted as 'entry not found' (as opposed to unable to read data), and
            // could lead to invalid interpration. Just exit immediately, as we can't
            // continue anyway, and all writes should be atomic.
            abort();
        }
    }
    // Writes do not need similar protection, as failure to write is handled by the caller.
};

static CCoinsViewDB* pcoinsdbview = NULL;
static CCoinsViewErrorCatcher* pcoinscatcher = NULL;

#ifdef ENABLE_WALLET
inline void FlushWallet(bool shutdown = false) { if(pwalletMain) CDB::bitdb.Flush(shutdown);}
#endif
void FlushWalletAndStopMinting()
{
#ifdef ENABLE_WALLET
    FlushWallet();
    GenerateDivi(false, NULL, 0);
#endif
}

void LoadFeeEstimatesForMempool()
{
    boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
    CAutoFile est_filein(fopen(est_path.string().c_str(), "rb"), SER_DISK, CLIENT_VERSION);
    // Allowed to fail as this file IS missing on first startup.
    if (!est_filein.IsNull())
        mempool.ReadFeeEstimates(est_filein);
}

void SaveFeeEstimatesFromMempool()
{
    if (settings.GetArg("-savemempoolfees",false))
    {
        boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
        CAutoFile est_fileout(fopen(est_path.string().c_str(), "wb"), SER_DISK, CLIENT_VERSION);
        if (!est_fileout.IsNull())
            mempool.WriteFeeEstimates(est_fileout);
        else
            LogPrintf("%s: Failed to write fee estimates to %s\n", __func__, est_path.string());
    }
}

void DeallocateShallowDatabases()
{
    delete pcoinsTip;
    delete pcoinscatcher;
    delete pcoinsdbview;
    delete pblocktree;

    pcoinsTip = NULL;
    pcoinscatcher = NULL;
    pcoinsdbview = NULL;
    pblocktree = NULL;
    GetSporkManager().DeallocateDatabase();
}

void CleanAndReallocateShallowDatabases(const std::pair<std::size_t,std::size_t>& blockTreeAndCoinDBCacheSizes)
{
    DeallocateShallowDatabases();
    GetSporkManager().AllocateDatabase();
    pblocktree = new CBlockTreeDB(blockTreeAndCoinDBCacheSizes.first, false, fReindex);
    pcoinsdbview = new CCoinsViewDB(blockTreeAndCoinDBCacheSizes.second, false, fReindex);
    pcoinscatcher = new CCoinsViewErrorCatcher(pcoinsdbview);
    pcoinsTip = new CCoinsViewCache(pcoinscatcher);
}

void FlushStateAndDeallocateShallowDatabases()
{
    LOCK(cs_main);
    if (pcoinsTip != NULL) {
        FlushStateToDisk();
        //record that client took the proper shutdown procedure
        pblocktree->WriteFlag("shutdown", true);
    }
    DeallocateShallowDatabases();
}

/** Preparing steps before shutting down or restarting the wallet */
void PrepareShutdown()
{
    fRequestShutdown = true;  // Needed when we shutdown the wallet
    fRestartRequested = true; // Needed when we restart the wallet
    LogPrintf("%s: In progress...\n", __func__);
    static CCriticalSection cs_Shutdown;
    TRY_LOCK(cs_Shutdown, lockShutdown);
    if (!lockShutdown)
        return;

    /// Note: Shutdown() must be able to handle cases in which InitializeDivi() failed part of the way,
    /// for example if the data directory was found to be locked.
    /// Be sure that anything that writes files or flushes caches only does this if the respective
    /// module was initialized.
    RenameThread("divi-shutoff");
    mempool.AddTransactionsUpdated(1);
    StopRPCThreads();
    FlushWalletAndStopMinting();
    StopNode();
    InterruptTorControl();
    StopTorControl();
    SaveMasternodeDataToDisk();
    UnregisterNodeSignals(GetNodeSignals());
    SaveFeeEstimatesFromMempool();
    FlushStateAndDeallocateShallowDatabases();

#ifdef ENABLE_WALLET
    FlushWallet(true);
#endif
#if ENABLE_ZMQ
    if (pzmqNotificationInterface) {
        UnregisterValidationInterface(pzmqNotificationInterface);
        delete pzmqNotificationInterface;
        pzmqNotificationInterface = NULL;
    }
#endif
#ifndef WIN32
    boost::filesystem::remove(GetPidFile(settings));
#endif

    UnregisterAllValidationInterfaces();
}

/**
* Shutdown is split into 2 parts:
* Part 1: shut down everything but the main wallet instance (done in PrepareShutdown() )
* Part 2: delete wallet instance
*
* In case of a restart PrepareShutdown() was already called before, but this method here gets
* called implicitly when the parent object is deleted. In this case we have to skip the
* PrepareShutdown() part because it was already executed and just delete the wallet instance.
*/
void MainShutdown()
{
    // Shutdown part 1: prepare shutdown
    if (!fRestartRequested) {
        PrepareShutdown();
    }

// Shutdown part 2: delete wallet instance
#ifdef ENABLE_WALLET
    delete pwalletMain;
    pwalletMain = NULL;
#endif
    CleanupP2PConnections();
    LogPrintf("%s: done\n", __func__);
}

StartAndShutdownSignals::StartAndShutdownSignals(
    ): startShutdown()
    , shutdownRequested()
    , shutdown()
{
    startShutdown.connect(&MainStartShutdown);
    shutdownRequested.connect(&MainShutdownRequested);
    shutdown.connect(&MainShutdown);
}
static StartAndShutdownSignals startAndShutdownSignals;

void StartShutdown()
{
    startAndShutdownSignals.startShutdown();
}
bool ShutdownRequested()
{
    bool val = *startAndShutdownSignals.shutdownRequested();
    return val;
}
void Shutdown()
{
    startAndShutdownSignals.shutdown();
}

void UnitTestShutdown()
{
  exit(0);
}

void UnitTestStartShutdown()
{
  exit(0);
}

bool UnitTestShutdownRequested()
{
  return false;
}

void StartAndShutdownSignals::EnableUnitTestSignals()
{
    startAndShutdownSignals.shutdown.disconnect(&MainShutdown);
    startAndShutdownSignals.startShutdown.disconnect(&MainStartShutdown);
    startAndShutdownSignals.shutdownRequested.disconnect(&MainShutdownRequested);
    startAndShutdownSignals.shutdown.connect(&UnitTestShutdown);
    startAndShutdownSignals.startShutdown.connect(&UnitTestStartShutdown);
    startAndShutdownSignals.shutdownRequested.connect(&UnitTestShutdownRequested);
}

/**
 * Signal handlers are very limited in what they are allowed to do, so:
 */
void HandleSIGTERM(int)
{
    fRequestShutdown = true;
}

void HandleSIGHUP(int)
{
    fReopenDebugLog = true;
}

static void BlockNotifyCallback(const uint256& hashNewTip)
{
    std::string strCmd = settings.GetArg("-blocknotify", "");

    boost::replace_all(strCmd, "%s", hashNewTip.GetHex());
    boost::thread t(runCommand, strCmd); // thread runs free
}

struct CImportingNow {
    CImportingNow()
    {
        assert(fImporting == false);
        fImporting = true;
    }

    ~CImportingNow()
    {
        assert(fImporting == true);
        fImporting = false;
    }
};

void ThreadImport(std::vector<boost::filesystem::path> vImportFiles)
{
    RenameThread("divi-loadblk");

    // -reindex
    if (fReindex) {
        CImportingNow imp;
        int nFile = 0;
        while (true) {
            CDiskBlockPos pos(nFile, 0);
            if (!BlockFileExists(pos, "blk"))
                break; // No block files left to reindex
            FILE* file = OpenBlockFile(pos, true);
            if (!file)
                break; // This error is logged in OpenBlockFile
            LogPrintf("Reindexing block file blk%05u.dat...\n", (unsigned int)nFile);
            LoadExternalBlockFile(file, &pos);
            nFile++;
        }
        pblocktree->WriteReindexing(false);
        fReindex = false;
        LogPrintf("Reindexing finished\n");
        // To avoid ending up in a situation without genesis block, re-try initializing (no-op if reindexing worked):
        InitBlockIndex();
    }

    // hardcoded $DATADIR/bootstrap.dat
    boost::filesystem::path pathBootstrap = GetDataDir() / "bootstrap.dat";
    if (boost::filesystem::exists(pathBootstrap)) {
        FILE* file = fopen(pathBootstrap.string().c_str(), "rb");
        if (file) {
            CImportingNow imp;
            boost::filesystem::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old";
            LogPrintf("Importing bootstrap.dat...\n");
            LoadExternalBlockFile(file);
            RenameOver(pathBootstrap, pathBootstrapOld);
        } else {
            LogPrintf("Warning: Could not open bootstrap file %s\n", pathBootstrap.string());
        }
    }

    // -loadblock=
    BOOST_FOREACH (boost::filesystem::path& path, vImportFiles) {
        FILE* file = fopen(path.string().c_str(), "rb");
        if (file) {
            CImportingNow imp;
            LogPrintf("Importing blocks file %s...\n", path.string());
            LoadExternalBlockFile(file);
        } else {
            LogPrintf("Warning: Could not open blocks file %s\n", path.string());
        }
    }

    if (settings.GetBoolArg("-stopafterblockimport", false)) {
        LogPrintf("Stopping after block import\n");
        StartShutdown();
    }
}

/** Sanity checks
 *  Ensure that DIVI is running in a usable environment with all
 *  necessary library support.
 */
bool VerifyECCAndLibCCompatibilityAreAvailable(void)
{
    if (!ECC_InitSanityCheck()) {
        InitError("OpenSSL appears to lack support for elliptic curve cryptography. For more "
                  "information, visit https://en.bitcoin.it/wiki/OpenSSL_and_EC_Libraries");
        return false;
    }
    if (!glibc_sanity_test() || !glibcxx_sanity_test())
        return false;

    return true;
}

bool VerifyCriticalDependenciesAreAvailable()
{
    // ********************************************************* Step 4: sanity checks

    // Sanity check
    if (!VerifyECCAndLibCCompatibilityAreAvailable())
        return InitError(strprintf(translate("Initialization sanity check failed. %s is shutting down."), translate(PACKAGE_NAME)));

    // Probe the data directory lock to give an early error message, if possible
    return true;
}

bool EnableWalletFeatures()
{
    if (settings.GetBoolArg("-salvagewallet", false)) {
        // Rewrite just private keys: rescan to find transactions
        if (settings.SoftSetBoolArg("-rescan", true))
            LogPrintf("InitializeDivi : parameter interaction: -salvagewallet=1 -> setting -rescan=1\n");
    }

    // -zapwallettx implies a rescan
    if (settings.GetBoolArg("-zapwallettxes", false)) {
        if (settings.SoftSetBoolArg("-rescan", true))
            LogPrintf("InitializeDivi : parameter interaction: -zapwallettxes=<mode> -> setting -rescan=1\n");
    }

    return true;
}

bool CheckCriticalUnsupportedFeaturesAreNotUsed()
{
    // Check for -debugnet
    if (settings.GetBoolArg("-debugnet", false))
        InitWarning(translate("Warning: Unsupported argument -debugnet ignored, use -debug=net."));
    // Check for -socks - as this is a privacy risk to continue, exit here
    if (settings.ParameterIsSet("-socks"))
        return InitError(translate("Error: Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported."));
    // Check for -tor - as this is a privacy risk to continue, exit here
    if (settings.GetBoolArg("-tor", false))
        return InitError(translate("Error: Unsupported argument -tor found, use -onion."));
    // Check level must be 4 for zerocoin checks
    if (settings.ParameterIsSet("-checklevel"))
        return InitError(translate("Error: Unsupported argument -checklevel found. Checklevel must be level 4."));

    if (settings.GetBoolArg("-benchmark", false))
        InitWarning(translate("Warning: Unsupported argument -benchmark ignored, use -debug=bench."));

    return true;
}

void SetConsistencyChecks()
{
    // Checkmempool and checkblockindex default to true in regtest mode
    mempool.setSanityCheck(settings.GetBoolArg("-checkmempool", Params().DefaultConsistencyChecks()));
    fCheckBlockIndex = settings.GetBoolArg("-checkblockindex", Params().DefaultConsistencyChecks());
    CCheckpointServices::fEnabled = settings.GetBoolArg("-checkpoints", true);
}

void SetNumberOfThreadsToCheckScripts()
{
    // -par=0 means autodetect, but nScriptCheckThreads==0 means no concurrency
    nScriptCheckThreads = settings.GetArg("-par", DEFAULT_SCRIPTCHECK_THREADS);
    if (nScriptCheckThreads <= 0)
        nScriptCheckThreads += boost::thread::hardware_concurrency();
    if (nScriptCheckThreads <= 1)
        nScriptCheckThreads = 0;
    else if (nScriptCheckThreads > MAX_SCRIPTCHECK_THREADS)
        nScriptCheckThreads = MAX_SCRIPTCHECK_THREADS;
}

bool WalletIsDisabled()
{
#ifdef ENABLE_WALLET
    return settings.GetBoolArg("-disablewallet", false);
#else
    return true;
#endif
}

bool SetTransactionRequirements()
{
    // Fee-per-kilobyte amount considered the same as "free"
    // If you are mining, be careful setting this:
    // if you set it to zero then
    // a transaction spammer can cheaply fill blocks using
    // 1-satoshi-fee transactions. It should be set above the real
    // cost to you of processing a transaction.
    FeeAndPriorityCalculator& feeAndPriorityCalculator = FeeAndPriorityCalculator::instance();
    if (settings.ParameterIsSet("-minrelaytxfee")) {
        CAmount n = 0;
        if (ParseMoney(settings.GetParameter("-minrelaytxfee"), n) && n > 0)
            feeAndPriorityCalculator.setFeeRate(n);
        else
            return InitError(strprintf(translate("Invalid amount for -minrelaytxfee=<amount>: '%s'"), settings.GetParameter("-minrelaytxfee")));
    }
#ifdef ENABLE_WALLET
    if (settings.ParameterIsSet("-maxtxfee")) {
        CAmount nMaxFee = 0;
        if (!ParseMoney(settings.GetParameter("-maxtxfee"), nMaxFee))
            return InitError(strprintf(translate("Invalid amount for -maxtxfee=<amount>: '%s'"), settings.GetParameter("-maxtxfee")));
        if (nMaxFee > nHighTransactionMaxFeeWarning)
            InitWarning(translate("Warning: -maxtxfee is set very high! Fees this large could be paid on a single transaction."));
        maxTxFee = nMaxFee;
        const CFeeRate& currentFeeRate = feeAndPriorityCalculator.getFeeRateQuote();
        if (CFeeRate(maxTxFee, 1000) < currentFeeRate) {
            return InitError(strprintf(translate("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
                settings.GetParameter("-maxtxfee"), currentFeeRate.ToString()));
        }
    }
#endif
    return true;
}

bool TryLockDataDirectory(const std::string& datadir)
{
    // Make sure only a single DIVI process is using the data directory.
    boost::filesystem::path pathLockFile = GetDataDir() / ".lock";
    FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist.
    if (file) fclose(file);
    static boost::interprocess::file_lock lock(pathLockFile.string().c_str());

    // Wait maximum 10 seconds if an old wallet is still running. Avoids lockup during restart
    if (!lock.timed_lock(boost::get_system_time() + boost::posix_time::seconds(10)))
        return InitError(strprintf(translate("Cannot obtain a lock on data directory %s. DIVI Core is probably already running."), datadir));
    return true;
}

bool CheckWalletFileExists(std::string strDataDir)
{
    std::string strWalletFile = settings.GetArg("-wallet", "wallet.dat");
    // Wallet file must be a plain filename without a directory
    if (strWalletFile != boost::filesystem::basename(strWalletFile) + boost::filesystem::extension(strWalletFile))
        return InitError(strprintf(translate("Wallet %s resides outside data directory %s"), strWalletFile, strDataDir));

    return true;
}

void StartScriptVerificationThreads(boost::thread_group& threadGroup)
{
    if (nScriptCheckThreads) {
        for (int i = 0; i < nScriptCheckThreads - 1; i++)
            threadGroup.create_thread(&TransactionInputChecker::ThreadScriptCheck);
    }
}

#ifdef ENABLE_WALLET

void ClearFoldersForResync()
{
    uiInterface.InitMessage(translate("Preparing for resync..."));
    // Delete the local blockchain folders to force a resync from scratch to get a consitent blockchain-state
    boost::filesystem::path blocksDir = GetDataDir() / "blocks";
    boost::filesystem::path chainstateDir = GetDataDir() / "chainstate";
    boost::filesystem::path sporksDir = GetDataDir() / "sporks";

    LogPrintf("Deleting blockchain folders blocks, chainstate and sporks\n");
    // We delete in 4 individual steps in case one of the folder is missing already
    try {
        if (boost::filesystem::exists(blocksDir)){
            boost::filesystem::remove_all(blocksDir);
            LogPrintf("-resync: folder deleted: %s\n", blocksDir.string());
        }

        if (boost::filesystem::exists(chainstateDir)){
            boost::filesystem::remove_all(chainstateDir);
            LogPrintf("-resync: folder deleted: %s\n", chainstateDir.string());
        }

        if (boost::filesystem::exists(sporksDir)){
            boost::filesystem::remove_all(sporksDir);
            LogPrintf("-resync: folder deleted: %s\n", sporksDir.string());
        }

    } catch (boost::filesystem::filesystem_error& error) {
        LogPrintf("Failed to delete blockchain folders %s\n", error.what());
    }
}

#endif
bool BackupWallet(std::string strDataDir, bool fDisableWallet)
{
#ifdef ENABLE_WALLET
    std::string strWalletFile = settings.GetArg("-wallet", "wallet.dat");
    if (!fDisableWallet) {
        WalletBackupFeatureContainer walletBackupFeatureContainer(
            settings.GetArg("-createwalletbackups",nWalletBackups), strWalletFile, strDataDir);
        LogPrintf("backing up wallet\n");
        if(walletBackupFeatureContainer.GetWalletIntegrityVerifier().CheckWalletIntegrity(strDataDir, strWalletFile))
        {
            return walletBackupFeatureContainer.GetBackupCreator().BackupWallet() &&
                walletBackupFeatureContainer.GetMonthlyBackupCreator().BackupWallet();
        }
        else
        {
            LogPrintf("Error: Wallet integrity check failed.");
            return false;
        }
    }
#endif // ENABLE_WALLET
    return true;
}

void PruneHDSeedParameterInteraction()
{
    if (settings.ParameterIsSet("-hdseed") && IsHex(settings.GetArg("-hdseed", "not hex")) && (settings.ParameterIsSet("-mnemonic") || settings.ParameterIsSet("-mnemonicpassphrase"))) {
        settings.ForceRemoveArg("-mnemonic");
        settings.ForceRemoveArg("-mnemonicpassphrase");
        LogPrintf("%s: parameter interaction: can't use -hdseed and -mnemonic/-mnemonicpassphrase together, will prefer -seed\n", __func__);
    }
}

void PrintInitialLogHeader(bool fDisableWallet, int numberOfFileDescriptors, const std::string& dataDirectoryInUse)
{
    const int maximumNumberOfConnections = GetMaxConnections();
    LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
    LogPrintf("DIVI version %s (%s)\n", FormatFullVersion(), CLIENT_DATE);
    LogPrintf("Using OpenSSL version %s\n", SSLeay_version(SSLEAY_VERSION));
    if(!fDisableWallet) LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0));
    if (!fLogTimestamps) LogPrintf("Startup time: %s\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()));
    LogPrintf("Default data directory %s\n", GetDefaultDataDir().string());
    LogPrintf("Using data directory %s\n", dataDirectoryInUse);
    LogPrintf("Using config file %s\n", settings.GetConfigFile().string());
    LogPrintf("Using at most %i connections (%i file descriptors available)\n", maximumNumberOfConnections, numberOfFileDescriptors);
    LogPrintf("Using %u threads for script verification\n", nScriptCheckThreads);
}

bool SetSporkKey()
{
    CSporkManager& sporkManager = GetSporkManager();
    sporkManager.SetSporkAddress(Params().SporkKey());
    if (settings.ParameterIsSet("-sporkkey")) // spork priv key
    {
        if (!sporkManager.SetPrivKey(settings.GetArg("-sporkkey", "")))
            return InitError(translate("Unable to sign spork message, wrong key?"));
    }
    return true;
}

void WarmUpRPCAndStartRPCThreads()
{
    /* Start the RPC server already.  It will be started in "warmup" mode
     * and not really process calls already (but it will signify connections
     * that the server is there and will be ready later).  Warmup mode will
     * be disabled when initialisation is finished.
     */
    if (settings.GetBoolArg("-server", false)) {
        uiInterface.InitMessage.connect(SetRPCWarmupStatus);
        StartRPCThreads();
    }
}

void CreateHardlinksForBlocks()
{
    fReindex = settings.GetBoolArg("-reindex", false);
    // Upgrading to 0.8; hard-link the old blknnnn.dat files into /blocks/
    boost::filesystem::path blocksDir = GetDataDir() / "blocks";
    if (!boost::filesystem::exists(blocksDir)) {
        boost::filesystem::create_directories(blocksDir);
        bool linked = false;
        for (unsigned int i = 1; i < 10000; i++) {
            boost::filesystem::path source = GetDataDir() / strprintf("blk%04u.dat", i);
            if (!boost::filesystem::exists(source)) break;
            boost::filesystem::path dest = blocksDir / strprintf("blk%05u.dat", i - 1);
            try {
                boost::filesystem::create_hard_link(source, dest);
                LogPrintf("Hardlinked %s -> %s\n", source.string(), dest.string());
                linked = true;
            } catch (boost::filesystem::filesystem_error& e) {
                // Note: hardlink creation failing is not a disaster, it just means
                // blocks will get re-downloaded from peers.
                LogPrintf("Error hardlinking blk%04u.dat : %s\n", i, e.what());
                break;
            }
        }
        if (linked) {
            fReindex = true;
        }
    }
}

std::pair<size_t,size_t> CalculateDBCacheSizes()
{
    size_t nTotalCache = (settings.GetArg("-dbcache", DEFAULT_DB_CACHE_SIZE) << 20);
    size_t nBlockTreeDBCache = 0;
    size_t nCoinDBCache = 0;
    if (nTotalCache < (MIN_DB_CACHE_SIZE << 20))
        nTotalCache = (MIN_DB_CACHE_SIZE << 20); // total cache cannot be less than MIN_DB_CACHE_SIZE
    else if (nTotalCache > (MAX_DB_CACHE_SIZE << 20))
        nTotalCache = (MAX_DB_CACHE_SIZE << 20); // total cache cannot be greater than MAX_DB_CACHE_SIZE
    nBlockTreeDBCache = nTotalCache / 8;
    if (nBlockTreeDBCache > (1 << 21) && !settings.GetBoolArg("-txindex", true))
        nBlockTreeDBCache = (1 << 21); // block tree db cache shouldn't be larger than 2 MiB
    nTotalCache -= nBlockTreeDBCache;
    nCoinDBCache = nTotalCache / 2; // use half of the remaining cache for coindb cache
    nTotalCache -= nCoinDBCache;
    nCoinCacheSize = nTotalCache / 300; // coins in memory require around 300 bytes

    return std::make_pair(nBlockTreeDBCache,nCoinDBCache);
}

bool TryToLoadBlocks(bool& fLoaded, std::string& strLoadError)
{
    const bool skipLoadingDueToError = true;
    try {
        UnloadBlockIndex();
        std::pair<std::size_t, std::size_t> dbCacheSizes = CalculateDBCacheSizes();
        CleanAndReallocateShallowDatabases(dbCacheSizes);

        if (fReindex)
            pblocktree->WriteReindexing(true);

        // DIVI: load previous sessions sporks if we have them.
        uiInterface.InitMessage(translate("Loading sporks..."));
        GetSporkManager().LoadSporksFromDB();

        uiInterface.InitMessage(translate("Loading block index..."));
        std::string strBlockIndexError = "";
        if (!LoadBlockIndex(strBlockIndexError)) {
            strLoadError = translate("Error loading block database");
            strLoadError = strprintf("%s : %s", strLoadError, strBlockIndexError);
            return skipLoadingDueToError;
        }

        // If the loaded chain has a wrong genesis, bail out immediately
        // (we're likely using a testnet datadir, or the other way around).
        if (!mapBlockIndex.empty() && mapBlockIndex.count(Params().HashGenesisBlock()) == 0)
            return InitError(translate("Incorrect or no genesis block found. Wrong datadir for network?"));

        // Initialize the block index (no-op if non-empty database was already loaded)
        if (!InitBlockIndex()) {
            strLoadError = translate("Error initializing block database");
            return skipLoadingDueToError;
        }

        // Check for changed -txindex state
        if (fTxIndex != settings.GetBoolArg("-txindex", true)) {
            strLoadError = translate("You need to rebuild the database using -reindex to change -txindex");
            return skipLoadingDueToError;
        }

        uiInterface.InitMessage(translate("Verifying blocks..."));

        // Flag sent to validation code to let it know it can skip certain checks
        fVerifyingBlocks = true;

        {

            LOCK(cs_main);
            const BlockDiskDataReader blockDiskReader;
            ActiveChainManager chainManager(fAddressIndex,pblocktree,blockDiskReader);
            CVerifyDB dbVerifier(
                chainManager,
                chainActive,
                uiInterface,
                nCoinCacheSize,
                &ShutdownRequested);
            if (!dbVerifier.VerifyDB(pcoinsdbview,pcoinsTip, 4, settings.GetArg("-checkblocks", 100)))
            {
                strLoadError = translate("Corrupted block database detected");
                fVerifyingBlocks = false;
                return skipLoadingDueToError;
            }
        }
    } catch (std::exception& e) {
        if (fDebug) LogPrintf("%s\n", e.what());
        strLoadError = translate("Error opening block database");
        fVerifyingBlocks = false;
        return skipLoadingDueToError;
    }

    fVerifyingBlocks = false;
    fLoaded = true;

    return true;
}

bool CreateNewWalletIfOneIsNotAvailable(std::string strWalletFile, std::ostringstream& strErrors)
{
    bool fFirstRun = true;
    pwalletMain = new CWallet(strWalletFile, chainActive, mapBlockIndex);
    DBErrors nLoadWalletRet = pwalletMain->LoadWallet(fFirstRun);
    if (nLoadWalletRet != DB_LOAD_OK) {
        if (nLoadWalletRet == DB_CORRUPT)
            strErrors << translate("Error loading wallet.dat: Wallet corrupted") << "\n";
        else if (nLoadWalletRet == DB_NONCRITICAL_ERROR) {
            std::string msg(translate("Warning: error reading wallet.dat! All keys read correctly, but transaction data"
                            " or address book entries might be missing or incorrect."));
            InitWarning(msg);
        } else if (nLoadWalletRet == DB_TOO_NEW)
            strErrors << translate("Error loading wallet.dat: Wallet requires newer version of DIVI Core") << "\n";
        else if (nLoadWalletRet == DB_NEED_REWRITE) {
            strErrors << translate("Wallet needed to be rewritten: restart DIVI Core to complete") << "\n";
            LogPrintf("%s", strErrors.str());
            return InitError(strErrors.str());
        } else
            strErrors << translate("Error loading wallet.dat") << "\n";
    }

    if (settings.GetBoolArg("-upgradewallet", fFirstRun)) {
        int nMaxVersion = settings.GetArg("-upgradewallet", 0);
        if (nMaxVersion == 0) // the -upgradewallet without argument case
        {
            LogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
            nMaxVersion = CLIENT_VERSION;
            pwalletMain->SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately
        } else
            LogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
        if (nMaxVersion < pwalletMain->GetVersion())
            strErrors << translate("Cannot downgrade wallet") << "\n";
        pwalletMain->SetMaxVersion(nMaxVersion);
    }

    if (fFirstRun)
    {
        // Create new keyUser and set as default key
        if (settings.GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET) && !pwalletMain->IsHDEnabled()) {
            if (settings.GetArg("-mnemonicpassphrase", "").size() > 256) {
                InitError(translate("Mnemonic passphrase is too long, must be at most 256 characters"));
                return false;
            }
            // generate a new master key
            pwalletMain->GenerateNewHDChain();

            // ensure this wallet.dat can only be opened by clients supporting HD
            pwalletMain->SetMinVersion(FEATURE_HD);
        }

        CPubKey newDefaultKey;
        if (pwalletMain->GetKeyFromPool(newDefaultKey, false)) {
            pwalletMain->SetDefaultKey(newDefaultKey);
            if (!pwalletMain->SetAddressBook(pwalletMain->vchDefaultKey.GetID(), "", "receive")) {
                InitError(translate("Cannot write default address") += "\n");
                return false;
            }
        }

        pwalletMain->SetBestChain(chainActive.GetLocator());

    }
    else if (settings.ParameterIsSet("-usehd")) {
        bool useHD = settings.GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET);
        if (pwalletMain->IsHDEnabled() && !useHD) {
            InitError(strprintf(translate("Error loading %s: You can't disable HD on a already existing HD wallet"),
                                pwalletMain->strWalletFile));
            return false;
        }
        if (!pwalletMain->IsHDEnabled() && useHD) {
            InitError(strprintf(translate("Error loading %s: You can't enable HD on a already existing non-HD wallet"),
                                pwalletMain->strWalletFile));
            return false;
        }
    }

    // Warn user every time he starts non-encrypted HD wallet
    if (!settings.GetBoolArg("-allowunencryptedwallet", false) && settings.GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET) && !pwalletMain->IsLocked()) {
        InitWarning(translate("Make sure to encrypt your wallet and delete all non-encrypted backups after you verified that wallet works!"));
    }

    return true;
}

void ScanBlockchainForWalletUpdates(std::string strWalletFile,const std::vector<CWalletTx>& vWtx, int64_t& nStart)
{
    CBlockIndex* pindexRescan = chainActive.Tip();
    if (settings.GetBoolArg("-rescan", false))
        pindexRescan = chainActive.Genesis();
    else {
        CWalletDB walletdb(settings,strWalletFile);
        CBlockLocator locator;
        if (walletdb.ReadBestBlock(locator))
            pindexRescan = FindForkInGlobalIndex(chainActive, locator);
        else
            pindexRescan = chainActive.Genesis();
    }
    if (chainActive.Tip() && chainActive.Tip() != pindexRescan) {
        uiInterface.InitMessage(translate("Rescanning..."));
        LogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height() - pindexRescan->nHeight, pindexRescan->nHeight);
        nStart = GetTimeMillis();
        pwalletMain->ScanForWalletTransactions(pindexRescan, true);
        LogPrintf(" rescan      %15dms\n", GetTimeMillis() - nStart);
        pwalletMain->SetBestChain(chainActive.GetLocator());
        pwalletMain->IncrementDBUpdateCount();

        // Restore wallet transaction metadata after -zapwallettxes=1
        if (settings.GetBoolArg("-zapwallettxes", false) && settings.GetArg("-zapwallettxes", "1") != "2") {
            pwalletMain->UpdateTransactionMetadata(vWtx);
        }
    }
}

void LockUpMasternodeCollateral()
{
    if (pwalletMain) {
        LogPrintf("Locking Masternodes:\n");
        LOCK(pwalletMain->cs_wallet);

        CWallet& walletReference = *pwalletMain;
        LockUpMasternodeCollateral(
            settings,
            [&walletReference](const COutPoint& outpoint)
            {
                walletReference.LockCoin(outpoint);
            });
    }
}

bool ZapWalletTransactionsIfRequested(const std::string& strWalletFile, std::vector<CWalletTx>& vWtx)
{
    if (settings.GetBoolArg("-zapwallettxes", false))
    {
        uiInterface.InitMessage(translate("Zapping all transactions from wallet..."));

        pwalletMain = new CWallet(strWalletFile, chainActive, mapBlockIndex);
        DBErrors nZapWalletRet = pwalletMain->ZapWalletTx(vWtx);
        if (nZapWalletRet != DB_LOAD_OK) {
            uiInterface.InitMessage(translate("Error loading wallet.dat: Wallet corrupted"));
            return false;
        }

        delete pwalletMain;
        pwalletMain = NULL;
    }
    return true;
}

bool InitializeDivi(boost::thread_group& threadGroup)
{
// ********************************************************* Step 1: setup
#ifdef _MSC_VER
    // Turn off Microsoft heap dump noise
    _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
    _CrtSetReportFile(_CRT_WARN, CreateFileA("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
#endif
#if _MSC_VER >= 1400
    // Disable confusing "helpful" text message on abort, Ctrl-C
    _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
#endif
#ifdef WIN32
// Enable Data Execution Prevention (DEP)
// Minimum supported OS versions: WinXP SP3, WinVista >= SP1, Win Server 2008
// A failure is non-critical and needs no further attention!
#ifndef PROCESS_DEP_ENABLE
// We define this here, because GCCs winbase.h limits this to _WIN32_WINNT >= 0x0601 (Windows 7),
// which is not correct. Can be removed, when GCCs winbase.h is fixed!
#define PROCESS_DEP_ENABLE 0x00000001
#endif
    typedef BOOL(WINAPI * PSETPROCDEPPOL)(DWORD);
    PSETPROCDEPPOL setProcDEPPol = (PSETPROCDEPPOL)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "SetProcessDEPPolicy");
    if (setProcDEPPol != NULL) setProcDEPPol(PROCESS_DEP_ENABLE);

    // Initialize Windows Sockets
    WSADATA wsadata;
    int ret = WSAStartup(MAKEWORD(2, 2), &wsadata);
    if (ret != NO_ERROR || LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wVersion) != 2) {
        return InitError(strprintf("Error: Winsock library failed to start (WSAStartup returned error %d)", ret));
    }
#endif
#ifndef WIN32

    if (settings.GetBoolArg("-sysperms", false)) {
#ifdef ENABLE_WALLET
        if (!settings.GetBoolArg("-disablewallet", false))
            return InitError("Error: -sysperms is not allowed in combination with enabled wallet functionality");
#endif
    } else {
        umask(077);
    }

    // Clean shutdown on SIGTERM
    struct sigaction sa;
    sa.sa_handler = HandleSIGTERM;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sigaction(SIGTERM, &sa, NULL);
    sigaction(SIGINT, &sa, NULL);

    // Reopen debug.log on SIGHUP
    struct sigaction sa_hup;
    sa_hup.sa_handler = HandleSIGHUP;
    sigemptyset(&sa_hup.sa_mask);
    sa_hup.sa_flags = 0;
    sigaction(SIGHUP, &sa_hup, NULL);

#if defined(__SVR4) && defined(__sun)
    // ignore SIGPIPE on Solaris
    signal(SIGPIPE, SIG_IGN);
#endif
#endif

    // ********************************************************* Step 2: parameter interactions
    // Set this early so that parameter interactions go to console
    UIMessenger uiMessenger(uiInterface);
    SetLoggingAndDebugSettings();

    SetNetworkingParameters();

    if(!EnableWalletFeatures())
    {
        return false;
    }

    // Make sure enough file descriptors are available
    int numberOfFileDescriptors;
    if(!SetNumberOfFileDescriptors(uiMessenger,numberOfFileDescriptors))
    {
        return false;
    }

    // ********************************************************* Step 3: parameter-to-internal-flags

    if(!CheckCriticalUnsupportedFeaturesAreNotUsed())
    {
        return false;
    }
    SetConsistencyChecks();
    SetNumberOfThreadsToCheckScripts();

    // Staking needs a CWallet instance, so make sure wallet is enabled
    bool fDisableWallet = WalletIsDisabled();
    if (fDisableWallet) {
        if (settings.SoftSetBoolArg("-staking", false))
            LogPrintf("InitializeDivi : parameter interaction: wallet functionality not enabled -> setting -staking=0\n");
    }
    if(!SetTransactionRequirements())
    {
        return false;
    }

    if (settings.ParameterIsSet("-protocolversion")) {
        SetProtocolVersion(settings.GetArg("-protocolversion", PROTOCOL_VERSION));
    }

    // ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log
    // Sanity check
    if (!VerifyCriticalDependenciesAreAvailable())
        return InitError(translate("Initialization sanity check failed. DIVI Core is shutting down."));

    std::string strDataDir = GetDataDir().string();
    if(!TryLockDataDirectory(strDataDir))
    {
        return false;
    }
    if(!fDisableWallet && !CheckWalletFileExists(strDataDir))
    {
        return false;
    }

#ifndef WIN32
    CreatePidFile(GetPidFile(settings), getpid());
#endif
    PrintInitialLogHeader(fDisableWallet,numberOfFileDescriptors,strDataDir);
    StartScriptVerificationThreads(threadGroup);

    if(!SetSporkKey())
    {
        return false;
    }
    WarmUpRPCAndStartRPCThreads();

    int64_t nStart;

    // ********************************************************* Step 5: Backup wallet and verify wallet database integrity
    BackupWallet(strDataDir, fDisableWallet);
    if (settings.GetBoolArg("-resync", false))
    {
        ClearFoldersForResync();
    }
    // ********************************************************* Step 6: network initialization

    if(!InitializeP2PNetwork(uiMessenger))
    {
        return false;
    }

    PruneHDSeedParameterInteraction();

#if ENABLE_ZMQ
    pzmqNotificationInterface = CZMQNotificationInterface::CreateWithArguments(settings);

    if (pzmqNotificationInterface) {
        RegisterValidationInterface(pzmqNotificationInterface);
    }
#endif

    // ********************************************************* Step 7: load block chain
    CreateHardlinksForBlocks();
    bool fLoaded = false;
    while (!fLoaded) {
        bool fReset = fReindex;
        std::string strLoadError;

        uiInterface.InitMessage(translate("Loading block index..."));

        nStart = GetTimeMillis();
        if(!TryToLoadBlocks(fLoaded,strLoadError))
        {
            return false;
        }

        if (!fLoaded) {
            // first suggest a reindex
            if (!fReset) {
                bool fRet = uiInterface.ThreadSafeMessageBox(
                    strLoadError + ".\n\n" + translate("Do you want to rebuild the block database now?"),
                    "", CClientUIInterface::MSG_ERROR | CClientUIInterface::BTN_ABORT);
                if (fRet) {
                    fReindex = true;
                    fRequestShutdown = false;
                } else {
                    LogPrintf("Aborted block database rebuild. Exiting.\n");
                    return false;
                }
            } else {
                return InitError(strLoadError);
            }
        }
    }

    // As LoadBlockIndex can take several minutes, it's possible the user
    // requested to kill the GUI during the last operation. If so, exit.
    // As the program has not fully started yet, Shutdown() is possibly overkill.
    if (fRequestShutdown) {
        LogPrintf("Shutdown requested. Exiting.\n");
        return false;
    }
    LogPrintf(" block index %15dms\n", GetTimeMillis() - nStart);

    LoadFeeEstimatesForMempool();

// ********************************************************* Step 8: load wallet
    std::ostringstream strErrors;
#ifdef ENABLE_WALLET
    const std::string strWalletFile = settings.GetArg("-wallet", "wallet.dat");
    if (fDisableWallet) {
        pwalletMain = NULL;
        LogPrintf("Wallet disabled!\n");
    } else {
        // needed to restore wallet transaction meta data after -zapwallettxes
        std::vector<CWalletTx> vWtx;
        if(!ZapWalletTransactionsIfRequested(strWalletFile,vWtx))
        {
            return false;
        }

        uiInterface.InitMessage(translate("Loading wallet..."));
        fVerifyingBlocks = true;

        nStart = GetTimeMillis();
        if(!CreateNewWalletIfOneIsNotAvailable(strWalletFile,strErrors))
        {
            return false;
        }
        if(settings.GetBoolArg("-spendzeroconfchange", false))
        {
            // Off by default in wallet
            pwalletMain->toggleSpendingZeroConfirmationOutputs();
        }

        LogPrintf("%s", strErrors.str());
        LogPrintf(" wallet      %15dms\n", GetTimeMillis() - nStart);

        RegisterValidationInterface(pwalletMain);

        ScanBlockchainForWalletUpdates(strWalletFile,vWtx,nStart);
        fVerifyingBlocks = false;

    }  // (!fDisableWallet)
#else  // ENABLE_WALLET
    LogPrintf("No wallet compiled in!\n");
#endif // !ENABLE_WALLET
    // ********************************************************* Step 9: import blocks

    if (settings.ParameterIsSet("-blocknotify"))
        uiInterface.NotifyBlockTip.connect(BlockNotifyCallback);

    // scan for better chains in the block chain database, that are not yet connected in the active best chain
    CValidationState state;
    if (!ActivateBestChain(state))
        strErrors << "Failed to connect best block";

    std::vector<boost::filesystem::path> vImportFiles;
    if (settings.ParameterIsSet("-loadblock")) {
        BOOST_FOREACH (std::string strFile, settings.GetMultiParameter("-loadblock"))
            vImportFiles.push_back(strFile);
    }
    threadGroup.create_thread(boost::bind(&ThreadImport, vImportFiles));
    if (chainActive.Tip() == NULL) {
        LogPrintf("Waiting for genesis block to be imported...\n");
        while (!fRequestShutdown && chainActive.Tip() == NULL)
            MilliSleep(10);
    }

    // ********************************************************* Step 10: setup ObfuScation
    std::string errorMessage;
    if(!LoadMasternodeDataFromDisk(uiMessenger,GetDataDir().string()) )
    {
        return false;
    }
    if(!InitializeMasternodeIfRequested(settings,fTxIndex,errorMessage))
    {
        return InitError(errorMessage);
    }
    LockUpMasternodeCollateral();
    threadGroup.create_thread(boost::bind(&ThreadMasternodeBackgroundSync));
    LogPrintf("fLiteMode %d\n", fLiteMode);

    // ********************************************************* Step 11: start node

    if (!CheckDiskSpace())
        return false;

    if (!strErrors.str().empty())
        return InitError(strErrors.str());

    //// debug print
    LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size());
    LogPrintf("chainActive.Height() = %d\n", chainActive.Height());
#ifdef ENABLE_WALLET
    LogPrintf("setKeyPool.size() = %u\n", pwalletMain ? pwalletMain->GetKeyPoolSize() : 0);
    LogPrintf("mapAddressBook.size() = %u\n", pwalletMain ? pwalletMain->mapAddressBook.size() : 0);
#endif

    if (settings.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION))
        StartTorControl(threadGroup);

    StartNode(threadGroup,pwalletMain);

#ifdef ENABLE_WALLET
    // Generate coins in the background
    if (pwalletMain)
        GenerateDivi(settings.GetBoolArg("-gen", false), pwalletMain, settings.GetArg("-genproclimit", 1));
#endif

    // ********************************************************* Step 12: finished

    SetRPCWarmupFinished();
    uiInterface.InitMessage(translate("Done loading"));

#ifdef ENABLE_WALLET
    if (pwalletMain) {
        // Add wallet transactions that aren't already in a block to mapTransactions
        pwalletMain->ReacceptWalletTransactions();

        // Run a thread to flush wallet periodically
        if (settings.GetBoolArg("-flushwallet", true))
        {
            threadGroup.create_thread(boost::bind(&ThreadFlushWalletDB, boost::ref(pwalletMain->strWalletFile)));
        }
    }
#endif

    return !fRequestShutdown;
}


text:
// Copyright 2008 by BBN Technologies Corp.
// All Rights Reserved.

#include "Generic/common/leak_detection.h"

#include "Spanish/parse/es_LanguageSpecificFunctions.h"
#include <boost/algorithm/string.hpp>
#include "Spanish/parse/es_STags.h"

bool SpanishLanguageSpecificFunctions::isHyphen(Symbol sym) {
	return false;
}
bool SpanishLanguageSpecificFunctions::isBasicPunctuationOrConjunction(Symbol sym){
	return false;
}
bool SpanishLanguageSpecificFunctions::isNoCrossPunctuation(Symbol sym){
	return false;
}
bool SpanishLanguageSpecificFunctions::isSentenceEndingPunctuation(Symbol sym){
	return false;
}
bool SpanishLanguageSpecificFunctions::isNPtypeLabel(Symbol sym){
	return false;
}
bool SpanishLanguageSpecificFunctions::isPPLabel(Symbol sym){
	return false;
}
Symbol SpanishLanguageSpecificFunctions::getNPlabel(){
	return SpanishSTags::SN;
}
Symbol SpanishLanguageSpecificFunctions::getNameLabel(){
	// JD 2015-08-04 - JSerif/Metro parser do not reimplement the name constraints
	// changing the Spanish name label is a partial workaround
	return SpanishSTags::SN;
}
Symbol SpanishLanguageSpecificFunctions::getCoreNPlabel(){
	return SpanishSTags::NPA;
}
Symbol SpanishLanguageSpecificFunctions::getDateLabel(){
	return SpanishSTags::POS_W;
}
Symbol SpanishLanguageSpecificFunctions::getProperNounLabel(){
	return SpanishSTags::POS_NP;
}
bool SpanishLanguageSpecificFunctions::isCoreNPLabel(Symbol sym){
	return false;
}
bool SpanishLanguageSpecificFunctions::isPrimaryNamePOStag(Symbol sym, EntityType type){
	return false;
}
bool SpanishLanguageSpecificFunctions::isSecondaryNamePOStag(Symbol sym, EntityType type){
	return false;
}
Symbol SpanishLanguageSpecificFunctions::getDefaultNamePOStag(EntityType type){
	return SpanishSTags::POS_NP;
}
bool SpanishLanguageSpecificFunctions::isNPtypePOStag(Symbol sym){
	return false;
}
Symbol SpanishLanguageSpecificFunctions::getSymbolForParseNodeLeaf(Symbol sym){
	std::wstring str = sym.to_string();
	boost::to_lower(str);
	// If any parens made it this far, then quote them now.  This can
	// happen eg if our input tokenization contains URLs with URLs in
	// them.
	boost::replace_all(str, L"(", L"-LRB-");
	boost::replace_all(str, L")", L"-RRB-");
	return Symbol(str.c_str());
}
bool SpanishLanguageSpecificFunctions::matchesHeadToken(Mention *, CorrectMention *){
	return false;
}
bool SpanishLanguageSpecificFunctions::matchesHeadToken(const SynNode *, CorrectMention *){
	return false;
}

max_stars_repo_name: BBN-E/serif

max_issues_repo_name: BBN-E/serif

max_forks_repo_name: BBN-E/serif