<commit_before>#include<iostream>
#include <cstdlib>
#include <cstdio>
#include <array>

using RawField = std::array<std::array<char, 32>, 32>;
using RawStone = std::array<std::array<char, 8>, 8>;

class Field {
  private:
    int score = 0;
  public:
    RawField raw = {};
    int Score() const {
      return score;
    }
    bool TryPutStone(int stone_number, int base_x, int base_y, int manipulate_info);
};

class Stone {
  public:
    RawStone raw = {};
};

Field max_score_field;
Stone reserved_stones[256];
int number_of_stone = 0;

void Parse(Field* f) {
  for (int i = 0; i < 32; ++i) {
    fread(f->raw[i].data(), sizeof(char[32]), 1, stdin);
    getchar(); //CR
    getchar(); //LF
  }
  scanf("\n%d\n", &number_of_stone);
  for (int i = 0; i < number_of_stone; ++i) {
    for (int j = 0; j < 8; ++j) {
      fread(reserved_stones[i].raw[j].data(), sizeof(char[8]), 1, stdin);
      getchar(); //CR
      getchar(); //LF
    }
    getchar(); //CR
    getchar(); //LF
  }

}
void DumpField(const Field& f) {
  for (int i = 0; i < 32; ++i) {
    for (int j = 0; j < 32; ++j) {
      putc(f.raw[i][j], stdout);
    }
    puts("");
  }
}

void Solve(Field f, const int look_nth_stone) {
  if (look_nth_stone > number_of_stone) {
    if (f.Score() > max_score_field.Score()) {
      max_score_field = f;
    }
      return;
  }

  Solve(f, look_nth_stone + 1);
  Field backup = f;

  for (int x = -7; x < 32; ++x) {
    for (int y = -7; y < 32; ++y) {
      if (f.TryPutStone(look_nth_stone, x, y, 0)) {
        Solve(f, look_nth_stone+1);
        f = backup;
      }
    }
  }
}

void DumpStones() {
  for (int i = 0; i < number_of_stone; ++i) {
    for (int j = 0; j < 8; ++j) {
      for (int k = 0; k < 8; ++k) {
        putc(reserved_stones[i].raw[j][k], stdout);
      }
      puts("");
    }
    puts("");
  }
}
int main() {
  Field reserved_field;
  // get_problemfile();
  Parse(&reserved_field);
  Solve(reserved_field, 0);
  DumpField(max_score_field);
  // solve();
  // submit_answer();
  return 0;
}

bool Field::TryPutStone(int stone_number, int base_x, int base_y, int manipulate_info) {
  RawField backup_field = raw;
  int backup_score = score;
  RawStone& sraw = reserved_stones[stone_number].raw;
  for (int x = 0; x < 8; ++x) {
    for (int y = 0; y < 8; ++y) {
      if (y + base_y < 0 || y + base_y >= 32 || x + base_x < 0 || x + base_x >= 32) {
        continue;
      }
      if (sraw[y][x] == '1') {
        if(raw[y + base_y][x + base_x] == '1') {
          raw = backup_field;
          score = backup_score;
          return false;
        }
        raw[y + base_y][x + base_x] = '1';
        ++score;
      }
    }
  }
  return true;
}
<commit_msg>Add function: StoneRotate<commit_after>#include<iostream>
#include <cstdlib>
#include <cstdio>
#include <array>

#include <boost/test/unit_test.hpp>

using RawField = std::array<std::array<char, 32>, 32>;
using RawStone = std::array<std::array<char, 8>, 8>;

constexpr int ROTATE_90 = 1,
          ROTATE_180 = 2,
          ROTATE_270 = 4,
          REVERSED = 8;

class Field {
  private:
    int score = 0;
  public:
    RawField raw = {};
    int Score() const {
      return score;
    }
    bool TryPutStone(int stone_number, int base_x, int base_y, int manipulate_info);
};

class Stone {
  public:
    RawStone raw = {};
};

Field max_score_field;
Stone reserved_stones[256];
int number_of_stone = 0;

void Parse(Field* f) {
  for (int i = 0; i < 32; ++i) {
    fread(f->raw[i].data(), sizeof(char[32]), 1, stdin);
    getchar(); //CR
    getchar(); //LF
  }
  scanf("\n%d\n", &number_of_stone);
  for (int i = 0; i < number_of_stone; ++i) {
    for (int j = 0; j < 8; ++j) {
      fread(reserved_stones[i].raw[j].data(), sizeof(char[8]), 1, stdin);
      getchar(); //CR
      getchar(); //LF
    }
    getchar(); //CR
    getchar(); //LF
  }

}
void DumpField(const Field& f) {
  for (int i = 0; i < 32; ++i) {
    for (int j = 0; j < 32; ++j) {
      putc(f.raw[i][j], stdout);
    }
    puts("");
  }
}

void Solve(Field f, const int look_nth_stone) {
  if (look_nth_stone > number_of_stone) {
    if (f.Score() > max_score_field.Score()) {
      max_score_field = f;
    }
      return;
  }

  Solve(f, look_nth_stone + 1);
  Field backup = f;

  for (int x = -7; x < 32; ++x) {
    for (int y = -7; y < 32; ++y) {
      if (f.TryPutStone(look_nth_stone, x, y, 0)) {
        Solve(f, look_nth_stone+1);
        f = backup;
      }
    }
  }
}

void DumpStones() {
  for (int i = 0; i < number_of_stone; ++i) {
    for (int j = 0; j < 8; ++j) {
      for (int k = 0; k < 8; ++k) {
        putc(reserved_stones[i].raw[j][k], stdout);
      }
      puts("");
    }
    puts("");
  }
}
int main() {
  Field reserved_field;
  // get_problemfile();
  Parse(&reserved_field);
  Solve(reserved_field, 0);
  DumpField(max_score_field);
  // solve();
  // submit_answer();
  return 0;
}

RawStone StoneRotate(RawStone& stone, int manipulate_info) {
  RawStone rotated;
  switch (manipulate_info) {
    case ROTATE_90:
      for (int y = 0; y < 8; ++y) {
        for (int x = 0; x < 8; ++x){
          rotated[y][x] = stone[x][7-y];
        }
      }
      return rotated;
    case ROTATE_180:
      return StoneRotate(std::move(StoneRotate(stone, ROTATE_90)), ROTATE_90);
    case ROTATE_270:
      return StoneRotate(std::move(StoneRotate(stone, ROTATE_180)), ROTATE_90);
    case REVERSED:
      for (int y = 0; y < 8; ++y) {
        for (int x = 0; x < 8; ++x) {
          rotated[y][x] = stone[y][7-x];
        }
      }
      return rotated;
    case REVERSED | ROTATE_90:
      return StoneRotate(std::move(StoneRotate(stone, ROTATE_90), REVERSED);
    case REVERSED | ROTATE_180:
      return StoneRotate(std::move(StoneRotate(stone, ROTATE_180), REVERSED);
    case REVERSED | ROTATE_270:
      return StoneRotate(std::move(StoneRotate(stone, ROTATE_270), REVERSED);
  }
  return stone;
}

bool Field::TryPutStone(int stone_number, int base_x, int base_y, int manipulate_info) {
  // 書き換えるので、もどせるようにしておく
  RawField backup_field = raw;
  int backup_score = score;
  RawStone& sraw = reserved_stones[stone_number].raw;
  for (int x = 0; x < 8; ++x) {
    for (int y = 0; y < 8; ++y) {
      if (y + base_y < 0 || y + base_y >= 32 || x + base_x < 0 || x + base_x >= 32) {
        continue;
      }
      if (sraw[y][x] == '1') {
        if(backup_score != 0 && raw[y + base_y][x + base_x] == '1') { //score = 1、つまり最初に置く石なら判定しない
          raw = backup_field;
          score = backup_score;
          return false;
        }
        raw[y + base_y][x + base_x] = '1';
        ++score;
      }
    }
  }
  return true;
}
<|endoftext|>


<commit_before>#include "TransformModel.hpp"
#include <envire_core/items/Transform.hpp>
#include <glog/logging.h>

namespace envire { namespace viz {

TransformModel::TransformModel() :
  QStandardItemModel()
{
  setColumnCount(2);
  QStringList headerLabels;
  headerLabels.append("");
  headerLabels.append("Value");
  setHorizontalHeaderLabels(headerLabels);

  QStandardItem *parentItem = invisibleRootItem();

  QList<QStandardItem*> transItemList;
  QStandardItem* transItem = new QStandardItem("Translation");
  QStandardItem* transItemValue = new QStandardItem("");
  transItem->setEditable(false);
  transItemValue->setEditable(false);
  transItemList.append(transItem);
  transItemList.append(transItemValue);
  parentItem->appendRow(transItemList);

  QList<QStandardItem*> rotItemList;
  QStandardItem* rotItem = new QStandardItem("Orientation");
  QStandardItem* rotItemValue = new QStandardItem("");
  rotItem->setEditable(false);
  rotItemValue->setEditable(false);
  rotItemList.append(rotItem);
  rotItemList.append(rotItemValue);
  parentItem->appendRow(rotItemList);

  QList<QStandardItem*> transX;
  QList<QStandardItem*> transY;
  QList<QStandardItem*> transZ;

  QStandardItem* transXText = new QStandardItem("X");
  transXText->setEditable(false);
  QStandardItem* transYText = new QStandardItem("Y");
  transYText->setEditable(false);
  QStandardItem* transZText = new QStandardItem("Z");
  transZText->setEditable(false);

  transX.append(transXText);
  transY.append(transYText);
  transZ.append(transZText);
  transX.append(&transXItem);
  transY.append(&transYItem);
  transZ.append(&transZItem);

  transItem->appendRow(transX);
  transItem->appendRow(transY);
  transItem->appendRow(transZ);

  QList<QStandardItem*> rotX;
  QList<QStandardItem*> rotY;
  QList<QStandardItem*> rotZ;
  QList<QStandardItem*> rotW;

  QStandardItem* rotXText = new QStandardItem("X");
  QStandardItem* rotYText = new QStandardItem("Y");
  QStandardItem* rotZText = new QStandardItem("Z");
  QStandardItem* rotWText = new QStandardItem("W");
  rotXText->setEditable(false);
  rotYText->setEditable(false);
  rotZText->setEditable(false);
  rotWText->setEditable(false);

  rotX.append(rotXText);
  rotY.append(rotYText);
  rotZ.append(rotZText);
  rotW.append(rotWText);

  rotX.append(&rotXItem);
  rotY.append(&rotYItem);
  rotZ.append(&rotZItem);
  rotW.append(&rotWItem);

  rotItem->appendRow(rotX);
  rotItem->appendRow(rotY);
  rotItem->appendRow(rotZ);
  rotItem->appendRow(rotW);

  QList<QStandardItem*> timestampList;
  QStandardItem* timestampText = new QStandardItem("Timestamp");
  timestampText->setEditable(false);
  timestampList.append(timestampText);
  timestampList.append(&timestampItem);
  parentItem->appendRow(timestampList);

  connect(this, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(itemChangedSlot(QStandardItem*)));
  setTransform(tf);//works because tf is default constructed to Identity
}

void TransformModel::setTransform(const envire::core::Transform& newValue)
{
  tf = newValue;
  transXItem.setData(QVariant::fromValue<double>(tf.transform.translation.x()) ,Qt::DisplayRole);
  transYItem.setData(QVariant::fromValue<double>(tf.transform.translation.y()) ,Qt::DisplayRole);
  transZItem.setData(QVariant::fromValue<double>(tf.transform.translation.z()) ,Qt::DisplayRole);

  rotXItem.setData(QVariant::fromValue<double>(tf.transform.orientation.x()) ,Qt::DisplayRole);
  rotYItem.setData(QVariant::fromValue<double>(tf.transform.orientation.y()) ,Qt::DisplayRole);
  rotZItem.setData(QVariant::fromValue<double>(tf.transform.orientation.z()) ,Qt::DisplayRole);
  rotWItem.setData(QVariant::fromValue<double>(tf.transform.orientation.w()) ,Qt::DisplayRole);

  timestampItem.setData(QVariant(QString::fromStdString(tf.time.toString())), Qt::DisplayRole);
}

void  TransformModel::itemChangedSlot(QStandardItem * item)
{
  const double data = item->data(Qt::DisplayRole).toDouble();
  if(item == &transXItem)
  {
    tf.transform.translation.x() = data;
  }
  else if(item == &transYItem)
  {
    tf.transform.translation.y() = data;
  }
  else if(item == &transZItem)
  {
    tf.transform.translation.z() = data;
  }
  else if(item == &rotXItem)
  {
    tf.transform.orientation.x() = data;
  }
  else if(item == &rotYItem)
  {
    tf.transform.orientation.y() = data;
  }
  else if(item == &rotZItem)
  {
    tf.transform.orientation.z() = data;
  }
  else if(item == &rotWItem)
  {
    tf.transform.orientation.w() = data;
  }
  else if(item == &timestampItem)
  {
    const std::string timeStr = item->data(Qt::DisplayRole).toString().toStdString();
    try
    {
      std::cout << "TIME: " << timeStr << std::endl;
      tf.time = base::Time::fromString(timeStr);
    }
    catch(const std::runtime_error& ex)
    {
      LOG(ERROR) << "Cannot parse timestamp: " << ex.what();
      timestampItem.setData(QVariant(QString::fromStdString(tf.time.toString())), Qt::DisplayRole);
    }
  }
  emit transformChanged(tf);
}

void TransformModel::setEditable(const bool value)
{
  transXItem.setEditable(value);
  transYItem.setEditable(value);
  transZItem.setEditable(value);

  rotXItem.setEditable(value);
  rotYItem.setEditable(value);
  rotZItem.setEditable(value);
  rotWItem.setEditable(value);

  timestampItem.setEditable(value);
}

const envire::core::Transform& TransformModel::getTransform() const
{
  return tf;
}

}}<commit_msg>viz: TransformModel initiailize with identity instead of nan<commit_after>#include "TransformModel.hpp"
#include <envire_core/items/Transform.hpp>
#include <glog/logging.h>

namespace envire { namespace viz {

TransformModel::TransformModel() :
  QStandardItemModel()
{
  tf.setIdentity();
  setColumnCount(2);
  QStringList headerLabels;
  headerLabels.append("");
  headerLabels.append("Value");
  setHorizontalHeaderLabels(headerLabels);

  QStandardItem *parentItem = invisibleRootItem();

  QList<QStandardItem*> transItemList;
  QStandardItem* transItem = new QStandardItem("Translation");
  QStandardItem* transItemValue = new QStandardItem("");
  transItem->setEditable(false);
  transItemValue->setEditable(false);
  transItemList.append(transItem);
  transItemList.append(transItemValue);
  parentItem->appendRow(transItemList);

  QList<QStandardItem*> rotItemList;
  QStandardItem* rotItem = new QStandardItem("Orientation");
  QStandardItem* rotItemValue = new QStandardItem("");
  rotItem->setEditable(false);
  rotItemValue->setEditable(false);
  rotItemList.append(rotItem);
  rotItemList.append(rotItemValue);
  parentItem->appendRow(rotItemList);

  QList<QStandardItem*> transX;
  QList<QStandardItem*> transY;
  QList<QStandardItem*> transZ;

  QStandardItem* transXText = new QStandardItem("X");
  transXText->setEditable(false);
  QStandardItem* transYText = new QStandardItem("Y");
  transYText->setEditable(false);
  QStandardItem* transZText = new QStandardItem("Z");
  transZText->setEditable(false);

  transX.append(transXText);
  transY.append(transYText);
  transZ.append(transZText);
  transX.append(&transXItem);
  transY.append(&transYItem);
  transZ.append(&transZItem);

  transItem->appendRow(transX);
  transItem->appendRow(transY);
  transItem->appendRow(transZ);

  QList<QStandardItem*> rotX;
  QList<QStandardItem*> rotY;
  QList<QStandardItem*> rotZ;
  QList<QStandardItem*> rotW;

  QStandardItem* rotXText = new QStandardItem("X");
  QStandardItem* rotYText = new QStandardItem("Y");
  QStandardItem* rotZText = new QStandardItem("Z");
  QStandardItem* rotWText = new QStandardItem("W");
  rotXText->setEditable(false);
  rotYText->setEditable(false);
  rotZText->setEditable(false);
  rotWText->setEditable(false);

  rotX.append(rotXText);
  rotY.append(rotYText);
  rotZ.append(rotZText);
  rotW.append(rotWText);

  rotX.append(&rotXItem);
  rotY.append(&rotYItem);
  rotZ.append(&rotZItem);
  rotW.append(&rotWItem);

  rotItem->appendRow(rotX);
  rotItem->appendRow(rotY);
  rotItem->appendRow(rotZ);
  rotItem->appendRow(rotW);

  QList<QStandardItem*> timestampList;
  QStandardItem* timestampText = new QStandardItem("Timestamp");
  timestampText->setEditable(false);
  timestampList.append(timestampText);
  timestampList.append(&timestampItem);
  parentItem->appendRow(timestampList);

  connect(this, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(itemChangedSlot(QStandardItem*)));
  setTransform(tf);//works because tf is default constructed to Identity
}

void TransformModel::setTransform(const envire::core::Transform& newValue)
{
  tf = newValue;
  transXItem.setData(QVariant::fromValue<double>(tf.transform.translation.x()) ,Qt::DisplayRole);
  transYItem.setData(QVariant::fromValue<double>(tf.transform.translation.y()) ,Qt::DisplayRole);
  transZItem.setData(QVariant::fromValue<double>(tf.transform.translation.z()) ,Qt::DisplayRole);

  rotXItem.setData(QVariant::fromValue<double>(tf.transform.orientation.x()) ,Qt::DisplayRole);
  rotYItem.setData(QVariant::fromValue<double>(tf.transform.orientation.y()) ,Qt::DisplayRole);
  rotZItem.setData(QVariant::fromValue<double>(tf.transform.orientation.z()) ,Qt::DisplayRole);
  rotWItem.setData(QVariant::fromValue<double>(tf.transform.orientation.w()) ,Qt::DisplayRole);

  timestampItem.setData(QVariant(QString::fromStdString(tf.time.toString())), Qt::DisplayRole);
}

void  TransformModel::itemChangedSlot(QStandardItem * item)
{
  const double data = item->data(Qt::DisplayRole).toDouble();
  if(item == &transXItem)
  {
    tf.transform.translation.x() = data;
  }
  else if(item == &transYItem)
  {
    tf.transform.translation.y() = data;
  }
  else if(item == &transZItem)
  {
    tf.transform.translation.z() = data;
  }
  else if(item == &rotXItem)
  {
    tf.transform.orientation.x() = data;
  }
  else if(item == &rotYItem)
  {
    tf.transform.orientation.y() = data;
  }
  else if(item == &rotZItem)
  {
    tf.transform.orientation.z() = data;
  }
  else if(item == &rotWItem)
  {
    tf.transform.orientation.w() = data;
  }
  else if(item == &timestampItem)
  {
    const std::string timeStr = item->data(Qt::DisplayRole).toString().toStdString();
    try
    {
      std::cout << "TIME: " << timeStr << std::endl;
      tf.time = base::Time::fromString(timeStr);
    }
    catch(const std::runtime_error& ex)
    {
      LOG(ERROR) << "Cannot parse timestamp: " << ex.what();
      timestampItem.setData(QVariant(QString::fromStdString(tf.time.toString())), Qt::DisplayRole);
    }
  }
  emit transformChanged(tf);
}

void TransformModel::setEditable(const bool value)
{
  transXItem.setEditable(value);
  transYItem.setEditable(value);
  transZItem.setEditable(value);

  rotXItem.setEditable(value);
  rotYItem.setEditable(value);
  rotZItem.setEditable(value);
  rotWItem.setEditable(value);

  timestampItem.setEditable(value);
}

const envire::core::Transform& TransformModel::getTransform() const
{
  return tf;
}

}}<|endoftext|>


<commit_before>/*
 * This file is part of SpeakEasy.
 * Copyright (C) 2011-2014  Lambert Clara <lambert.clara@yahoo.fr>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * @file    SE_CGUIManager.cpp
 * @brief   2D GUI Manager
 *
 * @author  Lambert Clara <lambert.clara@yahoo.fr>
 * @date    Created : 2011-08-23
 */

#include "SE_CGUIManager.h"

#include <cassert>

#include "config.h"
#include "SE_CGUIGLFW.h"

#include "SE_CLogManager.h"

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
SE_CGUIManager::~SE_CGUIManager()
{
    // ensure that shutDown was called before destroying the manager
    assert(!m_pGUISystem);
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
bool SE_CGUIManager::startUp()
{
    m_pGUISystem = new SE_CGUIGLFW();

    if(m_pGUISystem->init())
    {
        seLogInfo("GUI System successfully initialized");
        if(m_pGUISystem->openWindow())
        {
            seLogInfo("GUI System window successfully opened");
            m_initSuccess = true;
        }
    }

    if(m_initSuccess)
    {
        seLogInfo("SE_CGUIManager successfully started");
    }
    return m_initSuccess;
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
bool SE_CGUIManager::shutDown()
{
    bool shutDownSuccessfull = false;
    if(m_pGUISystem)
    {
        shutDownSuccessfull = m_initSuccess ? m_pGUISystem->close() : true;
        delete m_pGUISystem;
        m_pGUISystem = nullptr;
    }

    if(shutDownSuccessfull)
    {
        seLogInfo("SE_CGUIManager successfully shut downed");
    }
    return shutDownSuccessfull;
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
bool SE_CGUIManager::doWork()
{
    bool shouldContinue = false;
    if(m_pGUISystem)
    {
        m_pGUISystem->swapBuffers();
        shouldContinue = !m_pGUISystem->windowClosed() && !m_pGUISystem->quitPressed();
    }
    else
    {
        shouldContinue = false;
    }
    return shouldContinue;
}
<commit_msg>Use custom assert instead of std's<commit_after>/*
 * This file is part of SpeakEasy.
 * Copyright (C) 2011-2014  Lambert Clara <lambert.clara@yahoo.fr>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * @file    SE_CGUIManager.cpp
 * @brief   2D GUI Manager
 *
 * @author  Lambert Clara <lambert.clara@yahoo.fr>
 * @date    Created : 2011-08-23
 */

#include "SE_CGUIManager.h"

#include "config.h"
#include "SE_CGUIGLFW.h"

#include "SE_CLogManager.h"

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
SE_CGUIManager::~SE_CGUIManager()
{
    // ensure that shutDown was called before destroying the manager
    seAssert(!m_pGUISystem, "The GUI System is still allocated!");
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
bool SE_CGUIManager::startUp()
{
    m_pGUISystem = new SE_CGUIGLFW();

    if(m_pGUISystem->init())
    {
        seLogInfo("GUI System successfully initialized");
        if(m_pGUISystem->openWindow())
        {
            seLogInfo("GUI System window successfully opened");
            m_initSuccess = true;
        }
    }

    if(m_initSuccess)
    {
        seLogInfo("SE_CGUIManager successfully started");
    }
    return m_initSuccess;
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
bool SE_CGUIManager::shutDown()
{
    bool shutDownSuccessfull = false;
    if(m_pGUISystem)
    {
        shutDownSuccessfull = m_initSuccess ? m_pGUISystem->close() : true;
        delete m_pGUISystem;
        m_pGUISystem = nullptr;
    }

    if(shutDownSuccessfull)
    {
        seLogInfo("SE_CGUIManager successfully shut downed");
    }
    return shutDownSuccessfull;
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
bool SE_CGUIManager::doWork()
{
    bool shouldContinue = false;
    if(m_pGUISystem)
    {
        m_pGUISystem->swapBuffers();
        shouldContinue = !m_pGUISystem->windowClosed() && !m_pGUISystem->quitPressed();
    }
    else
    {
        shouldContinue = false;
    }
    return shouldContinue;
}
<|endoftext|>


<commit_before>// -*- c++ -*-
/********************************************************************
 * AUTHORS: Vijay Ganesh, Trevor Hansen
 *
 * BEGIN DATE: November, 2005
 *
 * LICENSE: Please view LICENSE file in the home dir of this Program
 ********************************************************************/

#include "STP.h"
#include "DifficultyScore.h"
#include "../to-sat/AIG/ToSATAIG.h"
#include "../simplifier/constantBitP/ConstantBitPropagation.h"
#include "../simplifier/constantBitP/NodeToFixedBitsMap.h"
#include "../sat/SimplifyingMinisat.h"
#include "../sat/MinisatCore.h"
#include "../sat/CryptoMinisat.h"

namespace BEEV {

   // The absolute TopLevel function that invokes STP on the input
    // formula
  SOLVER_RETURN_TYPE STP::TopLevelSTP(const ASTNode& inputasserts,
				      const ASTNode& query)
  {
    ASTNode original_input = bm->CreateNode(AND,
					    inputasserts,
					    bm->CreateNode(NOT, query));

    //solver instantiated here
//#if defined CRYPTOMINISAT2
    //MINISAT::Solver NewSolver;

    //if(bm->UserFlags.print_cnf_flag)
      //{
	//NewSolver.needLibraryCNFFile(bm->UserFlags.cnf_dump_filename);
      //}
//#endif

    SATSolver *newS;
    if (bm->UserFlags.solver_to_use == UserDefinedFlags::SIMPLIFYING_MINISAT_SOLVER)
		newS = new SimplifyingMinisat();
    else if (bm->UserFlags.solver_to_use == UserDefinedFlags::CRYPTOMINISAT_SOLVER)
                    newS = new CryptoMinisat();
    else
      newS = new MinisatCore<Minisat::Solver>();

    SATSolver& NewSolver = *newS;

    if(bm->UserFlags.stats_flag)
      {
	NewSolver.setVerbosity(1);
      }

	SOLVER_RETURN_TYPE result;
    if(bm->UserFlags.num_absrefine_flag)
      {
     result =  UserGuided_AbsRefine(NewSolver,
				    original_input);
      }
    else
      {
	result = TopLevelSTPAux(NewSolver,
			      original_input, original_input);
      }

    delete newS;

    return result;

  } //End of TopLevelSTP()

  //Acceps a query, calls the SAT solver and generates Valid/InValid.
  //if returned 0 then input is INVALID if returned 1 then input is
  //VALID if returned 2 then UNDECIDED
  SOLVER_RETURN_TYPE STP::TopLevelSTPAux(SATSolver& NewSolver,
					 const ASTNode& modified_input,
					 const ASTNode& original_input)
  {
    ASTNode inputToSAT = modified_input;
    ASTNode orig_input = original_input;
    bm->ASTNodeStats("input asserts and query: ", inputToSAT);

    ASTNode simplified_solved_InputToSAT = inputToSAT;

    long initial_difficulty_score = DifficultyScore::score(original_input);

    //round of substitution, solving, and simplification. ensures that
    //DAG is minimized as much as possibly, and ideally should
    //garuntee that all liketerms in BVPLUSes have been combined.
    bm->SimplifyWrites_InPlace_Flag = false;
    bm->Begin_RemoveWrites = false;
    bm->start_abstracting = false;
    bm->TermsAlreadySeenMap_Clear();
    do
      {
        inputToSAT = simplified_solved_InputToSAT;

        if(bm->UserFlags.optimize_flag)
          {

        	int initialSize = simp->Return_SolverMap()->size();

            simplified_solved_InputToSAT =
            	simp->CreateSubstitutionMap(simplified_solved_InputToSAT, arrayTransformer);

            // Imagine:
			// The simplifier simplifies (0 + T) to T
			// Then bvsolve introduces (0 + T)
			// Then CreateSubstitutionMap decides T maps to a constant, but leaving another (0+T).
			// When we go to simplify (0 + T) will still be in the simplify cache, so will be mapped to T.
			// But it shouldn't be T, it should be a constant.
			// Applying the substitution map fixes this case.
            //
			if (initialSize != simp->Return_SolverMap()->size())
			{
				simplified_solved_InputToSAT = simp->applySubstitutionMap(simplified_solved_InputToSAT);
				simp->haveAppliedSubstitutionMap();
			}

            bm->ASTNodeStats("after pure substitution: ",
                             simplified_solved_InputToSAT);

            simplified_solved_InputToSAT =
              simp->SimplifyFormula_TopLevel(simplified_solved_InputToSAT,
                                             false);

            bm->ASTNodeStats("after simplification: ",
                             simplified_solved_InputToSAT);
          }

        if(bm->UserFlags.wordlevel_solve_flag && bm->UserFlags.optimize_flag)
          {
            simplified_solved_InputToSAT =
              bvsolver->TopLevelBVSolve(simplified_solved_InputToSAT);
            bm->ASTNodeStats("after solving: ", simplified_solved_InputToSAT);
          }

      }
    while (inputToSAT != simplified_solved_InputToSAT);

    if (bm->UserFlags.bitConstantProp_flag)
      {
        bm->ASTNodeStats("Before Constant Bit Propagation begins: ",
            simplified_solved_InputToSAT);

        bm->GetRunTimes()->start(RunTimes::ConstantBitPropagation);
        simplifier::constantBitP::ConstantBitPropagation cb(simp, bm->defaultNodeFactory,simplified_solved_InputToSAT);
        simplified_solved_InputToSAT = cb.topLevelBothWays(simplified_solved_InputToSAT);

        bm->GetRunTimes()->stop(RunTimes::ConstantBitPropagation);

        if (cb.isUnsatisfiable())
          simplified_solved_InputToSAT = bm->ASTFalse;

      }

    bm->ASTNodeStats("Before SimplifyWrites_Inplace begins: ",
                     simplified_solved_InputToSAT);

    bm->SimplifyWrites_InPlace_Flag = true;
    bm->Begin_RemoveWrites = false;
    bm->start_abstracting = false;
    bm->TermsAlreadySeenMap_Clear();
    do
      {
        inputToSAT = simplified_solved_InputToSAT;

        if(bm->UserFlags.optimize_flag)
          {
            simplified_solved_InputToSAT =
            	simp->CreateSubstitutionMap(simplified_solved_InputToSAT, arrayTransformer);

            bm->ASTNodeStats("after pure substitution: ",
                             simplified_solved_InputToSAT);

            simplified_solved_InputToSAT =
              simp->SimplifyFormula_TopLevel(simplified_solved_InputToSAT,
                                             false);
            bm->ASTNodeStats("after simplification: ",
                             simplified_solved_InputToSAT);
          }

        // The word level solver uses the simplifier to apply the rewrites it makes,
        // without optimisations enabled. It will enter infinite loops on some input.
        // Instead it could use the apply function of the substitution map, but it
        // doesn't yet...
        if(bm->UserFlags.wordlevel_solve_flag && bm->UserFlags.optimize_flag)
          {
            simplified_solved_InputToSAT =
              bvsolver->TopLevelBVSolve(simplified_solved_InputToSAT);
            bm->ASTNodeStats("after solving: ", simplified_solved_InputToSAT);
          }
      } while (inputToSAT != simplified_solved_InputToSAT);

    bm->ASTNodeStats("After SimplifyWrites_Inplace: ",
                     simplified_solved_InputToSAT);

    bm->TermsAlreadySeenMap_Clear();

    bm->start_abstracting = false;
    bm->SimplifyWrites_InPlace_Flag = false;
    bm->Begin_RemoveWrites = false;

    long final_difficulty_score = DifficultyScore::score(simplified_solved_InputToSAT);
    if (bm->UserFlags.stats_flag)
    {
    	cerr << "Initial Difficulty Score:" << initial_difficulty_score <<endl;
    	cerr << "Final Difficulty Score:" << final_difficulty_score <<endl;
    }

    const bool arrayops = containsArrayOps(original_input);
    bool optimize_enabled = bm->UserFlags.optimize_flag;
    if (final_difficulty_score > 2 *initial_difficulty_score  && !arrayops)
    {
    	// If the simplified problem is harder, than the
    	// initial problem we revert back to the initial
    	// problem.

    	if (bm->UserFlags.stats_flag)
    		cerr << "simplification made the problem harder, reverting."<<endl;
    	simplified_solved_InputToSAT = original_input;

    	// I do this to clear the substitution/solver map.
    	// Not sure what would happen if it contained simplifications
    	// that haven't been applied.
    	simp->ClearAllTables();

    	// The arrayTransformer calls simplify. We don't want
    	// it to put back in all the bad simplifications.
    	bm->UserFlags.optimize_flag = false;
    }

    simplified_solved_InputToSAT =
      arrayTransformer->TransformFormula_TopLevel(simplified_solved_InputToSAT);
    bm->ASTNodeStats("after transformation: ", simplified_solved_InputToSAT);
    bm->TermsAlreadySeenMap_Clear();

	bm->UserFlags.optimize_flag = optimize_enabled;

    SOLVER_RETURN_TYPE res;
    if (bm->UserFlags.arrayread_refinement_flag)
      {
        bm->counterexample_checking_during_refinement = true;
      }

    // We are about to solve. Clear out all the memory associated with caches
    // that we won't need again.
    simp->ClearCaches();
    simp->haveAppliedSubstitutionMap();
    bm->ClearAllTables();

    // Deleting it clears out all the buckets associated with hashmaps etc. too.
    delete bvsolver;
    bvsolver = new BVSolver(bm,simp);

    if(bm->UserFlags.stats_flag)
    	simp->printCacheStatus();

    // If it doesn't contain array operations, use ABC's CNF generation.
    if (!arrayops || !bm->UserFlags.arrayread_refinement_flag)
    {
      simplifier::constantBitP::ConstantBitPropagation* cb = NULL;

    if (bm->UserFlags.bitConstantProp_flag)
      {
        bm->ASTNodeStats("Before Constant Bit Propagation begins: ",
            simplified_solved_InputToSAT);

        bm->GetRunTimes()->start(RunTimes::ConstantBitPropagation);

        cb = new simplifier::constantBitP::ConstantBitPropagation(simp, bm->defaultNodeFactory,simplified_solved_InputToSAT);

        bm->GetRunTimes()->stop(RunTimes::ConstantBitPropagation);

        if (cb->isUnsatisfiable())
           simplified_solved_InputToSAT = bm->ASTFalse;
      }

    ToSATAIG toSATAIG(bm,cb);

    res =
      Ctr_Example->CallSAT_ResultCheck(NewSolver,
                                       simplified_solved_InputToSAT,
                                       orig_input,
                                       &toSATAIG
                                       );

    }
    else
      {
      res =
        Ctr_Example->CallSAT_ResultCheck(NewSolver,
                                         simplified_solved_InputToSAT,
                                         orig_input,
                                         tosat
                                         );

      }

    if (SOLVER_UNDECIDED != res)
      {
        CountersAndStats("print_func_stats", bm);
        return res;
      }

    assert(arrayops); // should only go to abstraction refinement if there are array ops.
    assert(bm->UserFlags.arrayread_refinement_flag); // Refinement must be enabled too.

    res =
      Ctr_Example->SATBased_ArrayReadRefinement(NewSolver,
                                                simplified_solved_InputToSAT,
                                                orig_input,
                                                tosat);
    if (SOLVER_UNDECIDED != res)
      {
        CountersAndStats("print_func_stats", bm);
        return res;
      }

    res =
      Ctr_Example->SATBased_ArrayWriteRefinement(NewSolver, orig_input,tosat);
    if (SOLVER_UNDECIDED != res)
      {
        CountersAndStats("print_func_stats", bm);
        return res;
      }

    res =
      Ctr_Example->SATBased_ArrayReadRefinement(NewSolver,
                                                simplified_solved_InputToSAT,
                                                orig_input,tosat);
    if (SOLVER_UNDECIDED != res)
      {
        CountersAndStats("print_func_stats", bm);
        return res;
      }

    if(!bm->UserFlags.num_absrefine_flag)
      {
    	FatalError("TopLevelSTPAux: reached the end without proper conclusion:"
		   "either a divide by zero in the input or a bug in STP");
	//bogus return to make the compiler shut up
	return SOLVER_ERROR;
      }
    else
      {
	return res;
      }
  } //End of TopLevelSTPAux

  //UserGuided abstraction refinement
  SOLVER_RETURN_TYPE
  STP::
  UserGuided_AbsRefine(SATSolver& NewSolver,
		       const ASTNode& original_input)
  {
    ASTVec v = bm->GetAsserts_WithKey(0);
    if(v.empty())
      {
	FatalError("UserGuided_AbsRefine: Something is seriously wrong."\
		   "The input set is empty");
      }
    ASTNode sureAddInput =
      (v.size() == 1) ? v[0] : bm->CreateNode(AND, v);

    SOLVER_RETURN_TYPE res = SOLVER_UNDECIDED;
    res = TopLevelSTPAux(NewSolver, sureAddInput, original_input);
    if(SOLVER_UNDECIDED != res)
      {
	return res;
      }

    //Do refinement here
    if(AND != original_input.GetKind())
      {
	FatalError("UserGuided_AbsRefine: The input must be an AND");
      }

    ASTVec RefineFormulasVec;
    ASTVec RemainingFormulasVec;
    ASTNode asttrue = bm->CreateNode(TRUE);
    ASTNode astfalse = bm->CreateNode(FALSE);
    for(int count=0; count < bm->UserFlags.num_absrefine; count++)
      {
	RemainingFormulasVec.clear();
	RemainingFormulasVec.push_back(asttrue);
	RefineFormulasVec.clear();
	RefineFormulasVec.push_back(asttrue);
	ASTVec InputKids = original_input.GetChildren();
	for(ASTVec::iterator it = InputKids.begin(), itend = InputKids.end();
	    it!=itend;it++)
	  {
	    Ctr_Example->ClearComputeFormulaMap();
	    if(astfalse == Ctr_Example->ComputeFormulaUsingModel(*it))
	      {
		RefineFormulasVec.push_back(*it);
	      }
	    else
	      {
		RemainingFormulasVec.push_back(*it);
	      }
	  }
	ASTNode RefineFormulas =
	  (RefineFormulasVec.size() == 1) ?
	  RefineFormulasVec[0] : bm->CreateNode(AND, RefineFormulasVec);
	res = TopLevelSTPAux(NewSolver, RefineFormulas, original_input);
	if(SOLVER_UNDECIDED != res)
	  {
	    return res;
	  }
      }

    ASTNode RemainingFormulas =
      (RemainingFormulasVec.size() == 1) ?
      RemainingFormulasVec[0] : bm->CreateNode(AND, RemainingFormulasVec);
    res = TopLevelSTPAux(NewSolver, RemainingFormulas, original_input);

    if(SOLVER_UNDECIDED != res)
      {
	return res;
      }

    FatalError("TopLevelSTPAux: reached the end without proper conclusion:"
	       "either a divide by zero in the input or a bug in STP");
    return SOLVER_ERROR;
  } //End of UserGuided_AbsRefine()
}; //end of namespace
<commit_msg>Fix. Apply substitutions in another place to avoid an assertion error.<commit_after>// -*- c++ -*-
/********************************************************************
 * AUTHORS: Vijay Ganesh, Trevor Hansen
 *
 * BEGIN DATE: November, 2005
 *
 * LICENSE: Please view LICENSE file in the home dir of this Program
 ********************************************************************/

#include "STP.h"
#include "DifficultyScore.h"
#include "../to-sat/AIG/ToSATAIG.h"
#include "../simplifier/constantBitP/ConstantBitPropagation.h"
#include "../simplifier/constantBitP/NodeToFixedBitsMap.h"
#include "../sat/SimplifyingMinisat.h"
#include "../sat/MinisatCore.h"
#include "../sat/CryptoMinisat.h"

namespace BEEV {

   // The absolute TopLevel function that invokes STP on the input
    // formula
  SOLVER_RETURN_TYPE STP::TopLevelSTP(const ASTNode& inputasserts,
				      const ASTNode& query)
  {
    ASTNode original_input = bm->CreateNode(AND,
					    inputasserts,
					    bm->CreateNode(NOT, query));

    //solver instantiated here
//#if defined CRYPTOMINISAT2
    //MINISAT::Solver NewSolver;

    //if(bm->UserFlags.print_cnf_flag)
      //{
	//NewSolver.needLibraryCNFFile(bm->UserFlags.cnf_dump_filename);
      //}
//#endif

    SATSolver *newS;
    if (bm->UserFlags.solver_to_use == UserDefinedFlags::SIMPLIFYING_MINISAT_SOLVER)
		newS = new SimplifyingMinisat();
    else if (bm->UserFlags.solver_to_use == UserDefinedFlags::CRYPTOMINISAT_SOLVER)
                    newS = new CryptoMinisat();
    else
      newS = new MinisatCore<Minisat::Solver>();

    SATSolver& NewSolver = *newS;

    if(bm->UserFlags.stats_flag)
      {
	NewSolver.setVerbosity(1);
      }

	SOLVER_RETURN_TYPE result;
    if(bm->UserFlags.num_absrefine_flag)
      {
     result =  UserGuided_AbsRefine(NewSolver,
				    original_input);
      }
    else
      {
	result = TopLevelSTPAux(NewSolver,
			      original_input, original_input);
      }

    delete newS;

    return result;

  } //End of TopLevelSTP()

  //Acceps a query, calls the SAT solver and generates Valid/InValid.
  //if returned 0 then input is INVALID if returned 1 then input is
  //VALID if returned 2 then UNDECIDED
  SOLVER_RETURN_TYPE STP::TopLevelSTPAux(SATSolver& NewSolver,
					 const ASTNode& modified_input,
					 const ASTNode& original_input)
  {
    ASTNode inputToSAT = modified_input;
    ASTNode orig_input = original_input;
    bm->ASTNodeStats("input asserts and query: ", inputToSAT);

    ASTNode simplified_solved_InputToSAT = inputToSAT;

    long initial_difficulty_score = DifficultyScore::score(original_input);

    //round of substitution, solving, and simplification. ensures that
    //DAG is minimized as much as possibly, and ideally should
    //garuntee that all liketerms in BVPLUSes have been combined.
    bm->SimplifyWrites_InPlace_Flag = false;
    bm->Begin_RemoveWrites = false;
    bm->start_abstracting = false;
    bm->TermsAlreadySeenMap_Clear();
    do
      {
        inputToSAT = simplified_solved_InputToSAT;

        if(bm->UserFlags.optimize_flag)
          {

        	int initialSize = simp->Return_SolverMap()->size();

            simplified_solved_InputToSAT =
            	simp->CreateSubstitutionMap(simplified_solved_InputToSAT, arrayTransformer);

            // Imagine:
			// The simplifier simplifies (0 + T) to T
			// Then bvsolve introduces (0 + T)
			// Then CreateSubstitutionMap decides T maps to a constant, but leaving another (0+T).
			// When we go to simplify (0 + T) will still be in the simplify cache, so will be mapped to T.
			// But it shouldn't be T, it should be a constant.
			// Applying the substitution map fixes this case.
            //
			if (initialSize != simp->Return_SolverMap()->size())
			{
				simplified_solved_InputToSAT = simp->applySubstitutionMap(simplified_solved_InputToSAT);
				simp->haveAppliedSubstitutionMap();
			}

            bm->ASTNodeStats("after pure substitution: ",
                             simplified_solved_InputToSAT);

            simplified_solved_InputToSAT =
              simp->SimplifyFormula_TopLevel(simplified_solved_InputToSAT,
                                             false);

            bm->ASTNodeStats("after simplification: ",
                             simplified_solved_InputToSAT);
          }

        if(bm->UserFlags.wordlevel_solve_flag && bm->UserFlags.optimize_flag)
          {
            simplified_solved_InputToSAT =
              bvsolver->TopLevelBVSolve(simplified_solved_InputToSAT);
            bm->ASTNodeStats("after solving: ", simplified_solved_InputToSAT);
          }

      }
    while (inputToSAT != simplified_solved_InputToSAT);

    if (bm->UserFlags.bitConstantProp_flag)
      {
        bm->ASTNodeStats("Before Constant Bit Propagation begins: ",
            simplified_solved_InputToSAT);

        bm->GetRunTimes()->start(RunTimes::ConstantBitPropagation);
        simplifier::constantBitP::ConstantBitPropagation cb(simp, bm->defaultNodeFactory,simplified_solved_InputToSAT);
        simplified_solved_InputToSAT = cb.topLevelBothWays(simplified_solved_InputToSAT);

        bm->GetRunTimes()->stop(RunTimes::ConstantBitPropagation);

        if (cb.isUnsatisfiable())
          simplified_solved_InputToSAT = bm->ASTFalse;

      }

    bm->ASTNodeStats("Before SimplifyWrites_Inplace begins: ",
                     simplified_solved_InputToSAT);

    bm->SimplifyWrites_InPlace_Flag = true;
    bm->Begin_RemoveWrites = false;
    bm->start_abstracting = false;
    bm->TermsAlreadySeenMap_Clear();
    do
      {
        inputToSAT = simplified_solved_InputToSAT;

        if(bm->UserFlags.optimize_flag)
          {
        	int initialSize = simp->Return_SolverMap()->size();

        	simplified_solved_InputToSAT =
            	simp->CreateSubstitutionMap(simplified_solved_InputToSAT, arrayTransformer);

			if (initialSize != simp->Return_SolverMap()->size())
			{
				simplified_solved_InputToSAT = simp->applySubstitutionMap(simplified_solved_InputToSAT);
				simp->haveAppliedSubstitutionMap();
			}

            bm->ASTNodeStats("after pure substitution: ",
                             simplified_solved_InputToSAT);

            simplified_solved_InputToSAT =
              simp->SimplifyFormula_TopLevel(simplified_solved_InputToSAT,
                                             false);
            bm->ASTNodeStats("after simplification: ",
                             simplified_solved_InputToSAT);
          }

        // The word level solver uses the simplifier to apply the rewrites it makes,
        // without optimisations enabled. It will enter infinite loops on some input.
        // Instead it could use the apply function of the substitution map, but it
        // doesn't yet...
        if(bm->UserFlags.wordlevel_solve_flag && bm->UserFlags.optimize_flag)
          {
            simplified_solved_InputToSAT =
              bvsolver->TopLevelBVSolve(simplified_solved_InputToSAT);
            bm->ASTNodeStats("after solving: ", simplified_solved_InputToSAT);
          }
      } while (inputToSAT != simplified_solved_InputToSAT);

    bm->ASTNodeStats("After SimplifyWrites_Inplace: ",
                     simplified_solved_InputToSAT);

    bm->TermsAlreadySeenMap_Clear();

    bm->start_abstracting = false;
    bm->SimplifyWrites_InPlace_Flag = false;
    bm->Begin_RemoveWrites = false;

    long final_difficulty_score = DifficultyScore::score(simplified_solved_InputToSAT);
    if (bm->UserFlags.stats_flag)
    {
    	cerr << "Initial Difficulty Score:" << initial_difficulty_score <<endl;
    	cerr << "Final Difficulty Score:" << final_difficulty_score <<endl;
    }

    const bool arrayops = containsArrayOps(original_input);
    bool optimize_enabled = bm->UserFlags.optimize_flag;
    if (final_difficulty_score > 2 *initial_difficulty_score  && !arrayops)
    {
    	// If the simplified problem is harder, than the
    	// initial problem we revert back to the initial
    	// problem.

    	if (bm->UserFlags.stats_flag)
    		cerr << "simplification made the problem harder, reverting."<<endl;
    	simplified_solved_InputToSAT = original_input;

    	// I do this to clear the substitution/solver map.
    	// Not sure what would happen if it contained simplifications
    	// that haven't been applied.
    	simp->ClearAllTables();

    	// The arrayTransformer calls simplify. We don't want
    	// it to put back in all the bad simplifications.
    	bm->UserFlags.optimize_flag = false;
    }

    simplified_solved_InputToSAT =
      arrayTransformer->TransformFormula_TopLevel(simplified_solved_InputToSAT);
    bm->ASTNodeStats("after transformation: ", simplified_solved_InputToSAT);
    bm->TermsAlreadySeenMap_Clear();

	bm->UserFlags.optimize_flag = optimize_enabled;

    SOLVER_RETURN_TYPE res;
    if (bm->UserFlags.arrayread_refinement_flag)
      {
        bm->counterexample_checking_during_refinement = true;
      }

    // We are about to solve. Clear out all the memory associated with caches
    // that we won't need again.
    simp->ClearCaches();
    simp->haveAppliedSubstitutionMap();
    bm->ClearAllTables();

    // Deleting it clears out all the buckets associated with hashmaps etc. too.
    delete bvsolver;
    bvsolver = new BVSolver(bm,simp);

    if(bm->UserFlags.stats_flag)
    	simp->printCacheStatus();

    // If it doesn't contain array operations, use ABC's CNF generation.
    if (!arrayops || !bm->UserFlags.arrayread_refinement_flag)
    {
      simplifier::constantBitP::ConstantBitPropagation* cb = NULL;

    if (bm->UserFlags.bitConstantProp_flag)
      {
        bm->ASTNodeStats("Before Constant Bit Propagation begins: ",
            simplified_solved_InputToSAT);

        bm->GetRunTimes()->start(RunTimes::ConstantBitPropagation);

        cb = new simplifier::constantBitP::ConstantBitPropagation(simp, bm->defaultNodeFactory,simplified_solved_InputToSAT);

        bm->GetRunTimes()->stop(RunTimes::ConstantBitPropagation);

        if (cb->isUnsatisfiable())
           simplified_solved_InputToSAT = bm->ASTFalse;
      }

    ToSATAIG toSATAIG(bm,cb);

    res =
      Ctr_Example->CallSAT_ResultCheck(NewSolver,
                                       simplified_solved_InputToSAT,
                                       orig_input,
                                       &toSATAIG
                                       );

    }
    else
      {
      res =
        Ctr_Example->CallSAT_ResultCheck(NewSolver,
                                         simplified_solved_InputToSAT,
                                         orig_input,
                                         tosat
                                         );

      }

    if (SOLVER_UNDECIDED != res)
      {
        CountersAndStats("print_func_stats", bm);
        return res;
      }

    assert(arrayops); // should only go to abstraction refinement if there are array ops.
    assert(bm->UserFlags.arrayread_refinement_flag); // Refinement must be enabled too.

    res =
      Ctr_Example->SATBased_ArrayReadRefinement(NewSolver,
                                                simplified_solved_InputToSAT,
                                                orig_input,
                                                tosat);
    if (SOLVER_UNDECIDED != res)
      {
        CountersAndStats("print_func_stats", bm);
        return res;
      }

    res =
      Ctr_Example->SATBased_ArrayWriteRefinement(NewSolver, orig_input,tosat);
    if (SOLVER_UNDECIDED != res)
      {
        CountersAndStats("print_func_stats", bm);
        return res;
      }

    res =
      Ctr_Example->SATBased_ArrayReadRefinement(NewSolver,
                                                simplified_solved_InputToSAT,
                                                orig_input,tosat);
    if (SOLVER_UNDECIDED != res)
      {
        CountersAndStats("print_func_stats", bm);
        return res;
      }

    if(!bm->UserFlags.num_absrefine_flag)
      {
    	FatalError("TopLevelSTPAux: reached the end without proper conclusion:"
		   "either a divide by zero in the input or a bug in STP");
	//bogus return to make the compiler shut up
	return SOLVER_ERROR;
      }
    else
      {
	return res;
      }
  } //End of TopLevelSTPAux

  //UserGuided abstraction refinement
  SOLVER_RETURN_TYPE
  STP::
  UserGuided_AbsRefine(SATSolver& NewSolver,
		       const ASTNode& original_input)
  {
    ASTVec v = bm->GetAsserts_WithKey(0);
    if(v.empty())
      {
	FatalError("UserGuided_AbsRefine: Something is seriously wrong."\
		   "The input set is empty");
      }
    ASTNode sureAddInput =
      (v.size() == 1) ? v[0] : bm->CreateNode(AND, v);

    SOLVER_RETURN_TYPE res = SOLVER_UNDECIDED;
    res = TopLevelSTPAux(NewSolver, sureAddInput, original_input);
    if(SOLVER_UNDECIDED != res)
      {
	return res;
      }

    //Do refinement here
    if(AND != original_input.GetKind())
      {
	FatalError("UserGuided_AbsRefine: The input must be an AND");
      }

    ASTVec RefineFormulasVec;
    ASTVec RemainingFormulasVec;
    ASTNode asttrue = bm->CreateNode(TRUE);
    ASTNode astfalse = bm->CreateNode(FALSE);
    for(int count=0; count < bm->UserFlags.num_absrefine; count++)
      {
	RemainingFormulasVec.clear();
	RemainingFormulasVec.push_back(asttrue);
	RefineFormulasVec.clear();
	RefineFormulasVec.push_back(asttrue);
	ASTVec InputKids = original_input.GetChildren();
	for(ASTVec::iterator it = InputKids.begin(), itend = InputKids.end();
	    it!=itend;it++)
	  {
	    Ctr_Example->ClearComputeFormulaMap();
	    if(astfalse == Ctr_Example->ComputeFormulaUsingModel(*it))
	      {
		RefineFormulasVec.push_back(*it);
	      }
	    else
	      {
		RemainingFormulasVec.push_back(*it);
	      }
	  }
	ASTNode RefineFormulas =
	  (RefineFormulasVec.size() == 1) ?
	  RefineFormulasVec[0] : bm->CreateNode(AND, RefineFormulasVec);
	res = TopLevelSTPAux(NewSolver, RefineFormulas, original_input);
	if(SOLVER_UNDECIDED != res)
	  {
	    return res;
	  }
      }

    ASTNode RemainingFormulas =
      (RemainingFormulasVec.size() == 1) ?
      RemainingFormulasVec[0] : bm->CreateNode(AND, RemainingFormulasVec);
    res = TopLevelSTPAux(NewSolver, RemainingFormulas, original_input);

    if(SOLVER_UNDECIDED != res)
      {
	return res;
      }

    FatalError("TopLevelSTPAux: reached the end without proper conclusion:"
	       "either a divide by zero in the input or a bug in STP");
    return SOLVER_ERROR;
  } //End of UserGuided_AbsRefine()
}; //end of namespace
<|endoftext|>


<commit_before>#include "braincloud/internal/SaveDataHelper.h"

#if !defined(__APPLE__)

#if defined(WINDOWS) || defined(WIN32)
#include <Windows.h>
#endif

SaveDataHelper * SaveDataHelper::m_instance = NULL;

SaveDataHelper::SaveDataHelper()
: m_savePath("")
{

}

SaveDataHelper * SaveDataHelper::getInstance()
{
	if (m_instance == NULL)
	{
		m_instance = new SaveDataHelper();
	}

	return m_instance;
}

void SaveDataHelper::initialize(const char * companyName, const char * gameName)
{
#if defined(WINDOWS) || defined(WIN32)
	if (companyName != NULL && gameName != NULL)
	{
		std::string companyNameStr = companyName;
		std::string gameNameStr = gameName;
		m_savePath = std::string("Software\\" + companyNameStr + "\\" + gameNameStr + "\\");
	}
#endif
}

void SaveDataHelper::saveData(const char * key, const char * data)
{
#if defined(WINDOWS) || defined(WIN32)
#ifdef WINAPI_FAMILY
	std::string skey = key;
	std::string sdata = data;
	std::wstring wskey;
	std::wstring wsdata;
	for (auto c : skey) {
		wskey += (wchar_t)c;
	}
	for (auto c : sdata) {
		wsdata += (wchar_t)c;
	}
	Windows::Storage::ApplicationDataContainer^ localSettings = Windows::Storage::ApplicationData::Current->LocalSettings;
	auto values = localSettings->Values;
	values->Insert(
		ref new Platform::String(wskey.c_str()),
		dynamic_cast<Windows::Foundation::PropertyValue^>(Windows::Foundation::PropertyValue::CreateString(ref new Platform::String(wsdata.c_str()))));
#else
	if (m_savePath.empty())
	{
		return;
	}

	LONG status;
	HKEY hKey;

	status = RegOpenKeyExA(HKEY_CURRENT_USER, m_savePath.c_str(), 0, KEY_ALL_ACCESS, &hKey);
	if ((status == ERROR_SUCCESS) && (hKey != NULL)) {
		status = RegSetValueExA(hKey, key, 0, REG_SZ, (BYTE*)data, ((DWORD)strlen(data) + 1)*sizeof(char));
		RegCloseKey(hKey);
	}
	else if (status == ERROR_FILE_NOT_FOUND) {
		// Key didn't exist, create it
		SECURITY_ATTRIBUTES sAttribs = { sizeof(SECURITY_ATTRIBUTES) };
		DWORD dwDisposition = 0;
		status = RegCreateKeyExA(HKEY_CURRENT_USER, m_savePath.c_str(), 0, "", REG_OPTION_VOLATILE, KEY_ALL_ACCESS, &sAttribs, &hKey, &dwDisposition);
		if (status == ERROR_SUCCESS) {
			// Set it's value
			status = RegOpenKeyExA(HKEY_CURRENT_USER, m_savePath.c_str(), 0, KEY_ALL_ACCESS, &hKey);
			if ((status == ERROR_SUCCESS) && (hKey != NULL)) {
				status = RegSetValueExA(hKey, key, 0, REG_SZ, (BYTE*)data, ((DWORD)strlen(data) + 1)*sizeof(char));
				RegCloseKey(hKey);
			}
		}
	}
#endif
#endif
}

std::string SaveDataHelper::readData(const char * key)
{
    std::string sdata;

#if defined(WINDOWS) || defined(WIN32)
#ifdef WINAPI_FAMILY
	std::string skey = key;
	std::wstring wskey;
	for (auto c : skey) {
		wskey += (wchar_t)c;
	}
	Windows::Storage::ApplicationDataContainer^ localSettings = Windows::Storage::ApplicationData::Current->LocalSettings;
	auto values = localSettings->Values;
	Platform::String^ value = safe_cast<Platform::String^>(localSettings->Values->Lookup(ref new Platform::String(wskey.c_str())));
	if (!value) return "";
	std::wstring wsdata = value->Data();
	for (auto c : wsdata) {
		sdata += (char)c;
	}
#else
	if (m_savePath.empty())
	{
		return "";
	}

	LONG status;
	HKEY hKey;
	status = RegOpenKeyExA(HKEY_CURRENT_USER, m_savePath.c_str(), 0, KEY_READ, &hKey);
	if ((status == ERROR_SUCCESS) && (hKey != NULL)) {
		unsigned long type = REG_SZ, size = 1024;
		char res[1024] = "";

		status = RegQueryValueExA(hKey,
			key, NULL, &type, (LPBYTE)&res[0], &size);

		RegCloseKey(hKey);

		if (status == ERROR_SUCCESS) {
			sdata = res;
		}
	}
#endif
#else
    // android/linux implementation?
#endif

    return sdata;
}

void SaveDataHelper::deleteData(const char * key)
{
#if defined(WINDOWS) || defined(WIN32)
#ifdef WINAPI_FAMILY
	std::string skey = key;
	std::wstring wskey;
	for (auto c : skey) {
		wskey += (wchar_t)c;
	}
	Windows::Storage::ApplicationDataContainer^ localSettings = Windows::Storage::ApplicationData::Current->LocalSettings;
	auto values = localSettings->Values;
	values->Remove(ref new Platform::String(wskey.c_str()));
#else
	if (m_savePath.empty())
	{
		return;
	}

	std::string data;

	LONG status;
	HKEY hKey;
	status = RegOpenKeyExA(HKEY_CURRENT_USER, m_savePath.c_str(), 0, KEY_SET_VALUE, &hKey);
	if ((status == ERROR_SUCCESS) && (hKey != NULL)) {
		unsigned long type = REG_SZ, size = 1024;
		char res[1024] = "";

		status = RegDeleteValueA(hKey, key);
		RegCloseKey(hKey);
	}
#endif
#endif
}

#endif //__APPLE__
<commit_msg>Fixed bad ifdef for windows desktop apps.<commit_after>#include "braincloud/internal/SaveDataHelper.h"

#if !defined(__APPLE__)

#if defined(WINDOWS) || defined(WIN32)
#include <Windows.h>
#endif

SaveDataHelper * SaveDataHelper::m_instance = NULL;

SaveDataHelper::SaveDataHelper()
: m_savePath("")
{

}

SaveDataHelper * SaveDataHelper::getInstance()
{
	if (m_instance == NULL)
	{
		m_instance = new SaveDataHelper();
	}

	return m_instance;
}

void SaveDataHelper::initialize(const char * companyName, const char * gameName)
{
#if defined(WINDOWS) || defined(WIN32)
	if (companyName != NULL && gameName != NULL)
	{
		std::string companyNameStr = companyName;
		std::string gameNameStr = gameName;
		m_savePath = std::string("Software\\" + companyNameStr + "\\" + gameNameStr + "\\");
	}
#endif
}

void SaveDataHelper::saveData(const char * key, const char * data)
{
#if defined(WINDOWS) || defined(WIN32)
#if defined WINAPI_FAMILY && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
	std::string skey = key;
	std::string sdata = data;
	std::wstring wskey;
	std::wstring wsdata;
	for (auto c : skey) {
		wskey += (wchar_t)c;
	}
	for (auto c : sdata) {
		wsdata += (wchar_t)c;
	}
	Windows::Storage::ApplicationDataContainer^ localSettings = Windows::Storage::ApplicationData::Current->LocalSettings;
	auto values = localSettings->Values;
	values->Insert(
		ref new Platform::String(wskey.c_str()),
		dynamic_cast<Windows::Foundation::PropertyValue^>(Windows::Foundation::PropertyValue::CreateString(ref new Platform::String(wsdata.c_str()))));
#else
	if (m_savePath.empty())
	{
		return;
	}

	LONG status;
	HKEY hKey;

	status = RegOpenKeyExA(HKEY_CURRENT_USER, m_savePath.c_str(), 0, KEY_ALL_ACCESS, &hKey);
	if ((status == ERROR_SUCCESS) && (hKey != NULL)) {
		status = RegSetValueExA(hKey, key, 0, REG_SZ, (BYTE*)data, ((DWORD)strlen(data) + 1)*sizeof(char));
		RegCloseKey(hKey);
	}
	else if (status == ERROR_FILE_NOT_FOUND) {
		// Key didn't exist, create it
		SECURITY_ATTRIBUTES sAttribs = { sizeof(SECURITY_ATTRIBUTES) };
		DWORD dwDisposition = 0;
		status = RegCreateKeyExA(HKEY_CURRENT_USER, m_savePath.c_str(), 0, "", REG_OPTION_VOLATILE, KEY_ALL_ACCESS, &sAttribs, &hKey, &dwDisposition);
		if (status == ERROR_SUCCESS) {
			// Set it's value
			status = RegOpenKeyExA(HKEY_CURRENT_USER, m_savePath.c_str(), 0, KEY_ALL_ACCESS, &hKey);
			if ((status == ERROR_SUCCESS) && (hKey != NULL)) {
				status = RegSetValueExA(hKey, key, 0, REG_SZ, (BYTE*)data, ((DWORD)strlen(data) + 1)*sizeof(char));
				RegCloseKey(hKey);
			}
		}
	}
#endif
#endif
}

std::string SaveDataHelper::readData(const char * key)
{
    std::string sdata;

#if defined(WINDOWS) || defined(WIN32)
#if defined WINAPI_FAMILY && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
	std::string skey = key;
	std::wstring wskey;
	for (auto c : skey) {
		wskey += (wchar_t)c;
	}
	Windows::Storage::ApplicationDataContainer^ localSettings = Windows::Storage::ApplicationData::Current->LocalSettings;
	auto values = localSettings->Values;
	Platform::String^ value = safe_cast<Platform::String^>(localSettings->Values->Lookup(ref new Platform::String(wskey.c_str())));
	if (!value) return "";
	std::wstring wsdata = value->Data();
	for (auto c : wsdata) {
		sdata += (char)c;
	}
#else
	if (m_savePath.empty())
	{
		return "";
	}

	LONG status;
	HKEY hKey;
	status = RegOpenKeyExA(HKEY_CURRENT_USER, m_savePath.c_str(), 0, KEY_READ, &hKey);
	if ((status == ERROR_SUCCESS) && (hKey != NULL)) {
		unsigned long type = REG_SZ, size = 1024;
		char res[1024] = "";

		status = RegQueryValueExA(hKey,
			key, NULL, &type, (LPBYTE)&res[0], &size);

		RegCloseKey(hKey);

		if (status == ERROR_SUCCESS) {
			sdata = res;
		}
	}
#endif
#else
    // android/linux implementation?
#endif

    return sdata;
}

void SaveDataHelper::deleteData(const char * key)
{
#if defined(WINDOWS) || defined(WIN32)
#if defined WINAPI_FAMILY && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
	std::string skey = key;
	std::wstring wskey;
	for (auto c : skey) {
		wskey += (wchar_t)c;
	}
	Windows::Storage::ApplicationDataContainer^ localSettings = Windows::Storage::ApplicationData::Current->LocalSettings;
	auto values = localSettings->Values;
	values->Remove(ref new Platform::String(wskey.c_str()));
#else
	if (m_savePath.empty())
	{
		return;
	}

	std::string data;

	LONG status;
	HKEY hKey;
	status = RegOpenKeyExA(HKEY_CURRENT_USER, m_savePath.c_str(), 0, KEY_SET_VALUE, &hKey);
	if ((status == ERROR_SUCCESS) && (hKey != NULL)) {
		unsigned long type = REG_SZ, size = 1024;
		char res[1024] = "";

		status = RegDeleteValueA(hKey, key);
		RegCloseKey(hKey);
	}
#endif
#endif
}

#endif //__APPLE__
<|endoftext|>


<commit_before>#include "experiment.h"
#include <mintsystem/timer.h>
#include <stdio.h>
#include <stdlib.h>

//--------------------------------------------------------------
//  Run a set of experiments indefinitely while logging stats
//--------------------------------------------------------------
void LoopForever(const std::vector<IExperiment*>& exps)
{
    TimeKeeper* timeKeepers = new TimeKeeper[exps.size()];

    mint_timer_tick_t logInterval = (mint_timer_tick_t) (1 * mint_timer_secondsToTicks);
    mint_timer_tick_t nextLog = mint_timer_get() + logInterval;
    mint_timer_tick_t totalTime = 0;
    for (;;)
    {
        for (size_t i = 0; i < exps.size(); i++)
        {
            exps[i]->Run(timeKeepers[i]);
        }

        mint_timer_tick_t now = mint_timer_get();
        if (mint_timer_greater_or_equal(now, nextLog))
        {
            printf("------------------------------------\n");
            for (size_t j = 0; j < exps.size(); j++)
                printf("experiment #%d: %d iterations, failures = %d, average = %f ms\n", j, timeKeepers[j].trials, timeKeepers[j].failures, timeKeepers[j].getAverageTime() * 1000);
            nextLog = now + logInterval;
        }
    }

    delete[] timeKeepers;
}
<commit_msg>Fix Xcode warnings<commit_after>#include "experiment.h"
#include <mintsystem/timer.h>
#include <stdio.h>
#include <stdlib.h>

//--------------------------------------------------------------
//  Run a set of experiments indefinitely while logging stats
//--------------------------------------------------------------
void LoopForever(const std::vector<IExperiment*>& exps)
{
    TimeKeeper* timeKeepers = new TimeKeeper[exps.size()];

    mint_timer_tick_t logInterval = (mint_timer_tick_t) (1 * mint_timer_secondsToTicks);
    mint_timer_tick_t nextLog = mint_timer_get() + logInterval;
    for (;;)
    {
        for (size_t i = 0; i < exps.size(); i++)
        {
            exps[i]->Run(timeKeepers[i]);
        }

        mint_timer_tick_t now = mint_timer_get();
        if (mint_timer_greater_or_equal(now, nextLog))
        {
            printf("------------------------------------\n");
            for (size_t j = 0; j < exps.size(); j++)
                printf("experiment #%d: %d iterations, failures = %d, average = %f ms\n", (int) j, timeKeepers[j].trials, timeKeepers[j].failures, timeKeepers[j].getAverageTime() * 1000);
            nextLog = now + logInterval;
        }
    }

    delete[] timeKeepers;
}
<|endoftext|>


<commit_before><commit_msg>linux: fix truncated text in connect buttons in gear dialog<commit_after><|endoftext|>


<commit_before><commit_msg>Implemented algorithm to check if tree is balanced.<commit_after><|endoftext|>


<commit_before>/**
 * This file is part of the "libfnord" project
 *   Copyright (c) 2015 Paul Asmuth
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <fnord-tsdb/StreamChunk.h>
#include <fnord-base/io/fileutil.h>
#include <fnord-base/uri.h>
#include <fnord-base/util/Base64.h>
#include <fnord-base/util/binarymessagewriter.h>
#include <fnord-base/wallclock.h>
#include <fnord-msg/MessageEncoder.h>

namespace fnord {
namespace tsdb {

RefPtr<StreamChunk> StreamChunk::create(
    const String& streamchunk_key,
    const String& stream_key,
    RefPtr<StreamProperties> config,
    TSDBNodeRef* node) {
  return RefPtr<StreamChunk>(
      new StreamChunk(
          streamchunk_key,
          stream_key,
          config,
          node));
}

RefPtr<StreamChunk> StreamChunk::reopen(
    const String& stream_key,
    const StreamChunkState& state,
    RefPtr<StreamProperties> config,
    TSDBNodeRef* node) {
  return RefPtr<StreamChunk>(
      new StreamChunk(
          stream_key,
          state,
          config,
          node));
}

String StreamChunk::streamChunkKeyFor(
    const String& stream_key,
    DateTime time,
    Duration partition_size) {
  util::BinaryMessageWriter buf(stream_key.size() + 32);

  auto cs = partition_size.microseconds();
  auto ts = (time.unixMicros() / cs) * cs / kMicrosPerSecond;

  buf.append(stream_key.data(), stream_key.size());
  buf.appendUInt8(27);
  buf.appendVarUInt(ts);

  return String((char *) buf.data(), buf.size());
}

String StreamChunk::streamChunkKeyFor(
    const String& stream_key,
    DateTime time,
    const StreamProperties& properties) {
  return streamChunkKeyFor(stream_key, time, properties.chunk_size);
}

Vector<String> StreamChunk::streamChunkKeysFor(
    const String& stream_key,
    DateTime from,
    DateTime until,
    const StreamProperties& properties) {
  auto cs = properties.chunk_size.microseconds();
  auto first_chunk = (from.unixMicros() / cs) * cs;
  auto last_chunk = (until.unixMicros() / cs) * cs;

  Vector<String> res;
  for (auto t = first_chunk; t <= last_chunk; t += cs) {
    res.emplace_back(streamChunkKeyFor(stream_key, t, properties));
  }

  return res;
}

StreamChunk::StreamChunk(
    const String& streamchunk_key,
    const String& stream_key,
    RefPtr<StreamProperties> config,
    TSDBNodeRef* node) :
    stream_key_(stream_key),
    key_(streamchunk_key),
    config_(config),
    node_(node),
    records_(
        FileUtil::joinPaths(
            node->db_path,
            StringUtil::stripShell(stream_key) + ".")),
    last_compaction_(0) {
  records_.setMaxDatafileSize(config_->max_datafile_size);
}

StreamChunk::StreamChunk(
    const String& streamchunk_key,
    const StreamChunkState& state,
    RefPtr<StreamProperties> config,
    TSDBNodeRef* node) :
    stream_key_(state.stream_key),
    key_(streamchunk_key),
    config_(config),
    node_(node),
    records_(
        FileUtil::joinPaths(
            node->db_path,
            StringUtil::stripShell(state.stream_key) + "."),
        state.record_state),
    repl_offsets_(state.repl_offsets),
    last_compaction_(0) {
  scheduleCompaction();
  node_->compactionq.insert(this, WallClock::unixMicros());
  node_->replicationq.insert(this, WallClock::unixMicros());
  node_->indexq.insert(this, WallClock::unixMicros());
  records_.setMaxDatafileSize(config_->max_datafile_size);
}

void StreamChunk::insertRecord(
    uint64_t record_id,
    const Buffer& record) {
  std::unique_lock<std::mutex> lk(mutex_);

  auto old_ver = records_.version();
  records_.addRecord(record_id, record);
  if (records_.version() != old_ver) {
    commitState();
  }

  scheduleCompaction();
}

void StreamChunk::insertRecords(const Vector<RecordRef>& records) {
  std::unique_lock<std::mutex> lk(mutex_);

  auto old_ver = records_.version();
  records_.addRecords(records);
  if (records_.version() != old_ver) {
    commitState();
  }

  scheduleCompaction();
}

void StreamChunk::scheduleCompaction() {
  auto now = WallClock::unixMicros();
  auto interval = config_->compaction_interval.microseconds();
  auto last = last_compaction_.unixMicros();
  uint64_t compaction_delay = 0;

  if (last + interval > now) {
    compaction_delay = (last + interval) - now;
  }

  node_->compactionq.insert(this, now + compaction_delay);
}

void StreamChunk::compact() {
  std::unique_lock<std::mutex> lk(mutex_);
  last_compaction_ = DateTime::now();
  lk.unlock();

  Set<String> deleted_files;
  records_.compact(&deleted_files);

  lk.lock();
  commitState();
  lk.unlock();

  node_->replicationq.insert(this, WallClock::unixMicros());
  node_->indexq.insert(this, WallClock::unixMicros());

  for (const auto& f : deleted_files) {
    FileUtil::rm(f);
  }
}

void StreamChunk::replicate() {
  std::unique_lock<std::mutex> lk(replication_mutex_);

  auto cur_offset = records_.lastOffset();
  auto replicas = node_->replication_scheme->replicasFor(key_);
  bool dirty = false;
  bool needs_replication = false;
  bool has_error = false;

  for (const auto& r : replicas) {
    auto& off = repl_offsets_[r.unique_id];

    if (off < cur_offset) {
      try {
        auto rep_offset = replicateTo(r.addr, off);
        dirty = true;
        off = rep_offset;
        if (off < cur_offset) {
          needs_replication = true;
        }
      } catch (const std::exception& e) {
        has_error = true;

        fnord::logError(
          "tsdb.replication",
          e,
          "Error while replicating stream '$0' to '$1'",
          stream_key_,
          r.addr);
      }
    }
  }

  for (auto cur = repl_offsets_.begin(); cur != repl_offsets_.end(); ) {
    bool found;
    for (const auto& r : replicas) {
      if (r.unique_id == cur->first) {
        found = true;
        break;
      }
    }

    if (found) {
      ++cur;
    } else {
      cur = repl_offsets_.erase(cur);
      dirty = true;
    }
  }

  if (dirty) {
    std::unique_lock<std::mutex> lk(mutex_);
    commitState();
  }

  if (needs_replication) {
    node_->replicationq.insert(this, WallClock::unixMicros());
  } else if (has_error) {
    node_->replicationq.insert(
        this,
        WallClock::unixMicros() + 30 * kMicrosPerSecond);
  }
}

uint64_t StreamChunk::replicateTo(const String& addr, uint64_t offset) {
  size_t batch_size = 1024;
  util::BinaryMessageWriter batch;

  auto start_offset = records_.firstOffset();
  if (start_offset > offset) {
    offset = start_offset;
  }

  size_t n = 0;
  records_.fetchRecords(offset, batch_size, [this, &batch, &n] (
      uint64_t record_id,
      const void* record_data,
      size_t record_size) {
    ++n;

    batch.appendUInt64(record_id);
    batch.appendVarUInt(record_size);
    batch.append(record_data, record_size);
  });

  String encoded_key;
  util::Base64::encode(key_, &encoded_key);

  fnord::logDebug(
      "tsdb.replication",
      "Replicating to $0; stream='$1' chunk='$2' offset=$3",
      addr,
      stream_key_,
      encoded_key,
      offset);

  URI uri(StringUtil::format(
      "http://$0/tsdb/replicate?stream=$1&chunk=$2",
      addr,
      URI::urlEncode(stream_key_),
      URI::urlEncode(encoded_key)));

  http::HTTPRequest req(http::HTTPMessage::M_POST, uri.pathAndQuery());
  req.addHeader("Host", uri.hostAndPort());
  req.addHeader("Content-Type", "application/fnord-msg");
  req.addBody(batch.data(), batch.size());

  auto res = node_->http->executeRequest(req);
  res.wait();

  const auto& r = res.get();
  if (r.statusCode() != 201) {
    RAISEF(kRuntimeError, "received non-201 response: $0", r.body().toString());
  }

  return offset + n;
}

void StreamChunk::buildIndexes() {
  std::unique_lock<std::mutex> lk(indexbuild_mutex_);

  for (const auto& dset : config_->derived_datasets) {
    buildDerivedDataset(dset);
  }
}

void StreamChunk::buildDerivedDataset(RefPtr<DerivedDataset> dset) {
  String dset_key = "\x1b";
  dset_key.append(key_);
  dset_key.append("~" + dset->name());

  DerivedDatasetState old_state;
  {
    auto txn = node_->db->startTransaction(true);
    auto buf = txn->get(dset_key);
    txn->abort();
    if (!buf.isEmpty()) {
      util::BinaryMessageReader reader(buf.get().data(), buf.get().size());
      old_state.decode(&reader);
    }
  }

  auto cur_offset = records_.lastOffset();
  if (old_state.last_offset >= cur_offset) {
    return;
  }

  DerivedDatasetState new_state;
  new_state.last_offset = cur_offset;

  Set<String> delete_after_commit;
  try {
    dset->update(
        &records_,
        old_state.last_offset,
        cur_offset,
        old_state.state,
        &new_state.state,
        &delete_after_commit);
  } catch (const std::exception& e) {
    fnord::logError(
        "fnord.tsdb",
        e,
        "error while building derived dataset '$0'",
        dset->name());

    return;
  }

  {
    util::BinaryMessageWriter buf;
    new_state.encode(&buf);

    auto txn = node_->db->startTransaction(false);
    txn->update(dset_key.data(), dset_key.size(), buf.data(), buf.size());
    txn->commit();
  }

  for (const auto& f : delete_after_commit) {
    FileUtil::rm(f);
  }
}

Buffer StreamChunk::fetchDerivedDataset(const String& dataset_name) {
  String dset_key = "\x1b";
  dset_key.append(key_);
  dset_key.append("~" + dataset_name);
  DerivedDatasetState dset;

  auto txn = node_->db->startTransaction(true);
  auto buf = txn->get(dset_key);
  txn->abort();

  if (buf.isEmpty()) {
    return Buffer{};
  } else {
    util::BinaryMessageReader reader(buf.get().data(), buf.get().size());
    dset.decode(&reader);
    return dset.state;
  }
}

Vector<String> StreamChunk::listFiles() const {
  return records_.listDatafiles();
}

PartitionInfo StreamChunk::partitionInfo() const {
  PartitionInfo pi;
  pi.set_partition_key(util::Base64::encode(key_));
  pi.set_stream_key(stream_key_);
  pi.set_version(records_.version());
  pi.set_exists(true);
  return pi;
}

void StreamChunk::commitState() {
  StreamChunkState state;
  state.record_state = records_.getState();
  state.stream_key = stream_key_;
  state.repl_offsets = repl_offsets_;

  util::BinaryMessageWriter buf;
  state.encode(&buf);

  auto txn = node_->db->startTransaction(false);
  txn->update(key_.data(), key_.size(), buf.data(), buf.size());
  txn->commit();
}

void StreamChunkState::encode(
    util::BinaryMessageWriter* writer) const {
  writer->appendLenencString(stream_key);
  record_state.encode(writer);

  writer->appendVarUInt(repl_offsets.size());
  for (const auto& ro : repl_offsets) {
    writer->appendVarUInt(ro.first);
    writer->appendVarUInt(ro.second);
  }

  writer->appendVarUInt(record_state.version);
}

void StreamChunkState::decode(util::BinaryMessageReader* reader) {
  stream_key = reader->readLenencString();
  record_state.decode(reader);

  auto nrepl_offsets = reader->readVarUInt();
  for (int i = 0; i < nrepl_offsets; ++i) {
    auto id = reader->readVarUInt();
    auto off = reader->readVarUInt();
    repl_offsets.emplace(id, off);
  }

  record_state.version = reader->readVarUInt();
}

}
}
<commit_msg>add some debug logging<commit_after>/**
 * This file is part of the "libfnord" project
 *   Copyright (c) 2015 Paul Asmuth
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <fnord-tsdb/StreamChunk.h>
#include <fnord-base/io/fileutil.h>
#include <fnord-base/uri.h>
#include <fnord-base/util/Base64.h>
#include <fnord-base/util/binarymessagewriter.h>
#include <fnord-base/wallclock.h>
#include <fnord-msg/MessageEncoder.h>

namespace fnord {
namespace tsdb {

RefPtr<StreamChunk> StreamChunk::create(
    const String& streamchunk_key,
    const String& stream_key,
    RefPtr<StreamProperties> config,
    TSDBNodeRef* node) {
  return RefPtr<StreamChunk>(
      new StreamChunk(
          streamchunk_key,
          stream_key,
          config,
          node));
}

RefPtr<StreamChunk> StreamChunk::reopen(
    const String& stream_key,
    const StreamChunkState& state,
    RefPtr<StreamProperties> config,
    TSDBNodeRef* node) {
  return RefPtr<StreamChunk>(
      new StreamChunk(
          stream_key,
          state,
          config,
          node));
}

String StreamChunk::streamChunkKeyFor(
    const String& stream_key,
    DateTime time,
    Duration partition_size) {
  util::BinaryMessageWriter buf(stream_key.size() + 32);

  auto cs = partition_size.microseconds();
  auto ts = (time.unixMicros() / cs) * cs / kMicrosPerSecond;

  buf.append(stream_key.data(), stream_key.size());
  buf.appendUInt8(27);
  buf.appendVarUInt(ts);

  return String((char *) buf.data(), buf.size());
}

String StreamChunk::streamChunkKeyFor(
    const String& stream_key,
    DateTime time,
    const StreamProperties& properties) {
  return streamChunkKeyFor(stream_key, time, properties.chunk_size);
}

Vector<String> StreamChunk::streamChunkKeysFor(
    const String& stream_key,
    DateTime from,
    DateTime until,
    const StreamProperties& properties) {
  auto cs = properties.chunk_size.microseconds();
  auto first_chunk = (from.unixMicros() / cs) * cs;
  auto last_chunk = (until.unixMicros() / cs) * cs;

  Vector<String> res;
  for (auto t = first_chunk; t <= last_chunk; t += cs) {
    res.emplace_back(streamChunkKeyFor(stream_key, t, properties));
  }

  return res;
}

StreamChunk::StreamChunk(
    const String& streamchunk_key,
    const String& stream_key,
    RefPtr<StreamProperties> config,
    TSDBNodeRef* node) :
    stream_key_(stream_key),
    key_(streamchunk_key),
    config_(config),
    node_(node),
    records_(
        FileUtil::joinPaths(
            node->db_path,
            StringUtil::stripShell(stream_key) + ".")),
    last_compaction_(0) {
  records_.setMaxDatafileSize(config_->max_datafile_size);
}

StreamChunk::StreamChunk(
    const String& streamchunk_key,
    const StreamChunkState& state,
    RefPtr<StreamProperties> config,
    TSDBNodeRef* node) :
    stream_key_(state.stream_key),
    key_(streamchunk_key),
    config_(config),
    node_(node),
    records_(
        FileUtil::joinPaths(
            node->db_path,
            StringUtil::stripShell(state.stream_key) + "."),
        state.record_state),
    repl_offsets_(state.repl_offsets),
    last_compaction_(0) {
  scheduleCompaction();
  node_->compactionq.insert(this, WallClock::unixMicros());
  node_->replicationq.insert(this, WallClock::unixMicros());
  node_->indexq.insert(this, WallClock::unixMicros());
  records_.setMaxDatafileSize(config_->max_datafile_size);
}

void StreamChunk::insertRecord(
    uint64_t record_id,
    const Buffer& record) {
  std::unique_lock<std::mutex> lk(mutex_);

  auto old_ver = records_.version();
  records_.addRecord(record_id, record);
  if (records_.version() != old_ver) {
    commitState();
  }

  scheduleCompaction();
}

void StreamChunk::insertRecords(const Vector<RecordRef>& records) {
  std::unique_lock<std::mutex> lk(mutex_);

  auto old_ver = records_.version();
  records_.addRecords(records);
  if (records_.version() != old_ver) {
    commitState();
  }

  scheduleCompaction();
}

void StreamChunk::scheduleCompaction() {
  auto now = WallClock::unixMicros();
  auto interval = config_->compaction_interval.microseconds();
  auto last = last_compaction_.unixMicros();
  uint64_t compaction_delay = 0;

  if (last + interval > now) {
    compaction_delay = (last + interval) - now;
  }

  node_->compactionq.insert(this, now + compaction_delay);
}

void StreamChunk::compact() {
  std::unique_lock<std::mutex> lk(mutex_);
  last_compaction_ = DateTime::now();
  lk.unlock();

  String encoded_key;
  util::Base64::encode(key_, &encoded_key);

  fnord::logDebug(
      "tsdb.replication",
      "Compacting partition; stream='$0' partition='$1'",
      stream_key_,
      encoded_key);

  Set<String> deleted_files;
  records_.compact(&deleted_files);

  lk.lock();
  commitState();
  lk.unlock();

  node_->replicationq.insert(this, WallClock::unixMicros());
  node_->indexq.insert(this, WallClock::unixMicros());

  for (const auto& f : deleted_files) {
    FileUtil::rm(f);
  }
}

void StreamChunk::replicate() {
  std::unique_lock<std::mutex> lk(replication_mutex_);

  auto cur_offset = records_.lastOffset();
  auto replicas = node_->replication_scheme->replicasFor(key_);
  bool dirty = false;
  bool needs_replication = false;
  bool has_error = false;

  for (const auto& r : replicas) {
    auto& off = repl_offsets_[r.unique_id];

    if (off < cur_offset) {
      try {
        auto rep_offset = replicateTo(r.addr, off);
        dirty = true;
        off = rep_offset;
        if (off < cur_offset) {
          needs_replication = true;
        }
      } catch (const std::exception& e) {
        has_error = true;

        fnord::logError(
          "tsdb.replication",
          e,
          "Error while replicating stream '$0' to '$1'",
          stream_key_,
          r.addr);
      }
    }
  }

  for (auto cur = repl_offsets_.begin(); cur != repl_offsets_.end(); ) {
    bool found;
    for (const auto& r : replicas) {
      if (r.unique_id == cur->first) {
        found = true;
        break;
      }
    }

    if (found) {
      ++cur;
    } else {
      cur = repl_offsets_.erase(cur);
      dirty = true;
    }
  }

  if (dirty) {
    std::unique_lock<std::mutex> lk(mutex_);
    commitState();
  }

  if (needs_replication) {
    node_->replicationq.insert(this, WallClock::unixMicros());
  } else if (has_error) {
    node_->replicationq.insert(
        this,
        WallClock::unixMicros() + 30 * kMicrosPerSecond);
  }
}

uint64_t StreamChunk::replicateTo(const String& addr, uint64_t offset) {
  size_t batch_size = 1024;
  util::BinaryMessageWriter batch;

  auto start_offset = records_.firstOffset();
  if (start_offset > offset) {
    offset = start_offset;
  }

  size_t n = 0;
  records_.fetchRecords(offset, batch_size, [this, &batch, &n] (
      uint64_t record_id,
      const void* record_data,
      size_t record_size) {
    ++n;

    batch.appendUInt64(record_id);
    batch.appendVarUInt(record_size);
    batch.append(record_data, record_size);
  });

  String encoded_key;
  util::Base64::encode(key_, &encoded_key);

  fnord::logDebug(
      "tsdb.replication",
      "Replicating to $0; stream='$1' partition='$2' offset=$3",
      addr,
      stream_key_,
      encoded_key,
      offset);

  URI uri(StringUtil::format(
      "http://$0/tsdb/replicate?stream=$1&chunk=$2",
      addr,
      URI::urlEncode(stream_key_),
      URI::urlEncode(encoded_key)));

  http::HTTPRequest req(http::HTTPMessage::M_POST, uri.pathAndQuery());
  req.addHeader("Host", uri.hostAndPort());
  req.addHeader("Content-Type", "application/fnord-msg");
  req.addBody(batch.data(), batch.size());

  auto res = node_->http->executeRequest(req);
  res.wait();

  const auto& r = res.get();
  if (r.statusCode() != 201) {
    RAISEF(kRuntimeError, "received non-201 response: $0", r.body().toString());
  }

  return offset + n;
}

void StreamChunk::buildIndexes() {
  std::unique_lock<std::mutex> lk(indexbuild_mutex_);

  for (const auto& dset : config_->derived_datasets) {
    buildDerivedDataset(dset);
  }
}

void StreamChunk::buildDerivedDataset(RefPtr<DerivedDataset> dset) {
  String dset_key = "\x1b";
  dset_key.append(key_);
  dset_key.append("~" + dset->name());

  DerivedDatasetState old_state;
  {
    auto txn = node_->db->startTransaction(true);
    auto buf = txn->get(dset_key);
    txn->abort();
    if (!buf.isEmpty()) {
      util::BinaryMessageReader reader(buf.get().data(), buf.get().size());
      old_state.decode(&reader);
    }
  }

  auto cur_offset = records_.lastOffset();
  if (old_state.last_offset >= cur_offset) {
    return;
  }

  DerivedDatasetState new_state;
  new_state.last_offset = cur_offset;

  Set<String> delete_after_commit;
  try {
    dset->update(
        &records_,
        old_state.last_offset,
        cur_offset,
        old_state.state,
        &new_state.state,
        &delete_after_commit);
  } catch (const std::exception& e) {
    fnord::logError(
        "fnord.tsdb",
        e,
        "error while building derived dataset '$0'",
        dset->name());

    return;
  }

  {
    util::BinaryMessageWriter buf;
    new_state.encode(&buf);

    auto txn = node_->db->startTransaction(false);
    txn->update(dset_key.data(), dset_key.size(), buf.data(), buf.size());
    txn->commit();
  }

  for (const auto& f : delete_after_commit) {
    FileUtil::rm(f);
  }
}

Buffer StreamChunk::fetchDerivedDataset(const String& dataset_name) {
  String dset_key = "\x1b";
  dset_key.append(key_);
  dset_key.append("~" + dataset_name);
  DerivedDatasetState dset;

  auto txn = node_->db->startTransaction(true);
  auto buf = txn->get(dset_key);
  txn->abort();

  if (buf.isEmpty()) {
    return Buffer{};
  } else {
    util::BinaryMessageReader reader(buf.get().data(), buf.get().size());
    dset.decode(&reader);
    return dset.state;
  }
}

Vector<String> StreamChunk::listFiles() const {
  return records_.listDatafiles();
}

PartitionInfo StreamChunk::partitionInfo() const {
  PartitionInfo pi;
  pi.set_partition_key(util::Base64::encode(key_));
  pi.set_stream_key(stream_key_);
  pi.set_version(records_.version());
  pi.set_exists(true);
  return pi;
}

void StreamChunk::commitState() {
  StreamChunkState state;
  state.record_state = records_.getState();
  state.stream_key = stream_key_;
  state.repl_offsets = repl_offsets_;

  util::BinaryMessageWriter buf;
  state.encode(&buf);

  auto txn = node_->db->startTransaction(false);
  txn->update(key_.data(), key_.size(), buf.data(), buf.size());
  txn->commit();
}

void StreamChunkState::encode(
    util::BinaryMessageWriter* writer) const {
  writer->appendLenencString(stream_key);
  record_state.encode(writer);

  writer->appendVarUInt(repl_offsets.size());
  for (const auto& ro : repl_offsets) {
    writer->appendVarUInt(ro.first);
    writer->appendVarUInt(ro.second);
  }

  writer->appendVarUInt(record_state.version);
}

void StreamChunkState::decode(util::BinaryMessageReader* reader) {
  stream_key = reader->readLenencString();
  record_state.decode(reader);

  auto nrepl_offsets = reader->readVarUInt();
  for (int i = 0; i < nrepl_offsets; ++i) {
    auto id = reader->readVarUInt();
    auto off = reader->readVarUInt();
    repl_offsets.emplace(id, off);
  }

  record_state.version = reader->readVarUInt();
}

}
}
<|endoftext|>