<commit_before>//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
//  This source code is licensed under the BSD-style license found in the
//  LICENSE file in the root directory of this source tree. An additional grant
//  of patent rights can be found in the PATENTS file in the same directory.
//
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.

#include "util/histogram.h"
#include "util/histogram_windowing.h"

#include <algorithm>

namespace rocksdb {

namespace {
  const HistogramBucketMapper bucketMapper;
}

HistogramWindowingImpl::HistogramWindowingImpl() {
  env_ = Env::Default();
  window_stats_.reset(new HistogramStat[num_windows_]);
  Clear();
}

HistogramWindowingImpl::HistogramWindowingImpl(
    uint64_t num_windows,
    uint64_t micros_per_window,
    uint64_t min_num_per_window) :
      num_windows_(num_windows),
      micros_per_window_(micros_per_window),
      min_num_per_window_(min_num_per_window) {
  env_ = Env::Default();
  window_stats_.reset(new HistogramStat[num_windows_]);
  Clear();
}

HistogramWindowingImpl::~HistogramWindowingImpl(){
  window_stats_.release();
}

void HistogramWindowingImpl::Clear() {
  std::lock_guard<std::mutex> lock(mutex_);

  stats_.Clear();
  for (size_t i = 0; i < num_windows_; i++) {
    window_stats_[i].Clear();
  }
  current_window_.store(0, std::memory_order_relaxed);
  last_swap_time_.store(env_->NowMicros(), std::memory_order_relaxed);
}

bool HistogramWindowingImpl::Empty() const { return stats_.Empty(); }

// This function is designed to be lock free, as it's in the critical path
// of any operation.
// Each individual value is atomic, it is just that some samples can go
// in the older bucket which is tolerable.
void HistogramWindowingImpl::Add(uint64_t value){
  TimerTick();

  // Parent (global) member update
  stats_.Add(value);

  // Current window update
  window_stats_[current_window()].Add(value);
}

void HistogramWindowingImpl::Merge(const Histogram& other) {
  if (strcmp(Name(), other.Name()) == 0) {
    Merge(dynamic_cast<const HistogramWindowingImpl&>(other));
  }
}

void HistogramWindowingImpl::Merge(const HistogramWindowingImpl& other) {
  std::lock_guard<std::mutex> lock(mutex_);
  stats_.Merge(other.stats_);

  if (stats_.num_buckets_ != other.stats_.num_buckets_ ||
      micros_per_window_ != other.micros_per_window_) {
    return;
  }

  uint64_t cur_window = current_window();
  uint64_t other_cur_window = other.current_window();
  // going backwards for alignment
  for (unsigned int i = 0;
                    i < std::min(num_windows_, other.num_windows_); i++) {
    uint64_t window_index =
        (cur_window + num_windows_ - i) % num_windows_;
    uint64_t other_window_index =
        (other_cur_window + other.num_windows_ - i) % other.num_windows_;

    window_stats_[window_index].Merge(other.window_stats_[other_window_index]);
  }
}

std::string HistogramWindowingImpl::ToString() const {
  return stats_.ToString();
}

double HistogramWindowingImpl::Median() const {
  return Percentile(50.0);
}

double HistogramWindowingImpl::Percentile(double p) const {
  // Retry 3 times in total
  for (int retry = 0; retry < 3; retry++) {
    uint64_t start_num = stats_.num();
    double result = stats_.Percentile(p);
    // Detect if swap buckets or Clear() was called during calculation
    if (stats_.num() >= start_num) {
      return result;
    }
  }
  return 0.0;
}

double HistogramWindowingImpl::Average() const {
  return stats_.Average();
}

double HistogramWindowingImpl::StandardDeviation() const {
  return stats_.StandardDeviation();
}

void HistogramWindowingImpl::Data(HistogramData * const data) const {
  stats_.Data(data);
}

void HistogramWindowingImpl::TimerTick() {
  uint64_t curr_time = env_->NowMicros();
  if (curr_time - last_swap_time() > micros_per_window_ &&
      window_stats_[current_window()].num() >= min_num_per_window_) {
    SwapHistoryBucket();
  }
}

void HistogramWindowingImpl::SwapHistoryBucket() {
  // Threads executing Add() would be competing for this mutex, the first one
  // who got the metex would take care of the bucket swap, other threads
  // can skip this.
  // If mutex is held by Merge() or Clear(), next Add() will take care of the
  // swap, if needed.
  if (mutex_.try_lock()) {
    last_swap_time_.store(env_->NowMicros(), std::memory_order_relaxed);

    uint64_t next_window = (current_window() + 1) % num_windows_;

    // subtract next buckets from totals and swap to next buckets
    HistogramStat& stats_to_drop = window_stats_[next_window];

    if (!stats_to_drop.Empty()) {
      for (size_t b = 0; b < stats_.num_buckets_; b++){
        stats_.buckets_[b].fetch_sub(
            stats_to_drop.bucket_at(b), std::memory_order_relaxed);
      }

      if (stats_.min() == stats_to_drop.min()) {
        uint64_t new_min = bucketMapper.LastValue();
        for (unsigned int i = 1; i < num_windows_; i++) {
          uint64_t m = window_stats_[(next_window + i) % num_windows_].min();
          if (m < new_min) new_min = m;
        }
        stats_.min_.store(new_min, std::memory_order_relaxed);
      }

      if (stats_.max() == stats_to_drop.max()) {
        uint64_t new_max = 0;
        for (unsigned int i = 1; i < num_windows_; i++) {
          uint64_t m = window_stats_[(next_window + i) % num_windows_].max();
          if (m > new_max) new_max = m;
        }
        stats_.max_.store(new_max, std::memory_order_relaxed);
      }

      stats_.num_.fetch_sub(stats_to_drop.num(), std::memory_order_relaxed);
      stats_.sum_.fetch_sub(stats_to_drop.sum(), std::memory_order_relaxed);
      stats_.sum_squares_.fetch_sub(
                  stats_to_drop.sum_squares(), std::memory_order_relaxed);

      stats_to_drop.Clear();
    }

    // advance to next window bucket
    current_window_.store(next_window, std::memory_order_relaxed);

    mutex_.unlock();
  }
}

}  // namespace rocksdb
<commit_msg>remove division from histogramwidowing impl<commit_after>//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
//  This source code is licensed under the BSD-style license found in the
//  LICENSE file in the root directory of this source tree. An additional grant
//  of patent rights can be found in the PATENTS file in the same directory.
//
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.

#include "util/histogram.h"
#include "util/histogram_windowing.h"

#include <algorithm>

namespace rocksdb {

namespace {
  const HistogramBucketMapper bucketMapper;
}

HistogramWindowingImpl::HistogramWindowingImpl() {
  env_ = Env::Default();
  window_stats_.reset(new HistogramStat[num_windows_]);
  Clear();
}

HistogramWindowingImpl::HistogramWindowingImpl(
    uint64_t num_windows,
    uint64_t micros_per_window,
    uint64_t min_num_per_window) :
      num_windows_(num_windows),
      micros_per_window_(micros_per_window),
      min_num_per_window_(min_num_per_window) {
  env_ = Env::Default();
  window_stats_.reset(new HistogramStat[num_windows_]);
  Clear();
}

HistogramWindowingImpl::~HistogramWindowingImpl(){
  window_stats_.release();
}

void HistogramWindowingImpl::Clear() {
  std::lock_guard<std::mutex> lock(mutex_);

  stats_.Clear();
  for (size_t i = 0; i < num_windows_; i++) {
    window_stats_[i].Clear();
  }
  current_window_.store(0, std::memory_order_relaxed);
  last_swap_time_.store(env_->NowMicros(), std::memory_order_relaxed);
}

bool HistogramWindowingImpl::Empty() const { return stats_.Empty(); }

// This function is designed to be lock free, as it's in the critical path
// of any operation.
// Each individual value is atomic, it is just that some samples can go
// in the older bucket which is tolerable.
void HistogramWindowingImpl::Add(uint64_t value){
  TimerTick();

  // Parent (global) member update
  stats_.Add(value);

  // Current window update
  window_stats_[current_window()].Add(value);
}

void HistogramWindowingImpl::Merge(const Histogram& other) {
  if (strcmp(Name(), other.Name()) == 0) {
    Merge(dynamic_cast<const HistogramWindowingImpl&>(other));
  }
}

void HistogramWindowingImpl::Merge(const HistogramWindowingImpl& other) {
  std::lock_guard<std::mutex> lock(mutex_);
  stats_.Merge(other.stats_);

  if (stats_.num_buckets_ != other.stats_.num_buckets_ ||
      micros_per_window_ != other.micros_per_window_) {
    return;
  }

  uint64_t cur_window = current_window();
  uint64_t other_cur_window = other.current_window();
  // going backwards for alignment
  for (unsigned int i = 0;
                    i < std::min(num_windows_, other.num_windows_); i++) {
    uint64_t window_index =
        (cur_window + num_windows_ - i) % num_windows_;
    uint64_t other_window_index =
        (other_cur_window + other.num_windows_ - i) % other.num_windows_;

    window_stats_[window_index].Merge(other.window_stats_[other_window_index]);
  }
}

std::string HistogramWindowingImpl::ToString() const {
  return stats_.ToString();
}

double HistogramWindowingImpl::Median() const {
  return Percentile(50.0);
}

double HistogramWindowingImpl::Percentile(double p) const {
  // Retry 3 times in total
  for (int retry = 0; retry < 3; retry++) {
    uint64_t start_num = stats_.num();
    double result = stats_.Percentile(p);
    // Detect if swap buckets or Clear() was called during calculation
    if (stats_.num() >= start_num) {
      return result;
    }
  }
  return 0.0;
}

double HistogramWindowingImpl::Average() const {
  return stats_.Average();
}

double HistogramWindowingImpl::StandardDeviation() const {
  return stats_.StandardDeviation();
}

void HistogramWindowingImpl::Data(HistogramData * const data) const {
  stats_.Data(data);
}

void HistogramWindowingImpl::TimerTick() {
  uint64_t curr_time = env_->NowMicros();
  if (curr_time - last_swap_time() > micros_per_window_ &&
      window_stats_[current_window()].num() >= min_num_per_window_) {
    SwapHistoryBucket();
  }
}

void HistogramWindowingImpl::SwapHistoryBucket() {
  // Threads executing Add() would be competing for this mutex, the first one
  // who got the metex would take care of the bucket swap, other threads
  // can skip this.
  // If mutex is held by Merge() or Clear(), next Add() will take care of the
  // swap, if needed.
  if (mutex_.try_lock()) {
    last_swap_time_.store(env_->NowMicros(), std::memory_order_relaxed);

    uint64_t curr_window = current_window();
    uint64_t next_window = (curr_window == num_windows_ - 1) ?
                                                    0 : curr_window + 1;

    // subtract next buckets from totals and swap to next buckets
    HistogramStat& stats_to_drop = window_stats_[next_window];

    if (!stats_to_drop.Empty()) {
      for (size_t b = 0; b < stats_.num_buckets_; b++){
        stats_.buckets_[b].fetch_sub(
            stats_to_drop.bucket_at(b), std::memory_order_relaxed);
      }

      if (stats_.min() == stats_to_drop.min()) {
        uint64_t new_min = bucketMapper.LastValue();
        for (unsigned int i = 0; i < num_windows_; i++) {
          if (i != next_window) {
            uint64_t m = window_stats_[i].min();
            if (m < new_min) new_min = m;
          }
        }
        stats_.min_.store(new_min, std::memory_order_relaxed);
      }

      if (stats_.max() == stats_to_drop.max()) {
        uint64_t new_max = 0;
        for (unsigned int i = 0; i < num_windows_; i++) {
          if (i != next_window) {
            uint64_t m = window_stats_[i].max();
            if (m > new_max) new_max = m;
          }
        }
        stats_.max_.store(new_max, std::memory_order_relaxed);
      }

      stats_.num_.fetch_sub(stats_to_drop.num(), std::memory_order_relaxed);
      stats_.sum_.fetch_sub(stats_to_drop.sum(), std::memory_order_relaxed);
      stats_.sum_squares_.fetch_sub(
                  stats_to_drop.sum_squares(), std::memory_order_relaxed);

      stats_to_drop.Clear();
    }

    // advance to next window bucket
    current_window_.store(next_window, std::memory_order_relaxed);

    mutex_.unlock();
  }
}

}  // namespace rocksdb
<|endoftext|>


<commit_before>#ifndef BUW_SDFLOADER_HPP
#define BUW_SDFLOADER_HPP

#include <string>
#include <scene.hpp>
#include <iostream>
#include <fstream>
#include <vector>
#include <regex>

void sdf_splitString(std::string const& input, std::vector<std::string>& output) {
	std::istringstream tmp{input};
	do {
		std::string sub{""};
		tmp >> sub;
		output.push_back(sub);
	} while(tmp);
}

bool sdf_isMaterial(std::string const& input) {
	std::regex rgx_material{"define[\\s\\t]material[\\s\\t]\\S+[\\s\\t]([0-9][\\s\\t]){9}[0-9].*"};
	if(std::regex_match(input,rgx_material)) {
		return true;
	}
	return false;
}

void sdf_parseMaterial(std::string const& input, std::map<Material>& materials) {
	std::vector<std::string> parsed;
	sdf_splitString(input,parsed);
	Color ka = {std::stof(parsed[3]),std::stof(parsed[4]),std::stof(parsed[5])};
	Color kd = {std::stof(parsed[6]),std::stof(parsed[7]),std::stof(parsed[8])};
	Color ks = {std::stof(parsed[9]),std::stof(parsed[10]),std::stof(parsed[11])};
	materials.insert(materials.end(),
		std::pair<std:string,Material>{parsed[2],{parsed[2],ka,kd,ks,std::stof(parsed[12]});
}

bool sdf_isComment(std::string const& input) {
	std::regex rgx_comment{"^#.*"};
	if(std::regex_match(input, rgx_comment)) {
		return true;
	}
	return false;
}

void sdf_loadScene(std::ifstream& file, Scene& scene) {
	std::string line{""};
	while(std::getline(file,line)) {
		//Comment
		if(sdf_isComment(line)) {
			continue;
		}
		// Material
		//Material* tmp_material{nullptr};
		if(sdf_isMaterial(line)) {
			sdf_parseMaterial(line,scene.materials);
			//scene.materials.push_back(tmp_material);
			continue;
		}
	}
}

#endif
<commit_msg>try fix sdfloader the third<commit_after>#ifndef BUW_SDFLOADER_HPP
#define BUW_SDFLOADER_HPP

#include <string>
#include <scene.hpp>
#include <iostream>
#include <fstream>
#include <vector>
#include <regex>

void sdf_splitString(std::string const& input, std::vector<std::string>& output) {
	std::istringstream tmp{input};
	do {
		std::string sub{""};
		tmp >> sub;
		output.push_back(sub);
	} while(tmp);
}

bool sdf_isMaterial(std::string const& input) {
	std::regex rgx_material{"define[\\s\\t]material[\\s\\t]\\S+[\\s\\t]([0-9][\\s\\t]){9}[0-9].*"};
	if(std::regex_match(input,rgx_material)) {
		return true;
	}
	return false;
}

void sdf_parseMaterial(std::string const& input, std::map<std::string,Material>& materials) {
	std::vector<std::string> parsed;
	sdf_splitString(input,parsed);
	Color ka = {std::stof(parsed[3]),std::stof(parsed[4]),std::stof(parsed[5])};
	Color kd = {std::stof(parsed[6]),std::stof(parsed[7]),std::stof(parsed[8])};
	Color ks = {std::stof(parsed[9]),std::stof(parsed[10]),std::stof(parsed[11])};
	materials.insert(materials.end(),
		std::pair<std:string,Material>{parsed[2],{parsed[2],ka,kd,ks,std::stof(parsed[12]});
}

bool sdf_isComment(std::string const& input) {
	std::regex rgx_comment{"^#.*"};
	if(std::regex_match(input, rgx_comment)) {
		return true;
	}
	return false;
}

void sdf_loadScene(std::ifstream& file, Scene& scene) {
	std::string line{""};
	while(std::getline(file,line)) {
		//Comment
		if(sdf_isComment(line)) {
			continue;
		}
		// Material
		//Material* tmp_material{nullptr};
		if(sdf_isMaterial(line)) {
			sdf_parseMaterial(line,scene.materials);
			//scene.materials.push_back(tmp_material);
			continue;
		}
	}
}

#endif
<|endoftext|>


<commit_before>#include <QCoreApplication>
#include <QDebug>
#include <QUrl>
#include <QUrlQuery>
#include <QMessageBox>

#include "isichazamazwi.h"
#include "ui_isichazamazwi.h"

#include "nt_operations.h"
#include "db_operations.h"

isichazamazwi::isichazamazwi(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::isichazamazwi)
{
    ui->setupUi(this);
    ui->rbtn_google->setChecked(true);
    ui->menuTranslator->addAction(tr("Exit"),this, SLOT(exit()), tr("Alt+F4"));
    ui->menuTranslator->addAction(tr("Offline Mode"),this, SLOT(offline()));
    ui->btn_save_it->setVisible(false);

    trayMenu = new QMenu(this);
    trayMenu->addAction(tr("Exit"),this, SLOT(exit()));

    trayIcon = new QSystemTrayIcon(this);
    trayIcon->setIcon(QIcon("../../Files/try.png"));
    trayIcon->setContextMenu(trayMenu);

    trayIcon->show();
    trayIcon->showMessage("isichazamazwi", "Dictionary is started!..",QSystemTrayIcon::Information, 2510);

}

isichazamazwi::~isichazamazwi()
{
    delete ui;
}
void isichazamazwi::exit()
{
    close();
    qApp->quit();
}

void print_message_box(QString text)
{
    QMessageBox Msgbox;
    Msgbox.setText(text);
    Msgbox.setStandardButtons(QMessageBox::Ok);
    Msgbox.exec();
}

void isichazamazwi::offline()
{
    isichazamazwi::offlineMode = true;

    trayIcon->showMessage("isichazamazwi", "Your dictionary run offline mode!..",QSystemTrayIcon::Information, 2510);
    QWidget::setWindowTitle("isichazamazwi (offline mode)");

}

QString parse_http(QString &src)
{
    try {
        src = QString("...");

    } catch (...) {

    }

    return src;
}

void isichazamazwi::on_btn_translate_clicked()
{
    int type;

    if(ui->rbtn_google->isChecked())
        type = 0;
    else if(ui->rbtn_yandex->isChecked())
        type = 1;
    else if (ui->rbtn_bing->isChecked())
        type = 2;
    else
        type = -1;

    QString src = ui->txt_source->text();
    QString dest =send_http_request(src,type);
    parse_http(dest);

    ui->txt_destination->setText(QString::number(type));
    ui->btn_save_it->setVisible(true);
    ui->btn_translate->setVisible(false);

}

void isichazamazwi::on_btn_save_it_clicked()
{
    try {

        db_operations db("isichazamazwi.db");
        db.insert_word(ui->txt_source->text(),ui->txt_destination->text(),2);

    } catch (...) {
        return;
    }

    print_message_box("your word ("+ ui->txt_source->text() + ") added \nlocal dictionary!..");

}

void isichazamazwi::on_rbtn_google_clicked()
{
    ui->btn_save_it->setVisible(false);
    ui->btn_translate->setVisible(true);
}

void isichazamazwi::on_rbtn_yandex_clicked()
{
    ui->btn_save_it->setVisible(false);
    ui->btn_translate->setVisible(true);
}

void isichazamazwi::on_rbtn_bing_clicked()
{
    ui->btn_save_it->setVisible(false);
    ui->btn_translate->setVisible(true);
}
<commit_msg>Online|Ofline switch mode added<commit_after>#include <QCoreApplication>
#include <QDebug>
#include <QUrl>
#include <QUrlQuery>
#include <QMessageBox>

#include "isichazamazwi.h"
#include "ui_isichazamazwi.h"

#include "nt_operations.h"
#include "db_operations.h"

isichazamazwi::isichazamazwi(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::isichazamazwi)
{
    ui->setupUi(this);
    ui->rbtn_google->setChecked(true);
    ui->menuTranslator->addAction(tr("Exit"),this, SLOT(exit()), tr("Alt+F4"));
    ui->menuTranslator->addAction(tr("Offline|Online Mode"),this, SLOT(offline()));
    ui->btn_save_it->setVisible(false);

    trayMenu = new QMenu(this);
    trayMenu->addAction(tr("Exit"),this, SLOT(exit()));

    trayIcon = new QSystemTrayIcon(this);
    trayIcon->setIcon(QIcon("../../Files/try.png"));
    trayIcon->setContextMenu(trayMenu);

    trayIcon->show();
    trayIcon->showMessage("isichazamazwi", "Dictionary is started!..",QSystemTrayIcon::Information, 2510);

}

isichazamazwi::~isichazamazwi()
{
    delete ui;
}
void isichazamazwi::exit()
{
    close();
    qApp->quit();
}

void print_message_box(QString text)
{
    QMessageBox Msgbox;
    Msgbox.setText(text);
    Msgbox.setStandardButtons(QMessageBox::Ok);
    Msgbox.exec();
}

void isichazamazwi::offline()
{
    if(!isichazamazwi::offlineMode)
    {
        isichazamazwi::offlineMode = true;
        trayIcon->showMessage("isichazamazwi", "Your dictionary run offline mode!..",QSystemTrayIcon::Information, 2510);
        QWidget::setWindowTitle("isichazamazwi (offline mode)");
    }
    else
    {
        isichazamazwi::offlineMode = false;
        trayIcon->showMessage("isichazamazwi", "Your dictionary run online mode!..",QSystemTrayIcon::Information, 2510);
        QWidget::setWindowTitle("isichazamazwi");
    }

}

QString parse_http(QString &src)
{
    try {
        src = QString("...");

    } catch (...) {

    }

    return src;
}

void isichazamazwi::on_btn_translate_clicked()
{
    int type;

    if(ui->rbtn_google->isChecked())
        type = 0;
    else if(ui->rbtn_yandex->isChecked())
        type = 1;
    else if (ui->rbtn_bing->isChecked())
        type = 2;
    else
        type = -1;

    QString src = ui->txt_source->text();
    QString dest =send_http_request(src,type);
    parse_http(dest);

    ui->txt_destination->setText(QString::number(type));
    ui->btn_save_it->setVisible(true);
    ui->btn_translate->setVisible(false);

}

void isichazamazwi::on_btn_save_it_clicked()
{
    try {

        db_operations db("isichazamazwi.db");
        db.insert_word(ui->txt_source->text(),ui->txt_destination->text(),2);

    } catch (...) {
        return;
    }

    print_message_box("your word ("+ ui->txt_source->text() + ") added \nlocal dictionary!..");

}

void isichazamazwi::on_rbtn_google_clicked()
{
    ui->btn_save_it->setVisible(false);
    ui->btn_translate->setVisible(true);
}

void isichazamazwi::on_rbtn_yandex_clicked()
{
    ui->btn_save_it->setVisible(false);
    ui->btn_translate->setVisible(true);
}

void isichazamazwi::on_rbtn_bing_clicked()
{
    ui->btn_save_it->setVisible(false);
    ui->btn_translate->setVisible(true);
}
<|endoftext|>


<commit_before>/** @file debug_log.hpp
 *
 * @brief Debug logging facilities
 *
 * @author Matthew Harvey
 * @date 01 September 2013
 *
 * Copyright (c) 2013, Matthew Harvey. All rights reserved.
 *
 * @todo Documentation and testing.
 */

#ifndef GUARD_debug_log_hpp
#define GUARD_debug_log_hpp

#include <iostream>

namespace jewel
{

class Log
{
public:
	enum Level
	{
		trace,
		info,
		debug,
		warning,
		error,
		fatal
	};

	static Level threshold()
	{
		return threshold_aux();
	}

	static void set_threshold(Level p_level)
	{
		threshold_aux() = p_level;
		return;
	}

	static void flush()
	{
		std::clog.flush();
		return;
	}

private:

	static Level& threshold_aux()
	{
		static Level ret = debug;
		return ret;
	}
};

#ifdef DEBUG

	#define JEWEL_TEST_FATAL(level) \
			if (level >= Log::fatal) \
			{ \
				std::clog << "OBITUARY:\t"\
				          << "Application terminated due to Log::fatal." \
				          << std::endl; \
				std::terminate(); \
			}

	#define JEWEL_LOG(level, msg) \
		if (level >= Log::threshold()) \
		{ \
			std::clog << "SEVERITY:\t" << level \
					  << "\tMESSAGE:\t" msg \
					  << "\n"; \
			JEWEL_TEST_FATAL(level); \
		}

	#define JEWEL_LOG_LOCATION(level) \
		if (level >= Log::threshold()) \
		{ \
			std::clog << "SEVERITY:\t" << level \
			          << "\tFUNCTION:\t" << __func__ \
			          << "\tFILE:\t" << __FILE__ \
					  << "\tLINE:\t" << __LINE__ \
					  << "\n"; \
			JEWEL_TEST_FATAL(level); \
		}

	#define JEWEL_LOG_VALUE(level, val) \
		if (level >= Log::threshold()) \
		{ \
			std::clog << "SEVERITY:\t" \
			          << "\tEXPRESSION:\t" << #val \
					  << "\tVALUE:\t" << x \
					  << "\n"; \
			JEWEL_TEST_FATAL(level); \
		}

#else

	#define JEWEL_TEST_FATAL(level) 0
	#define JEWEL_LOG(level, msg) 0
	#define JEWEL_LOG_LOCATION(level) 0
	#define JEWEL_LOG_VALUE(level, val) 0

#endif

}  // namespace jewel

#endif  // GUARD_debug_log_hpp
<commit_msg>Fixed issue in "debug_log.hpp" with namespace / macro interaction.<commit_after>/** @file debug_log.hpp
 *
 * @brief Debug logging facilities
 *
 * @author Matthew Harvey
 * @date 01 September 2013
 *
 * Copyright (c) 2013, Matthew Harvey. All rights reserved.
 *
 * @todo Documentation and testing.
 */

#ifndef GUARD_debug_log_hpp
#define GUARD_debug_log_hpp

#include <iostream>

namespace jewel
{

class Log
{
public:
	enum Level
	{
		trace,
		info,
		debug,
		warning,
		error,
		fatal
	};

	static Level threshold()
	{
		return threshold_aux();
	}

	static void set_threshold(Level p_level)
	{
		threshold_aux() = p_level;
		return;
	}

	static void flush()
	{
		std::clog.flush();
		return;
	}

private:

	static Level& threshold_aux()
	{
		static Level ret = debug;
		return ret;
	}
};

}  // namespace jewel

#ifdef DEBUG

	#define JEWEL_TEST_FATAL(level) \
			if (level >= jewel::Log::fatal) \
			{ \
				std::clog << "OBITUARY:\t"\
				          << "Application terminated due to Log::fatal." \
				          << std::endl; \
				std::terminate(); \
			}

	#define JEWEL_LOG(level, msg) \
		if (level >= jewel::Log::threshold()) \
		{ \
			std::clog << "SEVERITY:\t" << level \
					  << "\tMESSAGE:\t" msg \
					  << "\n"; \
			JEWEL_TEST_FATAL(level); \
		}

	#define JEWEL_LOG_LOCATION(level) \
		if (level >= jewel::Log::threshold()) \
		{ \
			std::clog << "SEVERITY:\t" << level \
			          << "\tFUNCTION:\t" << __func__ \
			          << "\tFILE:\t" << __FILE__ \
					  << "\tLINE:\t" << __LINE__ \
					  << "\n"; \
			JEWEL_TEST_FATAL(level); \
		}

	#define JEWEL_LOG_VALUE(level, val) \
		if (level >= jewel::Log::threshold()) \
		{ \
			std::clog << "SEVERITY:\t" \
			          << "\tEXPRESSION:\t" << #val \
					  << "\tVALUE:\t" << x \
					  << "\n"; \
			JEWEL_TEST_FATAL(level); \
		}

#else

	#define JEWEL_TEST_FATAL(level) 0
	#define JEWEL_LOG(level, msg) 0
	#define JEWEL_LOG_LOCATION(level) 0
	#define JEWEL_LOG_VALUE(level, val) 0

#endif

#endif  // GUARD_debug_log_hpp
<|endoftext|>


<commit_before>
#include <string.h>
#include "atXMLBuffer.h++"

atXMLBuffer::atXMLBuffer(char * xmlName)
{
   // Save the header and footer for this overall XML document
   sprintf(xml_header, "<%s>", xmlName);
   sprintf(xml_footer, "</%s>", xmlName);

   // Initialize the internal XML buffer length
   xml_buffer_size = 0;

   // Initialize the xml DTD (we aren't using one in this case and also
   // don't need a context then)
   xml_dtd = NULL;

   // Initialize the documents buffer (we will collect any documents
   // from the XML elements into this list and send them back)
   xml_document_list = new atList();
}

atXMLBuffer::atXMLBuffer(char * xmlName, char * dtdFilename)
{
   // Save the header and footer for this overall XML document
   sprintf((char *) xml_header, "<%s>", xmlName);
   sprintf((char *) xml_footer, "</%s>", xmlName);

   // Initialize the internal XML buffer length
   xml_buffer_size = 0;

   // Open and initialize the DTD file (used for validating XML)
   xml_dtd = xmlParseDTD(NULL, (const xmlChar *) dtdFilename);

   // Initialize the XML context information (used during XML validation
   // to print warnings and errors)
   xml_context.userData = stderr;
   xml_context.error = (xmlValidityErrorFunc ) fprintf;
   xml_context.warning = (xmlValidityWarningFunc ) fprintf;

   // Initialize the documents buffer (we will collect any documents
   // from the XML elements into this list and send them back)
   xml_document_list = new atList();
}

atXMLBuffer::~atXMLBuffer()
{
   // Free up the DTD if we created it
   if (xml_dtd != NULL)
      xmlFreeDtd(xml_dtd);

   // Free up XML document list
   if (xml_document_list != NULL)
      delete xml_document_list;
}

void atXMLBuffer::processXMLDocument()
{
   xmlDocPtr         doc;
   xmlNodePtr        current;
   char              fullHeader[256];
   xmlChar *         version;
   atXMLDocument *   xmlDoc;

   // Open the memory buffer as an XML document
   doc = xmlParseMemory((const char *) xml_buffer, xml_buffer_size);

   // Check to make sure the XML library understood the buffer
   if (doc == NULL)
   {
      // We didn't recognize the XML at all so warn the user and bail out
      notify(AT_WARN, "XML document not parsed successfully.\n");
      xmlFreeDoc(doc);
      return;
   }

   // Check to see if we're checking the XML against the DTD
   if (xml_dtd != NULL)
   {
      // We are so go ahead and validate the XML against the DTD
      if (xmlValidateDtd(&xml_context, doc, xml_dtd) == 0)
      {
         // The document failed the DTD check so warn the user and bail out
         notify(AT_WARN, "XML document not valid.\n");
         xmlFreeDoc(doc);
         return;
      }
   }

   // Ok, now let's get the XML root element (all non-empty XML documents
   // have a root)
   current = xmlDocGetRootElement(doc);

   // Check to see if we got something in the root (i.e. it's not an
   // empty document)
   if (current == NULL)
   {
      notify(AT_WARN, "XML document is empty.\n");
      xmlFreeDoc(doc);
      return;
   }

   // Now, check to make sure the root element is the header
   // (all XML documents start with the header and end with the footer
   sprintf(fullHeader, "<%s>", current->name);
   if (xmlStrcmp((xmlChar *) fullHeader, (xmlChar *) xml_header))
   {
      notify(AT_WARN, "XML document is of wrong type.\n");
      xmlFreeDoc(doc);
      return;
   }

   // Get the version of XML we're using from the header
   // (later on, we'll assume that NULL means 1.0)
   version = xmlGetProp(current, (const xmlChar *) "version");

   // The document is "certified" so add the document to the document list
   xmlDoc = new atXMLDocument((atXMLDocumentDocPtr ) doc);
   xml_document_list->addEntry(xmlDoc);

   // We're done so free the stuff we're required to free ourselves.  We
   // added the document itself to the list so we'll assume it's deallocated
   // later.
   xmlFree(version);
}

atList * atXMLBuffer::processBuffer(atBufferHandler * packetBuffer)
{
   u_char *   buffer;
   u_long     lengthRead;
   u_char *   nextNull;
   u_char *   newBuffer;
   atItem *   item;
   u_char *   endTag;
   int        partialChunkSize;
   int        numWhiteSpace;
   char       header[255];

   // Get the info from this buffer
   packetBuffer->retrieveBuffer(&buffer, &lengthRead);

   // Go through and eradicate NULL characters (the XML library will
   // consider it the end of the document)
   nextNull = (u_char *) memchr(buffer, '\0', lengthRead);
   while (nextNull != NULL)
   {
      // Slide the buffer up one to get rid of this NULL
      memmove(nextNull, nextNull+1, lengthRead - (nextNull - buffer));
      lengthRead--;

      // Find the next NULL
      nextNull = (u_char *) memchr(buffer, '\0', lengthRead);
   }

   // Allocate a buffer to hold this buffer and left over from the last pass
   newBuffer = (u_char *) calloc(xml_buffer_size+lengthRead+1, sizeof(u_char));
   if (newBuffer == NULL)
   {
      // We failed to allocate space (bad!) so assume we have nothing
      notify(AT_WARN, "Failed to allocate space for combining buffers.\n");
      lengthRead = 0;
   }
   else
   {
      // Stick any partial buffer that was saved last go around in front
      // of the new buffer (this is necessary to cover the case when the
      // end tag footer gets split between packets)
      memcpy(newBuffer, xml_buffer, xml_buffer_size);
      memcpy(&newBuffer[xml_buffer_size], buffer, lengthRead);
      lengthRead += xml_buffer_size;
      xml_buffer_size = 0;
   }

   // Make a string out of the buffer
   newBuffer[lengthRead] = '\0';

   // We will build up each recognized XML document and add it to a list
   // to return to the user so we need to clear it first (so go through
   // each list item in the list now and remove it)
   item = xml_document_list->getFirstEntry();
   while (item != NULL)
   {
      // Remove this list item
      xml_document_list->removeCurrentEntry();

      // Delete this list item to free up the memory since we're done
      // with it
      delete item;

      // Get the first node again (if there is one)
      item = xml_document_list->getFirstEntry();
   }

   // Check if we see the ending footer
   endTag = (u_char *) strstr((const char *) newBuffer, xml_footer);
   if (endTag != NULL)
   {
      // We need to loop in case there are multiple documents within
      // the buffer
      while (endTag != NULL)
      {
         // Copy through the ending footer to the internal
         // collected xml buffer
         partialChunkSize = (endTag - &newBuffer[0]) + strlen(xml_footer);
         memcpy(&xml_buffer[xml_buffer_size], newBuffer, partialChunkSize);
         xml_buffer_size += partialChunkSize;

         // Delete the part we just used (+1 for the NULL we tacked on)
         memmove(&newBuffer[0], &newBuffer[partialChunkSize],
                 lengthRead - partialChunkSize + 1);
         lengthRead -= partialChunkSize;

         // Eliminate any leading white space lines left in the buffer
         numWhiteSpace = strspn((const char *) newBuffer, " \r\n\t");
         if ( (numWhiteSpace > 0) && (numWhiteSpace <= lengthRead) )
         {
            // Move up the remaining part of the buffer (+1 for the NULL
            // we tacked on)
            memmove(&newBuffer[0], &newBuffer[numWhiteSpace],
                    (lengthRead - numWhiteSpace + 1) * sizeof(u_char));
            lengthRead -= numWhiteSpace;
         }

         // Process the document
         processXMLDocument();

         // Clear the internal xml buffer
         xml_buffer_size = 0;

         // See if there is another footer (in case there are two
         // or more within the buffer)
         endTag = (u_char *) strstr((const char *) newBuffer, xml_footer);
      }

      // Store remaining chunk (if any) in internal collected xml buffer
      if (lengthRead > 0)
      {
         // Copy remaining chunk into xml buffer and initialize
         // size to size of that remaining chunk
         memcpy(&xml_buffer[0], &newBuffer[0], lengthRead);
         xml_buffer_size = lengthRead;
      }
      else
      {
         // Nothing left in buffer so just initialize xml buffer
         xml_buffer[0] = '\0';
         xml_buffer_size = 0;
      }
   }
   else
   {
      // No ending found so just add what we received to the
      // internal collected xml buffer
      memcpy(&xml_buffer[xml_buffer_size], newBuffer, lengthRead);
      xml_buffer_size += lengthRead;
   }

   // Free the temporary buffer
   if (newBuffer != NULL)
      free(newBuffer);

   // Return the list of documents that were collected
   return xml_document_list;
}

<commit_msg>Clean up some type casting.<commit_after>
#include <string.h>
#include "atXMLBuffer.h++"

atXMLBuffer::atXMLBuffer(char * xmlName)
{
   // Save the header and footer for this overall XML document
   sprintf(xml_header, "<%s>", xmlName);
   sprintf(xml_footer, "</%s>", xmlName);

   // Initialize the internal XML buffer length
   xml_buffer_size = 0;

   // Initialize the xml DTD (we aren't using one in this case and also
   // don't need a context then)
   xml_dtd = NULL;

   // Initialize the documents buffer (we will collect any documents
   // from the XML elements into this list and send them back)
   xml_document_list = new atList();
}

atXMLBuffer::atXMLBuffer(char * xmlName, char * dtdFilename)
{
   // Save the header and footer for this overall XML document
   sprintf((char *) xml_header, "<%s>", xmlName);
   sprintf((char *) xml_footer, "</%s>", xmlName);

   // Initialize the internal XML buffer length
   xml_buffer_size = 0;

   // Open and initialize the DTD file (used for validating XML)
   xml_dtd = xmlParseDTD(NULL, (const xmlChar *) dtdFilename);

   // Initialize the XML context information (used during XML validation
   // to print warnings and errors)
   xml_context.userData = stderr;
   xml_context.error = (xmlValidityErrorFunc ) fprintf;
   xml_context.warning = (xmlValidityWarningFunc ) fprintf;

   // Initialize the documents buffer (we will collect any documents
   // from the XML elements into this list and send them back)
   xml_document_list = new atList();
}

atXMLBuffer::~atXMLBuffer()
{
   // Free up the DTD if we created it
   if (xml_dtd != NULL)
      xmlFreeDtd(xml_dtd);

   // Free up XML document list
   if (xml_document_list != NULL)
      delete xml_document_list;
}

void atXMLBuffer::processXMLDocument()
{
   xmlDocPtr         doc;
   xmlNodePtr        current;
   char              fullHeader[256];
   xmlChar *         version;
   atXMLDocument *   xmlDoc;

   // Open the memory buffer as an XML document
   doc = xmlParseMemory((const char *) xml_buffer, xml_buffer_size);

   // Check to make sure the XML library understood the buffer
   if (doc == NULL)
   {
      // We didn't recognize the XML at all so warn the user and bail out
      notify(AT_WARN, "XML document not parsed successfully.\n");
      xmlFreeDoc(doc);
      return;
   }

   // Check to see if we're checking the XML against the DTD
   if (xml_dtd != NULL)
   {
      // We are so go ahead and validate the XML against the DTD
      if (xmlValidateDtd(&xml_context, doc, xml_dtd) == 0)
      {
         // The document failed the DTD check so warn the user and bail out
         notify(AT_WARN, "XML document not valid.\n");
         xmlFreeDoc(doc);
         return;
      }
   }

   // Ok, now let's get the XML root element (all non-empty XML documents
   // have a root)
   current = xmlDocGetRootElement(doc);

   // Check to see if we got something in the root (i.e. it's not an
   // empty document)
   if (current == NULL)
   {
      notify(AT_WARN, "XML document is empty.\n");
      xmlFreeDoc(doc);
      return;
   }

   // Now, check to make sure the root element is the header
   // (all XML documents start with the header and end with the footer
   sprintf(fullHeader, "<%s>", current->name);
   if (xmlStrcmp((xmlChar *) fullHeader, (xmlChar *) xml_header))
   {
      notify(AT_WARN, "XML document is of wrong type.\n");
      xmlFreeDoc(doc);
      return;
   }

   // Get the version of XML we're using from the header
   // (later on, we'll assume that NULL means 1.0)
   version = xmlGetProp(current, (const xmlChar *) "version");

   // The document is "certified" so add the document to the document list
   xmlDoc = new atXMLDocument((atXMLDocumentDocPtr ) doc);
   xml_document_list->addEntry(xmlDoc);

   // We're done so free the stuff we're required to free ourselves.  We
   // added the document itself to the list so we'll assume it's deallocated
   // later.
   xmlFree(version);
}

atList * atXMLBuffer::processBuffer(atBufferHandler * packetBuffer)
{
   u_char *   buffer;
   u_long     lengthRead;
   u_char *   nextNull;
   u_char *   newBuffer;
   atItem *   item;
   u_char *   endTag;
   int        partialChunkSize;
   int        numWhiteSpace;

   // Get the info from this buffer
   packetBuffer->retrieveBuffer(&buffer, &lengthRead);

   // Go through and eradicate NULL characters (the XML library will
   // consider it the end of the document)
   nextNull = (u_char *) memchr(buffer, '\0', lengthRead);
   while (nextNull != NULL)
   {
      // Slide the buffer up one to get rid of this NULL
      memmove(nextNull, nextNull+1, lengthRead - (nextNull - buffer));
      lengthRead--;

      // Find the next NULL
      nextNull = (u_char *) memchr(buffer, '\0', lengthRead);
   }

   // Allocate a buffer to hold this buffer and left over from the last pass
   newBuffer = (u_char *) calloc(xml_buffer_size+lengthRead+1, sizeof(u_char));
   if (newBuffer == NULL)
   {
      // We failed to allocate space (bad!) so assume we have nothing
      notify(AT_WARN, "Failed to allocate space for combining buffers.\n");
      lengthRead = 0;
   }
   else
   {
      // Stick any partial buffer that was saved last go around in front
      // of the new buffer (this is necessary to cover the case when the
      // end tag footer gets split between packets)
      memcpy(newBuffer, xml_buffer, xml_buffer_size);
      memcpy(&newBuffer[xml_buffer_size], buffer, lengthRead);
      lengthRead += xml_buffer_size;
      xml_buffer_size = 0;
   }

   // Make a string out of the buffer
   newBuffer[lengthRead] = '\0';

   // We will build up each recognized XML document and add it to a list
   // to return to the user so we need to clear it first (so go through
   // each list item in the list now and remove it)
   item = xml_document_list->getFirstEntry();
   while (item != NULL)
   {
      // Remove this list item
      xml_document_list->removeCurrentEntry();

      // Delete this list item to free up the memory since we're done
      // with it
      delete item;

      // Get the first node again (if there is one)
      item = xml_document_list->getFirstEntry();
   }

   // Check if we see the ending footer
   endTag = (u_char *) strstr((const char *) newBuffer, xml_footer);
   if (endTag != NULL)
   {
      // We need to loop in case there are multiple documents within
      // the buffer
      while (endTag != NULL)
      {
         // Copy through the ending footer to the internal
         // collected xml buffer
         partialChunkSize = (int ) (endTag - &newBuffer[0]) +
                            (int ) strlen(xml_footer);
         memcpy(&xml_buffer[xml_buffer_size], newBuffer, partialChunkSize);
         xml_buffer_size += partialChunkSize;

         // Delete the part we just used (+1 for the NULL we tacked on)
         memmove(&newBuffer[0], &newBuffer[partialChunkSize],
                 lengthRead - partialChunkSize + 1);
         lengthRead -= partialChunkSize;

         // Eliminate any leading white space lines left in the buffer
         numWhiteSpace = (int ) strspn((const char *) newBuffer, " \r\n\t");
         if ( (numWhiteSpace > 0) && (numWhiteSpace <= lengthRead) )
         {
            // Move up the remaining part of the buffer (+1 for the NULL
            // we tacked on)
            memmove(&newBuffer[0], &newBuffer[numWhiteSpace],
                    (lengthRead - numWhiteSpace + 1) * sizeof(u_char));
            lengthRead -= numWhiteSpace;
         }

         // Process the document
         processXMLDocument();

         // Clear the internal xml buffer
         xml_buffer_size = 0;

         // See if there is another footer (in case there are two
         // or more within the buffer)
         endTag = (u_char *) strstr((const char *) newBuffer, xml_footer);
      }

      // Store remaining chunk (if any) in internal collected xml buffer
      if (lengthRead > 0)
      {
         // Copy remaining chunk into xml buffer and initialize
         // size to size of that remaining chunk
         memcpy(&xml_buffer[0], &newBuffer[0], lengthRead);
         xml_buffer_size = lengthRead;
      }
      else
      {
         // Nothing left in buffer so just initialize xml buffer
         xml_buffer[0] = '\0';
         xml_buffer_size = 0;
      }
   }
   else
   {
      // No ending found so just add what we received to the
      // internal collected xml buffer
      memcpy(&xml_buffer[xml_buffer_size], newBuffer, lengthRead);
      xml_buffer_size += lengthRead;
   }

   // Free the temporary buffer
   if (newBuffer != NULL)
      free(newBuffer);

   // Return the list of documents that were collected
   return xml_document_list;
}

<|endoftext|>


<commit_before>/*
 * fMBT, free Model Based Testing tool
 * Copyright (c) 2011, Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU Lesser General Public License,
 * version 2.1, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
 * more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */
#include "adapter_mapper.hh"
#include "model.hh"
#include "dparse.h"
#include <cstring>
#include <unistd.h>
#include "helper.hh"
#include "conf.hh"

#include <sstream>
#include <iostream>
#ifndef DROI
#include <boost/regex.hpp>
#endif

extern "C" {
extern D_ParserTables parser_tables_mrules;
}

extern Rules* amobj;

Adapter_mapper::Adapter_mapper(Log& log, std::string _params)
  : Adapter(log), Rules(), params(_params)
{
  robin=0;

}

Adapter_mapper::~Adapter_mapper()
{
  for(unsigned i=0;i<adapters.size();i++) {
    delete adapters[i];
  }
}
bool Adapter_mapper::init()
{
  load(params);
  if (!status) {
    return false;
  }
  for(unsigned i=0;i<adapters.size();i++) {
    if (adapters[i]) {
      if (!adapters[i]->init()) {
        return false;
      }
    }
  }
  return true;
}

std::string Adapter_mapper::stringify()
{
  std::ostringstream t(std::ios::out | std::ios::binary);

  /* Write adapters */

  for(unsigned i=1;i<adapters.size();i++) {
    if (adapters[i]) {
      t << i << "=\"" << removehash(adapter_names[i])
	<< capsulate(adapters[i]->stringify()) << std::endl;
    }
  }

  t << std::endl;
  /*
  for(std::map<int,adapter_action>::iterator it=m2.begin();
      it!=m2.end();it++) {
  */
  for(unsigned j=0;j<actions->size();j++) {
    std::map<int,adapter_action>::iterator it=m2.find(j);
    if (it!=m2.end()) {
      adapter_action a=it->second;
      int i=it->first;

      t << "\"" << (*actions)[i] << "\" -> ("
	<< a.first << ", \""
	<< adapter_anames[a.first][a.second]
	<< "\")" << std::endl;
    }
  }

  return t.str();
}

int Adapter_mapper::anum_create(int index,std::string& n) {

  for(unsigned int i=0;i<adapter_anames[index].size();i++) {
    if (adapter_anames[index][i]==n) {
      return i;
    }
  }

  if (adapter_anames[index].empty()) {
    std::string tau("");
    adapter_anames[index].push_back(tau);
  }

  adapter_anames[index].push_back(n);
  return adapter_anames[index].size()-1;
}

void Adapter_mapper::add_map(std::vector<int>& index,std::vector<std::string>& n,int action) {

  if (!status) {
    return;
  }
  int anum = anum_create(index[0],n[0]);

  log.debug("%s(%i,%s,%i) %i\n",__func__,index[0],n[0].c_str(),action,anum);

  adapter_action a(index[0],anum);
  if (!is_used(action) && !is_used(a)) {
    m1[a]=action;
    m2[action]=a;
    for(unsigned u=1;u<index.size();u++) {
      int bnum = anum_create(index[u],n[u]);
      adapter_action b(index[u],bnum);
      log.debug("%s(%i,%s,%i) %i",__func__,index[u],n[u].c_str(),action,bnum);
      if (l_tau[u]) {
	_tm2.insert(std::pair<int,adapter_action>(action,b));
      } else {
	_fm2.insert(std::pair<int,adapter_action>(action,b));
      }
    }
  } else {
    //log.debug("Error in '%s': ", load_name.c_str());
    if (is_used(action)) {
      errormsg=std::string("duplicate action on the model side: \"")+(*actions)[action]+std::string("\"");
    } else { //  is_used(a)
      errormsg=std::string("duplicate action on the adapter side: \"")+(*actions)[action]+std::string("\"");
    }
    status=false;
  }
  log.debug("%s ready",__func__);
}

bool Adapter_mapper::load(std::string& name)
{
  D_Parser *p = new_D_Parser(&parser_tables_mrules, 16);
  p->loc.pathname = name.c_str();
  char *s;

  log.debug("%s called",__func__);

  load_name = name;

  Rules* tmp=amobj;

  amobj=this;

  s=readfile(name.c_str());

  bool ret=dparse(p,s,std::strlen(s));

  ret=p->syntax_errors==0 && ret;

  if (ret && status) {
    log.debug("loading %s ok",name.c_str());
  } else {
    log.debug("loading %s failed",name.c_str());
    errormsg=std::string("Loading file \"")+name+std::string("\" failed");
    status=false;
    return status;
  }

  free(s);

  free_D_Parser(p);

  amobj=tmp;

  /* Time to load adapters */

  for(unsigned int i=0;i<adapter_names.size()&&status;i++) {
    if (adapter_names[i]!=std::string("")) {

      log.debug("Loading adapter \"%s\"",
             adapter_names[i].c_str());

      std::string adapter_class;
      std::string adapter_params;

      split(adapter_names[i],adapter_class,adapter_params);

      log.debug("class %s, params %i",
             adapter_class.c_str(),
             adapter_params.c_str());

      Adapter* a = AdapterFactory::create(log, adapter_class,
                                          adapter_params);

      if (!a || !a->status) {
	status=false;
	errormsg=std::string("Can't create adapter ")
	  + adapter_class + ":"+adapter_params;
      } else {
	a->set_actions(&adapter_anames[i]);
	log.debug("Created adapter to %p",a);
	a->setparent(this);
	adapters[i] = a;
	if (!a->status) {
	  status=false;
	  errormsg=a->errormsg;
	}
      }
    }
  }

  return status;
}

bool Adapter_mapper::is_used(int action)
{
  return (m2.find(action) != m2.end());
}

bool Adapter_mapper::is_used(adapter_action& action)
{
  return (m1.find(action)!=m1.end());
}

void Adapter_mapper::add_file(unsigned index, std::string& adaptername)
{
  log.debug("%s(%i,%s)",__func__,index,adaptername.c_str());
  if (adapter_names.capacity()<=index) {
    adapter_names.resize(index+2);
    adapter_anames.resize(index+2);
    adapters.resize(index+2);
  }
  adapter_names[index]=std::string(adaptername);
}

int Adapter_mapper::action_number(std::string& name)
{
  for(size_t i=0;i<actions->size();i++) {
    if ((*actions)[i]==name) {
      return i;
    }
  }
  return -1;
}

/*
 * Adds result action (We'll assume that there are at lest one
 * component)
 *
 */
void Adapter_mapper::add_result_action(std::string* name)
{
  if (!status) {
    return;
  }
  int action=action_number(*name);

  log.debug("%s(%s) called",__func__,name->c_str());

  if (action==-1) {
#ifndef DROI
    /* try regexp case */
    log.debug("Regexp case");
    const char* format_string = l_name[0].c_str();

    log.debug("Format string \"%s\"",format_string);

    boost::regex expression(*name);
    boost::cmatch what;

    for(unsigned int i=1;i<actions->size();i++) {
      log.debug("Action %s",(*actions)[i].c_str());
      if(boost::regex_match((*actions)[i].c_str(), what, expression)) {
        /* Match */
        if (!is_used(i)) {
	  std::vector<std::string> s;

	  if (l_index.size()!=l_name.size()) {
	    abort();
	  }

	  for(unsigned j=0;j<l_index.size();j++) {
	    s.push_back(replace(expression,
				l_name[j].c_str(),
				(*actions)[i].begin(),
				(*actions)[i].end()));
	  }
          add_map(l_index,s,i);
        } else {
          log.debug("action %s already used, won't add it again.");
        }
      }
    }
#endif
  } else {
    add_map(l_index,l_name,action);
  }
  l_index.resize(0);
  l_name.resize(0);
  l_tau.resize(0);
}

void Adapter_mapper::add_component(unsigned int index,std::string& name, bool tau)
{
  if (!status) {
    return;
  }
  /* Validate index */
  log.debug("%s(%i,%s)",__func__,index,name.c_str());

  if (index>=adapter_names.size() || adapter_names[index]==std::string("")) {

    log.debug("adapter_names.size() %i,"
           "adapter_names[index] \"%s\"",
           adapter_names.size(),adapter_names[index].c_str());

    log.debug("%s\n%s\n",
           adapter_names[1].c_str(),
           adapter_names[2].c_str());

    errormsg=std::string("index ") + to_string(index) + std::string(" out of bounds");
    status=false;
  }

  l_name.push_back(name);
  l_index.push_back(index);
  l_tau.push_back(tau);
}

int Adapter_mapper::adapter_action_execute(adapter_action& a)
{
  log.print("<redirect id=\"%i\" name=\"%s\" action=\"%s\"/>\n",
            a.first,adapter_names[a.first].c_str(),adapter_anames[a.first][a.second].c_str());

  std::vector<int> f;
  f.push_back(a.second);

  adapters[a.first]->execute(f);
  return f[0];
}

int Adapter_mapper::map_execute(adapter_action& a)
{
  /* redirect to correct adapter */
  log.debug("execute with adapter %i (%s) action %i (%s)\n",
         a.first,adapter_names[a.first].c_str(),a.second,
         adapter_anames[a.first][a.second].c_str());

  log.print("<redirect id=\"%i\" name=\"%s\" action=\"%s\"/>\n",
            a.first,adapter_names[a.first].c_str(),adapter_anames[a.first][a.second].c_str());

  std::vector<int> f;
  f.push_back(a.second);

  adapters[a.first]->execute(f);
  m1_convert(a.first,f);
  return f[0];
}

bool Adapter_mapper::map_execute(int& action)
{
  adapter_action a=m2[action];

  if (a.first==0) { /* No such action map? */
    log.debug("execute without adapter: %i (action not mapped to any adapter)\n",action);
    return false;
  }

  action=map_execute(a);

  return true;
}

void Adapter_mapper::execute(std::vector<int>& action)
{
  log.push("adapter_mapper");
  /* Output Actions for each component */

  bool tau=false;

  if (map_execute(action[0])) {
    std::pair<std::multimap<int,adapter_action>::iterator,
      std::multimap<int,adapter_action>::iterator> r =
      _tm2.equal_range(action[0]);
    adapter_action a;

    for(std::multimap<int,adapter_action>::iterator i=r.first;
	i!=r.second;i++)
      {
	a=i->second;
	log.debug("execute extras with check adapter %i (%s) action %i (%s)\n",
		  a.first,adapter_names[a.first].c_str(),a.second,
		  adapter_anames[a.first][a.second].c_str());

	// Handle true case
	if (a.second!=
	    adapter_action_execute(a)) {
	  /* ERROR. adapter didn't response as expected */
	  log.print("<configuration failure, returning tau>\n");
	  tau=true;
	}
      }

    r = _fm2.equal_range(action[0]);

    for(std::multimap<int,adapter_action>::iterator i=r.first;
	i!=r.second;i++)
      {
	// Handle false case
	a=i->second;
	log.debug("execute extras without check adapter %i (%s) action %i (%s)\n",
		  a.first,adapter_names[a.first].c_str(),a.second,
		  adapter_anames[a.first][a.second].c_str());

	adapter_action_execute(a);
      }

  }

  if (tau) {
    action.resize(1);
    action[0]=0;
  }

  log.pop();
}

void Adapter_mapper::m1_convert(int index,
				std::vector<int>&action)
{
  for(unsigned i=0;i<action.size();i++) {
    action[i] = m1[adapter_action(index,action[i])];
  }
}

int Adapter_mapper::observeRobin(std::vector<int> &action)
{
  if (adapters.empty()) {
    abort();
  }

  if (robin==adapters.size()) {
    if (silence_cnt==adapters.size()) {
      return SILENCE;
    }

    silence_cnt=0;
    robin=0;

   /* Let's update the current time */
    CHECK_TIMEOUT;

    usleep(sleeptime);
  }

  if (adapters[robin]==NULL) {
    robin++;
    silence_cnt++;
    return observeRobin(action);
  }

  int ret = adapters[robin]->observe(action,false);

  if (ret==SILENCE) {
    silence_cnt++;
  }

  if (ret>0)
    m1_convert(robin,action);

  robin++;
  return ret;
}

int Adapter_mapper::observe(std::vector<int> &action,bool block)
{
  silence_cnt=0;
  adapter_cnt=adapters.size();
  /* Ok. This is a bit hairy */
  do {
    int r=observeRobin(action);
    if (r>0) {
      return r;
    }

    if (r==TIMEOUT) {
      return r;
    }

    if (silence_cnt==adapter_cnt) {
      return SILENCE;
    }

  } while (block);
  return SILENCE;
}

FACTORY_DEFAULT_CREATOR(Adapter, Adapter_mapper, "mapper")
<commit_msg>Fix core dumpping on broken adapter mapping part XXMCI<commit_after>/*
 * fMBT, free Model Based Testing tool
 * Copyright (c) 2011, Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU Lesser General Public License,
 * version 2.1, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
 * more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */
#include "adapter_mapper.hh"
#include "model.hh"
#include "dparse.h"
#include <cstring>
#include <unistd.h>
#include "helper.hh"
#include "conf.hh"

#include <sstream>
#include <iostream>
#ifndef DROI
#include <boost/regex.hpp>
#endif

extern "C" {
extern D_ParserTables parser_tables_mrules;
}

extern Rules* amobj;

Adapter_mapper::Adapter_mapper(Log& log, std::string _params)
  : Adapter(log), Rules(), params(_params)
{
  robin=0;

}

Adapter_mapper::~Adapter_mapper()
{
  for(unsigned i=0;i<adapters.size();i++) {
    delete adapters[i];
  }
}
bool Adapter_mapper::init()
{
  load(params);
  if (!status) {
    return false;
  }
  for(unsigned i=0;i<adapters.size();i++) {
    if (adapters[i]) {
      if (!adapters[i]->init()) {
        return false;
      }
    }
  }
  return true;
}

std::string Adapter_mapper::stringify()
{
  std::ostringstream t(std::ios::out | std::ios::binary);

  /* Write adapters */

  for(unsigned i=1;i<adapters.size();i++) {
    if (adapters[i]) {
      t << i << "=\"" << removehash(adapter_names[i])
	<< capsulate(adapters[i]->stringify()) << std::endl;
    }
  }

  t << std::endl;
  /*
  for(std::map<int,adapter_action>::iterator it=m2.begin();
      it!=m2.end();it++) {
  */
  for(unsigned j=0;j<actions->size();j++) {
    std::map<int,adapter_action>::iterator it=m2.find(j);
    if (it!=m2.end()) {
      adapter_action a=it->second;
      int i=it->first;

      t << "\"" << (*actions)[i] << "\" -> ("
	<< a.first << ", \""
	<< adapter_anames[a.first][a.second]
	<< "\")" << std::endl;
    }
  }

  return t.str();
}

int Adapter_mapper::anum_create(int index,std::string& n) {

  for(unsigned int i=0;i<adapter_anames[index].size();i++) {
    if (adapter_anames[index][i]==n) {
      return i;
    }
  }

  if (adapter_anames[index].empty()) {
    std::string tau("");
    adapter_anames[index].push_back(tau);
  }

  adapter_anames[index].push_back(n);
  return adapter_anames[index].size()-1;
}

void Adapter_mapper::add_map(std::vector<int>& index,std::vector<std::string>& n,int action) {

  if (!status) {
    return;
  }
  int anum = anum_create(index[0],n[0]);

  log.debug("%s(%i,%s,%i) %i\n",__func__,index[0],n[0].c_str(),action,anum);

  adapter_action a(index[0],anum);
  if (!is_used(action) && !is_used(a)) {
    m1[a]=action;
    m2[action]=a;
    for(unsigned u=1;u<index.size();u++) {
      int bnum = anum_create(index[u],n[u]);
      adapter_action b(index[u],bnum);
      log.debug("%s(%i,%s,%i) %i",__func__,index[u],n[u].c_str(),action,bnum);
      if (l_tau[u]) {
	_tm2.insert(std::pair<int,adapter_action>(action,b));
      } else {
	_fm2.insert(std::pair<int,adapter_action>(action,b));
      }
    }
  } else {
    //log.debug("Error in '%s': ", load_name.c_str());
    if (is_used(action)) {
      errormsg=std::string("duplicate action on the model side: \"")+(*actions)[action]+std::string("\"");
    } else { //  is_used(a)
      errormsg=std::string("duplicate action on the adapter side: \"")+(*actions)[action]+std::string("\"");
    }
    status=false;
  }
  log.debug("%s ready",__func__);
}

bool Adapter_mapper::load(std::string& name)
{
  D_Parser *p = new_D_Parser(&parser_tables_mrules, 16);
  p->loc.pathname = name.c_str();
  char *s;

  log.debug("%s called",__func__);

  load_name = name;

  Rules* tmp=amobj;

  amobj=this;

  s=readfile(name.c_str());

  bool ret=dparse(p,s,std::strlen(s));

  ret=p->syntax_errors==0 && ret;

  if (ret && status) {
    log.debug("loading %s ok",name.c_str());
  } else {
    log.debug("loading %s failed",name.c_str());
    errormsg=std::string("Loading file \"")+name+std::string("\" failed");
    status=false;
    return status;
  }

  free(s);

  free_D_Parser(p);

  amobj=tmp;

  /* Time to load adapters */

  for(unsigned int i=0;i<adapter_names.size()&&status;i++) {
    if (adapter_names[i]!=std::string("")) {

      log.debug("Loading adapter \"%s\"",
             adapter_names[i].c_str());

      std::string adapter_class;
      std::string adapter_params;

      split(adapter_names[i],adapter_class,adapter_params);

      log.debug("class %s, params %i",
             adapter_class.c_str(),
             adapter_params.c_str());

      Adapter* a = AdapterFactory::create(log, adapter_class,
                                          adapter_params);

      if (!a || !a->status) {
	status=false;
	errormsg=std::string("Can't create adapter ")
	  + adapter_class + ":"+adapter_params;
      } else {
	a->set_actions(&adapter_anames[i]);
	log.debug("Created adapter to %p",a);
	a->setparent(this);
	adapters[i] = a;
	if (!a->status) {
	  status=false;
	  errormsg=a->errormsg;
	}
      }
    }
  }

  return status;
}

bool Adapter_mapper::is_used(int action)
{
  return (m2.find(action) != m2.end());
}

bool Adapter_mapper::is_used(adapter_action& action)
{
  return (m1.find(action)!=m1.end());
}

void Adapter_mapper::add_file(unsigned index, std::string& adaptername)
{
  log.debug("%s(%i,%s)",__func__,index,adaptername.c_str());
  if (adapter_names.capacity()<=index) {
    adapter_names.resize(index+2);
    adapter_anames.resize(index+2);
    adapters.resize(index+2);
  }
  adapter_names[index]=std::string(adaptername);
}

int Adapter_mapper::action_number(std::string& name)
{
  for(size_t i=0;i<actions->size();i++) {
    if ((*actions)[i]==name) {
      return i;
    }
  }
  return -1;
}

/*
 * Adds result action (We'll assume that there are at lest one
 * component)
 *
 */
void Adapter_mapper::add_result_action(std::string* name)
{
  if (!status) {
    return;
  }
  int action=action_number(*name);

  log.debug("%s(%s) called",__func__,name->c_str());

  if (action==-1) {
#ifndef DROI
    /* try regexp case */
    log.debug("Regexp case");
    if (l_name.empty()) {
      status=false;
      return;
    }
    const char* format_string = l_name[0].c_str();

    log.debug("Format string \"%s\"",format_string);

    boost::regex expression(*name);
    boost::cmatch what;

    for(unsigned int i=1;i<actions->size();i++) {
      log.debug("Action %s",(*actions)[i].c_str());
      if(boost::regex_match((*actions)[i].c_str(), what, expression)) {
        /* Match */
        if (!is_used(i)) {
	  std::vector<std::string> s;

	  if (l_index.size()!=l_name.size()) {
	    abort();
	  }

	  for(unsigned j=0;j<l_index.size();j++) {
	    s.push_back(replace(expression,
				l_name[j].c_str(),
				(*actions)[i].begin(),
				(*actions)[i].end()));
	  }
          add_map(l_index,s,i);
        } else {
          log.debug("action %s already used, won't add it again.");
        }
      }
    }
#endif
  } else {
    add_map(l_index,l_name,action);
  }
  l_index.resize(0);
  l_name.resize(0);
  l_tau.resize(0);
}

void Adapter_mapper::add_component(unsigned int index,std::string& name, bool tau)
{
  if (!status) {
    return;
  }
  /* Validate index */
  log.debug("%s(%i,%s)",__func__,index,name.c_str());

  if (index>=adapter_names.size() || adapter_names[index]==std::string("")) {

    log.debug("adapter_names.size() %i,"
           "adapter_names[index] \"%s\"",
           adapter_names.size(),adapter_names[index].c_str());

    log.debug("%s\n%s\n",
           adapter_names[1].c_str(),
           adapter_names[2].c_str());

    errormsg=std::string("index ") + to_string(index) + std::string(" out of bounds");
    status=false;
  }

  l_name.push_back(name);
  l_index.push_back(index);
  l_tau.push_back(tau);
}

int Adapter_mapper::adapter_action_execute(adapter_action& a)
{
  log.print("<redirect id=\"%i\" name=\"%s\" action=\"%s\"/>\n",
            a.first,adapter_names[a.first].c_str(),adapter_anames[a.first][a.second].c_str());

  std::vector<int> f;
  f.push_back(a.second);

  adapters[a.first]->execute(f);
  return f[0];
}

int Adapter_mapper::map_execute(adapter_action& a)
{
  /* redirect to correct adapter */
  log.debug("execute with adapter %i (%s) action %i (%s)\n",
         a.first,adapter_names[a.first].c_str(),a.second,
         adapter_anames[a.first][a.second].c_str());

  log.print("<redirect id=\"%i\" name=\"%s\" action=\"%s\"/>\n",
            a.first,adapter_names[a.first].c_str(),adapter_anames[a.first][a.second].c_str());

  std::vector<int> f;
  f.push_back(a.second);

  adapters[a.first]->execute(f);
  m1_convert(a.first,f);
  return f[0];
}

bool Adapter_mapper::map_execute(int& action)
{
  adapter_action a=m2[action];

  if (a.first==0) { /* No such action map? */
    log.debug("execute without adapter: %i (action not mapped to any adapter)\n",action);
    return false;
  }

  action=map_execute(a);

  return true;
}

void Adapter_mapper::execute(std::vector<int>& action)
{
  log.push("adapter_mapper");
  /* Output Actions for each component */

  bool tau=false;

  if (map_execute(action[0])) {
    std::pair<std::multimap<int,adapter_action>::iterator,
      std::multimap<int,adapter_action>::iterator> r =
      _tm2.equal_range(action[0]);
    adapter_action a;

    for(std::multimap<int,adapter_action>::iterator i=r.first;
	i!=r.second;i++)
      {
	a=i->second;
	log.debug("execute extras with check adapter %i (%s) action %i (%s)\n",
		  a.first,adapter_names[a.first].c_str(),a.second,
		  adapter_anames[a.first][a.second].c_str());

	// Handle true case
	if (a.second!=
	    adapter_action_execute(a)) {
	  /* ERROR. adapter didn't response as expected */
	  log.print("<configuration failure, returning tau>\n");
	  tau=true;
	}
      }

    r = _fm2.equal_range(action[0]);

    for(std::multimap<int,adapter_action>::iterator i=r.first;
	i!=r.second;i++)
      {
	// Handle false case
	a=i->second;
	log.debug("execute extras without check adapter %i (%s) action %i (%s)\n",
		  a.first,adapter_names[a.first].c_str(),a.second,
		  adapter_anames[a.first][a.second].c_str());

	adapter_action_execute(a);
      }

  }

  if (tau) {
    action.resize(1);
    action[0]=0;
  }

  log.pop();
}

void Adapter_mapper::m1_convert(int index,
				std::vector<int>&action)
{
  for(unsigned i=0;i<action.size();i++) {
    action[i] = m1[adapter_action(index,action[i])];
  }
}

int Adapter_mapper::observeRobin(std::vector<int> &action)
{
  if (adapters.empty()) {
    abort();
  }

  if (robin==adapters.size()) {
    if (silence_cnt==adapters.size()) {
      return SILENCE;
    }

    silence_cnt=0;
    robin=0;

   /* Let's update the current time */
    CHECK_TIMEOUT;

    usleep(sleeptime);
  }

  if (adapters[robin]==NULL) {
    robin++;
    silence_cnt++;
    return observeRobin(action);
  }

  int ret = adapters[robin]->observe(action,false);

  if (ret==SILENCE) {
    silence_cnt++;
  }

  if (ret>0)
    m1_convert(robin,action);

  robin++;
  return ret;
}

int Adapter_mapper::observe(std::vector<int> &action,bool block)
{
  silence_cnt=0;
  adapter_cnt=adapters.size();
  /* Ok. This is a bit hairy */
  do {
    int r=observeRobin(action);
    if (r>0) {
      return r;
    }

    if (r==TIMEOUT) {
      return r;
    }

    if (silence_cnt==adapter_cnt) {
      return SILENCE;
    }

  } while (block);
  return SILENCE;
}

FACTORY_DEFAULT_CREATOR(Adapter, Adapter_mapper, "mapper")
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2018 Cisco and/or its affiliates.
 * 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 "vom/pipe_cmds.hpp"

DEFINE_VAPI_MSG_IDS_PIPE_API_JSON;

namespace VOM {
namespace pipe_cmds {

create_cmd::create_cmd(HW::item<handle_t>& item,
                       const std::string& name,
                       uint32_t instance,
                       HW::item<pipe::handle_pair_t>& ends)
  : interface::create_cmd<vapi::Pipe_create>(item, name)
  , m_hdl_pair(ends)
  , m_instance(instance)
{
}

bool
create_cmd::operator==(const create_cmd& other) const
{
  return (m_name == other.m_name);
}

vapi_error_e
create_cmd::operator()(vapi::Pipe_create& reply)
{
  auto& payload = reply.get_response().get_payload();

  VOM_LOG(log_level_t::DEBUG) << to_string() << " " << payload.retval;

  const rc_t& rc = rc_t::from_vpp_retval(payload.retval);

  m_hdl_pair = { pipe::handle_pair_t(payload.pipe_sw_if_index[0],
                                     payload.pipe_sw_if_index[1]),
                 rc };

  fulfill(HW::item<handle_t>(payload.sw_if_index, rc));

  return (VAPI_OK);
}
rc_t
create_cmd::issue(connection& con)
{
  msg_t req(con.ctx(), std::ref(*this));

  auto& payload = req.get_request().get_payload();

  payload.is_specified = 1;
  payload.user_instance = m_instance;

  VAPI_CALL(req.execute());

  if (rc_t::OK == wait()) {
    insert_interface();
  }

  return rc_t::OK;
}

std::string
create_cmd::to_string() const
{
  std::ostringstream s;

  s << "pipe-create: " << m_name << " instance:" << m_instance;

  return (s.str());
}

delete_cmd::delete_cmd(HW::item<handle_t>& item,
                       HW::item<pipe::handle_pair_t>& end_pair)
  : interface::delete_cmd<vapi::Pipe_delete>(item)
  , m_hdl_pair(end_pair)
{
}

bool
delete_cmd::operator==(const delete_cmd& other) const
{
  return (m_hw_item == other.m_hw_item);
}

rc_t
delete_cmd::issue(connection& con)
{
  msg_t req(con.ctx(), std::ref(*this));

  VAPI_CALL(req.execute());

  wait();
  m_hw_item.set(rc_t::NOOP);
  m_hdl_pair.set(rc_t::NOOP);

  remove_interface();

  return (rc_t::OK);
}

std::string
delete_cmd::to_string() const
{
  return ("pipe-delete");
}

bool
dump_cmd::operator==(const dump_cmd& other) const
{
  return (true);
}

rc_t
dump_cmd::issue(connection& con)
{
  m_dump.reset(new msg_t(con.ctx(), std::ref(*this)));

  VAPI_CALL(m_dump->execute());

  wait();

  return rc_t::OK;
}

std::string
dump_cmd::to_string() const
{
  return ("pipe-dump");
}

} // namespace pipe_cmds
} // namespace VOM

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "mozilla")
 * End:
 */
<commit_msg>vom: Fixes for g++-9<commit_after>/*
 * Copyright (c) 2018 Cisco and/or its affiliates.
 * 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 "vom/pipe_cmds.hpp"

DEFINE_VAPI_MSG_IDS_PIPE_API_JSON;

namespace VOM {
namespace pipe_cmds {

create_cmd::create_cmd(HW::item<handle_t>& item,
                       const std::string& name,
                       uint32_t instance,
                       HW::item<pipe::handle_pair_t>& ends)
  : interface::create_cmd<vapi::Pipe_create>(item, name)
  , m_hdl_pair(ends)
  , m_instance(instance)
{}

bool
create_cmd::operator==(const create_cmd& other) const
{
  return (m_name == other.m_name);
}

vapi_error_e
create_cmd::operator()(vapi::Pipe_create& reply)
{
  auto& payload = reply.get_response().get_payload();

  VOM_LOG(log_level_t::DEBUG) << to_string() << " " << payload.retval;

  const rc_t& rc = rc_t::from_vpp_retval(payload.retval);

  m_hdl_pair = { pipe::handle_pair_t(
                   static_cast<handle_t>(payload.pipe_sw_if_index[0]),
                   static_cast<handle_t>(payload.pipe_sw_if_index[1])),
                 rc };

  fulfill(HW::item<handle_t>(payload.sw_if_index, rc));

  return (VAPI_OK);
}
rc_t
create_cmd::issue(connection& con)
{
  msg_t req(con.ctx(), std::ref(*this));

  auto& payload = req.get_request().get_payload();

  payload.is_specified = 1;
  payload.user_instance = m_instance;

  VAPI_CALL(req.execute());

  if (rc_t::OK == wait()) {
    insert_interface();
  }

  return rc_t::OK;
}

std::string
create_cmd::to_string() const
{
  std::ostringstream s;

  s << "pipe-create: " << m_name << " instance:" << m_instance;

  return (s.str());
}

delete_cmd::delete_cmd(HW::item<handle_t>& item,
                       HW::item<pipe::handle_pair_t>& end_pair)
  : interface::delete_cmd<vapi::Pipe_delete>(item)
  , m_hdl_pair(end_pair)
{}

bool
delete_cmd::operator==(const delete_cmd& other) const
{
  return (m_hw_item == other.m_hw_item);
}

rc_t
delete_cmd::issue(connection& con)
{
  msg_t req(con.ctx(), std::ref(*this));

  VAPI_CALL(req.execute());

  wait();
  m_hw_item.set(rc_t::NOOP);
  m_hdl_pair.set(rc_t::NOOP);

  remove_interface();

  return (rc_t::OK);
}

std::string
delete_cmd::to_string() const
{
  return ("pipe-delete");
}

bool
dump_cmd::operator==(const dump_cmd& other) const
{
  return (true);
}

rc_t
dump_cmd::issue(connection& con)
{
  m_dump.reset(new msg_t(con.ctx(), std::ref(*this)));

  VAPI_CALL(m_dump->execute());

  wait();

  return rc_t::OK;
}

std::string
dump_cmd::to_string() const
{
  return ("pipe-dump");
}

} // namespace pipe_cmds
} // namespace VOM

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "mozilla")
 * End:
 */
<|endoftext|>


<commit_before>// Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved.
#include "stdafx.h"
#include "DispatchQueue.h"
#include "at_exit.h"
#include <assert.h>

dispatch_aborted_exception::dispatch_aborted_exception(const std::string& what):
  autowiring_error(what)
{}

dispatch_aborted_exception::~dispatch_aborted_exception(void){}

DispatchQueue::DispatchQueue(void):
  m_dispatchCap(1024),
  m_aborted(false)
{}

DispatchQueue::~DispatchQueue(void) {
  // Wipe out each entry in the queue, we can't call any of them because we're in teardown
  for(DispatchThunkBase* thunk : m_dispatchQueue)
    delete thunk;

  while (!m_delayedQueue.empty()) {
    DispatchThunkDelayed thunk = m_delayedQueue.top();
    thunk.Reset();
    m_delayedQueue.pop();
  }
}

bool DispatchQueue::PromoteReadyDispatchersUnsafe(void) {
  // Move all ready elements out of the delayed queue and into the dispatch queue:
  size_t nInitial = m_delayedQueue.size();
  for(
    auto now = std::chrono::steady_clock::now();
    !m_delayedQueue.empty() && m_delayedQueue.top().GetReadyTime() < now;
    m_delayedQueue.pop()
  )
    // This item's ready time has elapsed, we can add it to our dispatch queue now:
    m_dispatchQueue.push_back(m_delayedQueue.top().Get());

  // Something was promoted if the dispatch queue size is different
  return nInitial != m_delayedQueue.size();
}

void DispatchQueue::DispatchEventUnsafe(std::unique_lock<std::mutex>& lk) {
  // Pull the ready thunk off of the front of the queue and pop it while we hold the lock.
  // Then, we will excecute the call while the lock has been released so we do not create
  // deadlocks.
  std::unique_ptr<DispatchThunkBase> thunk(m_dispatchQueue.front());
  m_dispatchQueue.pop_front();
  bool wasEmpty = m_dispatchQueue.empty();
  lk.unlock();

  MakeAtExit(
    [this, wasEmpty] {
      // If we emptied the queue, we'd like to reobtain the lock and tell everyone
      // that the queue is now empty.
      if(wasEmpty)
        m_queueUpdated.notify_all();
    }
  ),
  (*thunk)();
}

void DispatchQueue::Abort(void) {
  std::lock_guard<std::mutex> lk(m_dispatchLock);
  m_aborted = true;

  // Do not permit any more lambdas to be pended to our queue:
  m_dispatchCap = 0;

  // Destroy the whole dispatch queue:
  while(!m_dispatchQueue.empty()) {
    delete m_dispatchQueue.front();
    m_dispatchQueue.pop_front();
  }

  // Wake up anyone who is still waiting:
  m_queueUpdated.notify_all();
}

void DispatchQueue::WaitForEvent(void) {
  std::unique_lock<std::mutex> lk(m_dispatchLock);
  if (m_aborted)
    throw dispatch_aborted_exception("Dispatch queue was aborted while waiting for an event");

  // Unconditional delay:
  m_queueUpdated.wait(lk, [this]() -> bool {
    if (m_aborted)
      throw dispatch_aborted_exception("Dispatch queue was aborted while waiting for an event");

    return
      // We will need to transition out if the delay queue receives any items:
      !this->m_delayedQueue.empty() ||

      // We also transition out if the dispatch queue has any events:
      !this->m_dispatchQueue.empty();
  });

  if (m_dispatchQueue.empty()) {
    // The delay queue has items but the dispatch queue does not, we need to switch
    // to the suggested sleep timeout variant:
    WaitForEventUnsafe(lk, m_delayedQueue.top().GetReadyTime());
  }
  else {
    // We have an event, we can just hop over to this variant:
    DispatchEventUnsafe(lk);
  }
}

bool DispatchQueue::WaitForEvent(std::chrono::milliseconds milliseconds) {
  return WaitForEvent(std::chrono::steady_clock::now() + milliseconds);
}

bool DispatchQueue::WaitForEvent(std::chrono::steady_clock::time_point wakeTime) {
  if (wakeTime == std::chrono::steady_clock::time_point::max()) {
    // Maximal wait--we can optimize by using the zero-arguments version
    return WaitForEvent(), true;
  }

  std::unique_lock<std::mutex> lk(m_dispatchLock);
  return WaitForEventUnsafe(lk, wakeTime);
}

bool DispatchQueue::WaitForEventUnsafe(std::unique_lock<std::mutex>& lk, std::chrono::steady_clock::time_point wakeTime) {
  if (m_aborted)
    throw dispatch_aborted_exception("Dispatch queue was aborted while waiting for an event");

  while (m_dispatchQueue.empty()) {
    // Derive a wakeup time using the high precision timer:
    wakeTime = SuggestSoonestWakeupTimeUnsafe(wakeTime);

    // Now we wait, either for the timeout to elapse or for the dispatch queue itself to
    // transition to the "aborted" state.
    std::cv_status status = m_queueUpdated.wait_until(lk, wakeTime);

    // Short-circuit if the queue was aborted
    if (m_aborted)
      throw dispatch_aborted_exception("Dispatch queue was aborted while waiting for an event");

    if (PromoteReadyDispatchersUnsafe())
      // Dispatcher is ready to run!  Exit our loop and dispatch an event
      break;

    if (status == std::cv_status::timeout)
      // Can't proceed, queue is empty and nobody is ready to be run
      return false;
  }

  DispatchEventUnsafe(lk);
  return true;
}

bool DispatchQueue::DispatchEvent(void) {
  std::unique_lock<std::mutex> lk(m_dispatchLock);

  // If the queue is empty and we fail to promote anything, return here
  // Note that, due to short-circuiting, promotion will not take place if the queue is not empty.
  // This behavior is by design.
  if (m_dispatchQueue.empty() && !PromoteReadyDispatchersUnsafe())
    return false;

  assert(!m_dispatchQueue.empty());
  DispatchEventUnsafe(lk);
  return true;
}

int DispatchQueue::DispatchAllEvents(void) {
  int retVal = 0;
  while(DispatchEvent())
    retVal++;
  return retVal;
}

void DispatchQueue::AddExisting(DispatchThunkBase* pBase) {
  std::unique_lock<std::mutex> lk(m_dispatchLock);
  if(m_dispatchQueue.size() >= m_dispatchCap)
    return;

  m_dispatchQueue.push_back(pBase);
  m_queueUpdated.notify_all();
  OnPended(std::move(lk));
}

bool DispatchQueue::Barrier(std::chrono::nanoseconds timeout) {
  // Set up the lambda:
  auto complete = std::make_shared<bool>(false);
  *this += [complete] { *complete = true; };

  // Obtain the lock, wait until our variable is satisfied, which might be right away:
  std::unique_lock<std::mutex> lk(m_dispatchLock);
  bool rv = m_queueUpdated.wait_for(lk, timeout, [&] { return m_aborted || *complete; });
  if (m_aborted)
    throw dispatch_aborted_exception("Dispatch queue was aborted while a barrier was invoked");
  return rv;
}

void DispatchQueue::Barrier(void) {
  // Set up the lambda:
  bool complete = false;
  *this += [&] { complete = true; };

  // Obtain the lock, wait until our variable is satisfied, which might be right away:
  std::unique_lock<std::mutex> lk(m_dispatchLock);
  m_queueUpdated.wait(lk, [&] { return m_aborted || complete; });
  if (m_aborted)
    // At this point, the dispatch queue MUST be completely run down.  We have no outstanding references
    // to our stack-allocated "complete" variable.  Furthermore, after m_aborted is true, no further
    // dispatchers are permitted to be run.
    throw dispatch_aborted_exception("Dispatch queue was aborted while a barrier was invoked");
}

std::chrono::steady_clock::time_point
DispatchQueue::SuggestSoonestWakeupTimeUnsafe(std::chrono::steady_clock::time_point latestTime) const {
  return
    m_delayedQueue.empty() ?

    // Nothing in the queue, no way to suggest a shorter time
    latestTime :

    // Return the shorter of the maximum wait time and the time of the queue ready--we don't want to tell the
    // caller to wait longer than the limit of their interest.
    std::min(
      m_delayedQueue.top().GetReadyTime(),
      latestTime
    );
}

DispatchQueue::DispatchThunkDelayedExpression DispatchQueue::operator+=(std::chrono::steady_clock::time_point rhs) {
  return DispatchThunkDelayedExpression(this, rhs);
}

void DispatchQueue::operator+=(DispatchThunkDelayed&& rhs) {
  std::lock_guard<std::mutex> lk(m_dispatchLock);

  m_delayedQueue.push(std::forward<DispatchThunkDelayed>(rhs));
  if(
    m_delayedQueue.top().GetReadyTime() == rhs.GetReadyTime() &&
    m_dispatchQueue.empty()
  )
    // We're becoming the new next-to-execute entity, dispatch queue currently empty, trigger wakeup
    // so our newly pended delay thunk is eventually processed.
    m_queueUpdated.notify_all();
}
<commit_msg>Tweaking the error strings to differentiate between exception prior to or during WaitForEvent()<commit_after>// Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved.
#include "stdafx.h"
#include "DispatchQueue.h"
#include "at_exit.h"
#include <assert.h>

dispatch_aborted_exception::dispatch_aborted_exception(const std::string& what):
  autowiring_error(what)
{}

dispatch_aborted_exception::~dispatch_aborted_exception(void){}

DispatchQueue::DispatchQueue(void):
  m_dispatchCap(1024),
  m_aborted(false)
{}

DispatchQueue::~DispatchQueue(void) {
  // Wipe out each entry in the queue, we can't call any of them because we're in teardown
  for(DispatchThunkBase* thunk : m_dispatchQueue)
    delete thunk;

  while (!m_delayedQueue.empty()) {
    DispatchThunkDelayed thunk = m_delayedQueue.top();
    thunk.Reset();
    m_delayedQueue.pop();
  }
}

bool DispatchQueue::PromoteReadyDispatchersUnsafe(void) {
  // Move all ready elements out of the delayed queue and into the dispatch queue:
  size_t nInitial = m_delayedQueue.size();
  for(
    auto now = std::chrono::steady_clock::now();
    !m_delayedQueue.empty() && m_delayedQueue.top().GetReadyTime() < now;
    m_delayedQueue.pop()
  )
    // This item's ready time has elapsed, we can add it to our dispatch queue now:
    m_dispatchQueue.push_back(m_delayedQueue.top().Get());

  // Something was promoted if the dispatch queue size is different
  return nInitial != m_delayedQueue.size();
}

void DispatchQueue::DispatchEventUnsafe(std::unique_lock<std::mutex>& lk) {
  // Pull the ready thunk off of the front of the queue and pop it while we hold the lock.
  // Then, we will excecute the call while the lock has been released so we do not create
  // deadlocks.
  std::unique_ptr<DispatchThunkBase> thunk(m_dispatchQueue.front());
  m_dispatchQueue.pop_front();
  bool wasEmpty = m_dispatchQueue.empty();
  lk.unlock();

  MakeAtExit(
    [this, wasEmpty] {
      // If we emptied the queue, we'd like to reobtain the lock and tell everyone
      // that the queue is now empty.
      if(wasEmpty)
        m_queueUpdated.notify_all();
    }
  ),
  (*thunk)();
}

void DispatchQueue::Abort(void) {
  std::lock_guard<std::mutex> lk(m_dispatchLock);
  m_aborted = true;

  // Do not permit any more lambdas to be pended to our queue:
  m_dispatchCap = 0;

  // Destroy the whole dispatch queue:
  while(!m_dispatchQueue.empty()) {
    delete m_dispatchQueue.front();
    m_dispatchQueue.pop_front();
  }

  // Wake up anyone who is still waiting:
  m_queueUpdated.notify_all();
}

void DispatchQueue::WaitForEvent(void) {
  std::unique_lock<std::mutex> lk(m_dispatchLock);
  if (m_aborted)
    throw dispatch_aborted_exception("Dispatch queue was aborted prior to waiting for an event");

  // Unconditional delay:
  m_queueUpdated.wait(lk, [this]() -> bool {
    if (m_aborted)
      throw dispatch_aborted_exception("Dispatch queue was aborted while waiting for an event");

    return
      // We will need to transition out if the delay queue receives any items:
      !this->m_delayedQueue.empty() ||

      // We also transition out if the dispatch queue has any events:
      !this->m_dispatchQueue.empty();
  });

  if (m_dispatchQueue.empty()) {
    // The delay queue has items but the dispatch queue does not, we need to switch
    // to the suggested sleep timeout variant:
    WaitForEventUnsafe(lk, m_delayedQueue.top().GetReadyTime());
  }
  else {
    // We have an event, we can just hop over to this variant:
    DispatchEventUnsafe(lk);
  }
}

bool DispatchQueue::WaitForEvent(std::chrono::milliseconds milliseconds) {
  return WaitForEvent(std::chrono::steady_clock::now() + milliseconds);
}

bool DispatchQueue::WaitForEvent(std::chrono::steady_clock::time_point wakeTime) {
  if (wakeTime == std::chrono::steady_clock::time_point::max()) {
    // Maximal wait--we can optimize by using the zero-arguments version
    return WaitForEvent(), true;
  }

  std::unique_lock<std::mutex> lk(m_dispatchLock);
  return WaitForEventUnsafe(lk, wakeTime);
}

bool DispatchQueue::WaitForEventUnsafe(std::unique_lock<std::mutex>& lk, std::chrono::steady_clock::time_point wakeTime) {
  if (m_aborted)
    throw dispatch_aborted_exception("Dispatch queue was aborted prior to waiting for an event");

  while (m_dispatchQueue.empty()) {
    // Derive a wakeup time using the high precision timer:
    wakeTime = SuggestSoonestWakeupTimeUnsafe(wakeTime);

    // Now we wait, either for the timeout to elapse or for the dispatch queue itself to
    // transition to the "aborted" state.
    std::cv_status status = m_queueUpdated.wait_until(lk, wakeTime);

    // Short-circuit if the queue was aborted
    if (m_aborted)
      throw dispatch_aborted_exception("Dispatch queue was aborted while waiting for an event");

    if (PromoteReadyDispatchersUnsafe())
      // Dispatcher is ready to run!  Exit our loop and dispatch an event
      break;

    if (status == std::cv_status::timeout)
      // Can't proceed, queue is empty and nobody is ready to be run
      return false;
  }

  DispatchEventUnsafe(lk);
  return true;
}

bool DispatchQueue::DispatchEvent(void) {
  std::unique_lock<std::mutex> lk(m_dispatchLock);

  // If the queue is empty and we fail to promote anything, return here
  // Note that, due to short-circuiting, promotion will not take place if the queue is not empty.
  // This behavior is by design.
  if (m_dispatchQueue.empty() && !PromoteReadyDispatchersUnsafe())
    return false;

  assert(!m_dispatchQueue.empty());
  DispatchEventUnsafe(lk);
  return true;
}

int DispatchQueue::DispatchAllEvents(void) {
  int retVal = 0;
  while(DispatchEvent())
    retVal++;
  return retVal;
}

void DispatchQueue::AddExisting(DispatchThunkBase* pBase) {
  std::unique_lock<std::mutex> lk(m_dispatchLock);
  if(m_dispatchQueue.size() >= m_dispatchCap)
    return;

  m_dispatchQueue.push_back(pBase);
  m_queueUpdated.notify_all();
  OnPended(std::move(lk));
}

bool DispatchQueue::Barrier(std::chrono::nanoseconds timeout) {
  // Set up the lambda:
  auto complete = std::make_shared<bool>(false);
  *this += [complete] { *complete = true; };

  // Obtain the lock, wait until our variable is satisfied, which might be right away:
  std::unique_lock<std::mutex> lk(m_dispatchLock);
  bool rv = m_queueUpdated.wait_for(lk, timeout, [&] { return m_aborted || *complete; });
  if (m_aborted)
    throw dispatch_aborted_exception("Dispatch queue was aborted while a barrier was invoked");
  return rv;
}

void DispatchQueue::Barrier(void) {
  // Set up the lambda:
  bool complete = false;
  *this += [&] { complete = true; };

  // Obtain the lock, wait until our variable is satisfied, which might be right away:
  std::unique_lock<std::mutex> lk(m_dispatchLock);
  m_queueUpdated.wait(lk, [&] { return m_aborted || complete; });
  if (m_aborted)
    // At this point, the dispatch queue MUST be completely run down.  We have no outstanding references
    // to our stack-allocated "complete" variable.  Furthermore, after m_aborted is true, no further
    // dispatchers are permitted to be run.
    throw dispatch_aborted_exception("Dispatch queue was aborted while a barrier was invoked");
}

std::chrono::steady_clock::time_point
DispatchQueue::SuggestSoonestWakeupTimeUnsafe(std::chrono::steady_clock::time_point latestTime) const {
  return
    m_delayedQueue.empty() ?

    // Nothing in the queue, no way to suggest a shorter time
    latestTime :

    // Return the shorter of the maximum wait time and the time of the queue ready--we don't want to tell the
    // caller to wait longer than the limit of their interest.
    std::min(
      m_delayedQueue.top().GetReadyTime(),
      latestTime
    );
}

DispatchQueue::DispatchThunkDelayedExpression DispatchQueue::operator+=(std::chrono::steady_clock::time_point rhs) {
  return DispatchThunkDelayedExpression(this, rhs);
}

void DispatchQueue::operator+=(DispatchThunkDelayed&& rhs) {
  std::lock_guard<std::mutex> lk(m_dispatchLock);

  m_delayedQueue.push(std::forward<DispatchThunkDelayed>(rhs));
  if(
    m_delayedQueue.top().GetReadyTime() == rhs.GetReadyTime() &&
    m_dispatchQueue.empty()
  )
    // We're becoming the new next-to-execute entity, dispatch queue currently empty, trigger wakeup
    // so our newly pended delay thunk is eventually processed.
    m_queueUpdated.notify_all();
}
<|endoftext|>