<commit_before>#ifndef __CINT__
#include <AliCDBManager.h>
#include <AliFMDCalibDrawer.h>
#include <TSystem.h>
#include <TGFrame.h>
#include <TGButton.h>
#include <TGLayout.h>
#include <TGButtonGroup.h>
#include <TGNumberEntry.h>
#include <TGTextEntry.h>
#include <TCanvas.h>
#include <TError.h>
#include <TGLabel.h>
#else
class TGMainFrame;
class TGNumberEntry;
class TGTextEntry;
class TGHButtonGroup;
class TGCheckButton;
class TGTextButton;
class TGLayoutHints;
class TCanvas;
class TGLabel;
class TGHorizontalFrame;
class AliFMDCalibDrawer;
class TGGroupFrame;
#endif

class Menu
{
public:
  TGMainFrame       fMain;
  TGGroupFrame      fSetup;
  TGLabel           fLRun;
  TGNumberEntry     fRun;
  TGLabel           fLOCDB;
  TGTextEntry       fOCDB;
  TGTextButton      fInit;
  TGHorizontalFrame fFDet;
  TGLabel           fLDet;
  TGNumberEntry     fDet;
  TGHorizontalFrame fFRing;
  TGLabel           fLRing;
  TGTextEntry       fRing;
  TGHorizontalFrame fFSec;
  TGLabel           fLSec;
  TGNumberEntry     fSec;
  TGHorizontalFrame fFStr;
  TGLabel           fLStr;
  TGNumberEntry     fStr;
  TGHButtonGroup    fSelection;
  TGCheckButton     fPedestal;
  TGCheckButton     fNoise;
  TGCheckButton     fGain;
  TGCheckButton     fDead;
  TGCheckButton     fRate;
  TGCheckButton     fRange;
  TGCheckButton     fThreshold;
  TGTextButton      fDraw;
  TGLayoutHints     fLayout;

  AliFMDCalibDrawer fCD;
  TCanvas*          fCPedestal;
  TCanvas*          fCNoise;
  TCanvas*          fCGain;
  TCanvas*          fCDead;
  TCanvas*          fCRate;
  TCanvas*          fCRange;
  TCanvas*          fCThreshold;

  Menu(Int_t runNo)
    : fMain(gClient->GetRoot()),
      fSetup(&fMain, "Setup", kHorizontalFrame),
      fLRun(&fSetup, "Run: "),
      fRun(&fSetup, runNo, 8, -1, TGNumberFormat::kNESInteger,
	   TGNumberFormat::kNEAAnyNumber),
      fLOCDB(&fSetup, "OCDB:"),
      fOCDB(&fSetup, ""),
      fInit(&fSetup, "Init"),
      fFDet(&fMain),
      fLDet(&fFDet, "Detector:"),
      fDet(&fFDet, -1, 1, -1, TGNumberFormat::kNESInteger,
	   TGNumberFormat::kNEAAnyNumber, TGNumberFormat::kNELLimitMinMax,
	   -1, 3),
      fFRing(&fMain),
      fLRing(&fFRing,"Ring:"),
      fRing(&fFRing, ""),
      fFSec(&fMain),
      fLSec(&fFSec,"Sector:"),
      fSec(&fFSec, -1, 1, -1, TGNumberFormat::kNESInteger,
	   TGNumberFormat::kNEAAnyNumber, TGNumberFormat::kNELLimitMinMax,
	   -1, 39),
      fFStr(&fMain),
      fLStr(&fFStr,"Strip:"),
      fStr(&fFStr, -1, 1, -1, TGNumberFormat::kNESInteger,
	   TGNumberFormat::kNEAAnyNumber, TGNumberFormat::kNELLimitMinMax,
	   -1, 511),
      fSelection(&fMain, "what"),
      fPedestal(&fSelection, "Pedestal"),
      fNoise(&fSelection, "Noise"),
      fGain(&fSelection, "Gain"),
      fDead(&fSelection, "Dead"),
      fRate(&fSelection, "Rate"),
      fRange(&fSelection, "Range"),
      fThreshold(&fSelection, "Threshold"),
      fDraw(&fMain, "Draw"),
      fLayout(kLHintsExpandX, 2, 2, 2, 2)
  {
    fSetup.AddFrame(&fLRun,  &fLayout);
    fSetup.AddFrame(&fRun,   &fLayout);
    fSetup.AddFrame(&fLOCDB, &fLayout);
    fSetup.AddFrame(&fOCDB,  &fLayout);
    fSetup.AddFrame(&fInit,  &fLayout);

    fFDet.AddFrame(&fLDet,  &fLayout);
    fFDet.AddFrame(&fDet,   &fLayout);
    fFRing.AddFrame(&fLRing,&fLayout);
    fFRing.AddFrame(&fRing, &fLayout);
    fFSec.AddFrame(&fLSec,  &fLayout);
    fFSec.AddFrame(&fSec,   &fLayout);
    fFStr.AddFrame(&fLStr,  &fLayout);
    fFStr.AddFrame(&fStr,   &fLayout);

    fMain.AddFrame(&fSetup,      &fLayout);
    fMain.AddFrame(&fFDet,       &fLayout);
    fMain.AddFrame(&fFRing,      &fLayout);
    fMain.AddFrame(&fFSec,       &fLayout);
    fMain.AddFrame(&fFStr,       &fLayout);
    fMain.AddFrame(&fSelection,  &fLayout);
    fMain.AddFrame(&fDraw,       &fLayout);

    fRing.SetAlignment(kTextRight);
    fRing.SetInsertMode(TGTextEntry::kReplace);
    fRing.SetMaxLength(1);

    fMain.MapSubwindows();
    fMain.Resize(fMain.GetDefaultSize());
    fMain.MapWindow();

    fDraw.Connect("Clicked()", "Menu", this, "Handle()");
    fInit.Connect("Clicked()", "Menu", this, "Init()");

    fCD.Init(runNo);
  }
  TCanvas* MakeCanvas(const char* name, const char* title)
  {
    TCanvas* ret = new TCanvas(name, title, 1200, 900);
    ret->SetFillColor(0);
    ret->SetFillStyle(0);
    ret->SetBorderMode(0);
    ret->SetBorderSize(0);
    return ret;
  }
  void ClearCanvas(TCanvas* c)
  {
    c->Clear();
    c->SetTopMargin(0.02);
    c->SetRightMargin(0.02);
    c->SetBottomMargin(0.10);
    c->SetLeftMargin(0.10);
    c->cd();
  }
  void Init()
  {
    const Char_t* ocdb = fOCDB.GetText();
    Int_t         run  = fRun.GetIntNumber();
    Info("Init", "Initialising for run %d, OCDB @ %s", run, ocdb);
    fCD.Init(run, ocdb);
  }
  void Handle()
  {
    static Short_t oD;
    static Char_t  oR;
    static Short_t oS;
    static Short_t oT;
    Short_t d = fDet.GetIntNumber();
    Char_t  r = fRing.GetText()[0];
    Short_t s = fSec.GetIntNumber();
    Short_t t = fStr.GetIntNumber();
    Info("Handle", "D=%d, R=%c, S=%d, T=%d", d, (r == '\0' ? '-' : r), s, t);
    if (fPedestal.IsOn()) {
      Info("Handle", "Will draw pedestals");
      if (!fCPedestal) fCPedestal = MakeCanvas("peds", "Pedestals");
      ClearCanvas(fCPedestal);
      fCD.DrawPedestals(d, r, s, t);
    }
    if (fNoise.IsOn()) {
      Info("Handle", "Will draw noises");
      if (!fCNoise) fCNoise = MakeCanvas("noises", "Noises");
      ClearCanvas(fCNoise);
      fCD.DrawNoise(d, r, s, t);
    }
    if (fGain.IsOn()) {
      Info("Handle", "Will draw gains");
      if (!fCGain) fCGain = MakeCanvas("gains", "Gains");
      ClearCanvas(fCGain);
      fCD.DrawGains(d, r, s, t);
    }
    if (fDead.IsOn()) {
      Info("Handle", "Will draw deads");
      if (!fCDead) fCDead = MakeCanvas("deads", "Deads");
      ClearCanvas(fCDead);
      fCD.DrawDead(d, r, s, t);
    }
    if (fRate.IsOn()) {
      Info("Handle", "Will draw rates");
      if (!fCRate) fCRate = MakeCanvas("rates", "Rates");
      fCRate->Clear();
      fCRate->cd();
      fCD.DrawRates(d, r, s, t);
    }
    if (fRange.IsOn()) {
      Info("Handle", "Will draw ranges");
      if (!fCRange) fCRange = MakeCanvas("ranges", "Ranges");
      fCRange->Clear();
      fCRange->cd();
      fCD.DrawRanges(d, r, s, t);
    }
    if (fThreshold.IsOn()) {
      Info("Handle", "Will draw thresholds");
      if (!fCThreshold) fCThreshold = MakeCanvas("thresholds", "Thresholds");
      fCThreshold->Clear();
      fCThreshold->cd();
      fCD.DrawThresholds(d, r, s, t);
    }
  }
};

void
DrawCalib()
{
#ifdef __CINT__
  gSystem->Load("libFMDutil");
#endif

  AliCDBManager* cdb = AliCDBManager::Instance();
  cdb->SetDefaultStorage("local://$ALICE_ROOT/OCDB");
  cdb->SetSpecificStorage("FMD/Calib/Pedestal", "local:///mnt/hitachi/ocdb/2011");
  cdb->SetSpecificStorage("FMD/Calib/PulseGain", "local:///mnt/hitachi/ocdb/2011");

  Menu* m = new Menu(145167);
  // cd->DrawPedestals(d,r,s,t);
}
<commit_msg>Small fixes<commit_after>#ifndef __CINT__
#include <AliCDBManager.h>
#include <AliCDBStorage.h>
#include <AliFMDCalibDrawer.h>
#include <TSystem.h>
#include <TGFrame.h>
#include <TGButton.h>
#include <TGLayout.h>
#include <TGButtonGroup.h>
#include <TGNumberEntry.h>
#include <TGTextEntry.h>
#include <TCanvas.h>
#include <TError.h>
#include <TGLabel.h>
#else
class TGMainFrame;
class TGNumberEntry;
class TGTextEntry;
class TGHButtonGroup;
class TGCheckButton;
class TGTextButton;
class TGLayoutHints;
class TCanvas;
class TGLabel;
class TGHorizontalFrame;
class AliFMDCalibDrawer;
class TGGroupFrame;
#endif

class Menu
{
public:
  TGMainFrame       fMain;
  TGGroupFrame      fSetup;
  TGLabel           fLRun;
  TGNumberEntry     fRun;
  TGLabel           fLOCDB;
  TGTextEntry       fOCDB;
  TGTextButton      fInit;
  TGHorizontalFrame fFDet;
  TGLabel           fLDet;
  TGNumberEntry     fDet;
  TGHorizontalFrame fFRing;
  TGLabel           fLRing;
  TGTextEntry       fRing;
  TGHorizontalFrame fFSec;
  TGLabel           fLSec;
  TGNumberEntry     fSec;
  TGHorizontalFrame fFStr;
  TGLabel           fLStr;
  TGNumberEntry     fStr;
  TGHButtonGroup    fSelection;
  TGCheckButton     fPedestal;
  TGCheckButton     fNoise;
  TGCheckButton     fGain;
  TGCheckButton     fDead;
  TGCheckButton     fRate;
  TGCheckButton     fRange;
  TGCheckButton     fThreshold;
  TGTextButton      fDraw;
  TGLayoutHints     fLayout;

  AliFMDCalibDrawer fCD;
  TCanvas*          fCPedestal;
  TCanvas*          fCNoise;
  TCanvas*          fCGain;
  TCanvas*          fCDead;
  TCanvas*          fCRate;
  TCanvas*          fCRange;
  TCanvas*          fCThreshold;

  Menu(Int_t runNo)
    : fMain(gClient->GetRoot()),
      fSetup(&fMain, "Setup", kHorizontalFrame),
      fLRun(&fSetup, "Run: "),
      fRun(&fSetup, runNo, 8, -1, TGNumberFormat::kNESInteger,
	   TGNumberFormat::kNEAAnyNumber),
      fLOCDB(&fSetup, "OCDB:"),
      fOCDB(&fSetup, ""),
      fInit(&fSetup, "Init"),
      fFDet(&fMain),
      fLDet(&fFDet, "Detector:"),
      fDet(&fFDet, -1, 1, -1, TGNumberFormat::kNESInteger,
	   TGNumberFormat::kNEAAnyNumber, TGNumberFormat::kNELLimitMinMax,
	   -1, 3),
      fFRing(&fMain),
      fLRing(&fFRing,"Ring:"),
      fRing(&fFRing, ""),
      fFSec(&fMain),
      fLSec(&fFSec,"Sector:"),
      fSec(&fFSec, -1, 1, -1, TGNumberFormat::kNESInteger,
	   TGNumberFormat::kNEAAnyNumber, TGNumberFormat::kNELLimitMinMax,
	   -1, 39),
      fFStr(&fMain),
      fLStr(&fFStr,"Strip:"),
      fStr(&fFStr, -1, 1, -1, TGNumberFormat::kNESInteger,
	   TGNumberFormat::kNEAAnyNumber, TGNumberFormat::kNELLimitMinMax,
	   -1, 511),
      fSelection(&fMain, "what"),
      fPedestal(&fSelection, "Pedestal"),
      fNoise(&fSelection, "Noise"),
      fGain(&fSelection, "Gain"),
      fDead(&fSelection, "Dead"),
      fRate(&fSelection, "Rate"),
      fRange(&fSelection, "Range"),
      fThreshold(&fSelection, "Threshold"),
      fDraw(&fMain, "Draw"),
      fLayout(kLHintsExpandX, 2, 2, 2, 2),
      fCPedestal(0),
      fCNoise(0),
      fCGain(0),
      fCDead(0),
      fCRate(0),
      fCRange(0),
      fCThreshold(0)
  {
    fSetup.AddFrame(&fLRun,  &fLayout);
    fSetup.AddFrame(&fRun,   &fLayout);
    fSetup.AddFrame(&fLOCDB, &fLayout);
    fSetup.AddFrame(&fOCDB,  &fLayout);
    fSetup.AddFrame(&fInit,  &fLayout);

    fFDet.AddFrame(&fLDet,  &fLayout);
    fFDet.AddFrame(&fDet,   &fLayout);
    fFRing.AddFrame(&fLRing,&fLayout);
    fFRing.AddFrame(&fRing, &fLayout);
    fFSec.AddFrame(&fLSec,  &fLayout);
    fFSec.AddFrame(&fSec,   &fLayout);
    fFStr.AddFrame(&fLStr,  &fLayout);
    fFStr.AddFrame(&fStr,   &fLayout);

    fMain.AddFrame(&fSetup,      &fLayout);
    fMain.AddFrame(&fFDet,       &fLayout);
    fMain.AddFrame(&fFRing,      &fLayout);
    fMain.AddFrame(&fFSec,       &fLayout);
    fMain.AddFrame(&fFStr,       &fLayout);
    fMain.AddFrame(&fSelection,  &fLayout);
    fMain.AddFrame(&fDraw,       &fLayout);

    fRing.SetAlignment(kTextRight);
    fRing.SetInsertMode(TGTextEntry::kReplace);
    fRing.SetMaxLength(1);

    fMain.MapSubwindows();
    fMain.Resize(fMain.GetDefaultSize());
    fMain.MapWindow();

    fDraw.Connect("Clicked()", "Menu", this, "Handle()");
    fInit.Connect("Clicked()", "Menu", this, "Init()");

    AliCDBManager* cdb = AliCDBManager::Instance();
    if (cdb->GetDefaultStorage())
      fOCDB.SetText(cdb->GetDefaultStorage()->GetURI().Data());
    fCD.Init(runNo);
  }
  TCanvas* MakeCanvas(const char* name, const char* title)
  {
    TCanvas* ret = new TCanvas(name, title, 1200, 900);
    ret->SetFillColor(0);
    ret->SetFillStyle(0);
    ret->SetBorderMode(0);
    ret->SetBorderSize(0);
    return ret;
  }
  void ClearCanvas(TCanvas* c)
  {
    c->Clear();
    c->SetTopMargin(0.02);
    c->SetRightMargin(0.02);
    c->SetBottomMargin(0.10);
    c->SetLeftMargin(0.10);
    c->cd();
  }
  void Init()
  {
    const Char_t* ocdb = fOCDB.GetText();
    Int_t         run  = fRun.GetIntNumber();
    Info("Init", "Initialising for run %d, OCDB @ %s", run, ocdb);
    fCD.Init(run, ocdb);
  }
  void Handle()
  {
    // static Short_t oD;
    // static Char_t  oR;
    // static Short_t oS;
    // static Short_t oT;
    Short_t d = fDet.GetIntNumber();
    Char_t  r = fRing.GetText()[0];
    Short_t s = fSec.GetIntNumber();
    Short_t t = fStr.GetIntNumber();
    Info("Handle", "D=%d, R=%c, S=%d, T=%d", d, (r == '\0' ? '-' : r), s, t);
    if (fPedestal.IsOn()) {
      Info("Handle", "Will draw pedestals");
      if (!fCPedestal) fCPedestal = MakeCanvas("peds", "Pedestals");
      ClearCanvas(fCPedestal);
      fCD.DrawPedestals(d, r, s, t);
    }
    if (fNoise.IsOn()) {
      Info("Handle", "Will draw noises");
      if (!fCNoise) fCNoise = MakeCanvas("noises", "Noises");
      ClearCanvas(fCNoise);
      fCD.DrawNoise(d, r, s, t);
    }
    if (fGain.IsOn()) {
      Info("Handle", "Will draw gains");
      if (!fCGain) fCGain = MakeCanvas("gains", "Gains");
      ClearCanvas(fCGain);
      fCD.DrawGains(d, r, s, t);
    }
    if (fDead.IsOn()) {
      Info("Handle", "Will draw deads");
      if (!fCDead) fCDead = MakeCanvas("deads", "Deads");
      ClearCanvas(fCDead);
      fCD.DrawDead(d, r, s, t);
    }
    if (fRate.IsOn()) {
      Info("Handle", "Will draw rates");
      if (!fCRate) fCRate = MakeCanvas("rates", "Rates");
      fCRate->Clear();
      fCRate->cd();
      fCD.DrawRates(d, r, s, t);
    }
    if (fRange.IsOn()) {
      Info("Handle", "Will draw ranges");
      if (!fCRange) fCRange = MakeCanvas("ranges", "Ranges");
      fCRange->Clear();
      fCRange->cd();
      fCD.DrawRanges(d, r, s, t);
    }
    if (fThreshold.IsOn()) {
      Info("Handle", "Will draw thresholds");
      if (!fCThreshold) fCThreshold = MakeCanvas("thresholds", "Thresholds");
      fCThreshold->Clear();
      fCThreshold->cd();
      fCD.DrawThresholds(d, r, s, t);
    }
  }
};

void
DrawCalib()
{
#ifdef __CINT__
  gSystem->Load("libFMDutil");
#endif

  AliCDBManager* cdb = AliCDBManager::Instance();
  // cdb->SetDefaultStorage("local://$ALICE_ROOT/OCDB");
  // cdb->SetSpecificStorage("FMD/Calib/Pedestal", "local:///mnt/hitachi/ocdb/2011");
  // cdb->SetSpecificStorage("FMD/Calib/PulseGain",
  // "local:///mnt/hitachi/ocdb/2011");
  cdb->SetDefaultStorage("local:///mnt/hitachi/ocdb/2011");

  Menu* m = new Menu(145167);
  // cd->DrawPedestals(d,r,s,t);
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2012 Kim Walisch, <kim.walisch@gmail.com>.
// All rights reserved.
//
// This file is part of primesieve.
// Homepage: http://primesieve.googlecode.com
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//   * Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above
//     copyright notice, this list of conditions and the following
//     disclaimer in the documentation and/or other materials provided
//     with the distribution.
//   * Neither the name of the author nor the names of its
//     contributors may be used to endorse or promote products derived
//     from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

#include "SieveOfEratosthenes.h"
#include "PreSieve.h"
#include "EratSmall.h"
#include "EratMedium.h"
#include "EratBig.h"
#include "config.h"
#include "imath.h"

#include <stdint.h>
#include <stdexcept>
#include <cstdlib>

namespace soe {

const uint32_t SieveOfEratosthenes::bitValues_[8] = { 7, 11, 13, 17, 19, 23, 29, 31 };

/** De Bruijn sequence for first set bitValues_ */
const uint32_t SieveOfEratosthenes::bruijnBitValues_[32] =
{
    7,  11, 109, 13, 113, 59, 97, 17,
  119,  89,  79, 61, 101, 71, 19, 37,
  121, 107,  53, 91,  83, 77, 67, 31,
  103,  49,  73, 29,  47, 23, 43, 41
};

/**
 * @param start          Sieve the primes within the interval [start, stop].
 * @param stop           Sieve the primes within the interval [start, stop].
 * @param preSieveLimit  Multiples of small primes <= preSieveLimit are
 *                       pre-sieved to speed up the sieve of Eratosthenes,
 *                       preSieveLimit >= 13 && <= 23.
 * @param sieveSize      A sieve size in kilobytes, sieveSize >= 1 && <= 4096.
 */
SieveOfEratosthenes::SieveOfEratosthenes(uint64_t start,
                                         uint64_t stop,
                                         uint32_t preSieveLimit,
                                         uint32_t sieveSize) :
  start_(start),
  stop_(stop),
  sqrtStop_(static_cast<uint32_t>(isqrt(stop))),
  preSieve_(preSieveLimit),
  isFirstSegment_(true),
  sieve_(NULL),
  sieveSize_(sieveSize * 1024),
  eratSmall_(NULL),
  eratMedium_(NULL),
  eratBig_(NULL)
{
  if (start_ < 7 || start_ > stop_)
    throw std::logic_error("SieveOfEratosthenes: start must be >= 7 && <= stop.");
  // it makes no sense to use very small sieve sizes
  if (sieveSize_ < 1024)
    throw std::invalid_argument("SieveOfEratosthenes: sieveSize must be >= 1 kilobyte.");
  segmentLow_ = start_ - getByteRemainder(start_);
  // '+ 1' is a correction for primes of type i*30 + 31
  segmentHigh_ = segmentLow_ + sieveSize_ * NUMBERS_PER_BYTE + 1;
  initEratAlgorithms();
  // allocate the sieve of Eratosthenes array
  sieve_ = new uint8_t[sieveSize_];
}

SieveOfEratosthenes::~SieveOfEratosthenes() {
  delete[] sieve_;
  delete eratSmall_;
  delete eratMedium_;
  delete eratBig_;
}

/** returns bitValues_[ bitScanForward(v) ] */
uint32_t SieveOfEratosthenes::getFirstSetBitValue(uint32_t v) {
  return bruijnBitValues_[((v & -static_cast<int32_t>(v)) * 0x077CB531) >> 27];
}

uint32_t SieveOfEratosthenes::getPreSieveLimit() const {
  return preSieve_.getLimit();
}

uint32_t SieveOfEratosthenes::getByteRemainder(uint64_t n) {
  uint32_t remainder = static_cast<uint32_t>(n % NUMBERS_PER_BYTE);
  // correction for primes of type i*30 + 31
  if (remainder <= 1)
    remainder += NUMBERS_PER_BYTE;
  return remainder;
}

void SieveOfEratosthenes::initEratAlgorithms() {
  try {
    if (sqrtStop_ > preSieve_.getLimit()) {
      eratSmall_ = new EratSmall(*this);
      if (sqrtStop_ > eratSmall_->getLimit()) {
        eratMedium_ = new EratMedium(*this);
        if (sqrtStop_ > eratMedium_->getLimit())
          eratBig_ = new EratBig(*this);
      }
    }
  } catch (...) {
    delete eratSmall_;
    delete eratMedium_;
    delete eratBig_;
    throw;
  }
}

/**
 * Pre-sieve multiples of small primes <= preSieve_.getLimit()
 * to speed up the sieve of Eratosthenes.
 */
void SieveOfEratosthenes::preSieve() {
  preSieve_.doIt(sieve_, sieveSize_, segmentLow_);
  if (isFirstSegment_) {
    isFirstSegment_ = false;
    // correct preSieve_.doIt() for numbers <= 23
    if (start_ <= preSieve_.getLimit())
      sieve_[0] = 0xff;
    uint32_t startRemainder = getByteRemainder(start_);
    // unset bits corresponding to numbers < start_
    for (int i = 0; i < 8; i++) {
      if (bitValues_[i] < startRemainder)
        sieve_[0] &= ~(1 << i);
    }
  }
}

/**
 * Cross-off the multiples within the current segment i.e.
 * [segmentLow_+7, segmentHigh_].
 */
void SieveOfEratosthenes::crossOffMultiples() {
  if (eratSmall_ != NULL) {
    // process the sieving primes with many multiples per segment
    eratSmall_->sieve(sieve_, sieveSize_);
    if (eratMedium_ != NULL) {
      // process the sieving primes with a few multiples per segment
      eratMedium_->sieve(sieve_, sieveSize_);
      if (eratBig_ != NULL)
        // process the sieving primes with very few multiples per segment
        eratBig_->sieve(sieve_);
    }
  }
}

/**
 * Implementation of the segmented sieve of Eratosthenes.
 * sieve(uint32_t) must be called consecutively for all primes up to
 * sqrt(stop) in order to sieve the primes within the interval
 * [start_, stop_].
 */
void SieveOfEratosthenes::sieve(uint32_t prime) {
  const uint64_t primeSquared = isquare<uint64_t>(prime);

  // The following while loop segments the sieve of Eratosthenes, it
  // is executed when all sieving primes <= sqrt(segmentHigh_)
  // required to sieve the next segment have been stored in the erat*
  // objects (see below). Each loop iteration sieves the primes within
  // the interval [segmentLow_+7, segmentHigh_].
  while (segmentHigh_ < primeSquared) {
    preSieve();
    crossOffMultiples();
    segmentProcessed(sieve_, sieveSize_);
    segmentLow_ += sieveSize_ * NUMBERS_PER_BYTE;
    segmentHigh_ += sieveSize_ * NUMBERS_PER_BYTE;
  }

  // prime is added to eratSmall_ if it has many multiples per
  // segment, to eratMedium_ if it has a few multiples per segment
  // and to eratBig_ if it has very few multiples per segment.
  if (prime > eratSmall_->getLimit())
    if (prime > eratMedium_->getLimit())
            eratBig_->addSievingPrime(prime);
    else eratMedium_->addSievingPrime(prime);
  else    eratSmall_->addSievingPrime(prime);
}

/**
 * Sieve the last segments remaining after that sieve(uint32_t)
 * has been called for all primes up to sqrt(stop_).
 */
void SieveOfEratosthenes::finish() {
  // sieve all segments left except the last one
  while (segmentHigh_ < stop_) {
    preSieve();
    crossOffMultiples();
    segmentProcessed(sieve_, sieveSize_);
    segmentLow_ += sieveSize_ * NUMBERS_PER_BYTE;
    segmentHigh_ += sieveSize_ * NUMBERS_PER_BYTE;
  }
  uint32_t stopRemainder = getByteRemainder(stop_);
  // calculate the sieve size of the last segment
  sieveSize_ = static_cast<uint32_t>((stop_ - stopRemainder) - segmentLow_) / NUMBERS_PER_BYTE + 1;
  // sieve the last segment
  preSieve();
  crossOffMultiples();
  // unset bits corresponding to numbers > stop_
  for (int i = 0; i < 8; i++) {
    if (bitValues_[i] > stopRemainder)
      sieve_[sieveSize_ - 1] &= ~(1 << i);
  }
  segmentProcessed(sieve_, sieveSize_);
}

} // namespace soe
<commit_msg>improved code readability<commit_after>//
// Copyright (c) 2012 Kim Walisch, <kim.walisch@gmail.com>.
// All rights reserved.
//
// This file is part of primesieve.
// Homepage: http://primesieve.googlecode.com
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//   * Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above
//     copyright notice, this list of conditions and the following
//     disclaimer in the documentation and/or other materials provided
//     with the distribution.
//   * Neither the name of the author nor the names of its
//     contributors may be used to endorse or promote products derived
//     from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

#include "SieveOfEratosthenes.h"
#include "PreSieve.h"
#include "EratSmall.h"
#include "EratMedium.h"
#include "EratBig.h"
#include "config.h"
#include "imath.h"

#include <stdint.h>
#include <stdexcept>
#include <cstdlib>

namespace soe {

const uint32_t SieveOfEratosthenes::bitValues_[8] = { 7, 11, 13, 17, 19, 23, 29, 31 };

/** De Bruijn sequence for first set bitValues_ */
const uint32_t SieveOfEratosthenes::bruijnBitValues_[32] =
{
    7,  11, 109, 13, 113, 59, 97, 17,
  119,  89,  79, 61, 101, 71, 19, 37,
  121, 107,  53, 91,  83, 77, 67, 31,
  103,  49,  73, 29,  47, 23, 43, 41
};

/**
 * @param start          Sieve the primes within the interval [start, stop].
 * @param stop           Sieve the primes within the interval [start, stop].
 * @param preSieveLimit  Multiples of small primes <= preSieveLimit are
 *                       pre-sieved to speed up the sieve of Eratosthenes,
 *                       preSieveLimit >= 13 && <= 23.
 * @param sieveSize      A sieve size in kilobytes, sieveSize >= 1 && <= 4096.
 */
SieveOfEratosthenes::SieveOfEratosthenes(uint64_t start,
                                         uint64_t stop,
                                         uint32_t preSieveLimit,
                                         uint32_t sieveSize) :
  start_(start),
  stop_(stop),
  sqrtStop_(static_cast<uint32_t>(isqrt(stop))),
  preSieve_(preSieveLimit),
  isFirstSegment_(true),
  sieve_(NULL),
  sieveSize_(sieveSize * 1024),
  eratSmall_(NULL),
  eratMedium_(NULL),
  eratBig_(NULL)
{
  if (start_ < 7 || start_ > stop_)
    throw std::logic_error("SieveOfEratosthenes: start must be >= 7 && <= stop.");
  // it makes no sense to use very small sieve sizes
  if (sieveSize_ < 1024)
    throw std::invalid_argument("SieveOfEratosthenes: sieveSize must be >= 1 kilobyte.");
  segmentLow_ = start_ - getByteRemainder(start_);
  // '+ 1' is a correction for primes of type i*30 + 31
  segmentHigh_ = segmentLow_ + sieveSize_ * NUMBERS_PER_BYTE + 1;
  initEratAlgorithms();
  // allocate the sieve of Eratosthenes array
  sieve_ = new uint8_t[sieveSize_];
}

SieveOfEratosthenes::~SieveOfEratosthenes() {
  delete eratSmall_;
  delete eratMedium_;
  delete eratBig_;
  delete[] sieve_;
}

/** returns bitValues_[ bitScanForward(v) ] */
uint32_t SieveOfEratosthenes::getFirstSetBitValue(uint32_t v) {
  return bruijnBitValues_[((v & -static_cast<int32_t>(v)) * 0x077CB531) >> 27];
}

uint32_t SieveOfEratosthenes::getPreSieveLimit() const {
  return preSieve_.getLimit();
}

uint32_t SieveOfEratosthenes::getByteRemainder(uint64_t n) {
  uint32_t remainder = static_cast<uint32_t>(n % NUMBERS_PER_BYTE);
  // correction for primes of type i*30 + 31
  if (remainder <= 1)
    remainder += NUMBERS_PER_BYTE;
  return remainder;
}

void SieveOfEratosthenes::initEratAlgorithms() {
  try {
    if (sqrtStop_ > preSieve_.getLimit()) {
      eratSmall_ = new EratSmall(*this);
      if (sqrtStop_ > eratSmall_->getLimit()) {
        eratMedium_ = new EratMedium(*this);
        if (sqrtStop_ > eratMedium_->getLimit())
          eratBig_ = new EratBig(*this);
      }
    }
  } catch (...) {
    delete eratSmall_;
    delete eratMedium_;
    delete eratBig_;
    throw;
  }
}

/**
 * Pre-sieve multiples of small primes <= preSieve_.getLimit()
 * to speed up the sieve of Eratosthenes.
 */
void SieveOfEratosthenes::preSieve() {
  preSieve_.doIt(sieve_, sieveSize_, segmentLow_);
  if (isFirstSegment_) {
    isFirstSegment_ = false;
    // correct preSieve_.doIt() for numbers <= 23
    if (start_ <= preSieve_.getLimit())
      sieve_[0] = 0xff;
    uint32_t startRemainder = getByteRemainder(start_);
    // unset bits corresponding to numbers < start_
    for (int i = 0; i < 8; i++) {
      if (bitValues_[i] < startRemainder)
        sieve_[0] &= ~(1 << i);
    }
  }
}

/**
 * Cross-off the multiples within the current segment i.e.
 * [segmentLow_+7, segmentHigh_].
 */
void SieveOfEratosthenes::crossOffMultiples() {
  if (eratSmall_ != NULL) {
    // process the sieving primes with many multiples per segment
    eratSmall_->sieve(sieve_, sieveSize_);
    if (eratMedium_ != NULL) {
      // process the sieving primes with a few multiples per segment
      eratMedium_->sieve(sieve_, sieveSize_);
      if (eratBig_ != NULL)
        // process the sieving primes with very few multiples per segment
        eratBig_->sieve(sieve_);
    }
  }
}

/**
 * Implementation of the segmented sieve of Eratosthenes.
 * sieve(uint32_t) must be called consecutively for all primes up to
 * sqrt(stop) in order to sieve the primes within the interval
 * [start_, stop_].
 */
void SieveOfEratosthenes::sieve(uint32_t prime) {
  const uint64_t primeSquared = isquare<uint64_t>(prime);

  // The following while loop segments the sieve of Eratosthenes, it
  // is executed when all sieving primes <= sqrt(segmentHigh_)
  // required to sieve the next segment have been stored in the erat*
  // objects (see below). Each loop iteration sieves the primes within
  // the interval [segmentLow_+7, segmentHigh_].
  while (segmentHigh_ < primeSquared) {
    preSieve();
    crossOffMultiples();
    segmentProcessed(sieve_, sieveSize_);
    segmentLow_ += sieveSize_ * NUMBERS_PER_BYTE;
    segmentHigh_ += sieveSize_ * NUMBERS_PER_BYTE;
  }

  // prime is added to eratSmall_ if it has many multiples per
  // segment, to eratMedium_ if it has a few multiples per segment
  // and to eratBig_ if it has very few multiples per segment.
  if (prime > eratSmall_->getLimit())
    if (prime > eratMedium_->getLimit())
            eratBig_->addSievingPrime(prime);
    else eratMedium_->addSievingPrime(prime);
  else    eratSmall_->addSievingPrime(prime);
}

/**
 * Sieve the last segments remaining after that sieve(uint32_t)
 * has been called for all primes up to sqrt(stop_).
 */
void SieveOfEratosthenes::finish() {
  // sieve all segments left except the last one
  while (segmentHigh_ < stop_) {
    preSieve();
    crossOffMultiples();
    segmentProcessed(sieve_, sieveSize_);
    segmentLow_ += sieveSize_ * NUMBERS_PER_BYTE;
    segmentHigh_ += sieveSize_ * NUMBERS_PER_BYTE;
  }
  uint32_t stopRemainder = getByteRemainder(stop_);
  // calculate the sieve size of the last segment
  sieveSize_ = static_cast<uint32_t>((stop_ - stopRemainder) - segmentLow_) / NUMBERS_PER_BYTE + 1;
  // sieve the last segment
  preSieve();
  crossOffMultiples();
  // unset bits corresponding to numbers > stop_
  for (int i = 0; i < 8; i++) {
    if (bitValues_[i] > stopRemainder)
      sieve_[sieveSize_ - 1] &= ~(1 << i);
  }
  segmentProcessed(sieve_, sieveSize_);
}

} // namespace soe
<|endoftext|>


<commit_before>// This file is part of the AliceVision project.
// This Source Code Form is subject to the terms of the Mozilla Public License,
// v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.

#include <aliceVision/delaunaycut/mv_delaunay_GC.hpp>
#include <aliceVision/delaunaycut/mv_delaunay_meshSmooth.hpp>
#include <aliceVision/largeScale/reconstructionPlan.hpp>
#include <aliceVision/planeSweeping/ps_refine_rc.hpp>
#include <aliceVision/CUDAInterfaces/refine.hpp>
#include <aliceVision/common/fileIO.hpp>
#include <aliceVision/structures/image.hpp>

#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>

namespace bfs = boost::filesystem;
namespace po = boost::program_options;

bool checkHardwareCompatibility()
{
    if(listCUDADevices(false) < 1)
    {
        std::cerr << "ERROR: no CUDA capable devices were detected." << std::endl;
        return false;
    }
    return true;
}

bfs::path absolutePathNoExt(const bfs::path& p)
{
    return p.parent_path() / p.stem();
}

#define ALICEVISION_COUT(x) std::cout << x << std::endl
#define ALICEVISION_CERR(x) std::cerr << x << std::endl

int main(int argc, char* argv[])
{
    long startTime = clock();

    std::string iniFilepath;
    std::string inputDenseReconstruction;
    std::string inputMeshFilepath;
    std::string outputFolder;
    std::string outTextureFileTypeName = EImageFileType_enumToString(EImageFileType::PNG);
    bool flipNormals = false;
    TexturingParams texParams;

    po::options_description allParams("AliceVision texturing");

    po::options_description requiredParams("Required parameters");
    requiredParams.add_options()
        ("ini", po::value<std::string>(&iniFilepath)->required(),
            "Configuration file: mvs.ini (the undistorted images and camera poses should be in the same folder)).")
        ("inputDenseReconstruction", po::value<std::string>(&inputDenseReconstruction)->required(),
            "Path to the dense reconstruction (mesh with per vertex visibility).")
        ("output,o", po::value<std::string>(&outputFolder)->required(),
            "Folder for output mesh: OBJ, material and texture files.");

    po::options_description optionalParams("Optional parameters");
    optionalParams.add_options()
        ("outputTextureFileType", po::value<std::string>(&outTextureFileTypeName)->default_value(outTextureFileTypeName),
          EImageFileType_informations().c_str())
        ("textureSide", po::value<unsigned int>(&texParams.textureSide)->default_value(texParams.textureSide),
            "Output texture size")
        ("padding", po::value<unsigned int>(&texParams.padding)->default_value(texParams.padding),
            "Texture edge padding size in pixel")
        ("downscale", po::value<unsigned int>(&texParams.downscale)->default_value(texParams.downscale),
            "Texture downscale factor")
        ("inputMesh", po::value<std::string>(&inputMeshFilepath),
            "Optional input mesh to texture. By default, it will texture the inputReconstructionMesh.")
        ("flipNormals", po::value<bool>(&flipNormals),
            "Option to flip face normals. It can be needed as it depends on the vertices order in triangles and the convention change from one software to another.");

    allParams.add(requiredParams).add(optionalParams);

    po::variables_map vm;

    try
    {
      po::store(po::parse_command_line(argc, argv, allParams), vm);

      if(vm.count("help") || (argc == 1))
      {
        ALICEVISION_COUT(allParams);
        return EXIT_SUCCESS;
      }

      po::notify(vm);
    }
    catch(boost::program_options::required_option& e)
    {
      ALICEVISION_CERR("ERROR: " << e.what() << std::endl);
      ALICEVISION_COUT("Usage:\n\n" << allParams);
      return EXIT_FAILURE;
    }
    catch(boost::program_options::error& e)
    {
      ALICEVISION_CERR("ERROR: " << e.what() << std::endl);
      ALICEVISION_COUT("Usage:\n\n" << allParams);
      return EXIT_FAILURE;
    }

    // check hardware compatibility
    if(!checkHardwareCompatibility())
        return EXIT_FAILURE;

    ALICEVISION_COUT("ini file: " << iniFilepath);
    ALICEVISION_COUT("inputMesh: " << inputMeshFilepath);

    // set output texture file type
    const EImageFileType outputTextureFileType = EImageFileType_stringToEnum(outTextureFileTypeName);

    // .ini parsing
    multiviewInputParams mip(iniFilepath, "", "");
    const double simThr = mip._ini.get<double>("global.simThr", 0.0);
    multiviewParams mp(mip.getNbCameras(), &mip, (float) simThr);
    mv_prematch_cams pc(&mp);

    meshRetex mesh;
    mesh.texParams = texParams;
    mesh.me = new mv_mesh();

    if(!mesh.me->loadFromBin(inputDenseReconstruction))
    {
        std::cerr << "Unable to load: " << inputDenseReconstruction << std::endl;
        return EXIT_FAILURE;
    }

    bfs::path reconstructionMeshFolder = bfs::path(inputDenseReconstruction).parent_path();

    staticVector<staticVector<int>*>* ptsCams = loadArrayOfArraysFromFile<int>((reconstructionMeshFolder/"meshPtsCamsFromDGC.bin").string());
    if(ptsCams->size() != mesh.me->pts->size())
        throw std::runtime_error("Error: Reference mesh and associated visibilities don't have the same size.");
    // filterPtsCamsByMinimalPixelSize(refMesh, refPtsCams, &mp);
    bfs::create_directory(outputFolder);

    //std::cout << "Points with no visibilities " << std::count(ptsCams->begin(), ptsCams->end(), nullptr) << std::endl;

    // texturing from input mesh
    if(!inputMeshFilepath.empty())
    {
        ALICEVISION_COUT("An external input mesh is provided, so we remap the visibility from the reconstruction on it.");
        // remap visibilities from reconstruction onto input mesh
        mv_delaunay_GC delaunayGC(&mp, &pc);
        delaunayGC.initTetrahedralizationFromMeshVertices(mesh.me, false);
        delete mesh.me;
        mesh.me = new mv_mesh();
        mesh.loadFromOBJ(inputMeshFilepath, flipNormals);
        staticVector<staticVector<int>*>* otherPtsCams = delaunayGC.createPtsCamsForAnotherMesh(ptsCams, *mesh.me);
        std::swap(ptsCams, otherPtsCams);
        deleteArrayOfArrays<int>(&otherPtsCams);
    }
    if(!mesh.hasUVs())
    {
        ALICEVISION_COUT("The input mesh has no UV, so we generate them.");
        // generate UV coordinates based on automatic uv atlas
        auto* updatedPtsCams = mesh.generateUVs(mp, ptsCams);
        std::swap(ptsCams, updatedPtsCams);
        deleteArrayOfArrays<int>(&updatedPtsCams);
        mesh.saveAsOBJ(outputFolder, "texturedMesh", outputTextureFileType);
    }

    // generate textures
    ALICEVISION_COUT("Generate textures.");
    mesh.generateTextures(mp, ptsCams, outputFolder, outputTextureFileType);

    printfElapsedTime(startTime, "#");
    return EXIT_SUCCESS;
}
<commit_msg>[software] texturing: use the new visibility remapping for retexturing<commit_after>// This file is part of the AliceVision project.
// This Source Code Form is subject to the terms of the Mozilla Public License,
// v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.

#include <aliceVision/mesh/meshVisibility.hpp>
#include <aliceVision/delaunaycut/mv_delaunay_GC.hpp>
#include <aliceVision/delaunaycut/mv_delaunay_meshSmooth.hpp>
#include <aliceVision/largeScale/reconstructionPlan.hpp>
#include <aliceVision/planeSweeping/ps_refine_rc.hpp>
#include <aliceVision/CUDAInterfaces/refine.hpp>
#include <aliceVision/common/fileIO.hpp>
#include <aliceVision/structures/image.hpp>

#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>

namespace bfs = boost::filesystem;
namespace po = boost::program_options;

bool checkHardwareCompatibility()
{
    if(listCUDADevices(false) < 1)
    {
        std::cerr << "ERROR: no CUDA capable devices were detected." << std::endl;
        return false;
    }
    return true;
}

bfs::path absolutePathNoExt(const bfs::path& p)
{
    return p.parent_path() / p.stem();
}

#define ALICEVISION_COUT(x) std::cout << x << std::endl
#define ALICEVISION_CERR(x) std::cerr << x << std::endl

int main(int argc, char* argv[])
{
    long startTime = clock();

    std::string iniFilepath;
    std::string inputDenseReconstruction;
    std::string inputMeshFilepath;
    std::string outputFolder;
    std::string outTextureFileTypeName = EImageFileType_enumToString(EImageFileType::PNG);
    bool flipNormals = false;
    TexturingParams texParams;

    po::options_description allParams("AliceVision texturing");

    po::options_description requiredParams("Required parameters");
    requiredParams.add_options()
        ("ini", po::value<std::string>(&iniFilepath)->required(),
            "Configuration file: mvs.ini (the undistorted images and camera poses should be in the same folder)).")
        ("inputDenseReconstruction", po::value<std::string>(&inputDenseReconstruction)->required(),
            "Path to the dense reconstruction (mesh with per vertex visibility).")
        ("output,o", po::value<std::string>(&outputFolder)->required(),
            "Folder for output mesh: OBJ, material and texture files.");

    po::options_description optionalParams("Optional parameters");
    optionalParams.add_options()
        ("outputTextureFileType", po::value<std::string>(&outTextureFileTypeName)->default_value(outTextureFileTypeName),
          EImageFileType_informations().c_str())
        ("textureSide", po::value<unsigned int>(&texParams.textureSide)->default_value(texParams.textureSide),
            "Output texture size")
        ("padding", po::value<unsigned int>(&texParams.padding)->default_value(texParams.padding),
            "Texture edge padding size in pixel")
        ("downscale", po::value<unsigned int>(&texParams.downscale)->default_value(texParams.downscale),
            "Texture downscale factor")
        ("inputMesh", po::value<std::string>(&inputMeshFilepath),
            "Optional input mesh to texture. By default, it will texture the inputReconstructionMesh.")
        ("flipNormals", po::value<bool>(&flipNormals),
            "Option to flip face normals. It can be needed as it depends on the vertices order in triangles and the convention change from one software to another.");

    allParams.add(requiredParams).add(optionalParams);

    po::variables_map vm;

    try
    {
      po::store(po::parse_command_line(argc, argv, allParams), vm);

      if(vm.count("help") || (argc == 1))
      {
        ALICEVISION_COUT(allParams);
        return EXIT_SUCCESS;
      }

      po::notify(vm);
    }
    catch(boost::program_options::required_option& e)
    {
      ALICEVISION_CERR("ERROR: " << e.what() << std::endl);
      ALICEVISION_COUT("Usage:\n\n" << allParams);
      return EXIT_FAILURE;
    }
    catch(boost::program_options::error& e)
    {
      ALICEVISION_CERR("ERROR: " << e.what() << std::endl);
      ALICEVISION_COUT("Usage:\n\n" << allParams);
      return EXIT_FAILURE;
    }

    // check hardware compatibility
    if(!checkHardwareCompatibility())
        return EXIT_FAILURE;

    ALICEVISION_COUT("ini file: " << iniFilepath);
    ALICEVISION_COUT("inputMesh: " << inputMeshFilepath);

    // set output texture file type
    const EImageFileType outputTextureFileType = EImageFileType_stringToEnum(outTextureFileTypeName);

    // .ini parsing
    multiviewInputParams mip(iniFilepath, "", "");
    const double simThr = mip._ini.get<double>("global.simThr", 0.0);
    multiviewParams mp(mip.getNbCameras(), &mip, (float) simThr);
    mv_prematch_cams pc(&mp);

    meshRetex mesh;
    mesh.texParams = texParams;
    mesh.me = new mv_mesh();

    if(!mesh.me->loadFromBin(inputDenseReconstruction))
    {
        std::cerr << "Unable to load: " << inputDenseReconstruction << std::endl;
        return EXIT_FAILURE;
    }

    bfs::path reconstructionMeshFolder = bfs::path(inputDenseReconstruction).parent_path();

    mesh::PointsVisibility* ptsCams = loadArrayOfArraysFromFile<int>((reconstructionMeshFolder/"meshPtsCamsFromDGC.bin").string());
    if(ptsCams->size() != mesh.me->pts->size())
        throw std::runtime_error("Error: Reference mesh and associated visibilities don't have the same size.");
    // filterPtsCamsByMinimalPixelSize(refMesh, refPtsCams, &mp);
    bfs::create_directory(outputFolder);

    //std::cout << "Points with no visibilities " << std::count(ptsCams->begin(), ptsCams->end(), nullptr) << std::endl;

    // texturing from input mesh
    if(!inputMeshFilepath.empty())
    {
        ALICEVISION_COUT("An external input mesh is provided, so we remap the visibility from the reconstruction on it.");
        // remap visibilities from reconstruction onto input mesh
        meshRetex otherMesh;
        mesh::PointsVisibility otherPtsVisibilities;
        otherMesh.me = new mv_mesh();
        otherMesh.loadFromOBJ(inputMeshFilepath, flipNormals);
        mesh::remapMeshVisibilities(*mesh.me, *ptsCams, *otherMesh.me, otherPtsVisibilities);

        std::swap(mesh.me, otherMesh.me);
        ptsCams->swap(otherPtsVisibilities);
    }
    if(!mesh.hasUVs())
    {
        ALICEVISION_COUT("The input mesh has no UV, so we generate them.");
        // generate UV coordinates based on automatic uv atlas
        auto* updatedPtsCams = mesh.generateUVs(mp, ptsCams);
        std::swap(ptsCams, updatedPtsCams);
        deleteArrayOfArrays<int>(&updatedPtsCams);
        mesh.saveAsOBJ(outputFolder, "texturedMesh", outputTextureFileType);
    }

    // generate textures
    ALICEVISION_COUT("Generate textures.");
    mesh.generateTextures(mp, ptsCams, outputFolder, outputTextureFileType);

    printfElapsedTime(startTime, "#");
    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "ostree_object.h"
#include "logging/logging.h"
#include "ostree_repo.h"
#include "request_pool.h"

#include <assert.h>
#include <glib.h>
#include <iostream>

using std::string;

OSTreeObject::OSTreeObject(const OSTreeRepo &repo, const std::string &object_name)
    : file_path_(repo.root() / "/objects/" / object_name),
      object_name_(object_name),
      repo_(repo),
      refcount_(0),
      is_on_server_(OBJECT_STATE_UNKNOWN),

      curl_handle_(nullptr),
      form_post_(nullptr) {
  assert(boost::filesystem::is_regular_file(file_path_));
}

void OSTreeObject::AddParent(OSTreeObject *parent, std::list<OSTreeObject::ptr>::iterator parent_it) {
  parentref par;

  par.first = parent;
  par.second = parent_it;
  parents_.push_back(par);
}

void OSTreeObject::ChildNotify(std::list<OSTreeObject::ptr>::iterator child_it) {
  assert((*child_it)->is_on_server() == OBJECT_PRESENT);
  children_.erase(child_it);
}

void OSTreeObject::NotifyParents(RequestPool &pool) {
  assert(is_on_server_ == OBJECT_PRESENT);

  for (parentref parent : parents_) {
    parent.first->ChildNotify(parent.second);
    if (parent.first->children_ready()) {
      pool.AddUpload(parent.first);
    }
  }
}

void OSTreeObject::AppendChild(const OSTreeObject::ptr &child) {
  // the child could be already queried/uploaded by another parent
  if (child->is_on_server() == OBJECT_PRESENT) {
    return;
  }

  children_.push_back(child);
  auto last = children_.end();
  last--;
  child->AddParent(this, last);
}

// Can throw OSTreeObjectMissing if the repo is corrupt
void OSTreeObject::PopulateChildren() {
  const boost::filesystem::path ext = file_path_.extension();
  const GVariantType *content_type;
  bool is_commit;

  // variant types are borrowed from libostree/ostree_core.h,
  // but we don't want to create dependency on it
  if (ext.compare(".commit") == 0) {
    content_type = G_VARIANT_TYPE("(a{sv}aya(say)sstayay)");
    is_commit = true;
  } else if (ext.compare(".dirtree") == 0) {
    content_type = G_VARIANT_TYPE("(a(say)a(sayay))");
    is_commit = false;
  } else {
    return;
  }

  GError *gerror = nullptr;
  GMappedFile *mfile = g_mapped_file_new(file_path_.c_str(), FALSE, &gerror);

  if (mfile == nullptr) {
    throw std::runtime_error("Failed to map metadata file " + file_path_.native());
  }

  GVariant *contents =
      g_variant_new_from_data(content_type, g_mapped_file_get_contents(mfile), g_mapped_file_get_length(mfile), TRUE,
                              reinterpret_cast<GDestroyNotify>(g_mapped_file_unref), mfile);
  g_variant_ref_sink(contents);

  if (is_commit) {
    GVariant *content_csum_variant = nullptr;
    g_variant_get_child(contents, 6, "@ay", &content_csum_variant);

    gsize n_elts;
    const auto *csum = static_cast<const uint8_t *>(g_variant_get_fixed_array(content_csum_variant, &n_elts, 1));
    assert(n_elts == 32);
    AppendChild(repo_.GetObject(csum));

    GVariant *meta_csum_variant = nullptr;

    g_variant_get_child(contents, 7, "@ay", &meta_csum_variant);
    csum = static_cast<const uint8_t *>(g_variant_get_fixed_array(meta_csum_variant, &n_elts, 1));
    assert(n_elts == 32);
    AppendChild(repo_.GetObject(csum));

    g_variant_unref(meta_csum_variant);
    g_variant_unref(content_csum_variant);
  } else {
    GVariant *files_variant = nullptr;
    GVariant *dirs_variant = nullptr;

    files_variant = g_variant_get_child_value(contents, 0);
    dirs_variant = g_variant_get_child_value(contents, 1);

    gsize nfiles = g_variant_n_children(files_variant);
    gsize ndirs = g_variant_n_children(dirs_variant);

    for (gsize i = 0; i < nfiles; i++) {
      GVariant *csum_variant = nullptr;
      const char *fname = nullptr;

      g_variant_get_child(files_variant, i, "(&s@ay)", &fname, &csum_variant);
      gsize n_elts;
      const auto *csum = static_cast<const uint8_t *>(g_variant_get_fixed_array(csum_variant, &n_elts, 1));
      assert(n_elts == 32);
      AppendChild(repo_.GetObject(csum));

      g_variant_unref(csum_variant);
    }

    for (gsize i = 0; i < ndirs; i++) {
      GVariant *content_csum_variant = nullptr;
      GVariant *meta_csum_variant = nullptr;
      const char *fname = nullptr;
      g_variant_get_child(dirs_variant, i, "(&s@ay@ay)", &fname, &content_csum_variant, &meta_csum_variant);
      gsize n_elts;
      const auto *csum = static_cast<const uint8_t *>(g_variant_get_fixed_array(content_csum_variant, &n_elts, 1));
      assert(n_elts == 32);
      AppendChild(repo_.GetObject(csum));

      csum = static_cast<const uint8_t *>(g_variant_get_fixed_array(meta_csum_variant, &n_elts, 1));
      assert(n_elts == 32);
      AppendChild(repo_.GetObject(csum));

      g_variant_unref(meta_csum_variant);
      g_variant_unref(content_csum_variant);
    }

    g_variant_unref(dirs_variant);
    g_variant_unref(files_variant);
  }
  g_variant_unref(contents);
}

void OSTreeObject::QueryChildren(RequestPool &pool) {
  for (const OSTreeObject::ptr &child : children_) {
    if (child->is_on_server() == OBJECT_STATE_UNKNOWN) {
      pool.AddQuery(child);
    }
  }
}

string OSTreeObject::Url() const { return "objects/" + object_name_; }

void OSTreeObject::MakeTestRequest(const TreehubServer &push_target, CURLM *curl_multi_handle) {
  assert(!curl_handle_);
  curl_handle_ = curl_easy_init();
  curl_easy_setopt(curl_handle_, CURLOPT_VERBOSE, get_curlopt_verbose());
  current_operation_ = OSTREE_OBJECT_PRESENCE_CHECK;

  push_target.InjectIntoCurl(Url(), curl_handle_);
  curl_easy_setopt(curl_handle_, CURLOPT_NOBODY, 1);  // HEAD

  curl_easy_setopt(curl_handle_, CURLOPT_WRITEFUNCTION, &OSTreeObject::curl_handle_write);
  curl_easy_setopt(curl_handle_, CURLOPT_WRITEDATA, this);
  curl_easy_setopt(curl_handle_, CURLOPT_PRIVATE, this);  // Used by ostree_object_from_curl
  CURLMcode err = curl_multi_add_handle(curl_multi_handle, curl_handle_);
  if (err != 0) {
    LOG_ERROR << "err:" << curl_multi_strerror(err);
  }
  refcount_++;  // Because curl now has a reference to us
}

void OSTreeObject::Upload(const TreehubServer &push_target, CURLM *curl_multi_handle, const bool dryrun) {
  if (!dryrun) {
    LOG_INFO << "Uploading " << object_name_;
  } else {
    LOG_INFO << "Would upload " << object_name_;
    is_on_server_ = OBJECT_PRESENT;
    return;
  }
  assert(!curl_handle_);

  curl_handle_ = curl_easy_init();
  curl_easy_setopt(curl_handle_, CURLOPT_VERBOSE, get_curlopt_verbose());
  current_operation_ = OSTREE_OBJECT_UPLOADING;
  // TODO: error checking
  push_target.InjectIntoCurl(Url(), curl_handle_);
  curl_easy_setopt(curl_handle_, CURLOPT_WRITEFUNCTION, &OSTreeObject::curl_handle_write);
  curl_easy_setopt(curl_handle_, CURLOPT_WRITEDATA, this);

  assert(form_post_ == nullptr);
  struct curl_httppost *last_item = nullptr;
  curl_formadd(&form_post_, &last_item, CURLFORM_COPYNAME, "file", CURLFORM_FILE, file_path_.c_str(), CURLFORM_END);
  curl_easy_setopt(curl_handle_, CURLOPT_POST, 1);
  CURLcode e = curl_easy_setopt(curl_handle_, CURLOPT_HTTPPOST, form_post_);
  if (e != 0u) {
    LOG_ERROR << "curl_easy_setopt error: " << curl_easy_strerror(e);
  }

  curl_easy_setopt(curl_handle_, CURLOPT_PRIVATE, this);  // Used by ostree_object_from_curl

  CURLMcode err = curl_multi_add_handle(curl_multi_handle, curl_handle_);
  if (err != 0) {
    LOG_ERROR << "curl_multi_add_handle error:" << curl_multi_strerror(err);
  }
  refcount_++;  // Because curl now has a reference to us
}

void OSTreeObject::CurlDone(CURLM *curl_multi_handle) {
  refcount_--;            // Because curl now doesn't have a reference to us
  assert(refcount_ > 0);  // At least our parent should have a reference to us

  long rescode = 0;  // NOLINT
  curl_easy_getinfo(curl_handle_, CURLINFO_RESPONSE_CODE, &rescode);
  if (current_operation_ == OSTREE_OBJECT_PRESENCE_CHECK) {
    if (rescode == 200) {
      is_on_server_ = OBJECT_PRESENT;
    } else if (rescode == 404) {
      is_on_server_ = OBJECT_MISSING;
    } else {
      is_on_server_ = OBJECT_BREAKS_SERVER;
      LOG_ERROR << "OSTree fetch error: " << rescode;
      if (rescode == 0) {
        char *url = nullptr;
        curl_easy_getinfo(curl_handle_, CURLINFO_EFFECTIVE_URL, &url);
        LOG_ERROR << "Check your OSTree server in treehub.json: " << url;
      }
    }
  } else if (current_operation_ == OSTREE_OBJECT_UPLOADING) {
    // TODO: check that http_response_ matches the object hash
    curl_formfree(form_post_);
    form_post_ = nullptr;
    if (rescode == 200) {
      LOG_DEBUG << "OSTree upload successful";
      is_on_server_ = OBJECT_PRESENT;
    } else {
      LOG_ERROR << "OSTree upload error: " << rescode;
      is_on_server_ = OBJECT_BREAKS_SERVER;
    }
  } else {
    assert(0);
  }
  curl_multi_remove_handle(curl_multi_handle, curl_handle_);
  curl_easy_cleanup(curl_handle_);
  curl_handle_ = nullptr;
}

size_t OSTreeObject::curl_handle_write(void *buffer, size_t size, size_t nmemb, void *userp) {
  auto *that = static_cast<OSTreeObject *>(userp);
  that->http_response_.write(static_cast<const char *>(buffer), size * nmemb);
  return size * nmemb;
}

OSTreeObject::~OSTreeObject() {
  if (curl_handle_ != nullptr) {
    curl_easy_cleanup(curl_handle_);
    curl_handle_ = nullptr;
  }
}

OSTreeObject::ptr ostree_object_from_curl(CURL *curlhandle) {
  char *p;
  curl_easy_getinfo(curlhandle, CURLINFO_PRIVATE, &p);
  assert(p);
  auto *h = reinterpret_cast<OSTreeObject *>(p);
  return boost::intrusive_ptr<OSTreeObject>(h);
}

void intrusive_ptr_add_ref(OSTreeObject *h) { h->refcount_++; }

void intrusive_ptr_release(OSTreeObject *h) {
  if (--h->refcount_ == 0) {
    delete h;
  }
}

std::ostream &operator<<(std::ostream &stream, const OSTreeObject &o) {
  stream << o.object_name_;
  return stream;
}

std::ostream &operator<<(std::ostream &stream, const OSTreeObject::ptr &o) {
  stream << *o;
  return stream;
}

// vim: set tabstop=2 shiftwidth=2 expandtab:
<commit_msg>Pass a long to curl_easy_setopt<commit_after>#include "ostree_object.h"
#include "logging/logging.h"
#include "ostree_repo.h"
#include "request_pool.h"

#include <assert.h>
#include <glib.h>
#include <iostream>

using std::string;

OSTreeObject::OSTreeObject(const OSTreeRepo &repo, const std::string &object_name)
    : file_path_(repo.root() / "/objects/" / object_name),
      object_name_(object_name),
      repo_(repo),
      refcount_(0),
      is_on_server_(OBJECT_STATE_UNKNOWN),

      curl_handle_(nullptr),
      form_post_(nullptr) {
  assert(boost::filesystem::is_regular_file(file_path_));
}

void OSTreeObject::AddParent(OSTreeObject *parent, std::list<OSTreeObject::ptr>::iterator parent_it) {
  parentref par;

  par.first = parent;
  par.second = parent_it;
  parents_.push_back(par);
}

void OSTreeObject::ChildNotify(std::list<OSTreeObject::ptr>::iterator child_it) {
  assert((*child_it)->is_on_server() == OBJECT_PRESENT);
  children_.erase(child_it);
}

void OSTreeObject::NotifyParents(RequestPool &pool) {
  assert(is_on_server_ == OBJECT_PRESENT);

  for (parentref parent : parents_) {
    parent.first->ChildNotify(parent.second);
    if (parent.first->children_ready()) {
      pool.AddUpload(parent.first);
    }
  }
}

void OSTreeObject::AppendChild(const OSTreeObject::ptr &child) {
  // the child could be already queried/uploaded by another parent
  if (child->is_on_server() == OBJECT_PRESENT) {
    return;
  }

  children_.push_back(child);
  auto last = children_.end();
  last--;
  child->AddParent(this, last);
}

// Can throw OSTreeObjectMissing if the repo is corrupt
void OSTreeObject::PopulateChildren() {
  const boost::filesystem::path ext = file_path_.extension();
  const GVariantType *content_type;
  bool is_commit;

  // variant types are borrowed from libostree/ostree_core.h,
  // but we don't want to create dependency on it
  if (ext.compare(".commit") == 0) {
    content_type = G_VARIANT_TYPE("(a{sv}aya(say)sstayay)");
    is_commit = true;
  } else if (ext.compare(".dirtree") == 0) {
    content_type = G_VARIANT_TYPE("(a(say)a(sayay))");
    is_commit = false;
  } else {
    return;
  }

  GError *gerror = nullptr;
  GMappedFile *mfile = g_mapped_file_new(file_path_.c_str(), FALSE, &gerror);

  if (mfile == nullptr) {
    throw std::runtime_error("Failed to map metadata file " + file_path_.native());
  }

  GVariant *contents =
      g_variant_new_from_data(content_type, g_mapped_file_get_contents(mfile), g_mapped_file_get_length(mfile), TRUE,
                              reinterpret_cast<GDestroyNotify>(g_mapped_file_unref), mfile);
  g_variant_ref_sink(contents);

  if (is_commit) {
    GVariant *content_csum_variant = nullptr;
    g_variant_get_child(contents, 6, "@ay", &content_csum_variant);

    gsize n_elts;
    const auto *csum = static_cast<const uint8_t *>(g_variant_get_fixed_array(content_csum_variant, &n_elts, 1));
    assert(n_elts == 32);
    AppendChild(repo_.GetObject(csum));

    GVariant *meta_csum_variant = nullptr;

    g_variant_get_child(contents, 7, "@ay", &meta_csum_variant);
    csum = static_cast<const uint8_t *>(g_variant_get_fixed_array(meta_csum_variant, &n_elts, 1));
    assert(n_elts == 32);
    AppendChild(repo_.GetObject(csum));

    g_variant_unref(meta_csum_variant);
    g_variant_unref(content_csum_variant);
  } else {
    GVariant *files_variant = nullptr;
    GVariant *dirs_variant = nullptr;

    files_variant = g_variant_get_child_value(contents, 0);
    dirs_variant = g_variant_get_child_value(contents, 1);

    gsize nfiles = g_variant_n_children(files_variant);
    gsize ndirs = g_variant_n_children(dirs_variant);

    for (gsize i = 0; i < nfiles; i++) {
      GVariant *csum_variant = nullptr;
      const char *fname = nullptr;

      g_variant_get_child(files_variant, i, "(&s@ay)", &fname, &csum_variant);
      gsize n_elts;
      const auto *csum = static_cast<const uint8_t *>(g_variant_get_fixed_array(csum_variant, &n_elts, 1));
      assert(n_elts == 32);
      AppendChild(repo_.GetObject(csum));

      g_variant_unref(csum_variant);
    }

    for (gsize i = 0; i < ndirs; i++) {
      GVariant *content_csum_variant = nullptr;
      GVariant *meta_csum_variant = nullptr;
      const char *fname = nullptr;
      g_variant_get_child(dirs_variant, i, "(&s@ay@ay)", &fname, &content_csum_variant, &meta_csum_variant);
      gsize n_elts;
      const auto *csum = static_cast<const uint8_t *>(g_variant_get_fixed_array(content_csum_variant, &n_elts, 1));
      assert(n_elts == 32);
      AppendChild(repo_.GetObject(csum));

      csum = static_cast<const uint8_t *>(g_variant_get_fixed_array(meta_csum_variant, &n_elts, 1));
      assert(n_elts == 32);
      AppendChild(repo_.GetObject(csum));

      g_variant_unref(meta_csum_variant);
      g_variant_unref(content_csum_variant);
    }

    g_variant_unref(dirs_variant);
    g_variant_unref(files_variant);
  }
  g_variant_unref(contents);
}

void OSTreeObject::QueryChildren(RequestPool &pool) {
  for (const OSTreeObject::ptr &child : children_) {
    if (child->is_on_server() == OBJECT_STATE_UNKNOWN) {
      pool.AddQuery(child);
    }
  }
}

string OSTreeObject::Url() const { return "objects/" + object_name_; }

void OSTreeObject::MakeTestRequest(const TreehubServer &push_target, CURLM *curl_multi_handle) {
  assert(!curl_handle_);
  curl_handle_ = curl_easy_init();
  curl_easy_setopt(curl_handle_, CURLOPT_VERBOSE, get_curlopt_verbose());
  current_operation_ = OSTREE_OBJECT_PRESENCE_CHECK;

  push_target.InjectIntoCurl(Url(), curl_handle_);
  curl_easy_setopt(curl_handle_, CURLOPT_NOBODY, 1L);  // HEAD

  curl_easy_setopt(curl_handle_, CURLOPT_WRITEFUNCTION, &OSTreeObject::curl_handle_write);
  curl_easy_setopt(curl_handle_, CURLOPT_WRITEDATA, this);
  curl_easy_setopt(curl_handle_, CURLOPT_PRIVATE, this);  // Used by ostree_object_from_curl
  CURLMcode err = curl_multi_add_handle(curl_multi_handle, curl_handle_);
  if (err != 0) {
    LOG_ERROR << "err:" << curl_multi_strerror(err);
  }
  refcount_++;  // Because curl now has a reference to us
}

void OSTreeObject::Upload(const TreehubServer &push_target, CURLM *curl_multi_handle, const bool dryrun) {
  if (!dryrun) {
    LOG_INFO << "Uploading " << object_name_;
  } else {
    LOG_INFO << "Would upload " << object_name_;
    is_on_server_ = OBJECT_PRESENT;
    return;
  }
  assert(!curl_handle_);

  curl_handle_ = curl_easy_init();
  curl_easy_setopt(curl_handle_, CURLOPT_VERBOSE, get_curlopt_verbose());
  current_operation_ = OSTREE_OBJECT_UPLOADING;
  // TODO: error checking
  push_target.InjectIntoCurl(Url(), curl_handle_);
  curl_easy_setopt(curl_handle_, CURLOPT_WRITEFUNCTION, &OSTreeObject::curl_handle_write);
  curl_easy_setopt(curl_handle_, CURLOPT_WRITEDATA, this);

  assert(form_post_ == nullptr);
  struct curl_httppost *last_item = nullptr;
  curl_formadd(&form_post_, &last_item, CURLFORM_COPYNAME, "file", CURLFORM_FILE, file_path_.c_str(), CURLFORM_END);
  curl_easy_setopt(curl_handle_, CURLOPT_POST, 1);
  CURLcode e = curl_easy_setopt(curl_handle_, CURLOPT_HTTPPOST, form_post_);
  if (e != 0u) {
    LOG_ERROR << "curl_easy_setopt error: " << curl_easy_strerror(e);
  }

  curl_easy_setopt(curl_handle_, CURLOPT_PRIVATE, this);  // Used by ostree_object_from_curl

  CURLMcode err = curl_multi_add_handle(curl_multi_handle, curl_handle_);
  if (err != 0) {
    LOG_ERROR << "curl_multi_add_handle error:" << curl_multi_strerror(err);
  }
  refcount_++;  // Because curl now has a reference to us
}

void OSTreeObject::CurlDone(CURLM *curl_multi_handle) {
  refcount_--;            // Because curl now doesn't have a reference to us
  assert(refcount_ > 0);  // At least our parent should have a reference to us

  long rescode = 0;  // NOLINT
  curl_easy_getinfo(curl_handle_, CURLINFO_RESPONSE_CODE, &rescode);
  if (current_operation_ == OSTREE_OBJECT_PRESENCE_CHECK) {
    if (rescode == 200) {
      is_on_server_ = OBJECT_PRESENT;
    } else if (rescode == 404) {
      is_on_server_ = OBJECT_MISSING;
    } else {
      is_on_server_ = OBJECT_BREAKS_SERVER;
      LOG_ERROR << "OSTree fetch error: " << rescode;
      if (rescode == 0) {
        char *url = nullptr;
        curl_easy_getinfo(curl_handle_, CURLINFO_EFFECTIVE_URL, &url);
        LOG_ERROR << "Check your OSTree server in treehub.json: " << url;
      }
    }
  } else if (current_operation_ == OSTREE_OBJECT_UPLOADING) {
    // TODO: check that http_response_ matches the object hash
    curl_formfree(form_post_);
    form_post_ = nullptr;
    if (rescode == 200) {
      LOG_DEBUG << "OSTree upload successful";
      is_on_server_ = OBJECT_PRESENT;
    } else {
      LOG_ERROR << "OSTree upload error: " << rescode;
      is_on_server_ = OBJECT_BREAKS_SERVER;
    }
  } else {
    assert(0);
  }
  curl_multi_remove_handle(curl_multi_handle, curl_handle_);
  curl_easy_cleanup(curl_handle_);
  curl_handle_ = nullptr;
}

size_t OSTreeObject::curl_handle_write(void *buffer, size_t size, size_t nmemb, void *userp) {
  auto *that = static_cast<OSTreeObject *>(userp);
  that->http_response_.write(static_cast<const char *>(buffer), size * nmemb);
  return size * nmemb;
}

OSTreeObject::~OSTreeObject() {
  if (curl_handle_ != nullptr) {
    curl_easy_cleanup(curl_handle_);
    curl_handle_ = nullptr;
  }
}

OSTreeObject::ptr ostree_object_from_curl(CURL *curlhandle) {
  char *p;
  curl_easy_getinfo(curlhandle, CURLINFO_PRIVATE, &p);
  assert(p);
  auto *h = reinterpret_cast<OSTreeObject *>(p);
  return boost::intrusive_ptr<OSTreeObject>(h);
}

void intrusive_ptr_add_ref(OSTreeObject *h) { h->refcount_++; }

void intrusive_ptr_release(OSTreeObject *h) {
  if (--h->refcount_ == 0) {
    delete h;
  }
}

std::ostream &operator<<(std::ostream &stream, const OSTreeObject &o) {
  stream << o.object_name_;
  return stream;
}

std::ostream &operator<<(std::ostream &stream, const OSTreeObject::ptr &o) {
  stream << *o;
  return stream;
}

// vim: set tabstop=2 shiftwidth=2 expandtab:
<|endoftext|>


<commit_before>/*******************************************************************************
 * Copyright 2018 MINRES Technologies GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/
#include <array>
#include <boost/filesystem.hpp>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <fcntl.h>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// clang-format off
#ifdef HAS_SCV
#include <scv.h>
#else
#include <scv-tr.h>
namespace scv_tr {
#endif
// clang-format on
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
using namespace std;

// ----------------------------------------------------------------------------
enum EventType { BEGIN, RECORD, END };
using data_type = scv_extensions_if::data_type;
// ----------------------------------------------------------------------------
namespace {
class Base {
protected:
    boost::filesystem::path dir;
    Base(const std::string& name)
    : dir(name.c_str()) {
        if(boost::filesystem::exists(dir))
            boost::filesystem::remove_all(dir);
        boost::filesystem::create_directory(dir);
    }
};

struct Database : Base {
    uint64_t idx{0};
    Database(const std::string& name)
    : Base(name) {}

    inline uint64_t getIdOf(const std::string& str) {
        return idx;
    }

    inline void writeStream(uint64_t id, std::string name, std::string kind) {
//        c.writeStream(id, name, kind);
    }

    inline void writeGenerator(uint64_t id, std::string name, uint64_t stream) {
//        c.writeGenerator(id, name, stream);
    }

    inline uint64_t writeTransaction(uint64_t id, uint64_t generator) {
        return ++idx;//d.writeTx(id, generator, concurrencyLevel);
    }

    inline void writeTxTimepoint(uint64_t id, int type, uint64_t time, uint64_t file_offset) {
//        t.append(type, time, file_offset);
    }

    inline void writeAttribute(uint64_t id, EventType event, const string& name, data_type type, const string& value) {
//        d.writeAttribute(id, event, c.getIdOf(name), type, c.getIdOf(value));
    }

    inline void writeAttribute(uint64_t id, EventType event, const string& name, data_type type, uint64_t value) {
//        d.writeAttribute(id, event, c.getIdOf(name), type, value);
    }

    inline void writeAttribute(uint64_t id, EventType event, const string& name, data_type type, double value) {
        //        int exponent;
        //        const double mantissa = frexp(value, &exponent);
    }

    inline void writeRelation(const std::string& name, uint64_t sink_id, uint64_t src_id) {
//        d.writeRelation(c.getIdOf(name), src_id, sink_id);
    }
};

Database* db;
std::unordered_map<uint64_t, uint64_t> id2offset;

void dbCb(const scv_tr_db& _scv_tr_db, scv_tr_db::callback_reason reason, void* data) {
    // This is called from the scv_tr_db ctor.
    static string fName("DEFAULT_scv_tr_sqlite");
    switch(reason) {
    case scv_tr_db::CREATE:
        if((_scv_tr_db.get_name() != nullptr) && (strlen(_scv_tr_db.get_name()) != 0))
            fName = _scv_tr_db.get_name();
        try {
            db = new Database(fName);
        } catch(...) {
            _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Can't open recording file");
        }
        break;
    case scv_tr_db::DELETE:
        try {
            delete db;
        } catch(...) {
            _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Can't close recording file");
        }
        break;
    default:
        _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Unknown reason in scv_tr_db callback");
    }
}
// ----------------------------------------------------------------------------
void streamCb(const scv_tr_stream& s, scv_tr_stream::callback_reason reason, void* data) {
    if(reason == scv_tr_stream::CREATE) {
        try {
            db->writeStream(s.get_id(), s.get_name(), s.get_stream_kind());
        } catch(std::runtime_error& e) {
            _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Can't create stream");
        }
    }
}
// ----------------------------------------------------------------------------
void recordAttribute(uint64_t id, EventType event, const string& name, data_type type, const string& value) {
    try {
        db->writeAttribute(id, event, name, type, value);
    } catch(std::runtime_error& e) {
        _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Can't create attribute entry");
    }
}
// ----------------------------------------------------------------------------
void recordAttribute(uint64_t id, EventType event, const string& name, data_type type, long long value) {
    try {
        db->writeAttribute(id, event, name, type, static_cast<uint64_t>(value));
    } catch(std::runtime_error& e) {
        _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Can't create attribute entry");
    }
}
// ----------------------------------------------------------------------------
inline void recordAttribute(uint64_t id, EventType event, const string& name, data_type type, double value) {
    try {
        db->writeAttribute(id, event, name, type, value);
    } catch(std::runtime_error& e) {
        _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Can't create attribute entry");
    }
}

inline  std::string get_name(const char* prefix, const scv_extensions_if* my_exts_p) {
    static thread_local std::unordered_map<const scv_extensions_if*, std::string> name_lut;
    auto it = name_lut.find(my_exts_p);
    if(it!=name_lut.end()) return it->second;
    string name;
    if (prefix == "") {
        name = my_exts_p->get_name();
    } else {
        if ((my_exts_p->get_name() == nullptr) || (strlen(my_exts_p->get_name()) == 0)) {
            name = prefix;
        } else {
            name = std::string(prefix) + "." + my_exts_p->get_name();
        }
    }
    name_lut[my_exts_p]=(name == "")?"<unnamed>":  name;
    return (name == "")?"<unnamed>":  name;
}

// ----------------------------------------------------------------------------
void recordAttributes(uint64_t id, EventType eventType, char const* prefix, const scv_extensions_if* my_exts_p) {
    if(my_exts_p == nullptr)
        return;
    auto name = get_name(prefix, my_exts_p);
    switch(my_exts_p->get_type()) {
    case scv_extensions_if::RECORD: {
        int num_fields = my_exts_p->get_num_fields();
        if(num_fields > 0) {
            for(int field_counter = 0; field_counter < num_fields; field_counter++) {
                const scv_extensions_if* field_data_p = my_exts_p->get_field(field_counter);
                recordAttributes(id, eventType, prefix, field_data_p);
            }
        }
    } break;
    case scv_extensions_if::ENUMERATION:
        recordAttribute(id, eventType, name, scv_extensions_if::ENUMERATION,
                        my_exts_p->get_enum_string((int)(my_exts_p->get_integer())));
        break;
    case scv_extensions_if::BOOLEAN:
        recordAttribute(id, eventType, name, scv_extensions_if::BOOLEAN, my_exts_p->get_bool() ? "TRUE" : "FALSE");
        break;
    case scv_extensions_if::INTEGER:
    case scv_extensions_if::FIXED_POINT_INTEGER:
        recordAttribute(id, eventType, name, scv_extensions_if::INTEGER, my_exts_p->get_integer());
        break;
    case scv_extensions_if::UNSIGNED:
        recordAttribute(id, eventType, name, scv_extensions_if::UNSIGNED, my_exts_p->get_integer());
        break;
    case scv_extensions_if::POINTER:
        recordAttribute(id, eventType, name, scv_extensions_if::POINTER, (long long)my_exts_p->get_pointer());
        break;
    case scv_extensions_if::STRING:
        recordAttribute(id, eventType, name, scv_extensions_if::STRING, my_exts_p->get_string());
        break;
    case scv_extensions_if::FLOATING_POINT_NUMBER:
        recordAttribute(id, eventType, name, scv_extensions_if::FLOATING_POINT_NUMBER, my_exts_p->get_double());
        break;
    case scv_extensions_if::BIT_VECTOR: {
        sc_bv_base tmp_bv(my_exts_p->get_bitwidth());
        my_exts_p->get_value(tmp_bv);
        recordAttribute(id, eventType, name, scv_extensions_if::BIT_VECTOR, tmp_bv.to_string());
    } break;
    case scv_extensions_if::LOGIC_VECTOR: {
        sc_lv_base tmp_lv(my_exts_p->get_bitwidth());
        my_exts_p->get_value(tmp_lv);
        recordAttribute(id, eventType, name, scv_extensions_if::LOGIC_VECTOR, tmp_lv.to_string());
    } break;
    case scv_extensions_if::ARRAY:
        for(int array_elt_index = 0; array_elt_index < my_exts_p->get_array_size(); array_elt_index++) {
            const scv_extensions_if* field_data_p = my_exts_p->get_array_elt(array_elt_index);
            recordAttributes(id, eventType, prefix, field_data_p);
        }
        break;
    default: {
        std::array<char, 100> tmpString;
        sprintf(tmpString.data(), "Unsupported attribute type = %d", my_exts_p->get_type());
        _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, tmpString.data());
    }
    }
}
// ----------------------------------------------------------------------------
void generatorCb(const scv_tr_generator_base& g, scv_tr_generator_base::callback_reason reason, void* data) {
    if(reason == scv_tr_generator_base::CREATE && db) {
        try {
            db->writeGenerator(g.get_id(), g.get_name(), g.get_scv_tr_stream().get_id());
        } catch(std::runtime_error& e) {
            _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Can't create generator entry");
        }
    }
}
// ----------------------------------------------------------------------------
void transactionCb(const scv_tr_handle& t, scv_tr_handle::callback_reason reason, void* data) {
    if(!db)
        return;
    if(t.get_scv_tr_stream().get_scv_tr_db() == nullptr)
        return;
    if(t.get_scv_tr_stream().get_scv_tr_db()->get_recording() == false)
        return;

    uint64_t id = t.get_id();
    uint64_t streamId = t.get_scv_tr_stream().get_id();
    vector<uint64_t>::size_type concurrencyIdx;
    const scv_extensions_if* my_exts_p;
    switch(reason) {
    case scv_tr_handle::BEGIN: {
        my_exts_p = t.get_begin_exts_p();
        if(my_exts_p == nullptr)
            my_exts_p = t.get_scv_tr_generator_base().get_begin_exts_p();
        if(my_exts_p) {
            auto tmp_str = t.get_scv_tr_generator_base().get_begin_attribute_name()
                                 ? t.get_scv_tr_generator_base().get_begin_attribute_name()
                                 : "";
            recordAttributes(id, BEGIN, tmp_str, my_exts_p);
        }
    } break;
    case scv_tr_handle::END: {
        my_exts_p = t.get_end_exts_p();
        if(my_exts_p == nullptr)
            my_exts_p = t.get_scv_tr_generator_base().get_end_exts_p();
        if(my_exts_p) {
            auto tmp_str = t.get_scv_tr_generator_base().get_end_attribute_name()
                                 ? t.get_scv_tr_generator_base().get_end_attribute_name()
                                 : "";
            recordAttributes(t.get_id(), END, tmp_str, my_exts_p);
        }
    } break;
    default:;
    }
}
// ----------------------------------------------------------------------------
void attributeCb(const scv_tr_handle& t, const char* name, const scv_extensions_if* ext, void* data) {
    if(!db)
        return;
    if(t.get_scv_tr_stream().get_scv_tr_db() == nullptr)
        return;
    if(t.get_scv_tr_stream().get_scv_tr_db()->get_recording() == false)
        return;
    recordAttributes(t.get_id(), RECORD, name == nullptr ? "" : name, ext);
}
// ----------------------------------------------------------------------------
void relationCb(const scv_tr_handle& tr_1, const scv_tr_handle& tr_2, void* data,
                scv_tr_relation_handle_t relation_handle) {
    if(!db)
        return;
    if(tr_1.get_scv_tr_stream().get_scv_tr_db() == nullptr)
        return;
    if(tr_1.get_scv_tr_stream().get_scv_tr_db()->get_recording() == false)
        return;
    try {
        db->writeRelation(tr_1.get_scv_tr_stream().get_scv_tr_db()->get_relation_name(relation_handle), tr_1.get_id(),
                          tr_2.get_id());
    } catch(std::runtime_error& e) {
        _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Can't create transaction relation");
    }
}
} // namespace
// ----------------------------------------------------------------------------
void scv_tr_mtc_init() {
    scv_tr_db::register_class_cb(dbCb);
    scv_tr_stream::register_class_cb(streamCb);
    scv_tr_generator_base::register_class_cb(generatorCb);
    scv_tr_handle::register_class_cb(transactionCb);
    scv_tr_handle::register_record_attribute_cb(attributeCb);
    scv_tr_handle::register_relation_cb(relationCb);
}
// ----------------------------------------------------------------------------
#ifndef HAS_SCV
}
#endif
<commit_msg>small fixes in SCV tr file skeleton<commit_after>/*******************************************************************************
 * Copyright 2018 MINRES Technologies GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/
#include <array>
#include <boost/filesystem.hpp>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <fcntl.h>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <fstream>
// clang-format off
#ifdef HAS_SCV
#include <scv.h>
#else
#include <scv-tr.h>
namespace scv_tr {
#endif
// clang-format on
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
using namespace std;

// ----------------------------------------------------------------------------
enum EventType { BEGIN, RECORD, END };
using data_type = scv_extensions_if::data_type;
// ----------------------------------------------------------------------------
namespace {
class Base {
protected:
    boost::filesystem::path dir;
    std::ofstream out;
    bool const is_open;
    std::array<char, 1024> buffer;
    Base(const std::string& name)
    : dir(name.c_str()), out(name), is_open(out.is_open()){
//        if(boost::filesystem::exists(dir))
//            boost::filesystem::remove_all(dir);
//        boost::filesystem::create_directory(dir);
    }
    ~Base() {
        if(is_open) out.close();
    }
};

struct Database : Base {
    uint64_t idx{0};
    Database(const std::string& name)
    : Base(name) {}

    inline uint64_t getIdOf(const std::string& str) {
        return idx;
    }

    inline void writeStream(uint64_t id, std::string const& name, std::string const& kind) {
        if(is_open) {
            auto len = sprintf(buffer.data(), "scv_tr_stream (ID %lu, name \"%s\", kind \"%s\")\n", id, name.c_str(), kind.c_str());
            out.write(buffer.data(), len);
        }
    }

    inline void writeGenerator(uint64_t id, std::string const& name, uint64_t stream) {
        if(is_open) {
            auto len = sprintf(buffer.data(), "scv_tr_generator (ID %lu, name \"%s\", scv_tr_stream %lu,\n", id, name.c_str(), stream);
            out.write(buffer.data(), len);
        }
    }

    inline uint64_t writeTransaction(uint64_t id, uint64_t generator) {
        return ++idx;//d.writeTx(id, generator, concurrencyLevel);
    }

    inline void writeTxTimepoint(uint64_t id, int type, uint64_t time, uint64_t file_offset) {
//        t.append(type, time, file_offset);
    }

    inline void writeAttribute(uint64_t id, EventType event, const string& name, data_type type, const string& value) {
//        d.writeAttribute(id, event, c.getIdOf(name), type, c.getIdOf(value));
    }

    inline void writeAttribute(uint64_t id, EventType event, const string& name, data_type type, uint64_t value) {
//        d.writeAttribute(id, event, c.getIdOf(name), type, value);
    }

    inline void writeAttribute(uint64_t id, EventType event, const string& name, data_type type, double value) {
        //        int exponent;
        //        const double mantissa = frexp(value, &exponent);
    }

    inline void writeRelation(const std::string& name, uint64_t sink_id, uint64_t src_id) {
//        d.writeRelation(c.getIdOf(name), src_id, sink_id);
    }
};

Database* db;
std::unordered_map<uint64_t, uint64_t> id2offset;

void dbCb(const scv_tr_db& _scv_tr_db, scv_tr_db::callback_reason reason, void* data) {
    // This is called from the scv_tr_db ctor.
    static string fName("DEFAULT_scv_tr_sqlite");
    switch(reason) {
    case scv_tr_db::CREATE:
        if((_scv_tr_db.get_name() != nullptr) && (strlen(_scv_tr_db.get_name()) != 0))
            fName = _scv_tr_db.get_name();
        try {
            db = new Database(fName);
        } catch(...) {
            _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Can't open recording file");
        }
        break;
    case scv_tr_db::DELETE:
        try {
            delete db;
        } catch(...) {
            _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Can't close recording file");
        }
        break;
    default:
        _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Unknown reason in scv_tr_db callback");
    }
}
// ----------------------------------------------------------------------------
void streamCb(const scv_tr_stream& s, scv_tr_stream::callback_reason reason, void* data) {
    if(reason == scv_tr_stream::CREATE) {
        try {
            db->writeStream(s.get_id(), s.get_name(), s.get_stream_kind());
        } catch(std::runtime_error& e) {
            _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Can't create stream");
        }
    }
}
// ----------------------------------------------------------------------------
inline void recordAttribute(uint64_t id, EventType event, const string& name, data_type type, const string& value) {
    try {
        db->writeAttribute(id, event, name, type, value);
    } catch(std::runtime_error& e) {
        _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Can't create attribute entry");
    }
}
// ----------------------------------------------------------------------------
inline void recordAttribute(uint64_t id, EventType event, const string& name, data_type type, long long value) {
    try {
        db->writeAttribute(id, event, name, type, static_cast<uint64_t>(value));
    } catch(std::runtime_error& e) {
        _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Can't create attribute entry");
    }
}
// ----------------------------------------------------------------------------
inline void recordAttribute(uint64_t id, EventType event, const string& name, data_type type, double value) {
    try {
        db->writeAttribute(id, event, name, type, value);
    } catch(std::runtime_error& e) {
        _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Can't create attribute entry");
    }
}

inline  std::string get_name(const char* prefix, const scv_extensions_if* my_exts_p) {
    static thread_local std::unordered_map<const scv_extensions_if*, std::string> name_lut;
    auto it = name_lut.find(my_exts_p);
    if(it!=name_lut.end()) return it->second;
    string name;
    if (!prefix || strlen(prefix)==0) {
        name = my_exts_p->get_name();
    } else {
        if ((my_exts_p->get_name() == nullptr) || (strlen(my_exts_p->get_name()) == 0)) {
            name = prefix;
        } else {
            name = std::string(prefix) + "." + my_exts_p->get_name();
        }
    }
    name_lut[my_exts_p]=(name == "")?"<unnamed>":  name;
    return (name == "")?"<unnamed>":  name;
}

// ----------------------------------------------------------------------------
void recordAttributes(uint64_t id, EventType eventType, char const* prefix, const scv_extensions_if* my_exts_p) {
    if(my_exts_p == nullptr)
        return;
    auto name = get_name(prefix, my_exts_p);
    switch(my_exts_p->get_type()) {
    case scv_extensions_if::RECORD: {
        int num_fields = my_exts_p->get_num_fields();
        if(num_fields > 0) {
            for(int field_counter = 0; field_counter < num_fields; field_counter++) {
                const scv_extensions_if* field_data_p = my_exts_p->get_field(field_counter);
                recordAttributes(id, eventType, prefix, field_data_p);
            }
        }
    } break;
    case scv_extensions_if::ENUMERATION:
        recordAttribute(id, eventType, name, scv_extensions_if::ENUMERATION,
                        my_exts_p->get_enum_string((int)(my_exts_p->get_integer())));
        break;
    case scv_extensions_if::BOOLEAN:
        recordAttribute(id, eventType, name, scv_extensions_if::BOOLEAN, my_exts_p->get_bool() ? "TRUE" : "FALSE");
        break;
    case scv_extensions_if::INTEGER:
    case scv_extensions_if::FIXED_POINT_INTEGER:
        recordAttribute(id, eventType, name, scv_extensions_if::INTEGER, my_exts_p->get_integer());
        break;
    case scv_extensions_if::UNSIGNED:
        recordAttribute(id, eventType, name, scv_extensions_if::UNSIGNED, my_exts_p->get_integer());
        break;
    case scv_extensions_if::POINTER:
        recordAttribute(id, eventType, name, scv_extensions_if::POINTER, (long long)my_exts_p->get_pointer());
        break;
    case scv_extensions_if::STRING:
        recordAttribute(id, eventType, name, scv_extensions_if::STRING, my_exts_p->get_string());
        break;
    case scv_extensions_if::FLOATING_POINT_NUMBER:
        recordAttribute(id, eventType, name, scv_extensions_if::FLOATING_POINT_NUMBER, my_exts_p->get_double());
        break;
    case scv_extensions_if::BIT_VECTOR: {
        sc_bv_base tmp_bv(my_exts_p->get_bitwidth());
        my_exts_p->get_value(tmp_bv);
        recordAttribute(id, eventType, name, scv_extensions_if::BIT_VECTOR, tmp_bv.to_string());
    } break;
    case scv_extensions_if::LOGIC_VECTOR: {
        sc_lv_base tmp_lv(my_exts_p->get_bitwidth());
        my_exts_p->get_value(tmp_lv);
        recordAttribute(id, eventType, name, scv_extensions_if::LOGIC_VECTOR, tmp_lv.to_string());
    } break;
    case scv_extensions_if::ARRAY:
        for(int array_elt_index = 0; array_elt_index < my_exts_p->get_array_size(); array_elt_index++) {
            const scv_extensions_if* field_data_p = my_exts_p->get_array_elt(array_elt_index);
            recordAttributes(id, eventType, prefix, field_data_p);
        }
        break;
    default: {
        std::array<char, 100> tmpString;
        sprintf(tmpString.data(), "Unsupported attribute type = %d", my_exts_p->get_type());
        _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, tmpString.data());
    }
    }
}
// ----------------------------------------------------------------------------
void generatorCb(const scv_tr_generator_base& g, scv_tr_generator_base::callback_reason reason, void* data) {
    if(reason == scv_tr_generator_base::CREATE && db) {
        try {
            db->writeGenerator(g.get_id(), g.get_name(), g.get_scv_tr_stream().get_id());
        } catch(std::runtime_error& e) {
            _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Can't create generator entry");
        }
    }
}
// ----------------------------------------------------------------------------
void transactionCb(const scv_tr_handle& t, scv_tr_handle::callback_reason reason, void* data) {
    if(!db)
        return;
    if(t.get_scv_tr_stream().get_scv_tr_db() == nullptr)
        return;
    if(t.get_scv_tr_stream().get_scv_tr_db()->get_recording() == false)
        return;

    uint64_t id = t.get_id();
    vector<uint64_t>::size_type concurrencyIdx;
    const scv_extensions_if* my_exts_p;
    switch(reason) {
    case scv_tr_handle::BEGIN: {
        my_exts_p = t.get_begin_exts_p();
        if(my_exts_p == nullptr)
            my_exts_p = t.get_scv_tr_generator_base().get_begin_exts_p();
        if(my_exts_p) {
            auto tmp_str = t.get_scv_tr_generator_base().get_begin_attribute_name()
                                 ? t.get_scv_tr_generator_base().get_begin_attribute_name()
                                 : "";
            recordAttributes(id, BEGIN, tmp_str, my_exts_p);
        }
    } break;
    case scv_tr_handle::END: {
        my_exts_p = t.get_end_exts_p();
        if(my_exts_p == nullptr)
            my_exts_p = t.get_scv_tr_generator_base().get_end_exts_p();
        if(my_exts_p) {
            auto tmp_str = t.get_scv_tr_generator_base().get_end_attribute_name()
                                 ? t.get_scv_tr_generator_base().get_end_attribute_name()
                                 : "";
            recordAttributes(t.get_id(), END, tmp_str, my_exts_p);
        }
    } break;
    default:;
    }
}
// ----------------------------------------------------------------------------
void attributeCb(const scv_tr_handle& t, const char* name, const scv_extensions_if* ext, void* data) {
    if(!db)
        return;
    if(t.get_scv_tr_stream().get_scv_tr_db() == nullptr)
        return;
    if(t.get_scv_tr_stream().get_scv_tr_db()->get_recording() == false)
        return;
    recordAttributes(t.get_id(), RECORD, name == nullptr ? "" : name, ext);
}
// ----------------------------------------------------------------------------
void relationCb(const scv_tr_handle& tr_1, const scv_tr_handle& tr_2, void* data,
                scv_tr_relation_handle_t relation_handle) {
    if(!db)
        return;
    if(tr_1.get_scv_tr_stream().get_scv_tr_db() == nullptr)
        return;
    if(tr_1.get_scv_tr_stream().get_scv_tr_db()->get_recording() == false)
        return;
    try {
        db->writeRelation(tr_1.get_scv_tr_stream().get_scv_tr_db()->get_relation_name(relation_handle), tr_1.get_id(),
                          tr_2.get_id());
    } catch(std::runtime_error& e) {
        _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, "Can't create transaction relation");
    }
}
} // namespace
// ----------------------------------------------------------------------------
void scv_tr_mtc_init() {
    scv_tr_db::register_class_cb(dbCb);
    scv_tr_stream::register_class_cb(streamCb);
    scv_tr_generator_base::register_class_cb(generatorCb);
    scv_tr_handle::register_class_cb(transactionCb);
    scv_tr_handle::register_record_attribute_cb(attributeCb);
    scv_tr_handle::register_relation_cb(relationCb);
}
// ----------------------------------------------------------------------------
#ifndef HAS_SCV
}
#endif
<|endoftext|>


<commit_before>/*++
Copyright (c) 2012 Microsoft Corporation

Module Name:

    ufbv_tactic.cpp

Abstract:

    General purpose tactic for UFBV benchmarks.

Author:

    Christoph (cwinter) 2012-10-24

Notes:

--*/
#include"tactical.h"
#include"simplify_tactic.h"
#include"propagate_values_tactic.h"
#include"solve_eqs_tactic.h"
#include"distribute_forall_tactic.h"
#include"der_tactic.h"
#include"reduce_args_tactic.h"
#include"smt_tactic.h"
#include"nnf_tactic.h"
#include"macro_finder_tactic.h"
#include"ufbv_rewriter_tactic.h"
#include"quasi_macros_tactic.h"
#include"ufbv_tactic.h"

tactic * mk_der_fp_tactic(ast_manager & m, params_ref const & p) {
    return repeat(and_then(mk_der_tactic(m), mk_simplify_tactic(m, p)));
}

tactic * mk_ufbv_preprocessor_tactic(ast_manager & m, params_ref const & p) {
    params_ref no_elim_and(p);
    no_elim_and.set_bool(":elim-and", false);

    return and_then(
		mk_trace_tactic("ufbv_pre"),
                and_then(mk_simplify_tactic(m, p),
                         mk_propagate_values_tactic(m, p),
                         and_then(using_params(mk_macro_finder_tactic(m, no_elim_and), no_elim_and),
				  mk_simplify_tactic(m, p)),
                         and_then(mk_snf_tactic(m, p), mk_simplify_tactic(m, p)),
                         mk_elim_and_tactic(m, p),
                         mk_solve_eqs_tactic(m, p),
                         and_then(mk_der_fp_tactic(m, p), mk_simplify_tactic(m, p)),
                         and_then(mk_distribute_forall_tactic(m, p), mk_simplify_tactic(m, p))),
                and_then(and_then(mk_reduce_args_tactic(m, p), mk_simplify_tactic(m, p)),
                         and_then(mk_macro_finder_tactic(m, p), mk_simplify_tactic(m, p)),
                         and_then(mk_ufbv_rewriter_tactic(m, p), mk_simplify_tactic(m, p)),
                         and_then(mk_quasi_macros_tactic(m, p), mk_simplify_tactic(m, p)),
                         and_then(mk_der_fp_tactic(m, p), mk_simplify_tactic(m, p)),
                         mk_simplify_tactic(m, p)),
		mk_trace_tactic("ufbv_post"));
}

tactic * mk_ufbv_tactic(ast_manager & m, params_ref const & p) {
    params_ref main_p(p);
    main_p.set_bool(":mbqi", true);
    main_p.set_uint(":mbqi-max-iterations", -1);
    main_p.set_bool(":elim-and", true);
    main_p.set_bool(":solver", true);

    params_ref smt_p(p);
    smt_p.set_bool(":auto-config", false);

    tactic * t = and_then(repeat(mk_ufbv_preprocessor_tactic(m, main_p), 2),
                          using_params(mk_smt_tactic(smt_p), main_p));

    t->updt_params(p);

    return t;
}
<commit_msg>UFBV performance fix<commit_after>/*++
Copyright (c) 2012 Microsoft Corporation

Module Name:

    ufbv_tactic.cpp

Abstract:

    General purpose tactic for UFBV benchmarks.

Author:

    Christoph (cwinter) 2012-10-24

Notes:

--*/
#include"tactical.h"
#include"simplify_tactic.h"
#include"propagate_values_tactic.h"
#include"solve_eqs_tactic.h"
#include"distribute_forall_tactic.h"
#include"der_tactic.h"
#include"reduce_args_tactic.h"
#include"smt_tactic.h"
#include"nnf_tactic.h"
#include"macro_finder_tactic.h"
#include"ufbv_rewriter_tactic.h"
#include"quasi_macros_tactic.h"
#include"ufbv_tactic.h"

tactic * mk_der_fp_tactic(ast_manager & m, params_ref const & p) {
    return repeat(and_then(mk_der_tactic(m), mk_simplify_tactic(m, p)));
}

tactic * mk_ufbv_preprocessor_tactic(ast_manager & m, params_ref const & p) {
    params_ref no_elim_and(p);
    no_elim_and.set_bool(":elim-and", false);

    return and_then(
		mk_trace_tactic("ufbv_pre"),
                and_then(mk_simplify_tactic(m, p),
                         mk_propagate_values_tactic(m, p),
                         and_then(using_params(mk_macro_finder_tactic(m, no_elim_and), no_elim_and),
				  mk_simplify_tactic(m, p)),
                         and_then(mk_snf_tactic(m, p), mk_simplify_tactic(m, p)),
                         mk_elim_and_tactic(m, p),
                         mk_solve_eqs_tactic(m, p),
                         and_then(mk_der_fp_tactic(m, p), mk_simplify_tactic(m, p)),
                         and_then(mk_distribute_forall_tactic(m, p), mk_simplify_tactic(m, p))),
                and_then(and_then(mk_reduce_args_tactic(m, p), mk_simplify_tactic(m, p)),
                         and_then(mk_macro_finder_tactic(m, p), mk_simplify_tactic(m, p)),
                         and_then(mk_ufbv_rewriter_tactic(m, p), mk_simplify_tactic(m, p)),
                         and_then(mk_quasi_macros_tactic(m, p), mk_simplify_tactic(m, p)),
                         and_then(mk_der_fp_tactic(m, p), mk_simplify_tactic(m, p)),
                         mk_simplify_tactic(m, p)),
		mk_trace_tactic("ufbv_post"));
}

tactic * mk_ufbv_tactic(ast_manager & m, params_ref const & p) {
    params_ref main_p(p);
    main_p.set_bool(":mbqi", true);
    main_p.set_uint(":mbqi-max-iterations", -1);
    main_p.set_bool(":elim-and", true);
    main_p.set_bool(":solver", true);

    tactic * t = and_then(repeat(mk_ufbv_preprocessor_tactic(m, main_p), 2),
                          mk_smt_tactic_using(false, main_p));

    t->updt_params(p);

    return t;
}
<|endoftext|>