<commit_before>// $Id$

#if !defined(__CINT__) || defined(__MAKECINT__)
#include "Riostream.h"
#include "AliCDBManager.h"
#include "AliCDBEntry.h"
#include "AliGRPObject.h"
#include "AliDAQ.h"
#endif

/**
 * @file EnableHLTInGRP.C
 * @author Artur Szostak <artursz@iafrica.com>
 * @ingroup alihlt_tutorial
 * @brief Patches GRP to process recorded data with HT in mode A.
 *
 * Usage:
 *

 *   aliroot -b -q 'EnableHLTInGRP.C(\<runNumber\>,\<grpPath\>)'
 *

 * Where \<runNumber\> is the number of the run the GRP corresponds to. This
 * can be found from the file name of the GRP entry of interest in the CDB.
 * \<grpPath\> is the path to the local GRP/GRP/Data directory where the GRP
 * entry to be modified is stored. Setting a value for \<grpPath\> is optional
 * and is the current working directory by default.
 *
 * Data recorded in mode A will not have the HT bit set in the GRP's active
 * detector mask. Trying to process such data with the HT framework will fail.
 * To be able to process such runs the GRP must be downloaded and patched with
 * this macro. It will set the HT bit in the GRP and write a new version of
 * the GRP with and incremented version number.
 *
 * @return true if the macro completed successfully and false otherwise.
 */
bool EnableHLTInGRP(Int_t runNumber, const char* grpPath = "local://./")
{
	AliCDBManager* cdb = AliCDBManager::Instance();
	cdb->SetDefaultStorage("local://$ALICE_ROOT/OCDB");
	cdb->SetSpecificStorage("GRP/GRP/Data", grpPath);
	cdb->SetRun(runNumber);
	AliCDBEntry* entry = (AliCDBEntry*)cdb->Get("GRP/GRP/Data")->Clone();
	if (entry == NULL)
	{
		cerr << "ERROR: Could not fetch the GRP entry for run " << runNumber << " and path " << grpPath << endl;
		return false;
	}
	AliGRPObject* grp = (AliGRPObject*)entry->GetObject();
	if (grp == NULL)
	{
		cerr << "ERROR: Could not fetch the GRP object for run " << runNumber << " and path " << grpPath << endl;
		return false;
	}
	grp->SetDetectorMask(grp->GetDetectorMask() | (0x1 << AliDAQ::kHLTId));
	entry->SetVersion(entry->GetId().GetVersion() + 1);
	cdb->Put(entry);
	return true;
}

/// Just print the usage if no parameters are given.
void EnableHLTInGRP()
{
	cout << "Usage: EnableHLTInGRP.C'(<runNumber> [, <grpPath>])'" << endl;
	cout << "Where <runNumber> is the number of the run the GRP corresponds to." << endl;
	cout << "This can be found from the file name of the GRP entry of interest in the CDB." << endl;
	cout << "<grpPath> is the path to the local GRP/GRP/Data directory where the GRP entry to be modified is stored." << endl;
	cout << "Setting a value for <grpPath> is optional and is the current working directory by default." << endl;
}
<commit_msg>provide OCDB URI as macro argument<commit_after>// $Id$

#if !defined(__CINT__) || defined(__MAKECINT__)
#include "Riostream.h"
#include "AliCDBManager.h"
#include "AliCDBEntry.h"
#include "AliGRPObject.h"
#include "AliDAQ.h"
#endif

/**
 * @file EnableHLTInGRP.C
 * @author Artur Szostak <artursz@iafrica.com>
 * @ingroup alihlt_tutorial
 * @brief Patches GRP to process recorded data with HT in mode A.
 *
 * Usage:
 *

 *   aliroot -b -q 'EnableHLTInGRP.C(\<runNumber\>,\<grpPath\>)'
 *

 * Where \<runNumber\> is the number of the run the GRP corresponds to. This
 * can be found from the file name of the GRP entry of interest in the CDB.
 * \<grpPath\> is the path to the local GRP/GRP/Data directory where the GRP
 * entry to be modified is stored. Setting a value for \<grpPath\> is optional
 * and is the current working directory by default.
 *
 * Data recorded in mode A will not have the HT bit set in the GRP's active
 * detector mask. Trying to process such data with the HT framework will fail.
 * To be able to process such runs the GRP must be downloaded and patched with
 * this macro. It will set the HT bit in the GRP and write a new version of
 * the GRP with and incremented version number.
 *
 * @return true if the macro completed successfully and false otherwise.
 */
bool EnableHLTInGRP(Int_t runNumber,
		    const char* cdbURI = "local://$ALICE_ROOT/OCDB",
		    const char* grpPath = "local://./")
{
	AliCDBManager* cdb = AliCDBManager::Instance();
	cdb->SetDefaultStorage(cdbURI);
	cdb->SetSpecificStorage("GRP/GRP/Data", grpPath);
	cdb->SetRun(runNumber);
	AliCDBEntry* entry = (AliCDBEntry*)cdb->Get("GRP/GRP/Data")->Clone();
	if (entry == NULL)
	{
		cerr << "ERROR: Could not fetch the GRP entry for run " << runNumber << " and path " << grpPath << endl;
		return false;
	}
	AliGRPObject* grp = (AliGRPObject*)entry->GetObject();
	if (grp == NULL)
	{
		cerr << "ERROR: Could not fetch the GRP object for run " << runNumber << " and path " << grpPath << endl;
		return false;
	}
	grp->SetDetectorMask(grp->GetDetectorMask() | (0x1 << AliDAQ::kHLTId));
	entry->SetVersion(entry->GetId().GetVersion() + 1);
	cdb->Put(entry);
	return true;
}

/// Just print the usage if no parameters are given.
void EnableHLTInGRP()
{
	cout << "Usage: EnableHLTInGRP.C'(<runNumber> [, <grpPath>])'" << endl;
	cout << "Where <runNumber> is the number of the run the GRP corresponds to." << endl;
	cout << "This can be found from the file name of the GRP entry of interest in the CDB." << endl;
	cout << "<grpPath> is the path to the local GRP/GRP/Data directory where the GRP entry to be modified is stored." << endl;
	cout << "Setting a value for <grpPath> is optional and is the current working directory by default." << endl;
}
<|endoftext|>


<commit_before>#include "catch.hpp"
#include <simdee/common/storage.hpp>

struct vec_t {
    using scalar_t = char;
    enum { width = 3 };

    void aligned_store(scalar_t* ptr) const {
        std::copy(data, data + width, ptr);
    }

    scalar_t data[width];
};

using storage_t = sd::impl::storage<vec_t, vec_t::scalar_t, alignof(vec_t)>;

TEST_CASE("storage data access") {
    SECTION("via operator[]") {
        storage_t s;
        s[0] = 'x'; s[1] = 'y'; s[2] = 'z';
        REQUIRE((s[0] == 'x' && s[1] == 'y' && s[2] == 'z'));
    }
    SECTION("via data()") {
        storage_t s;
        auto d = s.data();
        d[0] = 'u'; d[1] = 'v'; d[2] = 'w';
        REQUIRE((s[0] == 'u' && s[1] == 'v' && s[2] == 'w'));
    }
}

TEST_CASE("storage construction and assigment", "[storage]") {
    auto good = [](const storage_t& s) {
        return s[0] == 'a' && s[1] == 'b' && s[2] == 'c';
    };
    auto implicit_test = [&good](storage_t s) {
        return good(s);
    };

    SECTION("copy") {
        storage_t s;
        s[0] = 'a'; s[1] = 'b'; s[2] = 'c';
        REQUIRE(implicit_test(s));
        storage_t assigned_test;
        assigned_test = s;
        REQUIRE(good(assigned_test));
    }
    SECTION("from vec_t") {
        vec_t v = { { 'a', 'b', 'c' } };
        storage_t explicit_test(v);
        REQUIRE(good(explicit_test));
        storage_t assigned_test;
        assigned_test = v;
        REQUIRE(good(assigned_test));
    }
    SECTION("from init list") {
        REQUIRE(implicit_test({'a', 'b', 'c'}));
        storage_t assigned_test;
        assigned_test = { 'a', 'b', 'c' };
        REQUIRE(good(assigned_test));
    }
}

TEST_CASE("storage comparison", "[storage]") {
    storage_t s1 = { 'd', 'e', 'f' };
    storage_t s2 = { 'd', 'e', 'f' };
    storage_t s3 = { 'd', 'e', 'g' };
    storage_t s4 = { 'd', 'f', 'e' };

    REQUIRE(s1 == s1);
    REQUIRE(s1 == s2);
    REQUIRE(s1 != s3);
    REQUIRE(s1 != s4);
    REQUIRE(s2 == s2);
    REQUIRE(s2 != s3);
    REQUIRE(s2 != s4);
    REQUIRE(s3 == s3);
    REQUIRE(s3 != s4);
    REQUIRE(s4 == s4);

    REQUIRE(s1 <= s1);
    REQUIRE(s1 >= s2);
    REQUIRE(s1 < s3);
    REQUIRE(s4 > s1);
    REQUIRE(s2 <= s3);
    REQUIRE(s4 >= s2);
    REQUIRE(!(s1 > s1));
    REQUIRE(!(s1 < s2));
    REQUIRE(!(s1 >= s3));
    REQUIRE(!(s4 <= s1));
    REQUIRE(!(s2 > s3));
    REQUIRE(!(s4 < s2));
}
<commit_msg>Work around a MSVC library warning<commit_after>#include "catch.hpp"
#include <simdee/common/storage.hpp>

struct vec_t {
    using scalar_t = char;
    enum { width = 3 };

    void aligned_store(scalar_t* ptr) const {
        for (int i = 0; i < width; i++) {
            ptr[i] = data[i];
        }
    }

    scalar_t data[width];
};

using storage_t = sd::impl::storage<vec_t, vec_t::scalar_t, alignof(vec_t)>;

TEST_CASE("storage data access") {
    SECTION("via operator[]") {
        storage_t s;
        s[0] = 'x'; s[1] = 'y'; s[2] = 'z';
        REQUIRE((s[0] == 'x' && s[1] == 'y' && s[2] == 'z'));
    }
    SECTION("via data()") {
        storage_t s;
        auto d = s.data();
        d[0] = 'u'; d[1] = 'v'; d[2] = 'w';
        REQUIRE((s[0] == 'u' && s[1] == 'v' && s[2] == 'w'));
    }
}

TEST_CASE("storage construction and assigment", "[storage]") {
    auto good = [](const storage_t& s) {
        return s[0] == 'a' && s[1] == 'b' && s[2] == 'c';
    };
    auto implicit_test = [&good](storage_t s) {
        return good(s);
    };

    SECTION("copy") {
        storage_t s;
        s[0] = 'a'; s[1] = 'b'; s[2] = 'c';
        REQUIRE(implicit_test(s));
        storage_t assigned_test;
        assigned_test = s;
        REQUIRE(good(assigned_test));
    }
    SECTION("from vec_t") {
        vec_t v = { { 'a', 'b', 'c' } };
        storage_t explicit_test(v);
        REQUIRE(good(explicit_test));
        storage_t assigned_test;
        assigned_test = v;
        REQUIRE(good(assigned_test));
    }
    SECTION("from init list") {
        REQUIRE(implicit_test({'a', 'b', 'c'}));
        storage_t assigned_test;
        assigned_test = { 'a', 'b', 'c' };
        REQUIRE(good(assigned_test));
    }
}

TEST_CASE("storage comparison", "[storage]") {
    storage_t s1 = { 'd', 'e', 'f' };
    storage_t s2 = { 'd', 'e', 'f' };
    storage_t s3 = { 'd', 'e', 'g' };
    storage_t s4 = { 'd', 'f', 'e' };

    REQUIRE(s1 == s1);
    REQUIRE(s1 == s2);
    REQUIRE(s1 != s3);
    REQUIRE(s1 != s4);
    REQUIRE(s2 == s2);
    REQUIRE(s2 != s3);
    REQUIRE(s2 != s4);
    REQUIRE(s3 == s3);
    REQUIRE(s3 != s4);
    REQUIRE(s4 == s4);

    REQUIRE(s1 <= s1);
    REQUIRE(s1 >= s2);
    REQUIRE(s1 < s3);
    REQUIRE(s4 > s1);
    REQUIRE(s2 <= s3);
    REQUIRE(s4 >= s2);
    REQUIRE(!(s1 > s1));
    REQUIRE(!(s1 < s2));
    REQUIRE(!(s1 >= s3));
    REQUIRE(!(s4 <= s1));
    REQUIRE(!(s2 > s3));
    REQUIRE(!(s4 < s2));
}
<|endoftext|>


<commit_before>#include <m3conf/m3config.h>
#include <m3conf/parser.h>
#include <m3conf/tokenizer.h>
#include <test/XTest.h>

XTS_TEST(ParserTests, testEmptyString) {
	struct Token* t;
	struct m3config* c;
	std::string data = "";
	XTS_ASSERT_EQUALS(0, tokenize(data.c_str(), data.size(), &t));
	c = parse(t);

	m3conf_free(c);
	free_tokens(t);
}
<commit_msg>Adding a decent-sized test.<commit_after>#include <m3conf/m3config.h>
#include <m3conf/parser.h>
#include <m3conf/tokenizer.h>
#include <test/XTest.h>

XTS_TEST(ParserTests, testEmptyString) {
	struct Token* t;
	struct m3config* c;
	std::string data = "";
	XTS_ASSERT_EQUALS(0, tokenize(data.c_str(), data.size(), &t));
	c = parse(t);

	m3conf_free(c);
	free_tokens(t);
}

XTS_TEST(ParserTests, testBigValid) {
	struct Token* t;
	struct m3config* c;
	std::string data = "a=1;b=\"3\";z{y{x{c=\"a\";w{d=0;}e=-1;}}f=\"qq\";}";
	XTS_ASSERT_EQUALS(0, tokenize(data.c_str(), data.size(), &t));
	c = parse(t);

	m3conf_free(c);
	free_tokens(t);
}
<|endoftext|>


<commit_before>#include <cassert>
#include <iostream>

#include <pqxx/connection>
#include <pqxx/subtransaction>
#include <pqxx/transaction>

using namespace PGSTD;
using namespace pqxx;

namespace
{
void test(connection_base &C, const string &desc)
{
  cout << "Testing " << desc << ":" << endl;

  // Trivial test: create subtransactions, and commit/abort
  work T0(C, "T0");
  cout << T0.exec("SELECT 'T0 starts'")[0][0].c_str() << endl;
  try
  {
    subtransaction T0a(T0, "T0a");
    T0a.commit();
  }
  catch (const feature_not_supported &e)
  {
    cerr << e.what() << endl;
    return 0;
  }
  subtransaction T0b(T0, "T0b");
  T0b.abort();
  cout << T0.exec("SELECT 'T0 ends'")[0][0].c_str() << endl;
  T0.commit();

  // Basic functionality: perform query in subtransaction; abort, continue
  work T1(C, "T1");
  cout << T1.exec("SELECT 'T1 starts'")[0][0].c_str() << endl;
  subtransaction T1a(T1, "T1a");
    cout << T1a.exec("SELECT '  a'")[0][0].c_str() << endl;
    T1a.commit();
  subtransaction T1b(T1, "T1b");
    cout << T1b.exec("SELECT '  b'")[0][0].c_str() << endl;
    T1b.abort();
  subtransaction T1c(T1, "T1c");
    cout << T1c.exec("SELECT '  c'")[0][0].c_str() << endl;
    T1c.commit();
  cout << T1.exec("SELECT 'T1 ends'")[0][0].c_str() << endl;
  T1.commit();
}

bool test_and_catch(connection_base &C, const string &desc)
{
  bool ok = false;
  try
  {
    test(C,desc);
    ok = true;
  }
  catch (const broken_connection &)
  {
    throw;
  }
  catch (const logic_error &)
  {
    throw;
  }
  catch (const exception &)
  {
    if (C.supports(connection_base::cap_nested_transactions))
      throw;
    cout << "Backend does not support nested transactions." << endl;
  }

  return ok;
}

} // namespace

// Test program for libpqxx.  Attempt to perform nested queries on various types
// of connections.
//
// Usage: test089
int main()
{
  try
  {
    asyncconnection A1;
    const bool ok = test_and_catch(A1, "asyncconnection (virgin)");

    asyncconnection A2;
    A2.activate();
    if (!A2.supports(connection_base::cap_nested_transactions))
    {
      if (ok)
	throw logic_error("Initialized asyncconnection doesn't support "
	    "nested transactions, but a virgin one does!");
      cout << "Backend does not support nested transactions.  Skipping test."
	   << endl;
      return 0;
    }

    if (!ok)
      throw logic_error("Virgin asyncconnection supports nested transactions, "
	  "but initialized one doesn't!");

    test(A2, "asyncconnection (initialized)");

    lazyconnection L1;
    test(L1, "lazyconnection (virgin)");

    lazyconnection L2;
    L2.activate();
    test(L2, "lazyconnection (initialized)");

    connection C;
    C.activate();
    C.deactivate();
    test(C, "connection (deactivated)");
  }
  catch (const sql_error &e)
  {
    cerr << "SQL error: " << e.what() << endl
         << "Query was: " << e.query() << endl;
    return 1;
  }
  catch (const exception &e)
  {
    cerr << "Exception: " << e.what() << endl;
    return 2;
  }
  catch (...)
  {
    cerr << "Unhandled exception" << endl;
    return 100;
  }

  return 0;
}

<commit_msg>Changed check for nested-transaction support<commit_after>#include <cassert>
#include <iostream>

#include <pqxx/connection>
#include <pqxx/subtransaction>
#include <pqxx/transaction>

using namespace PGSTD;
using namespace pqxx;

namespace
{
void test(connection_base &C, const string &desc)
{
  cout << "Testing " << desc << ":" << endl;

  // Trivial test: create subtransactions, and commit/abort
  work T0(C, "T0");
  cout << T0.exec("SELECT 'T0 starts'")[0][0].c_str() << endl;
  subtransaction T0a(T0, "T0a");
  T0a.commit();
  subtransaction T0b(T0, "T0b");
  T0b.abort();
  cout << T0.exec("SELECT 'T0 ends'")[0][0].c_str() << endl;
  T0.commit();

  // Basic functionality: perform query in subtransaction; abort, continue
  work T1(C, "T1");
  cout << T1.exec("SELECT 'T1 starts'")[0][0].c_str() << endl;
  subtransaction T1a(T1, "T1a");
    cout << T1a.exec("SELECT '  a'")[0][0].c_str() << endl;
    T1a.commit();
  subtransaction T1b(T1, "T1b");
    cout << T1b.exec("SELECT '  b'")[0][0].c_str() << endl;
    T1b.abort();
  subtransaction T1c(T1, "T1c");
    cout << T1c.exec("SELECT '  c'")[0][0].c_str() << endl;
    T1c.commit();
  cout << T1.exec("SELECT 'T1 ends'")[0][0].c_str() << endl;
  T1.commit();
}

bool test_and_catch(connection_base &C, const string &desc)
{
  bool ok = false;
  try
  {
    test(C,desc);
    ok = true;
  }
  catch (const broken_connection &)
  {
    throw;
  }
  catch (const logic_error &)
  {
    throw;
  }
  catch (const exception &)
  {
    if (C.supports(connection_base::cap_nested_transactions))
      throw;
    cout << "Backend does not support nested transactions." << endl;
  }

  return ok;
}

} // namespace

// Test program for libpqxx.  Attempt to perform nested queries on various types
// of connections.
//
// Usage: test089
int main()
{
  try
  {
    asyncconnection A1;
    const bool ok = test_and_catch(A1, "asyncconnection (virgin)");

    asyncconnection A2;
    A2.activate();
    if (!A2.supports(connection_base::cap_nested_transactions))
    {
      if (ok)
	throw logic_error("Initialized asyncconnection doesn't support "
	    "nested transactions, but a virgin one does!");
      cout << "Backend does not support nested transactions.  Skipping test."
	   << endl;
      return 0;
    }

    if (!ok)
      throw logic_error("Virgin asyncconnection supports nested transactions, "
	  "but initialized one doesn't!");

    try
    {
      test(A2, "asyncconnection (initialized)");
    }
    catch (const feature_not_supported &e)
    {
      cerr << e.what() << endl;
      return 0;
    }

    lazyconnection L1;
    test(L1, "lazyconnection (virgin)");

    lazyconnection L2;
    L2.activate();
    test(L2, "lazyconnection (initialized)");

    connection C;
    C.activate();
    C.deactivate();
    test(C, "connection (deactivated)");
  }
  catch (const sql_error &e)
  {
    cerr << "SQL error: " << e.what() << endl
         << "Query was: " << e.query() << endl;
    return 1;
  }
  catch (const exception &e)
  {
    cerr << "Exception: " << e.what() << endl;
    return 2;
  }
  catch (...)
  {
    cerr << "Unhandled exception" << endl;
    return 100;
  }

  return 0;
}

<|endoftext|>


<commit_before>#if !defined(__CINT__) || defined(__MAKECINT__)
#include <TFile.h>
#include <TH1F.h>
#include <TGraph.h>
#include <TStyle.h>
#include <TGrid.h>
#include <TCanvas.h>
#include <TObjArray.h>
#include "AliCDBEntry.h"
#include "AliITSCalibrationSDD.h"
#endif

// Macro to plot the calibration parameters from the OCDB file
// created from PEDESTAL and PULSER runs (OCDB/ITS/Calib/CalibSDD)
// Two methods ShowCalibrationSDD:
//  - the first takes the name of the file to be displayed
//  - the second builds the alien path+name from run number and file version
//
// Origin: F. Prino (prino@to.infn.it)

void ShowCalibrationSDD(Char_t *filnam="$ALICE_ROOT/ITS/Calib/CalibSDD/Run0_9999999_v0_s0.root", Int_t iMod=0){

  TFile *f=TFile::Open(filnam);
  AliCDBEntry *ent=(AliCDBEntry*)f->Get("AliCDBEntry");
  TObjArray *calSDD = (TObjArray *)ent->GetObject();
  printf("Entries in array=%d\n",calSDD->GetEntriesFast());
  TH1F* hmodstatus=new TH1F("hmodstatus","",260,0.5,260.5);
  TH1F* hnbadch=new TH1F("hnbadch","",260,0.5,260.5);
  TH1F* hbase=new TH1F("hbase","",60,0.5,120.5);
  TH1F* hnoise=new TH1F("hnoise","",100,0.,7.);
  TH1F* hgain=new TH1F("hgain","",100,0.,4.);
  TH1F* hchstatus=new TH1F("hchstatus","",2,-0.5,1.5);
  AliITSCalibrationSDD *cal;
  for(Int_t i=0; i<260; i++){
    cal=(AliITSCalibrationSDD*)calSDD->At(i);
    if(cal==0) continue;
    printf("Module %d (%d)   status = ",i,i+240);
    if(cal->IsBad()) printf("BAD\t");
    else printf("OK\t");
    printf("   Chip Status (0=OK, 1=BAD): ");
    for(Int_t ic=0; ic<8;ic++) printf("%d ",cal->IsChipBad(ic));
    if(cal->IsAMAt20MHz()) printf("      20 MHz sampling");
    else printf("      40 MHz sampling");
    printf("\n");
    if(cal->IsBad()) hmodstatus->SetBinContent(i+1,0);
    else hmodstatus->SetBinContent(i+1,1);
    hnbadch->SetBinContent(i+1,cal->GetDeadChannels());
    for(Int_t iAn=0; iAn<512; iAn++){
      Float_t base=cal->GetBaseline(iAn);
      Float_t noise=cal->GetNoiseAfterElectronics(iAn);
      Float_t gain=cal->GetChannelGain(iAn);
      if(cal->IsBadChannel(iAn)) hchstatus->Fill(0);
      if(!cal->IsBadChannel(iAn)){
	hbase->Fill(base);
	hchstatus->Fill(1);
	hnoise->Fill(noise);
	hgain->Fill(gain);
      }
    }
  }
  TCanvas *c0=new TCanvas("c0","Module status",800,800);
  c0->Divide(1,2);
  c0->cd(1);
  hmodstatus->Draw();
  hmodstatus->GetXaxis()->SetTitle("Module number");
  hmodstatus->GetYaxis()->SetTitle("Module status (1=OK, 0=BAD)");
  c0->cd(2);
  hnbadch->Draw();
  hnbadch->GetXaxis()->SetTitle("Module number");
  hnbadch->GetYaxis()->SetTitle("Number of bad anodes");

  TCanvas *c1=new TCanvas("c1","Anode calibration",800,800);
  c1->Divide(2,2);
  c1->cd(1);
  hbase->Draw();
  hbase->GetXaxis()->SetTitle("Baseline after equalization");
  hbase->GetXaxis()->CenterTitle();
  c1->cd(2);
  hnoise->Draw();
  hnoise->GetXaxis()->SetTitle("Noise");
  hnoise->GetXaxis()->CenterTitle();
  c1->cd(3);
  hgain->Draw();
  hgain->GetXaxis()->SetTitle("Gain");
  hgain->GetXaxis()->CenterTitle();
  c1->cd(4);
  hchstatus->Draw();
  hchstatus->GetXaxis()->SetTitle("Anode status (0=bad, 1=OK)");
  hchstatus->GetXaxis()->CenterTitle();

  cal=(AliITSCalibrationSDD*)calSDD->At(iMod);
  if(cal==0) return;
  printf("-----------------------------------\n");
  printf("Module %d    status = ",iMod);
  if(cal->IsBad()) printf("BAD\n");
  else printf("OK\n");
  printf("   Chip Status (0=OK, 1=BAD): ");
  for(Int_t ic=0; ic<8;ic++) printf("%d ",cal->IsChipBad(ic));
  printf("\n");
  printf("-----------------------------------\n");
  Int_t ipt=0;
  TGraph *gbad=new TGraph(0);
  gbad->SetTitle("Bad Channels");
  TGraph *gbase=new TGraph(0);
  gbase->SetTitle("Baselines");
  TGraph *gnoi=new TGraph(0);
  gnoi->SetTitle("Noise");
  TGraph *ggain=new TGraph(0);
  ggain->SetTitle("Gain");
  for(Int_t iAn=0; iAn<512; iAn++){
    Float_t bad=1;
    if(cal->IsBadChannel(iAn)) bad=0;
    Float_t base=cal->GetBaseline(iAn);
    Float_t noise=cal->GetNoiseAfterElectronics(iAn);
    Float_t gain=cal->GetChannelGain(iAn);
    gbad->SetPoint(ipt,(Float_t)iAn,bad);
    gbase->SetPoint(ipt,(Float_t)iAn,base);
    ggain->SetPoint(ipt,(Float_t)iAn,gain);
    gnoi->SetPoint(ipt,(Float_t)iAn,noise);
    ipt++;
  }
  Char_t ctit[100];
  sprintf(ctit,"Module %d",iMod);

  TCanvas *c2=new TCanvas("c2",ctit,1200,800);
  c2->Divide(2,2);

  c2->cd(1);
  gbase->SetMarkerStyle(7);
  gbase->Draw("AP");
  gbase->GetXaxis()->SetTitle("Anode Number");
  gbase->GetYaxis()->SetTitle("Baseline after equalization");
  c2->cd(2);
  gnoi->SetMarkerStyle(7);
  gnoi->Draw("AP");
  gnoi->GetXaxis()->SetTitle("Anode Number");
  gnoi->GetYaxis()->SetTitle("Noise");
  c2->cd(3);
  ggain->SetMarkerStyle(7);
  ggain->Draw("AP");
  ggain->GetXaxis()->SetTitle("Anode Number");
  ggain->GetYaxis()->SetTitle("Gain");
  c2->cd(4);
  gbad->SetMarkerStyle(7);
  gbad->Draw("AP");
  gbad->SetMinimum(-0.1);
  gbad->GetXaxis()->SetTitle("Anode Number");
  gbad->GetYaxis()->SetTitle("Anode Status (1=OK, 0=bad)");
}

void ShowCalibrationSDD(Int_t nrun, Int_t nv, Char_t* dir="LHC08d", Int_t nmod=0){
  TGrid::Connect("alien:",0,0,"t");
  Char_t filnam[200];
  sprintf(filnam,"alien:///alice/data/2008/%s/OCDB/ITS/Calib/CalibSDD/Run%d_999999999_v%d_s0.root",dir,nrun,nv);
  printf("Open file: %s\n",filnam);
  ShowCalibrationSDD(filnam,nmod);
}
<commit_msg>Updated macro to display SDD calibration (F. Prino)<commit_after>#if !defined(__CINT__) || defined(__MAKECINT__)
#include <TFile.h>
#include <TH1F.h>
#include <TGraph.h>
#include <TStyle.h>
#include <TGrid.h>
#include <TCanvas.h>
#include <TObjArray.h>
#include "AliCDBEntry.h"
#include "AliITSCalibrationSDD.h"
#endif

// Macro to plot the calibration parameters from the OCDB file
// created from PEDESTAL and PULSER runs (OCDB/ITS/Calib/CalibSDD)
// Two methods ShowCalibrationSDD:
//  - the first takes the name of the file to be displayed
//  - the second builds the alien path+name from run number and file version
//
// Origin: F. Prino (prino@to.infn.it)

void ShowCalibrationSDD(Int_t iMod=0, Char_t *filnam="$ALICE_ROOT/ITS/Calib/CalibSDD/Run0_9999999_v0_s0.root"){

  TFile *f=TFile::Open(filnam);
  AliCDBEntry *ent=(AliCDBEntry*)f->Get("AliCDBEntry");
  TObjArray *calSDD = (TObjArray *)ent->GetObject();
  printf("Entries in array=%d\n",calSDD->GetEntriesFast());
  TH1F* hmodstatus=new TH1F("hmodstatus","",260,0.5,260.5);
  TH1F* hnbadch=new TH1F("hnbadch","",260,0.5,260.5);
  TH1F* hbase=new TH1F("hbase","",60,0.5,120.5);
  TH1F* hnoise=new TH1F("hnoise","",100,0.,7.);
  TH1F* hgain=new TH1F("hgain","",100,0.,4.);
  TH1F* hchstatus=new TH1F("hchstatus","",2,-0.5,1.5);
  AliITSCalibrationSDD *cal;
  Int_t badModCounter3=0;
  Int_t badModCounter4=0;
  Int_t badAnodeCounter3=0;
  Int_t badAnodeCounter4=0;
  Int_t badAnodeCounterGoodMod3=0;
  Int_t badAnodeCounterGoodMod4=0;
  Int_t badAnodeCounterGoodModAndChip3=0;
  Int_t badAnodeCounterGoodModAndChip4=0;
  Int_t badChipCounter3=0;
  Int_t badChipCounter4=0;
  for(Int_t i=0; i<260; i++){
    cal=(AliITSCalibrationSDD*)calSDD->At(i);
    if(cal==0) continue;
    printf("Module %d (%d)   status = ",i,i+240);
    if(cal->IsBad()){
      printf("BAD\t");
      if(i<84) badModCounter3++;
      else badModCounter4++;
      hmodstatus->SetBinContent(i+1,0);
    }
    else{
      printf("OK\t");
      hmodstatus->SetBinContent(i+1,1);
      if(i<84) badAnodeCounterGoodMod3+=cal->GetDeadChannels();
      else badAnodeCounterGoodMod4+=cal->GetDeadChannels();
    }
    printf("   Chip Status (0=OK, 1=BAD): ");
    for(Int_t ic=0; ic<8;ic++){
      printf("%d ",cal->IsChipBad(ic));
      if(cal->IsChipBad(ic) && !cal->IsBad()){
	if(i<84) badChipCounter3++;
	else badChipCounter4++;
      }
    }
    if(cal->IsAMAt20MHz()) printf("      20 MHz sampling");
    else printf("      40 MHz sampling");
    printf("\n");
    if(i<84) badAnodeCounter3+=cal->GetDeadChannels();
    else badAnodeCounter4+=cal->GetDeadChannels();
    hnbadch->SetBinContent(i+1,cal->GetDeadChannels());
    for(Int_t iAn=0; iAn<512; iAn++){
      Int_t ic=cal->GetChip(iAn);
      if(!cal->IsChipBad(ic) && !cal->IsBad() && cal->IsBadChannel(iAn)){
	if(i<84) badAnodeCounterGoodModAndChip3++;
	else badAnodeCounterGoodModAndChip4++;
      }
      Float_t base=cal->GetBaseline(iAn);
      Float_t noise=cal->GetNoiseAfterElectronics(iAn);
      Float_t gain=cal->GetChannelGain(iAn);
      if(cal->IsBadChannel(iAn)) hchstatus->Fill(0);
      if(!cal->IsBadChannel(iAn)){
	hbase->Fill(base);
	hchstatus->Fill(1);
	hnoise->Fill(noise);
	hgain->Fill(gain);
      }
    }
  }
  Int_t totbad3=badModCounter3*512+badChipCounter3*64+badAnodeCounterGoodModAndChip3;
  Int_t tot3=6*14*512;
  Float_t fracbad3=(Float_t)totbad3/(Float_t)tot3;
  Int_t totbad4=badModCounter4*512+badChipCounter4*64+badAnodeCounterGoodModAndChip4;
  Int_t tot4=8*22*512;
  Float_t fracbad4=(Float_t)totbad4/(Float_t)tot4;
  Float_t fractot=(Float_t)(totbad3+totbad4)/(Float_t)(tot3+tot4);
  printf("----------------------Summary----------------------\n");
  printf("---- Layer 3 ----\n");
  printf("# of bad modules                      = %d\n",badModCounter3);
  printf("# of bad chips in good modules        = %d\n",badChipCounter3);
  printf("# of bad anodes in good modules+chips = %d\n",badAnodeCounterGoodModAndChip3);
  printf("Fraction of bads (anodes+chips+mod)   = %f\n",fracbad3);
  printf("---- Layer 4 ----\n");
  printf("# of bad modules                      = %d\n",badModCounter4);
  printf("# of bad chips in good modules        = %d\n",badChipCounter4);
  printf("# of bad anodes in good modules+chips = %d\n",badAnodeCounterGoodModAndChip4);
  printf("Fraction of bads (anodes+chips+mod)   = %f\n",fracbad4);
  printf("---- Total   ----\n");
  printf("# of bad modules                      = %d\n",badModCounter3+badModCounter4);
  printf("# of bad chips in good modules        = %d\n",badChipCounter3+badChipCounter4);
  printf("# of bad anodes in good modules+chips = %d\n",badAnodeCounterGoodModAndChip3+badAnodeCounterGoodModAndChip4);
  printf("Fraction of bads (anodes+chips+mod)   = %f\n",fractot);
  printf("---------------------------------------------------\n");

  TCanvas *c0=new TCanvas("c0","Module status",800,800);
  c0->Divide(1,2);
  c0->cd(1);
  hmodstatus->Draw();
  hmodstatus->GetXaxis()->SetTitle("Module number");
  hmodstatus->GetYaxis()->SetTitle("Module status (1=OK, 0=BAD)");
  c0->cd(2);
  hnbadch->Draw();
  hnbadch->GetXaxis()->SetTitle("Module number");
  hnbadch->GetYaxis()->SetTitle("Number of bad anodes");

  TCanvas *c1=new TCanvas("c1","Anode calibration",800,800);
  c1->Divide(2,2);
  c1->cd(1);
  hbase->Draw();
  hbase->GetXaxis()->SetTitle("Baseline after equalization");
  hbase->GetXaxis()->CenterTitle();
  c1->cd(2);
  hnoise->Draw();
  hnoise->GetXaxis()->SetTitle("Noise");
  hnoise->GetXaxis()->CenterTitle();
  c1->cd(3);
  hgain->Draw();
  hgain->GetXaxis()->SetTitle("Gain");
  hgain->GetXaxis()->CenterTitle();
  c1->cd(4);
  hchstatus->Draw();
  hchstatus->GetXaxis()->SetTitle("Anode status (0=bad, 1=OK)");
  hchstatus->GetXaxis()->CenterTitle();

  // Plot quantities for specified module

  cal=(AliITSCalibrationSDD*)calSDD->At(iMod);
  if(cal==0) return;
  printf("-----------------------------------\n");
  printf("Module %d    status = ",iMod);
  if(cal->IsBad()) printf("BAD\n");
  else printf("OK\n");
  printf("   Chip Status (0=OK, 1=BAD): ");
  for(Int_t ic=0; ic<8;ic++) printf("%d ",cal->IsChipBad(ic));
  printf("\n");
  printf("   Number of bad anodes =%d\n",cal->GetDeadChannels());
  printf("-----------------------------------\n");
  Int_t ipt=0;
  TGraph *gbad=new TGraph(0);
  gbad->SetTitle("Bad Channels");
  TGraph *gbase=new TGraph(0);
  gbase->SetTitle("Baselines");
  TGraph *gnoi=new TGraph(0);
  gnoi->SetTitle("Noise");
  TGraph *ggain=new TGraph(0);
  ggain->SetTitle("Gain");
  for(Int_t iAn=0; iAn<512; iAn++){
    Float_t bad=1;
    if(cal->IsBadChannel(iAn)) bad=0;
    Float_t base=cal->GetBaseline(iAn);
    Float_t noise=cal->GetNoiseAfterElectronics(iAn);
    Float_t gain=cal->GetChannelGain(iAn);
    gbad->SetPoint(ipt,(Float_t)iAn,bad);
    gbase->SetPoint(ipt,(Float_t)iAn,base);
    ggain->SetPoint(ipt,(Float_t)iAn,gain);
    gnoi->SetPoint(ipt,(Float_t)iAn,noise);
    ipt++;
  }
  Char_t ctit[100];
  sprintf(ctit,"Module %d",iMod);

  TCanvas *c2=new TCanvas("c2",ctit,1200,800);
  c2->Divide(2,2);

  c2->cd(1);
  gbase->SetMarkerStyle(7);
  gbase->Draw("AP");
  gbase->GetXaxis()->SetTitle("Anode Number");
  gbase->GetYaxis()->SetTitle("Baseline after equalization");
  c2->cd(2);
  gnoi->SetMarkerStyle(7);
  gnoi->Draw("AP");
  gnoi->GetXaxis()->SetTitle("Anode Number");
  gnoi->GetYaxis()->SetTitle("Noise");
  c2->cd(3);
  ggain->SetMarkerStyle(7);
  ggain->Draw("AP");
  ggain->GetXaxis()->SetTitle("Anode Number");
  ggain->GetYaxis()->SetTitle("Gain");
  c2->cd(4);
  gbad->SetMarkerStyle(7);
  gbad->Draw("AP");
  gbad->SetMinimum(-0.1);
  gbad->GetXaxis()->SetTitle("Anode Number");
  gbad->GetYaxis()->SetTitle("Anode Status (1=OK, 0=bad)");
}

void ShowCalibrationSDD(Int_t nrun, Int_t nv, Char_t* dir="LHC08d", Int_t nmod=0){
  TGrid::Connect("alien:",0,0,"t");
  Char_t filnam[200];
  sprintf(filnam,"alien:///alice/data/2008/%s/OCDB/ITS/Calib/CalibSDD/Run%d_999999999_v%d_s0.root",dir,nrun,nv);
  printf("Open file: %s\n",filnam);
  ShowCalibrationSDD(nmod,filnam);
}
<|endoftext|>


<commit_before>#include "Damage.h"

#include <iostream>
#include "Random.h"

Damage::Damage()
{
}

Damage::~Damage()
{
}

void Damage::damageDoop(Creature& player)
{
	//Sudo code
	//int ran = Random::randInt(0, deffenderDex);

	//if (ran < (deffenderDex / 3)) {maff = attackerDmg - (deffenderDmg / 8)}
	//if ((deffenderDex / 3) < ran < ((deffenderDex / 3) * 2)) {maff = attackerDmg}
	//if (ran > ((deffenderDex / 3) * 2)) {maff = (attackerDmg + (deffenderDmg / 8) )}

	//z = maff - DeffenderDef
	//if (z < 0) {z = 0};
	//damageToApply = xY + z
}
<commit_msg>Did Something<commit_after>#include "Damage.h"

#include <iostream>
#include "Random.h"

Damage::Damage()
{
}

Damage::~Damage()
{
}

void Damage::damageDoop(Creature& player)
{
	//Sudo code
	//int ran = Random::randInt(0, deffenderDex);

	//if (ran < (deffenderDex / 3)) {maff = attackerDmg - (deffenderDex / 8)}
	//if ((deffenderDex / 3) < ran < ((deffenderDex / 3) * 2)) {maff = attackerDex}
	//if (ran > ((deffenderDex / 3) * 2)) {maff = (attackerDmg + (deffenderDex / 8) )}

	//z = maff - DeffenderDef
	//if (z < 0) {z = 0};
	//damageToApply = xY + z
}
<|endoftext|>


<commit_before>#include "testing_suite.h"

using namespace std;
using namespace TOOLS;
using namespace TOOLS::UNIT_TEST;

/// @todo PREPARE_WITH DOES NOT WORK!

Test::Test() : name(""), method(NULL), object(NULL) {}

Test::Test(const string& name, tMethod meth, TestSuite* obj)
  : name(name), method(meth), object(obj) {}

TestSuite::TestSuite() : check_count(0), active_test(NULL), show_good_details(false) { }

void TestSuite::add_check(bool expr, int line) {
  active_test->res.result &= expr;
  active_test->lineno = line;
  check_count++;

  if(show_good_details || !expr) {
    const string lineinfo = (expr) ? " [good]" : " [bad]";
    if(XString(active_test->res.details).startswith("Line(s):"))
      active_test->res.details.append(", " + str(line) + lineinfo);
    else
      active_test->res.details.append("Line(s): " + str(line) + lineinfo);
  }
}

void TestSuite::add_exc_check(bool res, const std::string& excname, int line) {
  add_check(res, line);
  if(!res)
    active_test->res.details.append("[exc: " + excname + " line: " + str(line) + "] ");
}

void TestSuite::add_iter_check(bool res, int iters, tIntList errs, int line) {
  add_check(res, line);
  stringstream out;
  for(tIntIter i=errs.begin(); i!=errs.end(); ++i) {
    out << *i;
    if(i+1 != errs.end())
      out << ",";
  }
  if(!res)
    active_test->res.details.append("[eq_iter: iterations: " +
        str(iters) + " errors in: " + out.str() + "]");
}

void TestSuite::setup() {}
void TestSuite::tear_down() {}

void TestSuite::after_setup() {
  //active_test->details.append("Setup finished - ");
}

void TestSuite::after_tear_down() {
  //active_test->details.append("TearDown finished!");
}

void TestSuite::execute_tests(const string& suite_name) {
  for(tTestIter i=tests.begin(); i!=tests.end(); ++i) {
    i->second.res.id = suite_name + "::" + i->first;
    active_test = &i->second;
    setup();
    after_setup();
    try {
      (i->second.object->*i->second.method)(true);
    } catch(TOOLS::BaseException& e) {
      i->second.res.details.append(
          "[E] test failed - exception caught: " + e.output + " - ");
      i->second.res.result = false;
    } catch(exception& e) {
      i->second.res.details.append(
          "[E] test failed - std::exception caught: " + str(e.what()) + " - ");
      i->second.res.result = false;
    }
    tear_down();
    after_tear_down();
    active_test = NULL;
    i->second.res.show(false);
  }
}

TestResult::TestResult(const string& testid, bool res, const string& details)
  : id(testid), result(res), details(details) {}

TestResult::TestResult() : id(""), result(true) {}

void TestResult::show(bool show_details) {
  string icon, rating;
  if(result) {
    rating = "GOOD";
    icon = "+";
  } else {
    rating = "BAD!";
    icon = "-";
  }

  cout << "[" << icon << "] " << left << setw(45) << id << \
    setw(20) << right << rating << endl;

  if(details != "" && ((!show_details && !result) || show_details))
    cout << "[i]    " << details << endl;

}

TestFramework::TestFramework(int argc, char* argv[]) {
  show_details = (argc == 2 && str(argv[1]) == "-d") ? true : false;
}

TestFramework::~TestFramework() {
  for(tTestSuiteIter i=test_suites.begin(); i!=test_suites.end(); ++i)
    delete i->second;
}

void TestFramework::run() {
  for(tTestSuiteIter i=test_suites.begin(); i!=test_suites.end(); ++i)
    i->second->execute_tests(i->first);
}

void TestFramework::show_result_overview() {
  int good = 0;
  int bad = 0;
  int all_tests = 0;

  for(tTestSuiteIter i=test_suites.begin(); i!=test_suites.end(); ++i) {
    all_tests += i->second->check_count;
    for(tTestIter j=i->second->tests.begin(); j!=i->second->tests.end(); ++j) {
      (j->second.res.result) ? good++ : bad++;
    }
  }
  cout << endl << "[i] Finished TestRun (" <<
    all_tests << " checks done) - Tests: good: " << good;
  if(bad > 0)
    cout << " and bad: " << bad << endl;
  else
    cout << " and NO bad ones!" << endl;
}

void TestFramework::print_stacktrace(uint max_frames) {
    cerr << "[BT] ";

    void* addrlist[max_frames+1];
    int addrlen = backtrace(addrlist, sizeof(addrlist) / sizeof(void*));

    if(addrlen == 0) {
        cerr << "[E] backtrace() returned 0 - Error!" << endl;
        return;
    }
    // resolve addresses to -> "filename(function+address)"
    // symlist must be free()-ed !
    char** symlist = backtrace_symbols(addrlist, addrlen);

    size_t funcnamesize = 256;
    char* funcname = (char*)malloc(funcnamesize);

    // demangle all functionnames
    for (int i=1; i<addrlen; ++i) {
        char* begin_name = 0;
        char* begin_offset = 0;
        char* end_offset = 0;

        // find parentheses and +address offset surrounding the mangled name:
        // ./module(function+0x15c) [0x8048a6d]
        for (char *p = symlist[i]; *p; ++p) {
            if (*p == '(')
                begin_name = p;
            else if (*p == '+')
                begin_offset = p;
            else if (*p == ')' && begin_offset) {
                end_offset = p;
                break;
            }
        }

        if (begin_name && begin_offset && end_offset
            && begin_name < begin_offset) {
            *begin_name++ = '\0';
            *begin_offset++ = '\0';
            *end_offset = '\0';

            // mangled name is now in [begin_name, begin_offset) and caller
            // offset in [begin_offset, end_offset). now apply
            // __cxa_demangle():

            int status;
            char* ret = abi::__cxa_demangle(begin_name,
                                            funcname, &funcnamesize, &status);
            if (status == 0) {
                funcname = ret; // use possibly realloc()-ed string
                cerr << "[BT] " << symlist[i] << " " \
                     << funcname << "+" << begin_offset << endl;
            } else { // demangle failes
                cerr << "[BT] " << symlist[i] << " " \
                     << begin_name << "+" << begin_offset << endl;
            }
        } else // parsing failed
            cerr << "[BT]" << symlist[i] << endl;
    }
    free(funcname);
    free(symlist);
}

<commit_msg>fix output for print_stacktrace()<commit_after>#include "testing_suite.h"

using namespace std;
using namespace TOOLS;
using namespace TOOLS::UNIT_TEST;

/// @todo PREPARE_WITH DOES NOT WORK!

Test::Test() : name(""), method(NULL), object(NULL) {}

Test::Test(const string& name, tMethod meth, TestSuite* obj)
  : name(name), method(meth), object(obj) {}

TestSuite::TestSuite() : check_count(0), active_test(NULL), show_good_details(false) { }

void TestSuite::add_check(bool expr, int line) {
  active_test->res.result &= expr;
  active_test->lineno = line;
  check_count++;

  if(show_good_details || !expr) {
    const string lineinfo = (expr) ? " [good]" : " [bad]";
    if(XString(active_test->res.details).startswith("Line(s):"))
      active_test->res.details.append(", " + str(line) + lineinfo);
    else
      active_test->res.details.append("Line(s): " + str(line) + lineinfo);
  }
}

void TestSuite::add_exc_check(bool res, const std::string& excname, int line) {
  add_check(res, line);
  if(!res)
    active_test->res.details.append("[exc: " + excname + " line: " + str(line) + "] ");
}

void TestSuite::add_iter_check(bool res, int iters, tIntList errs, int line) {
  add_check(res, line);
  stringstream out;
  for(tIntIter i=errs.begin(); i!=errs.end(); ++i) {
    out << *i;
    if(i+1 != errs.end())
      out << ",";
  }
  if(!res)
    active_test->res.details.append("[eq_iter: iterations: " +
        str(iters) + " errors in: " + out.str() + "]");
}

void TestSuite::setup() {}
void TestSuite::tear_down() {}

void TestSuite::after_setup() {
  //active_test->details.append("Setup finished - ");
}

void TestSuite::after_tear_down() {
  //active_test->details.append("TearDown finished!");
}

void TestSuite::execute_tests(const string& suite_name) {
  for(tTestIter i=tests.begin(); i!=tests.end(); ++i) {
    i->second.res.id = suite_name + "::" + i->first;
    active_test = &i->second;
    setup();
    after_setup();
    try {
      (i->second.object->*i->second.method)(true);
    } catch(TOOLS::BaseException& e) {
      i->second.res.details.append(
          "[E] test failed - exception caught: " + e.output + " - ");
      i->second.res.result = false;
    } catch(exception& e) {
      i->second.res.details.append(
          "[E] test failed - std::exception caught: " + str(e.what()) + " - ");
      i->second.res.result = false;
    }
    tear_down();
    after_tear_down();
    active_test = NULL;
    i->second.res.show(false);
  }
}

TestResult::TestResult(const string& testid, bool res, const string& details)
  : id(testid), result(res), details(details) {}

TestResult::TestResult() : id(""), result(true) {}

void TestResult::show(bool show_details) {
  string icon, rating;
  if(result) {
    rating = "GOOD";
    icon = "+";
  } else {
    rating = "BAD!";
    icon = "-";
  }

  cout << "[" << icon << "] " << left << setw(45) << id << \
    setw(20) << right << rating << endl;

  if(details != "" && ((!show_details && !result) || show_details))
    cout << "[i]    " << details << endl;

}

TestFramework::TestFramework(int argc, char* argv[]) {
  show_details = (argc == 2 && str(argv[1]) == "-d") ? true : false;
}

TestFramework::~TestFramework() {
  for(tTestSuiteIter i=test_suites.begin(); i!=test_suites.end(); ++i)
    delete i->second;
}

void TestFramework::run() {
  for(tTestSuiteIter i=test_suites.begin(); i!=test_suites.end(); ++i)
    i->second->execute_tests(i->first);
}

void TestFramework::show_result_overview() {
  int good = 0;
  int bad = 0;
  int all_tests = 0;

  for(tTestSuiteIter i=test_suites.begin(); i!=test_suites.end(); ++i) {
    all_tests += i->second->check_count;
    for(tTestIter j=i->second->tests.begin(); j!=i->second->tests.end(); ++j) {
      (j->second.res.result) ? good++ : bad++;
    }
  }
  cout << endl << "[i] Finished TestRun (" <<
    all_tests << " checks done) - Tests: good: " << good;
  if(bad > 0)
    cout << " and bad: " << bad << endl;
  else
    cout << " and NO bad ones!" << endl;
}

void TestFramework::print_stacktrace(uint max_frames) {
    cerr << "[BT] Showing stacktrace: " << endl;

    void* addrlist[max_frames+1];
    int addrlen = backtrace(addrlist, sizeof(addrlist) / sizeof(void*));

    if(addrlen == 0) {
        cerr << "[E] backtrace() returned 0 - Error!" << endl;
        return;
    }
    // resolve addresses to -> "filename(function+address)"
    // symlist must be free()-ed !
    char** symlist = backtrace_symbols(addrlist, addrlen);

    size_t funcnamesize = 256;
    char* funcname = (char*)malloc(funcnamesize);

    // demangle all functionnames
    for (int i=1; i<addrlen; ++i) {
        char* begin_name = 0;
        char* begin_offset = 0;
        char* end_offset = 0;

        // find parentheses and +address offset surrounding the mangled name:
        // ./module(function+0x15c) [0x8048a6d]
        for (char *p = symlist[i]; *p; ++p) {
            if (*p == '(')
                begin_name = p;
            else if (*p == '+')
                begin_offset = p;
            else if (*p == ')' && begin_offset) {
                end_offset = p;
                break;
            }
        }

        if (begin_name && begin_offset && end_offset
            && begin_name < begin_offset) {
            *begin_name++ = '\0';
            *begin_offset++ = '\0';
            *end_offset = '\0';

            // mangled name is now in [begin_name, begin_offset) and caller
            // offset in [begin_offset, end_offset). now apply
            // __cxa_demangle():

            int status;
            char* ret = abi::__cxa_demangle(begin_name,
                                            funcname, &funcnamesize, &status);
            if (status == 0) {
                funcname = ret; // use possibly realloc()-ed string
                cerr << "[BT] " << symlist[i] << " " \
                     << funcname << "+" << begin_offset << endl;
            } else { // demangle failes
                cerr << "[BT] " << symlist[i] << " " \
                     << begin_name << "+" << begin_offset << endl;
            }
        } else // parsing failed
            cerr << "[BT]" << symlist[i] << endl;
    }
    free(funcname);
    free(symlist);
}

<|endoftext|>


<commit_before>#include <memory>
#include <stack>
#include <cstdio>

class Vector
{
public:
    Vector(float x, float y, float z): x_(x), y_(y), z_(z)
    {
        printf("Vector ctor\n");
    }

    virtual ~Vector()
    {
        x_ = 0;
        y_ = 0;
        z_ = 0;
        printf("~Vector\n");
    }

    float x_, y_, z_;
};

class Deleter
{
public:
    void operator() (Vector* v)
    {
    }

private:

};

class Pool
{
public:
    std::shared_ptr<Vector> create(float a, float b, float c)
    {
        printf("create object\n");
        Vector* v = NULL;

        if (!this->pool.empty())
        {
            printf("reuse memory\n");
            v = this->pool.top();
            this->pool.pop();
            v->x_ = a;
            v->y_ = b;
            v->z_ = c;
        }
        else
        {
            v = new Vector(1, 1, 1);
        }

        return std::shared_ptr<Vector>(v, std::bind(&Pool::free, this, std::placeholders::_1));
    }

    void free(Vector* v)
    {
        v->~Vector();
        printf("call free\n");
        this->pool.push(v);
    }

private:
    std::stack<Vector*> pool;
};

int main()
{
    {
        printf("create normal shared_ptr\n");
        std::shared_ptr<Vector> v(new Vector(1, 1, 1));
    }

    {
        printf("create shared_ptr with pool deleter\n");
        Pool p;
        std::shared_ptr<Vector> v(new Vector(1, 1, 1), std::bind(&Pool::free, p, std::placeholders::_1));
    }

    Pool p;
    {
        printf("get shared_ptr from pool\n");
        std::shared_ptr<Vector> v = p.create(1, 1, 1);
    }

    {
        printf("reuse shared_ptr from pool\n");
        std::shared_ptr<Vector> v = p.create(1, 1, 1);
    }

    return (0);
}
<commit_msg>* Remove redundant code<commit_after>#include <memory>
#include <stack>
#include <cstdio>

class Vector
{
public:
    Vector(float x, float y, float z): x_(x), y_(y), z_(z)
    {
        printf("Vector ctor\n");
    }

    virtual ~Vector()
    {
        x_ = 0;
        y_ = 0;
        z_ = 0;
        printf("~Vector\n");
    }

    float x_, y_, z_;
};

class Pool
{
public:
    std::shared_ptr<Vector> create(float a, float b, float c)
    {
        printf("create object\n");
        Vector* v = NULL;

        if (!this->pool.empty())
        {
            printf("reuse memory\n");
            v = this->pool.top();
            this->pool.pop();
            v->x_ = a;
            v->y_ = b;
            v->z_ = c;
        }
        else
        {
            v = new Vector(1, 1, 1);
        }

        return std::shared_ptr<Vector>(v, std::bind(&Pool::free, this, std::placeholders::_1));
    }

    void free(Vector* v)
    {
        v->~Vector();
        printf("call free\n");
        this->pool.push(v);
    }

private:
    std::stack<Vector*> pool;
};

int main()
{
    {
        printf("create normal shared_ptr\n");
        std::shared_ptr<Vector> v(new Vector(1, 1, 1));
    }

    {
        printf("create shared_ptr with pool deleter\n");
        Pool p;
        std::shared_ptr<Vector> v(new Vector(1, 1, 1), std::bind(&Pool::free, p, std::placeholders::_1));
    }

    Pool p;
    {
        printf("get shared_ptr from pool\n");
        std::shared_ptr<Vector> v = p.create(1, 1, 1);
    }

    {
        printf("reuse shared_ptr from pool\n");
        std::shared_ptr<Vector> v = p.create(1, 1, 1);
    }

    return (0);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <unistd.h>
#include <stdio.h>
#include <sys/unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <errno.h>
// #include<signal>

using namespace std;

bool execute (string pass)
{
	bool valid = true;

	char* test[80];
	//valid = 1;
	vector<string> command;
	string temp= "";
	unsigned j = 0;
	unsigned i = 0;

	while (i < pass.size())
	{
		for (j = i ; j < pass.size(); ++j)
		{
			if (pass.at(j) ==' ')
			{
				//this means we are moving to next word.
				++j;
				break;
			}
			else
			{
				temp = temp + pass.at(j);
			}
		}

		if (temp == "exit")
		{
			command.clear();
			temp.clear();
			exit(0);
		}

		command.push_back(temp);
		temp.clear();

		//so we can start basing on where we left off in pass string
		i = j;
	}

	unsigned k = 0;

	for(; k < command.size() ;++k)
    {
    	string temp_str = command.at(k);
        test[k] = (char*)temp_str.c_str();
    }

    test[k] = '\0';

	pid_t pid = fork();

	//if pid is less than 0, then fork failed
 	if (pid < 0)
 	{
 		perror("Fork failed");
 		exit(-1);
 	}

	/*run execvp in the child because execvp automatically terminates all
	  processes after it executes*/
 	if (pid == 0) //child process
    {
    	//if execvp returns -1, the command did not execute
        if (execvp(test[0], test) == -1)
        {
        	perror("exec");
        	exit(errno);
        	valid = false;
        }
        else
        {
        	//successful completion
        	exit(0);
        }
    }

	int num = 0;
	//tells parent to wait
	wait(&num);

	int num2 = WEXITSTATUS(num);

	//if errno > 0, it did not work
	if (num2 > 0)
	{
		valid = false;
	}

	//successful completion
	if (num2 == 0)
	{
		valid = true;
	}

	command.clear();
	return valid;
}

void parse (vector<string> &input)
{
	vector<string> reverse_input;

	//reverse the vector of inputs
	//so we can use pop_back (we could make a quene but we did this instead)
	for (int i = input.size() - 1; i >= 0; --i)
	{
		reverse_input.push_back(input.at(i));
	}

	//check if the 1st command is exit
	//if it is, exit the program
	if (input.at(0) == "exit")
	{
		input.clear();
		reverse_input.clear();
		exit(0);
	}

	//execute 1st command;
	bool  valid;
	int size = reverse_input.size();
	valid = execute(reverse_input.at(size - 1));
	reverse_input.pop_back();

	//parse this vector and execute accordingly
	for (int i = reverse_input.size() - 1; i >= 0; i = i - 2)
	{
		if (reverse_input.at(i) == ";")
		{
			//check for exit command
			if (reverse_input.at(i - 1) == "exit")
			{
				execute(reverse_input.at(i - 1));
			}

			//always execute a command that follows a semicolon
			execute(reverse_input.at(i - 1));
			reverse_input.pop_back();
			reverse_input.pop_back();
		}
		else if (reverse_input.at(i) == "&&")
		{
			if (valid == true) //1st command executed properly
			{
				//check for exit command
				if (reverse_input.at(i - 1) == "exit")
				{
					execute(reverse_input.at(i - 1));
				}

				//execute 2nd command
				execute(reverse_input.at(i - 1));
			}
			//if the 1st command is NOT valid, we do NOT want to execute the 2nd one
			/*whether we execute or not, we still want to pop_back() 3 times to
			  move to the next command*/
			reverse_input.pop_back();
			reverse_input.pop_back();
		}
		else if (reverse_input.at(i) == "||")
		{
			if (valid == false) //1st command did not execute
			{
				//check for exit command
				if (reverse_input.at(i - 1) == "exit")
				{
					execute(reverse_input.at(i - 1));
				}

				execute(reverse_input.at(i - 1));
			}

			//if the 1st command is VALID, we do NOT want to execute the 2nd one
			/*whether we execute or not, we still want to pop_back() 3 times to
			  move to the next command*/
			reverse_input.pop_back();
			reverse_input.pop_back();
		}
	}
}

int main()
{
	//loop until the user exits
	while (1)
	{
		//command line inputted by user
		char userInput[100];

		//to hold the user input after the comments are removed
		char userInput_no_comments[100];

		//get hostname (extra credit)
		char hostname[80];
	    gethostname(hostname, sizeof hostname);

		//print a command prompt (e.g. $)
		printf("%s $ ", hostname);
		// cout << "$ ";

		//read in command as one line
		cin.getline(userInput, 100);

		if(userInput[0] != '\0' || userInput[0] != ' ')
		{
			//ignore everything after '#' (everything after '#' is a comment)
			for (int i = 0; userInput[i] != '\0'; ++i)
			{
				if (userInput[i] == '#')
				{
					break;
				}

				userInput_no_comments[i] = userInput[i];
				userInput_no_comments[i + 1] = '\0';
			}

			//get connectors from userInput and store it into a vector
			//but in this vector && and || are stored as & & and | |
			vector<char> vector_connectors_separated;

			//FIX THIS LATER IF THERE IS TIME
			//DOES NOT ACCOUNT FOR JUST '&', JUST '|', OR MORE THAN TWO '&'s OR '|'s
			//ALSO DOES NOT ACCOUNT FOR MORE THAN ONE ';' IN A ROW
			for (unsigned i = 0; userInput_no_comments[i] != '\0'; ++i)
			{
				if (userInput_no_comments[i] == ';'|| userInput_no_comments[i] == '&'
					|| userInput_no_comments[i] == '|')
				{
					vector_connectors_separated.push_back(userInput[i]);
				}
			}

			//NOW COMBIN & and & into && and | and | into ||
			vector<string> vector_connectors;

			for (unsigned i = 0; i < vector_connectors_separated.size(); ++i)
			{
				if (vector_connectors_separated.at(i) == '&')
				{
					vector_connectors.push_back("&&");
					++i;
				}
				else if (vector_connectors_separated.at(i) == '|')
				{
					vector_connectors.push_back("||");
					++i;
				}
				else if (vector_connectors_separated.at(i) == ';')
				{
					vector_connectors.push_back(";");
				}
			}

			//use strtok to separate input into "tokens"
			char* tokens; //command and its arguments
			char delimiters[] = ";&&||";
			tokens = strtok(userInput_no_comments, delimiters);

			//stores all the commands and its arguments as separate "tokens"
			vector<char*> vector_tokens;

			while (tokens != NULL)
			{
				// int position =0;
				// while(())
				//remove first whitespace in token
				if (tokens[0] == ' ')
				{
					++tokens; //go to next character (ignore 1st white space)
				}

				vector_tokens.push_back(tokens);
				tokens = strtok(NULL, delimiters);
			}

			//convert the tokens from char* to string
			vector<string> vector_tokens_str;

			for (unsigned i = 0; i < vector_tokens.size(); ++i)
			{
				char* s = vector_tokens.at(i);
				string str(s);
				vector_tokens_str.push_back(str);
			}

			//put everything into one vector called input
			vector<string> input;

			for (unsigned i = 0; i < vector_tokens_str.size() - 1; ++i)
			{
				input.push_back(vector_tokens_str.at(i));
				input.push_back(vector_connectors.at(i));
			}

			//add in the last command
			/*if we put this in the for loop above, it would go out of range, because
			  vector_connectors is smalled than vector_tokens_str by one*/
			int size = vector_tokens_str.size();
			input.push_back(vector_tokens_str.at(size - 1));

			//clearing everyyything
			vector_tokens_str.clear();
			vector_connectors.clear();
			vector_connectors_separated.clear();
			// userInput = "";
			//delete[] userInput;
			// userInput_no_comments("");

			//run execute on commands
			parse(input);
		}
	}

	return 0;
}<commit_msg>extra credit works?<commit_after>#include <iostream>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <unistd.h>
#include <stdio.h>
#include <sys/unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <errno.h>
// #include<signal>

using namespace std;

bool execute (string pass)
{
	bool valid = true;

	char* test[80];
	//valid = 1;
	vector<string> command;
	string temp= "";
	unsigned j = 0;
	unsigned i = 0;

	while (i < pass.size())
	{
		for (j = i ; j < pass.size(); ++j)
		{
			if (pass.at(j) ==' ')
			{
				//this means we are moving to next word.
				++j;
				break;
			}
			else
			{
				temp = temp + pass.at(j);
			}
		}

		if (temp == "exit")
		{
			command.clear();
			temp.clear();
			exit(0);
		}

		command.push_back(temp);
		temp.clear();

		//so we can start basing on where we left off in pass string
		i = j;
	}

	unsigned k = 0;

	for(; k < command.size() ;++k)
    {
    	string temp_str = command.at(k);
        test[k] = (char*)temp_str.c_str();
    }

    test[k] = '\0';

	pid_t pid = fork();

	//if pid is less than 0, then fork failed
 	if (pid < 0)
 	{
 		perror("Fork failed");
 		exit(-1);
 	}

	/*run execvp in the child because execvp automatically terminates all
	  processes after it executes*/
 	if (pid == 0) //child process
    {
    	//if execvp returns -1, the command did not execute
        if (execvp(test[0], test) == -1)
        {
        	perror("exec");
        	exit(errno);
        	valid = false;
        }
        else
        {
        	//successful completion
        	exit(0);
        }
    }

	int num = 0;
	//tells parent to wait
	wait(&num);

	int num2 = WEXITSTATUS(num);

	//if errno > 0, it did not work
	if (num2 > 0)
	{
		valid = false;
	}

	//successful completion
	if (num2 == 0)
	{
		valid = true;
	}

	command.clear();
	return valid;
}

void parse (vector<string> &input)
{
	vector<string> reverse_input;

	//reverse the vector of inputs
	//so we can use pop_back (we could make a quene but we did this instead)
	for (int i = input.size() - 1; i >= 0; --i)
	{
		reverse_input.push_back(input.at(i));
	}

	//check if the 1st command is exit
	//if it is, exit the program
	if (input.at(0) == "exit")
	{
		input.clear();
		reverse_input.clear();
		exit(0);
	}

	//execute 1st command;
	bool  valid;
	int size = reverse_input.size();
	valid = execute(reverse_input.at(size - 1));
	reverse_input.pop_back();

	//parse this vector and execute accordingly
	for (int i = reverse_input.size() - 1; i >= 0; i = i - 2)
	{
		if (reverse_input.at(i) == ";")
		{
			//check for exit command
			if (reverse_input.at(i - 1) == "exit")
			{
				execute(reverse_input.at(i - 1));
			}

			//always execute a command that follows a semicolon
			execute(reverse_input.at(i - 1));
			reverse_input.pop_back();
			reverse_input.pop_back();
		}
		else if (reverse_input.at(i) == "&&")
		{
			if (valid == true) //1st command executed properly
			{
				//check for exit command
				if (reverse_input.at(i - 1) == "exit")
				{
					execute(reverse_input.at(i - 1));
				}

				//execute 2nd command
				execute(reverse_input.at(i - 1));
			}
			//if the 1st command is NOT valid, we do NOT want to execute the 2nd one
			/*whether we execute or not, we still want to pop_back() 3 times to
			  move to the next command*/
			reverse_input.pop_back();
			reverse_input.pop_back();
		}
		else if (reverse_input.at(i) == "||")
		{
			if (valid == false) //1st command did not execute
			{
				//check for exit command
				if (reverse_input.at(i - 1) == "exit")
				{
					execute(reverse_input.at(i - 1));
				}

				execute(reverse_input.at(i - 1));
			}

			//if the 1st command is VALID, we do NOT want to execute the 2nd one
			/*whether we execute or not, we still want to pop_back() 3 times to
			  move to the next command*/
			reverse_input.pop_back();
			reverse_input.pop_back();
		}
	}
}

int main()
{
	//loop until the user exits
	while (1)
	{
		//command line inputted by user
		char userInput[100];

		//to hold the user input after the comments are removed
		char userInput_no_comments[100];
//====================EXTRA CREDIT======================================
		//get hostname (extra credit)
		char hostname[80];
	    gethostname(hostname, sizeof hostname);
	    //get username
	    char *name;
	    name = getenv("USER");
    	printf("%s@",name);
		//print a command prompt (e.g. $)
		printf("%s $ ", hostname);
//==========================================================
		//read in command as one line
		cin.getline(userInput, 100);

		if(userInput[0] != '\0' || userInput[0] != ' ')
		{
			//ignore everything after '#' (everything after '#' is a comment)
			for (int i = 0; userInput[i] != '\0'; ++i)
			{
				if (userInput[i] == '#')
				{
					break;
				}

				userInput_no_comments[i] = userInput[i];
				userInput_no_comments[i + 1] = '\0';
			}

			//get connectors from userInput and store it into a vector
			//but in this vector && and || are stored as & & and | |
			vector<char> vector_connectors_separated;

			//FIX THIS LATER IF THERE IS TIME
			//DOES NOT ACCOUNT FOR JUST '&', JUST '|', OR MORE THAN TWO '&'s OR '|'s
			//ALSO DOES NOT ACCOUNT FOR MORE THAN ONE ';' IN A ROW
			for (unsigned i = 0; userInput_no_comments[i] != '\0'; ++i)
			{
				if (userInput_no_comments[i] == ';'|| userInput_no_comments[i] == '&'
					|| userInput_no_comments[i] == '|')
				{
					vector_connectors_separated.push_back(userInput[i]);
				}
			}

			//NOW COMBIN & and & into && and | and | into ||
			vector<string> vector_connectors;

			for (unsigned i = 0; i < vector_connectors_separated.size(); ++i)
			{
				if (vector_connectors_separated.at(i) == '&')
				{
					vector_connectors.push_back("&&");
					++i;
				}
				else if (vector_connectors_separated.at(i) == '|')
				{
					vector_connectors.push_back("||");
					++i;
				}
				else if (vector_connectors_separated.at(i) == ';')
				{
					vector_connectors.push_back(";");
				}
			}

			//use strtok to separate input into "tokens"
			char* tokens; //command and its arguments
			char delimiters[] = ";&&||";
			tokens = strtok(userInput_no_comments, delimiters);

			//stores all the commands and its arguments as separate "tokens"
			vector<char*> vector_tokens;

			while (tokens != NULL)
			{
				// int position =0;
				// while(())
				//remove first whitespace in token
				if (tokens[0] == ' ')
				{
					++tokens; //go to next character (ignore 1st white space)
				}

				vector_tokens.push_back(tokens);
				tokens = strtok(NULL, delimiters);
			}

			//convert the tokens from char* to string
			vector<string> vector_tokens_str;

			for (unsigned i = 0; i < vector_tokens.size(); ++i)
			{
				char* s = vector_tokens.at(i);
				string str(s);
				vector_tokens_str.push_back(str);
			}

			//put everything into one vector called input
			vector<string> input;

			for (unsigned i = 0; i < vector_tokens_str.size() - 1; ++i)
			{
				input.push_back(vector_tokens_str.at(i));
				input.push_back(vector_connectors.at(i));
			}

			//add in the last command
			/*if we put this in the for loop above, it would go out of range, because
			  vector_connectors is smalled than vector_tokens_str by one*/
			int size = vector_tokens_str.size();
			input.push_back(vector_tokens_str.at(size - 1));

			//clearing everyyything
			vector_tokens_str.clear();
			vector_connectors.clear();
			vector_connectors_separated.clear();
			// userInput = "";
			//delete[] userInput;
			// userInput_no_comments("");

			//run execute on commands
			parse(input);
		}
	}

	return 0;
}<|endoftext|>


<commit_before>#pragma once
#include "boost/pool/pool.hpp"

namespace spn {
	//! 整数値を型として扱う
	template <int N>
	struct Number2Type {};

	//! boost::object_poolをstd::allocatorとして扱うクラス
	template <class T, class IDType, size_t DefNum>
	class StdPool {
		public:
			static boost::pool<>	s_pool;

			// 型定義
			using size_type = size_t;
			using difference_type = ptrdiff_t;
			using pointer = T*;
			using const_pointer = const T*;
			using reference = T&;
			using const_reference = const T&;
			using value_type = T;

			// アロケータをU型にバインドする
			template <class U>
			struct rebind {
				using other = StdPool<U,IDType,DefNum>;
			};

			//! コンストラクタ
			StdPool() noexcept {}
			StdPool(const StdPool&) noexcept {}
			//! デストラクタ
			~StdPool() throw(){}

			//! メモリを割り当てる
			pointer allocate(size_type num, typename StdPool<T,IDType,DefNum>::const_pointer hint = 0) {
				if(num == 1)
					return reinterpret_cast<pointer>(s_pool.malloc());
				return reinterpret_cast<pointer>(s_pool.ordered_malloc(num));
			}
			//! 割当て済みの領域を初期化する
			void construct(pointer p, const T& value) {
				new( (void*)p ) T(value);
			}

			//! メモリを解放する
			void deallocate(pointer p, size_type num) {
				if(num == 1)
					s_pool.free(p);
				else
					s_pool.ordered_free(p);
			}
			//! 初期化済みの領域を削除する
			void destroy(pointer p) {
				p->~T();
			}

			//! アドレスを返す
			pointer address(reference value) const { return &value; }
			const_pointer address(const_reference value) const { return &value; }
			//! 割当てることができる最大の要素数を返す
			size_type max_size() const throw() {
				return std::numeric_limits<size_t>::max() / sizeof(T);
			}
	};
	template <class T, class IDType, size_t DefNum>
	boost::pool<> StdPool<T,IDType,DefNum>::s_pool(sizeof(T), DefNum);

	template <class T1, class T2, class ID1, class ID2, size_t DN1, size_t DN2>
	bool operator==(const StdPool<T1,ID1,DN1>&, const StdPool<T2,ID2,DN2>&) noexcept { return false; }
	template <class T, class ID, size_t DN>
	bool operator==(const StdPool<T,ID,DN>&, const StdPool<T,ID,DN>&) noexcept { return true; }

	template <class T1, class T2, class ID1, class ID2, size_t DN1, size_t DN2>
	bool operator!=(const StdPool<T1,ID1,DN1>&, const StdPool<T2,ID2,DN2>&) noexcept { return true; }
	template <class T, class ID, size_t DN>
	bool operator!=(const StdPool<T,ID,DN>&, const StdPool<T,ID,DN>&) noexcept { return false; }
}
<commit_msg>StdPoolの廃止: boost::fast_pool_allocatorを推奨<commit_after><|endoftext|>


<commit_before>#include <iostream>
#include <cstdlib>
#include <thread>
#include <map>
#include <chrono>
#include <ctime>

#include "bench.hpp"
#include "concurrent_counter.hpp"
#include "transactional.hpp"
#include "lock.hpp"

using namespace bench;

long hammerArray(counter::ConcurrentCounter *counter, int nthreads, int nwrites, bool isTx) {
  std::thread threads[nthreads];

  timer::time_point start_time = timer::now();

  // seed prng with time
  srand((unsigned)time(nullptr));

  sync::ThreadState ts;
  spinlock_t ts_lock;

  for (int thread_id = 0; thread_id < nthreads; ++thread_id) {

    threads[thread_id] = std::thread([thread_id, nwrites, counter, &ts, &ts_lock]() {
	int sz = counter->size();
	for (int times = 0; times < nwrites;  ++times) {
	  int idx = rand() % sz;
	  counter->increment(idx);
	}

	 {
	   //sync::TransactionalScope xact(ts_lock, true);
	   ts += sync::TransactionalScope::getStats();
	   //sync::TransactionalScope::printStats();
	 }

      });

  }

  for (int i = 0; i < nthreads; ++i) {
    threads[i].join();
  }

  timer::time_point end_time = timer::now();
  //if (isTx) {
  //sync::TransactionalScope::printStats(ts);
  //}
  return std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count();

}

int main(void) {

  std::size_t max_elements = 4096;

  int nthreads = 8, nwrites = 1000000;

  // Print CSV headers
  std::cout << "Implementation,NumElements,TimeMillis,ThroughputWPerSec,AvgNanos" << std::endl;
  std::string DELIM(",");

  double MICROS_TO_NANOS = 1000.0;
  double MICROS_TO_MILLIS = 0.001;
  double MICROS_TO_SECONDS = 0.000001;

  for (std::size_t num_elements = 1; num_elements <= max_elements; num_elements *= 2) {

    // Initialize all impls for testing
    std::map<Impl, counter::ConcurrentCounter*> impls;

    //impls[NoSync] =  new counter::IncorrectConcurrentCounter(num_elements);
    impls[Coarse] = new counter::CoarseConcurrentCounter(num_elements);
    impls[Fine] =  new counter::CoarseConcurrentCounter(num_elements);
    impls[RTMAdaptiveCoarse] =  new counter::RTMCoarseConcurrentCounter(num_elements);
    impls[RTMAdaptiveFine] =  new counter::RTMFineConcurrentCounter(num_elements);
    impls[RTMNaive] = new counter::RTMConcurrentCounter(num_elements);

    // run benchmarks on each array and print output
    for (auto& impl : impls) {
      bool isRTM = (impl.first >= RTMAdaptiveCoarse) && (impl.first <= RTMAdaptiveFine);
      auto run_time = hammerArray(impl.second, nthreads, nwrites, isRTM);
      int total_recorded = impl.second->total();
      int total_expected = nthreads * nwrites;

      // i should really be using the std::chrono time conversions but this code is low priority
      auto avg = run_time / (double)total_recorded;

      int missing = total_recorded - total_expected;
      std::cout << ImplStr[impl.first] << DELIM; // Implementation Col
      std::cout << num_elements << DELIM; // NumElements Col
      std::cout << (double)run_time * MICROS_TO_MILLIS << DELIM; // TimeMillis Col
      std::cout << total_recorded / ((double)run_time * MICROS_TO_SECONDS) << DELIM;
      std::cout << avg * MICROS_TO_NANOS  << std::endl; // AvgNanos Col
      if (total_recorded != total_expected) {
	std::cerr << "ERROR: MISSING WRITES!!!" << std::endl;
      }
      // std::cout << "Total = " << total_recorded << "\tExpected = " << total_expected << std::endl;
      // std::cout << ((total_recorded == total_expected) ?
      // 		    "All writes were recorded." :
      // 		    ((missing<0) ?
      // 		     (std::string("There were ") + std::to_string(-missing) + std::string(" missing writes!")) :
      // 		     (std::string("There were ") + std::to_string(missing) + std::string(" writes that should NOT have occured. This should never happen.")))) << std::endl;
      delete impl.second;
    }
  }

}
<commit_msg>generate much more data<commit_after>#include <iostream>
#include <cstdlib>
#include <thread>
#include <map>
#include <chrono>
#include <ctime>

#include "bench.hpp"
#include "concurrent_counter.hpp"
#include "transactional.hpp"
#include "lock.hpp"

using namespace bench;

long hammerArray(counter::ConcurrentCounter *counter, int nthreads, int nwrites, bool isTx) {
  std::thread threads[nthreads];

  timer::time_point start_time = timer::now();

  // seed prng with time
  srand((unsigned)time(nullptr));

  sync::ThreadState ts;
  spinlock_t ts_lock;

  for (int thread_id = 0; thread_id < nthreads; ++thread_id) {

    threads[thread_id] = std::thread([thread_id, nwrites, counter, &ts, &ts_lock]() {
	int sz = counter->size();
	for (int times = 0; times < nwrites;  ++times) {
	  int idx = rand() % sz;
	  counter->increment(idx);
	}

	 {
	   //sync::TransactionalScope xact(ts_lock, true);
	   ts += sync::TransactionalScope::getStats();
	   //sync::TransactionalScope::printStats();
	 }

      });

  }

  for (int i = 0; i < nthreads; ++i) {
    threads[i].join();
  }

  timer::time_point end_time = timer::now();
  //if (isTx) {
  //sync::TransactionalScope::printStats(ts);
  //}
  return std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count();

}

int main(void) {

  std::size_t max_elements = 4096;
  std::size_t granularity = 64;

  int nthreads = 8, nwrites = 1000000; // increase write count for additional accuracy

  // Print CSV headers
  std::cout << "Implementation,NumElements,TimeMillis,ThroughputWPerSec,AvgNanos" << std::endl;
  std::string DELIM(",");

  double MICROS_TO_NANOS = 1000.0;
  double MICROS_TO_MILLIS = 0.001;
  double MICROS_TO_SECONDS = 0.000001;

  for (std::size_t num_elements = granularity; num_elements <= max_elements; num_elements += granularity) {

    // Initialize all impls for testing
    std::map<Impl, counter::ConcurrentCounter*> impls;

    //impls[NoSync] =  new counter::IncorrectConcurrentCounter(num_elements);
    impls[Coarse] = new counter::CoarseConcurrentCounter(num_elements);
    impls[Fine] =  new counter::CoarseConcurrentCounter(num_elements);
    impls[RTMAdaptiveCoarse] =  new counter::RTMCoarseConcurrentCounter(num_elements);
    impls[RTMAdaptiveFine] =  new counter::RTMFineConcurrentCounter(num_elements);
    impls[RTMNaive] = new counter::RTMConcurrentCounter(num_elements);

    // run benchmarks on each array and print output
    for (auto& impl : impls) {
      bool isRTM = (impl.first >= RTMAdaptiveCoarse) && (impl.first <= RTMAdaptiveFine);
      auto run_time = hammerArray(impl.second, nthreads, nwrites, isRTM);
      int total_recorded = impl.second->total();
      int total_expected = nthreads * nwrites;

      // i should really be using the std::chrono time conversions but this code is low priority
      auto avg = run_time / (double)total_recorded;

      int missing = total_recorded - total_expected;
      std::cout << ImplStr[impl.first] << DELIM; // Implementation Col
      std::cout << num_elements << DELIM; // NumElements Col
      std::cout << (double)run_time * MICROS_TO_MILLIS << DELIM; // TimeMillis Col
      std::cout << total_recorded / ((double)run_time * MICROS_TO_SECONDS) << DELIM;
      std::cout << avg * MICROS_TO_NANOS  << std::endl; // AvgNanos Col
      if (total_recorded != total_expected) {
	std::cerr << "ERROR: MISSING WRITES!!!" << std::endl;
      }
      // std::cout << "Total = " << total_recorded << "\tExpected = " << total_expected << std::endl;
      // std::cout << ((total_recorded == total_expected) ?
      // 		    "All writes were recorded." :
      // 		    ((missing<0) ?
      // 		     (std::string("There were ") + std::to_string(-missing) + std::string(" missing writes!")) :
      // 		     (std::string("There were ") + std::to_string(missing) + std::string(" writes that should NOT have occured. This should never happen.")))) << std::endl;
      delete impl.second;
    }
  }

}
<|endoftext|>


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

#include "bloom.h"

#include "primitives/transaction.h"
#include "hash.h"
#include "script/script.h"
#include "script/standard.h"
#include "random.h"
#include "streams.h"

#include <math.h>
#include <stdlib.h>

#include <boost/foreach.hpp>

#define LN2SQUARED 0.4804530139182014246671025263266649717305529515945455
#define LN2 0.6931471805599453094172321214581765680755001343602552

using namespace std;

CBloomFilter::CBloomFilter(const unsigned int nElements, const double nFPRate, const unsigned int nTweakIn, unsigned char nFlagsIn) :
    /**
     * The ideal size for a bloom filter with a given number of elements and false positive rate is:
     * - nElements * log(fp rate) / ln(2)^2
     * We ignore filter parameters which will create a bloom filter larger than the protocol limits
     */
    vData(min((unsigned int)(-1  / LN2SQUARED * nElements * log(nFPRate)), MAX_BLOOM_FILTER_SIZE * 8) / 8),
    /**
     * The ideal number of hash functions is filter size * ln(2) / number of elements
     * Again, we ignore filter parameters which will create a bloom filter with more hash functions than the protocol limits
     * See https://en.wikipedia.org/wiki/Bloom_filter for an explanation of these formulas
     */
    isFull(false),
    isEmpty(true),
    nHashFuncs(min((unsigned int)(vData.size() * 8 / nElements * LN2), MAX_HASH_FUNCS)),
    nTweak(nTweakIn),
    nFlags(nFlagsIn)
{
}

// Private constructor used by CRollingBloomFilter
CBloomFilter::CBloomFilter(const unsigned int nElements, const double nFPRate, const unsigned int nTweakIn) :
    vData((unsigned int)(-1  / LN2SQUARED * nElements * log(nFPRate)) / 8),
    isFull(false),
    isEmpty(true),
    nHashFuncs((unsigned int)(vData.size() * 8 / nElements * LN2)),
    nTweak(nTweakIn),
    nFlags(BLOOM_UPDATE_NONE)
{
}

inline unsigned int CBloomFilter::Hash(unsigned int nHashNum, const std::vector<unsigned char>& vDataToHash) const
{
    // 0xFBA4C795 chosen as it guarantees a reasonable bit difference between nHashNum values.
    return MurmurHash3(nHashNum * 0xFBA4C795 + nTweak, vDataToHash) % (vData.size() * 8);
}

void CBloomFilter::insert(const vector<unsigned char>& vKey)
{
    if (isFull)
        return;
    for (unsigned int i = 0; i < nHashFuncs; i++)
    {
        unsigned int nIndex = Hash(i, vKey);
        // Sets bit nIndex of vData
        vData[nIndex >> 3] |= (1 << (7 & nIndex));
    }
    isEmpty = false;
}

void CBloomFilter::insert(const COutPoint& outpoint)
{
    CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
    stream << outpoint;
    vector<unsigned char> data(stream.begin(), stream.end());
    insert(data);
}

void CBloomFilter::insert(const uint256& hash)
{
    vector<unsigned char> data(hash.begin(), hash.end());
    insert(data);
}

bool CBloomFilter::contains(const vector<unsigned char>& vKey) const
{
    if (isFull)
        return true;
    if (isEmpty)
        return false;
    for (unsigned int i = 0; i < nHashFuncs; i++)
    {
        unsigned int nIndex = Hash(i, vKey);
        // Checks bit nIndex of vData
        if (!(vData[nIndex >> 3] & (1 << (7 & nIndex))))
            return false;
    }
    return true;
}

bool CBloomFilter::contains(const COutPoint& outpoint) const
{
    CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
    stream << outpoint;
    vector<unsigned char> data(stream.begin(), stream.end());
    return contains(data);
}

bool CBloomFilter::contains(const uint256& hash) const
{
    vector<unsigned char> data(hash.begin(), hash.end());
    return contains(data);
}

void CBloomFilter::clear()
{
    vData.assign(vData.size(),0);
    isFull = false;
    isEmpty = true;
}

void CBloomFilter::reset(const unsigned int nNewTweak)
{
    clear();
    nTweak = nNewTweak;
}

bool CBloomFilter::IsWithinSizeConstraints() const
{
    return vData.size() <= MAX_BLOOM_FILTER_SIZE && nHashFuncs <= MAX_HASH_FUNCS;
}

bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx)
{
    bool fFound = false;
    // Match if the filter contains the hash of tx
    //  for finding tx when they appear in a block
    if (isFull)
        return true;
    if (isEmpty)
        return false;
    const uint256& hash = tx.GetHash();
    if (contains(hash))
        fFound = true;

    for (unsigned int i = 0; i < tx.vout.size(); i++)
    {
        const CTxOut& txout = tx.vout[i];
        // Match if the filter contains any arbitrary script data element in any scriptPubKey in tx
        // If this matches, also add the specific output that was matched.
        // This means clients don't have to update the filter themselves when a new relevant tx
        // is discovered in order to find spending transactions, which avoids round-tripping and race conditions.
        CScript::const_iterator pc = txout.scriptPubKey.begin();
        vector<unsigned char> data;
        while (pc < txout.scriptPubKey.end())
        {
            opcodetype opcode;
            if (!txout.scriptPubKey.GetOp(pc, opcode, data))
                break;
            if (data.size() != 0 && contains(data))
            {
                fFound = true;
                if ((nFlags & BLOOM_UPDATE_MASK) == BLOOM_UPDATE_ALL)
                    insert(COutPoint(hash, i));
                else if ((nFlags & BLOOM_UPDATE_MASK) == BLOOM_UPDATE_P2PUBKEY_ONLY)
                {
                    txnouttype type;
                    vector<vector<unsigned char> > vSolutions;
                    if (Solver(txout.scriptPubKey, type, vSolutions) &&
                            (type == TX_PUBKEY || type == TX_MULTISIG))
                        insert(COutPoint(hash, i));
                }
                break;
            }
        }
    }

    if (fFound)
        return true;

    BOOST_FOREACH(const CTxIn& txin, tx.vin)
    {
        // Match if the filter contains an outpoint tx spends
        if (contains(txin.prevout))
            return true;

        // Match if the filter contains any arbitrary script data element in any scriptSig in tx
        CScript::const_iterator pc = txin.scriptSig.begin();
        vector<unsigned char> data;
        while (pc < txin.scriptSig.end())
        {
            opcodetype opcode;
            if (!txin.scriptSig.GetOp(pc, opcode, data))
                break;
            if (data.size() != 0 && contains(data))
                return true;
        }
    }

    return false;
}

void CBloomFilter::UpdateEmptyFull()
{
    bool full = true;
    bool empty = true;
    for (unsigned int i = 0; i < vData.size(); i++)
    {
        full &= vData[i] == 0xff;
        empty &= vData[i] == 0;
    }
    isFull = full;
    isEmpty = empty;
}

CRollingBloomFilter::CRollingBloomFilter(const unsigned int nElements, const double fpRate)
{
    double logFpRate = log(fpRate);
    /* The optimal number of hash functions is log(fpRate) / log(0.5), but
     * restrict it to the range 1-50. */
    nHashFuncs = std::max(1, std::min((int)round(logFpRate / log(0.5)), 50));
    /* In this rolling bloom filter, we'll store between 2 and 3 generations of nElements / 2 entries. */
    nEntriesPerGeneration = (nElements + 1) / 2;
    uint32_t nMaxElements = nEntriesPerGeneration * 3;
    /* The maximum fpRate = pow(1.0 - exp(-nHashFuncs * nMaxElements / nFilterBits), nHashFuncs)
     * =>          pow(fpRate, 1.0 / nHashFuncs) = 1.0 - exp(-nHashFuncs * nMaxElements / nFilterBits)
     * =>          1.0 - pow(fpRate, 1.0 / nHashFuncs) = exp(-nHashFuncs * nMaxElements / nFilterBits)
     * =>          log(1.0 - pow(fpRate, 1.0 / nHashFuncs)) = -nHashFuncs * nMaxElements / nFilterBits
     * =>          nFilterBits = -nHashFuncs * nMaxElements / log(1.0 - pow(fpRate, 1.0 / nHashFuncs))
     * =>          nFilterBits = -nHashFuncs * nMaxElements / log(1.0 - exp(logFpRate / nHashFuncs))
     */
    uint32_t nFilterBits = (uint32_t)ceil(-1.0 * nHashFuncs * nMaxElements / log(1.0 - exp(logFpRate / nHashFuncs)));
    data.clear();
    /* For each data element we need to store 2 bits. If both bits are 0, the
     * bit is treated as unset. If the bits are (01), (10), or (11), the bit is
     * treated as set in generation 1, 2, or 3 respectively.
     * These bits are stored in separate integers: position P corresponds to bit
     * (P & 63) of the integers data[(P >> 6) * 2] and data[(P >> 6) * 2 + 1]. */
    data.resize(((nFilterBits + 63) / 64) << 1);
    reset();
}

/* Similar to CBloomFilter::Hash */
static inline uint32_t RollingBloomHash(unsigned int nHashNum, uint32_t nTweak, const std::vector<unsigned char>& vDataToHash) {
    return MurmurHash3(nHashNum * 0xFBA4C795 + nTweak, vDataToHash);
}

void CRollingBloomFilter::insert(const std::vector<unsigned char>& vKey)
{
    if (nEntriesThisGeneration == nEntriesPerGeneration) {
        nEntriesThisGeneration = 0;
        nGeneration++;
        if (nGeneration == 4) {
            nGeneration = 1;
        }
        uint64_t nGenerationMask1 = -(uint64_t)(nGeneration & 1);
        uint64_t nGenerationMask2 = -(uint64_t)(nGeneration >> 1);
        /* Wipe old entries that used this generation number. */
        for (uint32_t p = 0; p < data.size(); p += 2) {
            uint64_t p1 = data[p], p2 = data[p + 1];
            uint64_t mask = (p1 ^ nGenerationMask1) | (p2 ^ nGenerationMask2);
            data[p] = p1 & mask;
            data[p + 1] = p2 & mask;
        }
    }
    nEntriesThisGeneration++;

    for (int n = 0; n < nHashFuncs; n++) {
        uint32_t h = RollingBloomHash(n, nTweak, vKey);
        int bit = h & 0x3F;
        uint32_t pos = (h >> 6) % data.size();
        /* The lowest bit of pos is ignored, and set to zero for the first bit, and to one for the second. */
        data[pos & ~1] = (data[pos & ~1] & ~(((uint64_t)1) << bit)) | ((uint64_t)(nGeneration & 1)) << bit;
        data[pos | 1] = (data[pos | 1] & ~(((uint64_t)1) << bit)) | ((uint64_t)(nGeneration >> 1)) << bit;
    }
}

void CRollingBloomFilter::insert(const uint256& hash)
{
    vector<unsigned char> vData(hash.begin(), hash.end());
    insert(vData);
}

bool CRollingBloomFilter::contains(const std::vector<unsigned char>& vKey) const
{
    for (int n = 0; n < nHashFuncs; n++) {
        uint32_t h = RollingBloomHash(n, nTweak, vKey);
        int bit = h & 0x3F;
        uint32_t pos = (h >> 6) % data.size();
        /* If the relevant bit is not set in either data[pos & ~1] or data[pos | 1], the filter does not contain vKey */
        if (!(((data[pos & ~1] | data[pos | 1]) >> bit) & 1)) {
            return false;
        }
    }
    return true;
}

bool CRollingBloomFilter::contains(const uint256& hash) const
{
    vector<unsigned char> vData(hash.begin(), hash.end());
    return contains(vData);
}

void CRollingBloomFilter::reset()
{
    nTweak = GetRand(std::numeric_limits<unsigned int>::max());
    nEntriesThisGeneration = 0;
    nGeneration = 1;
    for (std::vector<uint64_t>::iterator it = data.begin(); it != data.end(); it++) {
        *it = 0;
    }
}
<commit_msg>Fix msvc compiler error C4146 (minus operator applied to unsigned type)<commit_after>// Copyright (c) 2012-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "bloom.h"

#include "primitives/transaction.h"
#include "hash.h"
#include "script/script.h"
#include "script/standard.h"
#include "random.h"
#include "streams.h"

#include <math.h>
#include <stdlib.h>

#include <boost/foreach.hpp>

#define LN2SQUARED 0.4804530139182014246671025263266649717305529515945455
#define LN2 0.6931471805599453094172321214581765680755001343602552

using namespace std;

CBloomFilter::CBloomFilter(const unsigned int nElements, const double nFPRate, const unsigned int nTweakIn, unsigned char nFlagsIn) :
    /**
     * The ideal size for a bloom filter with a given number of elements and false positive rate is:
     * - nElements * log(fp rate) / ln(2)^2
     * We ignore filter parameters which will create a bloom filter larger than the protocol limits
     */
    vData(min((unsigned int)(-1  / LN2SQUARED * nElements * log(nFPRate)), MAX_BLOOM_FILTER_SIZE * 8) / 8),
    /**
     * The ideal number of hash functions is filter size * ln(2) / number of elements
     * Again, we ignore filter parameters which will create a bloom filter with more hash functions than the protocol limits
     * See https://en.wikipedia.org/wiki/Bloom_filter for an explanation of these formulas
     */
    isFull(false),
    isEmpty(true),
    nHashFuncs(min((unsigned int)(vData.size() * 8 / nElements * LN2), MAX_HASH_FUNCS)),
    nTweak(nTweakIn),
    nFlags(nFlagsIn)
{
}

// Private constructor used by CRollingBloomFilter
CBloomFilter::CBloomFilter(const unsigned int nElements, const double nFPRate, const unsigned int nTweakIn) :
    vData((unsigned int)(-1  / LN2SQUARED * nElements * log(nFPRate)) / 8),
    isFull(false),
    isEmpty(true),
    nHashFuncs((unsigned int)(vData.size() * 8 / nElements * LN2)),
    nTweak(nTweakIn),
    nFlags(BLOOM_UPDATE_NONE)
{
}

inline unsigned int CBloomFilter::Hash(unsigned int nHashNum, const std::vector<unsigned char>& vDataToHash) const
{
    // 0xFBA4C795 chosen as it guarantees a reasonable bit difference between nHashNum values.
    return MurmurHash3(nHashNum * 0xFBA4C795 + nTweak, vDataToHash) % (vData.size() * 8);
}

void CBloomFilter::insert(const vector<unsigned char>& vKey)
{
    if (isFull)
        return;
    for (unsigned int i = 0; i < nHashFuncs; i++)
    {
        unsigned int nIndex = Hash(i, vKey);
        // Sets bit nIndex of vData
        vData[nIndex >> 3] |= (1 << (7 & nIndex));
    }
    isEmpty = false;
}

void CBloomFilter::insert(const COutPoint& outpoint)
{
    CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
    stream << outpoint;
    vector<unsigned char> data(stream.begin(), stream.end());
    insert(data);
}

void CBloomFilter::insert(const uint256& hash)
{
    vector<unsigned char> data(hash.begin(), hash.end());
    insert(data);
}

bool CBloomFilter::contains(const vector<unsigned char>& vKey) const
{
    if (isFull)
        return true;
    if (isEmpty)
        return false;
    for (unsigned int i = 0; i < nHashFuncs; i++)
    {
        unsigned int nIndex = Hash(i, vKey);
        // Checks bit nIndex of vData
        if (!(vData[nIndex >> 3] & (1 << (7 & nIndex))))
            return false;
    }
    return true;
}

bool CBloomFilter::contains(const COutPoint& outpoint) const
{
    CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
    stream << outpoint;
    vector<unsigned char> data(stream.begin(), stream.end());
    return contains(data);
}

bool CBloomFilter::contains(const uint256& hash) const
{
    vector<unsigned char> data(hash.begin(), hash.end());
    return contains(data);
}

void CBloomFilter::clear()
{
    vData.assign(vData.size(),0);
    isFull = false;
    isEmpty = true;
}

void CBloomFilter::reset(const unsigned int nNewTweak)
{
    clear();
    nTweak = nNewTweak;
}

bool CBloomFilter::IsWithinSizeConstraints() const
{
    return vData.size() <= MAX_BLOOM_FILTER_SIZE && nHashFuncs <= MAX_HASH_FUNCS;
}

bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx)
{
    bool fFound = false;
    // Match if the filter contains the hash of tx
    //  for finding tx when they appear in a block
    if (isFull)
        return true;
    if (isEmpty)
        return false;
    const uint256& hash = tx.GetHash();
    if (contains(hash))
        fFound = true;

    for (unsigned int i = 0; i < tx.vout.size(); i++)
    {
        const CTxOut& txout = tx.vout[i];
        // Match if the filter contains any arbitrary script data element in any scriptPubKey in tx
        // If this matches, also add the specific output that was matched.
        // This means clients don't have to update the filter themselves when a new relevant tx
        // is discovered in order to find spending transactions, which avoids round-tripping and race conditions.
        CScript::const_iterator pc = txout.scriptPubKey.begin();
        vector<unsigned char> data;
        while (pc < txout.scriptPubKey.end())
        {
            opcodetype opcode;
            if (!txout.scriptPubKey.GetOp(pc, opcode, data))
                break;
            if (data.size() != 0 && contains(data))
            {
                fFound = true;
                if ((nFlags & BLOOM_UPDATE_MASK) == BLOOM_UPDATE_ALL)
                    insert(COutPoint(hash, i));
                else if ((nFlags & BLOOM_UPDATE_MASK) == BLOOM_UPDATE_P2PUBKEY_ONLY)
                {
                    txnouttype type;
                    vector<vector<unsigned char> > vSolutions;
                    if (Solver(txout.scriptPubKey, type, vSolutions) &&
                            (type == TX_PUBKEY || type == TX_MULTISIG))
                        insert(COutPoint(hash, i));
                }
                break;
            }
        }
    }

    if (fFound)
        return true;

    BOOST_FOREACH(const CTxIn& txin, tx.vin)
    {
        // Match if the filter contains an outpoint tx spends
        if (contains(txin.prevout))
            return true;

        // Match if the filter contains any arbitrary script data element in any scriptSig in tx
        CScript::const_iterator pc = txin.scriptSig.begin();
        vector<unsigned char> data;
        while (pc < txin.scriptSig.end())
        {
            opcodetype opcode;
            if (!txin.scriptSig.GetOp(pc, opcode, data))
                break;
            if (data.size() != 0 && contains(data))
                return true;
        }
    }

    return false;
}

void CBloomFilter::UpdateEmptyFull()
{
    bool full = true;
    bool empty = true;
    for (unsigned int i = 0; i < vData.size(); i++)
    {
        full &= vData[i] == 0xff;
        empty &= vData[i] == 0;
    }
    isFull = full;
    isEmpty = empty;
}

CRollingBloomFilter::CRollingBloomFilter(const unsigned int nElements, const double fpRate)
{
    double logFpRate = log(fpRate);
    /* The optimal number of hash functions is log(fpRate) / log(0.5), but
     * restrict it to the range 1-50. */
    nHashFuncs = std::max(1, std::min((int)round(logFpRate / log(0.5)), 50));
    /* In this rolling bloom filter, we'll store between 2 and 3 generations of nElements / 2 entries. */
    nEntriesPerGeneration = (nElements + 1) / 2;
    uint32_t nMaxElements = nEntriesPerGeneration * 3;
    /* The maximum fpRate = pow(1.0 - exp(-nHashFuncs * nMaxElements / nFilterBits), nHashFuncs)
     * =>          pow(fpRate, 1.0 / nHashFuncs) = 1.0 - exp(-nHashFuncs * nMaxElements / nFilterBits)
     * =>          1.0 - pow(fpRate, 1.0 / nHashFuncs) = exp(-nHashFuncs * nMaxElements / nFilterBits)
     * =>          log(1.0 - pow(fpRate, 1.0 / nHashFuncs)) = -nHashFuncs * nMaxElements / nFilterBits
     * =>          nFilterBits = -nHashFuncs * nMaxElements / log(1.0 - pow(fpRate, 1.0 / nHashFuncs))
     * =>          nFilterBits = -nHashFuncs * nMaxElements / log(1.0 - exp(logFpRate / nHashFuncs))
     */
    uint32_t nFilterBits = (uint32_t)ceil(-1.0 * nHashFuncs * nMaxElements / log(1.0 - exp(logFpRate / nHashFuncs)));
    data.clear();
    /* For each data element we need to store 2 bits. If both bits are 0, the
     * bit is treated as unset. If the bits are (01), (10), or (11), the bit is
     * treated as set in generation 1, 2, or 3 respectively.
     * These bits are stored in separate integers: position P corresponds to bit
     * (P & 63) of the integers data[(P >> 6) * 2] and data[(P >> 6) * 2 + 1]. */
    data.resize(((nFilterBits + 63) / 64) << 1);
    reset();
}

/* Similar to CBloomFilter::Hash */
static inline uint32_t RollingBloomHash(unsigned int nHashNum, uint32_t nTweak, const std::vector<unsigned char>& vDataToHash) {
    return MurmurHash3(nHashNum * 0xFBA4C795 + nTweak, vDataToHash);
}

void CRollingBloomFilter::insert(const std::vector<unsigned char>& vKey)
{
    if (nEntriesThisGeneration == nEntriesPerGeneration) {
        nEntriesThisGeneration = 0;
        nGeneration++;
        if (nGeneration == 4) {
            nGeneration = 1;
        }
        uint64_t nGenerationMask1 = 0 - (uint64_t)(nGeneration & 1);
        uint64_t nGenerationMask2 = 0 - (uint64_t)(nGeneration >> 1);
        /* Wipe old entries that used this generation number. */
        for (uint32_t p = 0; p < data.size(); p += 2) {
            uint64_t p1 = data[p], p2 = data[p + 1];
            uint64_t mask = (p1 ^ nGenerationMask1) | (p2 ^ nGenerationMask2);
            data[p] = p1 & mask;
            data[p + 1] = p2 & mask;
        }
    }
    nEntriesThisGeneration++;

    for (int n = 0; n < nHashFuncs; n++) {
        uint32_t h = RollingBloomHash(n, nTweak, vKey);
        int bit = h & 0x3F;
        uint32_t pos = (h >> 6) % data.size();
        /* The lowest bit of pos is ignored, and set to zero for the first bit, and to one for the second. */
        data[pos & ~1] = (data[pos & ~1] & ~(((uint64_t)1) << bit)) | ((uint64_t)(nGeneration & 1)) << bit;
        data[pos | 1] = (data[pos | 1] & ~(((uint64_t)1) << bit)) | ((uint64_t)(nGeneration >> 1)) << bit;
    }
}

void CRollingBloomFilter::insert(const uint256& hash)
{
    vector<unsigned char> vData(hash.begin(), hash.end());
    insert(vData);
}

bool CRollingBloomFilter::contains(const std::vector<unsigned char>& vKey) const
{
    for (int n = 0; n < nHashFuncs; n++) {
        uint32_t h = RollingBloomHash(n, nTweak, vKey);
        int bit = h & 0x3F;
        uint32_t pos = (h >> 6) % data.size();
        /* If the relevant bit is not set in either data[pos & ~1] or data[pos | 1], the filter does not contain vKey */
        if (!(((data[pos & ~1] | data[pos | 1]) >> bit) & 1)) {
            return false;
        }
    }
    return true;
}

bool CRollingBloomFilter::contains(const uint256& hash) const
{
    vector<unsigned char> vData(hash.begin(), hash.end());
    return contains(vData);
}

void CRollingBloomFilter::reset()
{
    nTweak = GetRand(std::numeric_limits<unsigned int>::max());
    nEntriesThisGeneration = 0;
    nGeneration = 1;
    for (std::vector<uint64_t>::iterator it = data.begin(); it != data.end(); it++) {
        *it = 0;
    }
}
<|endoftext|>