<commit_before>//=====================================================================//
/*! @file
    @brief  RX65N/RX72N Envision Kit デジタル・ストレージ・オシロスコープ @n
			マイコン内臓１２ビットＡ／Ｄ変換を使って、波形を観測するガジェット
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2018, 2020 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
/// #define CASH_KFONT

#include "common/renesas.hpp"
#include "common/cmt_mgr.hpp"
#include "common/fixed_fifo.hpp"
#include "common/sci_io.hpp"
#include "common/sci_i2c_io.hpp"
#include "common/format.hpp"
#include "common/command.hpp"
#include "common/shell.hpp"
#include "common/tpu_io.hpp"
#include "graphics/font8x16.hpp"
#include "graphics/graphics.hpp"
#include "graphics/filer.hpp"
#include "graphics/kfont.hpp"
#include "graphics/font.hpp"
#include "graphics/simple_dialog.hpp"

#include "chip/FT5206.hpp"

#include "capture.hpp"
#include "dso_gui.hpp"

namespace {

	static const int16_t LCD_X = 480;
	static const int16_t LCD_Y = 272;
	static const auto PIX = graphics::pixel::TYPE::RGB565;

	typedef utils::fixed_fifo<uint8_t, 64> RB64;
	typedef utils::fixed_fifo<uint8_t, 64> SB64;

#if defined(SIG_RX65N)

	static const char* sys_msg_ = { "RX65N Envision Kit" };

	typedef device::system_io<12'000'000> SYSTEM_IO;
	typedef device::PORT<device::PORT7, device::bitpos::B0> LED;
	typedef device::SCI9 SCI_CH;

	typedef device::PORT<device::PORT6, device::bitpos::B3> LCD_DISP;
	typedef device::PORT<device::PORT6, device::bitpos::B6> LCD_LIGHT;
	// フレームバッファ開始アドレスは、100 番地から開始とする。
	// ※０～ＦＦは未使用領域
	static void* LCD_ORG = reinterpret_cast<void*>(0x00000100);

	// SD カード電源制御を使わない場合、「device::NULL_PORT」を指定する。
	typedef device::PORT<device::PORT6, device::bitpos::B4> SDC_POWER;
	// 書き込み禁止は使わない
	typedef device::NULL_PORT SDC_WP;

	// タッチセンサー「RESET」制御ポート
	typedef device::PORT<device::PORT0, device::bitpos::B7> FT5206_RESET;
	// タッチセンサー I2C ポート設定
	typedef device::sci_i2c_io<device::SCI6, RB64, SB64, device::port_map::option::FIRST_I2C> FT5206_I2C;

#elif defined(SIG_RX72N)

	static const char* sys_msg_ = { "RX72N Envision Kit" };

	typedef device::system_io<16'000'000> SYSTEM_IO;
	typedef device::PORT<device::PORT4, device::bitpos::B0> LED;
	typedef device::SCI2 SCI_CH;

	// GLCDC の制御関係
	typedef device::PORT<device::PORTB, device::bitpos::B3> LCD_DISP;
	typedef device::PORT<device::PORT6, device::bitpos::B7> LCD_LIGHT;
	static void* LCD_ORG = reinterpret_cast<void*>(0x0080'0000);

	// SD カードの制御ポート設定
	typedef device::PORT<device::PORT4, device::bitpos::B2> SDC_POWER;
	// 書き込み禁止は使わない
	typedef device::NULL_PORT SDC_WP;

	// タッチセンサー「RESET」制御ポート
	typedef device::PORT<device::PORT6, device::bitpos::B6> FT5206_RESET;
	// タッチセンサー I2C ポート設定
	typedef device::sci_i2c_io<device::SCI6, RB64, SB64, device::port_map::option::THIRD_I2C> FT5206_I2C;

#endif

	typedef device::cmt_mgr<device::CMT0> CMT;
	CMT			cmt_;

	typedef utils::fixed_fifo<char, 512>  RECV_BUFF;
	typedef utils::fixed_fifo<char, 1024> SEND_BUFF;
	typedef device::sci_io<SCI_CH, RECV_BUFF, SEND_BUFF> SCI;
	SCI			sci_;

	// RX65N/RX72N Envision Kit の SDHI は、候補３になっている
	typedef fatfs::sdhi_io<device::SDHI, SDC_POWER, SDC_WP, device::port_map::option::THIRD> SDHI;
	SDHI		sdh_;

	typedef device::glcdc_mgr<device::GLCDC, LCD_X, LCD_Y, PIX> GLCDC_MGR;
	GLCDC_MGR	glcdc_mgr_(nullptr, LCD_ORG);

	typedef graphics::font8x16 AFONT;
	AFONT		afont_;
#ifdef CASH_KFONT
	typedef graphics::kfont<16, 16, 64> KFONT;
#else
	typedef graphics::kfont<16, 16> KFONT;
#endif
	KFONT		kfont_;
	typedef graphics::font<AFONT, KFONT> FONT;
	FONT		font_(afont_, kfont_);

	typedef graphics::render<GLCDC_MGR, FONT> RENDER;
	RENDER		render_(glcdc_mgr_, font_);

	// 標準カラーインスタンス
	typedef graphics::def_color DEF_COLOR;

	typedef dsos::capture<8192> CAPTURE;
	CAPTURE		capture_;

	FT5206_I2C	ft5206_i2c_;
	typedef chip::FT5206<FT5206_I2C> TOUCH;
	TOUCH		touch_(ft5206_i2c_);

	typedef gui::simple_dialog<RENDER, TOUCH> DIALOG;
	DIALOG      dialog_(render_, touch_);

	typedef dsos::dso_gui<RENDER, TOUCH, CAPTURE> DSO_GUI;
	DSO_GUI		dso_gui_(render_, touch_, capture_);

	typedef utils::command<256> CMD;
	CMD			cmd_;

	typedef utils::shell<CMD> SHELL;
	SHELL		shell_(cmd_);

	void update_led_()
	{
		static uint8_t n = 0;
		++n;
		if(n >= 30) {
			n = 0;
		}
		if(n < 10) {
			LED::P = 0;
		} else {
			LED::P = 1;
		}
	}

    void setup_touch_panel_()
    {
        render_.sync_frame();
        dialog_.modal(vtx::spos(400, 60),
            "Touch panel device wait...\nPlease touch it with some screen.");
        uint8_t nnn = 0;
        while(1) {
            render_.sync_frame();
            touch_.update();
            auto num = touch_.get_touch_num();
            if(num == 0) {
                ++nnn;
                if(nnn >= 60) break;
            } else {
                nnn = 0;
            }
        }
        render_.clear(DEF_COLOR::Black);
    }

	void command_()
	{
		if(!cmd_.service()) {
			return;
		}
		if(shell_.analize()) {
			return;
		}
		if(cmd_.cmp_word(0, "cap")) { // capture
//			trigger_ = utils::capture_trigger::SINGLE;
//			capture_.set_trigger(trigger_);
		} else if(cmd_.cmp_word(0, "help")) {
			shell_.help();
			utils::format("    cap        single trigger\n");
		} else {
			utils::format("Command error: '%s'\n") % cmd_.get_command();
		}
	}
}

/// widget の登録・グローバル関数
bool insert_widget(gui::widget* w)
{
	return 	dso_gui_.at_widd().insert(w);
}

/// widget の解除・グローバル関数
void remove_widget(gui::widget* w)
{
	dso_gui_.at_widd().remove(w);
}

extern "C" {

	void sci_putch(char ch)
	{
		sci_.putch(ch);
	}

	void sci_puts(const char* str)
	{
		sci_.puts(str);
	}

	char sci_getch(void)
	{
		return sci_.getch();
	}

	uint16_t sci_length()
	{
		return sci_.recv_length();
	}

	DSTATUS disk_initialize(BYTE drv) {
		return sdh_.disk_initialize(drv);
	}

	DSTATUS disk_status(BYTE drv) {
		return sdh_.disk_status(drv);
	}

	DRESULT disk_read(BYTE drv, BYTE* buff, DWORD sector, UINT count) {
		return sdh_.disk_read(drv, buff, sector, count);
	}

	DRESULT disk_write(BYTE drv, const BYTE* buff, DWORD sector, UINT count) {
		return sdh_.disk_write(drv, buff, sector, count);
	}

	DRESULT disk_ioctl(BYTE drv, BYTE ctrl, void* buff) {
		return sdh_.disk_ioctl(drv, ctrl, buff);
	}

	DWORD get_fattime(void) {
		time_t t = utils::str::get_compiled_time();
///		rtc_.get_time(t);
		return utils::str::get_fattime(t);
	}
}

int main(int argc, char** argv);

int main(int argc, char** argv)
{
	SYSTEM_IO::setup_system_clock();

	{  // SCI 設定
		static const uint8_t sci_level = 2;
		sci_.start(115200, sci_level);
	}

	{  // SD カード・クラスの初期化
		sdh_.start();
	}

	{  // キャプチャー開始
		uint32_t freq = 2000000;  // 2 MHz
//		uint32_t freq = 100000;  // 100 KHz
		if(!capture_.start(freq)) {
			utils::format("Capture not start...\n");
		}
	}

	utils::format("\r%s Start for Digital Storage Oscilloscope\n") % sys_msg_;

	{  // GLCDC の初期化
		LCD_DISP::DIR  = 1;
		LCD_LIGHT::DIR = 1;
		LCD_DISP::P  = 0;  // DISP Disable
		LCD_LIGHT::P = 0;  // BackLight Disable (No PWM)
		if(glcdc_mgr_.start()) {
			utils::format("Start GLCDC\n");
			LCD_DISP::P  = 1;  // DISP Enable
			LCD_LIGHT::P = 1;  // BackLight Enable (No PWM)
			if(!glcdc_mgr_.control(GLCDC_MGR::CONTROL_CMD::START_DISPLAY)) {
				utils::format("GLCDC ctrl fail...\n");
			}
		} else {
			utils::format("GLCDC Fail\n");
		}
	}

#if 0
	{  // DRW2D 初期化
		auto ver = render_.get_version();
		utils::format("DRW2D Version: %04X\n") % ver;

		if(render_.start()) {
			utils:: format("Start DRW2D\n");
		} else {
			utils:: format("DRW2D Fail\n");
		}
	}
#endif

	{  // FT5206 touch screen controller
		TOUCH::reset<FT5206_RESET>();
		uint8_t intr_lvl = 1;
		if(!ft5206_i2c_.start(FT5206_I2C::SPEED::STANDARD, intr_lvl)) {
			utils::format("FT5206 I2C Start Fail...\n");
		}
		if(!touch_.start()) {
			utils::format("FT5206 Start Fail...\n");
		}
	}

	setup_touch_panel_();

	dso_gui_.start();

	LED::OUTPUT();

	cmd_.set_prompt("# ");

	glcdc_mgr_.enable_double();

	while(1) {
		render_.sync_frame();

		touch_.update();

		sdh_.service();

		command_();

		dso_gui_.update();

		update_led_();
	}
}
<commit_msg>Update: DRW2D<commit_after>//=====================================================================//
/*! @file
    @brief  RX65N/RX72N Envision Kit デジタル・ストレージ・オシロスコープ @n
			マイコン内臓１２ビットＡ／Ｄ変換を使って、波形を観測するガジェット
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2018, 2020 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
/// #define CASH_KFONT

#include "common/renesas.hpp"
#include "common/cmt_mgr.hpp"
#include "common/fixed_fifo.hpp"
#include "common/sci_io.hpp"
#include "common/sci_i2c_io.hpp"
#include "common/format.hpp"
#include "common/command.hpp"
#include "common/shell.hpp"
#include "common/tpu_io.hpp"
#include "graphics/font8x16.hpp"
#include "graphics/graphics.hpp"
#include "graphics/filer.hpp"
#include "graphics/kfont.hpp"
#include "graphics/font.hpp"
#include "graphics/simple_dialog.hpp"

#include "chip/FT5206.hpp"

#include "capture.hpp"
#include "dso_gui.hpp"

namespace {

	static const int16_t LCD_X = 480;
	static const int16_t LCD_Y = 272;
	static const auto PIX = graphics::pixel::TYPE::RGB565;

	typedef utils::fixed_fifo<uint8_t, 64> RB64;
	typedef utils::fixed_fifo<uint8_t, 64> SB64;

#if defined(SIG_RX65N)

	static const char* sys_msg_ = { "RX65N Envision Kit" };

	typedef device::system_io<12'000'000> SYSTEM_IO;
	typedef device::PORT<device::PORT7, device::bitpos::B0> LED;
	typedef device::SCI9 SCI_CH;

	typedef device::PORT<device::PORT6, device::bitpos::B3> LCD_DISP;
	typedef device::PORT<device::PORT6, device::bitpos::B6> LCD_LIGHT;
	// フレームバッファ開始アドレスは、100 番地から開始とする。
	// ※０～ＦＦは未使用領域
	static void* LCD_ORG = reinterpret_cast<void*>(0x00000100);

	// SD カード電源制御を使わない場合、「device::NULL_PORT」を指定する。
	typedef device::PORT<device::PORT6, device::bitpos::B4> SDC_POWER;
	// 書き込み禁止は使わない
	typedef device::NULL_PORT SDC_WP;

	// タッチセンサー「RESET」制御ポート
	typedef device::PORT<device::PORT0, device::bitpos::B7> FT5206_RESET;
	// タッチセンサー I2C ポート設定
	typedef device::sci_i2c_io<device::SCI6, RB64, SB64, device::port_map::option::FIRST_I2C> FT5206_I2C;

#elif defined(SIG_RX72N)

	static const char* sys_msg_ = { "RX72N Envision Kit" };

	typedef device::system_io<16'000'000> SYSTEM_IO;
	typedef device::PORT<device::PORT4, device::bitpos::B0> LED;
	typedef device::SCI2 SCI_CH;

	// GLCDC の制御関係
	typedef device::PORT<device::PORTB, device::bitpos::B3> LCD_DISP;
	typedef device::PORT<device::PORT6, device::bitpos::B7> LCD_LIGHT;
	static void* LCD_ORG = reinterpret_cast<void*>(0x0080'0000);

	// SD カードの制御ポート設定
	typedef device::PORT<device::PORT4, device::bitpos::B2> SDC_POWER;
	// 書き込み禁止は使わない
	typedef device::NULL_PORT SDC_WP;

	// タッチセンサー「RESET」制御ポート
	typedef device::PORT<device::PORT6, device::bitpos::B6> FT5206_RESET;
	// タッチセンサー I2C ポート設定
	typedef device::sci_i2c_io<device::SCI6, RB64, SB64, device::port_map::option::THIRD_I2C> FT5206_I2C;

#endif

	typedef device::cmt_mgr<device::CMT0> CMT;
	CMT			cmt_;

	typedef utils::fixed_fifo<char, 512>  RECV_BUFF;
	typedef utils::fixed_fifo<char, 1024> SEND_BUFF;
	typedef device::sci_io<SCI_CH, RECV_BUFF, SEND_BUFF> SCI;
	SCI			sci_;

	// RX65N/RX72N Envision Kit の SDHI は、候補３になっている
	typedef fatfs::sdhi_io<device::SDHI, SDC_POWER, SDC_WP, device::port_map::option::THIRD> SDHI;
	SDHI		sdh_;

	typedef device::glcdc_mgr<device::GLCDC, LCD_X, LCD_Y, PIX> GLCDC_MGR;
	GLCDC_MGR	glcdc_mgr_(nullptr, LCD_ORG);

	typedef graphics::font8x16 AFONT;
	AFONT		afont_;
#ifdef CASH_KFONT
	typedef graphics::kfont<16, 16, 64> KFONT;
#else
	typedef graphics::kfont<16, 16> KFONT;
#endif
	KFONT		kfont_;
	typedef graphics::font<AFONT, KFONT> FONT;
	FONT		font_(afont_, kfont_);

//	typedef graphics::render<GLCDC_MGR, FONT> RENDER;
	typedef device::drw2d_mgr<GLCDC_MGR, FONT> RENDER;
	RENDER		render_(glcdc_mgr_, font_);

	// 標準カラーインスタンス
	typedef graphics::def_color DEF_COLOR;

	typedef dsos::capture<8192> CAPTURE;
	CAPTURE		capture_;

	FT5206_I2C	ft5206_i2c_;
	typedef chip::FT5206<FT5206_I2C> TOUCH;
	TOUCH		touch_(ft5206_i2c_);

	typedef gui::simple_dialog<RENDER, TOUCH> DIALOG;
	DIALOG      dialog_(render_, touch_);

	typedef dsos::dso_gui<RENDER, TOUCH, CAPTURE> DSO_GUI;
	DSO_GUI		dso_gui_(render_, touch_, capture_);

	typedef utils::command<256> CMD;
	CMD			cmd_;

	typedef utils::shell<CMD> SHELL;
	SHELL		shell_(cmd_);

	void update_led_()
	{
		static uint8_t n = 0;
		++n;
		if(n >= 30) {
			n = 0;
		}
		if(n < 10) {
			LED::P = 0;
		} else {
			LED::P = 1;
		}
	}

    void setup_touch_panel_()
    {
        render_.sync_frame();
        dialog_.modal(vtx::spos(400, 60),
            "Touch panel device wait...\nPlease touch it with some screen.");
        uint8_t nnn = 0;
        while(1) {
            render_.sync_frame();
            touch_.update();
            auto num = touch_.get_touch_num();
            if(num == 0) {
                ++nnn;
                if(nnn >= 60) break;
            } else {
                nnn = 0;
            }
        }
        render_.clear(DEF_COLOR::Black);
    }

	void command_()
	{
		if(!cmd_.service()) {
			return;
		}
		if(shell_.analize()) {
			return;
		}
		if(cmd_.cmp_word(0, "cap")) { // capture
//			trigger_ = utils::capture_trigger::SINGLE;
//			capture_.set_trigger(trigger_);
		} else if(cmd_.cmp_word(0, "help")) {
			shell_.help();
			utils::format("    cap        single trigger\n");
		} else {
			utils::format("Command error: '%s'\n") % cmd_.get_command();
		}
	}
}

/// widget の登録・グローバル関数
bool insert_widget(gui::widget* w)
{
	return 	dso_gui_.at_widd().insert(w);
}

/// widget の解除・グローバル関数
void remove_widget(gui::widget* w)
{
	dso_gui_.at_widd().remove(w);
}

extern "C" {

	void sci_putch(char ch)
	{
		sci_.putch(ch);
	}

	void sci_puts(const char* str)
	{
		sci_.puts(str);
	}

	char sci_getch(void)
	{
		return sci_.getch();
	}

	uint16_t sci_length()
	{
		return sci_.recv_length();
	}

	DSTATUS disk_initialize(BYTE drv) {
		return sdh_.disk_initialize(drv);
	}

	DSTATUS disk_status(BYTE drv) {
		return sdh_.disk_status(drv);
	}

	DRESULT disk_read(BYTE drv, BYTE* buff, DWORD sector, UINT count) {
		return sdh_.disk_read(drv, buff, sector, count);
	}

	DRESULT disk_write(BYTE drv, const BYTE* buff, DWORD sector, UINT count) {
		return sdh_.disk_write(drv, buff, sector, count);
	}

	DRESULT disk_ioctl(BYTE drv, BYTE ctrl, void* buff) {
		return sdh_.disk_ioctl(drv, ctrl, buff);
	}

	DWORD get_fattime(void) {
		time_t t = utils::str::get_compiled_time();
///		rtc_.get_time(t);
		return utils::str::get_fattime(t);
	}
}

int main(int argc, char** argv);

int main(int argc, char** argv)
{
	SYSTEM_IO::setup_system_clock();

	{  // SCI 設定
		static const uint8_t sci_level = 2;
		sci_.start(115200, sci_level);
	}

	{  // SD カード・クラスの初期化
		sdh_.start();
	}

	{  // キャプチャー開始
		uint32_t freq = 2000000;  // 2 MHz
//		uint32_t freq = 100000;  // 100 KHz
		if(!capture_.start(freq)) {
			utils::format("Capture not start...\n");
		}
	}

	utils::format("\r%s Start for Digital Storage Oscilloscope\n") % sys_msg_;

	{  // GLCDC の初期化
		LCD_DISP::DIR  = 1;
		LCD_LIGHT::DIR = 1;
		LCD_DISP::P  = 0;  // DISP Disable
		LCD_LIGHT::P = 0;  // BackLight Disable (No PWM)
		if(glcdc_mgr_.start()) {
			utils::format("Start GLCDC\n");
			LCD_DISP::P  = 1;  // DISP Enable
			LCD_LIGHT::P = 1;  // BackLight Enable (No PWM)
			if(!glcdc_mgr_.control(GLCDC_MGR::CONTROL_CMD::START_DISPLAY)) {
				utils::format("GLCDC ctrl fail...\n");
			}
			glcdc_mgr_.enable_double_buffer();
		} else {
			utils::format("GLCDC Fail\n");
		}
	}

	{  // DRW2D 初期化
		if(render_.start()) {
			utils:: format("Start DRW2D\n");
			auto ver = render_.get_version();
			utils::format("    Version: %04X\n") % ver;
		} else {
			utils:: format("DRW2D Fail\n");
		}
	}

	{  // FT5206 touch screen controller
		TOUCH::reset<FT5206_RESET>();
		uint8_t intr_lvl = 1;
		if(!ft5206_i2c_.start(FT5206_I2C::SPEED::STANDARD, intr_lvl)) {
			utils::format("FT5206 I2C Start Fail...\n");
		}
		if(!touch_.start()) {
			utils::format("FT5206 Start Fail...\n");
		}
	}

	setup_touch_panel_();

	dso_gui_.start();

	LED::OUTPUT();

	cmd_.set_prompt("# ");

	while(1) {
		render_.sync_frame();

		touch_.update();

		sdh_.service();

		command_();

		dso_gui_.update();

		update_led_();
	}
}
<|endoftext|>


<commit_before>//-- SystemZMachineScheduler.cpp - SystemZ Scheduler Interface -*- C++ -*---==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// -------------------------- Post RA scheduling ---------------------------- //
// SystemZPostRASchedStrategy is a scheduling strategy which is plugged into
// the MachineScheduler. It has a sorted Available set of SUs and a pickNode()
// implementation that looks to optimize decoder grouping and balance the
// usage of processor resources.
//===----------------------------------------------------------------------===//

#include "SystemZMachineScheduler.h"

using namespace llvm;

#define DEBUG_TYPE "misched"

#ifndef NDEBUG
// Print the set of SUs
void SystemZPostRASchedStrategy::SUSet::
dump(SystemZHazardRecognizer &HazardRec) {
  dbgs() << "{";
  for (auto &SU : *this) {
    HazardRec.dumpSU(SU, dbgs());
    if (SU != *rbegin())
      dbgs() << ",  ";
  }
  dbgs() << "}\n";
}
#endif

SystemZPostRASchedStrategy::
SystemZPostRASchedStrategy(const MachineSchedContext *C)
  : DAG(nullptr), HazardRec(C) {}

void SystemZPostRASchedStrategy::initialize(ScheduleDAGMI *dag) {
  DAG = dag;
  HazardRec.setDAG(dag);
  HazardRec.Reset();
}

// Pick the next node to schedule.
SUnit *SystemZPostRASchedStrategy::pickNode(bool &IsTopNode) {
  // Only scheduling top-down.
  IsTopNode = true;

  if (Available.empty())
    return nullptr;

  // If only one choice, return it.
  if (Available.size() == 1) {
    DEBUG (dbgs() << "+++ Only one: ";
           HazardRec.dumpSU(*Available.begin(), dbgs()); dbgs() << "\n";);
    return *Available.begin();
  }

  // All nodes that are possible to schedule are stored by in the
  // Available set.
  DEBUG(dbgs() << "+++ Available: "; Available.dump(HazardRec););

  Candidate Best;
  for (auto *SU : Available) {

    // SU is the next candidate to be compared against current Best.
    Candidate c(SU, HazardRec);

    // Remeber which SU is the best candidate.
    if (Best.SU == nullptr || c < Best) {
      Best = c;
      DEBUG(dbgs() << "+++ Best sofar: ";
            HazardRec.dumpSU(Best.SU, dbgs());
            if (Best.GroupingCost != 0)
              dbgs() << "\tGrouping cost:" << Best.GroupingCost;
            if (Best.ResourcesCost != 0)
              dbgs() << " Resource cost:" << Best.ResourcesCost;
            dbgs() << " Height:" << Best.SU->getHeight();
            dbgs() << "\n";);
    }

    // Once we know we have seen all SUs that affect grouping or use unbuffered
    // resources, we can stop iterating if Best looks good.
    if (!SU->isScheduleHigh && Best.noCost())
      break;
  }

  assert (Best.SU != nullptr);
  return Best.SU;
}

SystemZPostRASchedStrategy::Candidate::
Candidate(SUnit *SU_, SystemZHazardRecognizer &HazardRec) : Candidate() {
  SU = SU_;

  // Check the grouping cost. For a node that must begin / end a
  // group, it is positive if it would do so prematurely, or negative
  // if it would fit naturally into the schedule.
  GroupingCost = HazardRec.groupingCost(SU);

    // Check the resources cost for this SU.
  ResourcesCost = HazardRec.resourcesCost(SU);
}

bool SystemZPostRASchedStrategy::Candidate::
operator<(const Candidate &other) {

  // Check decoder grouping.
  if (GroupingCost < other.GroupingCost)
    return true;
  if (GroupingCost > other.GroupingCost)
    return false;

  // Compare the use of resources.
  if (ResourcesCost < other.ResourcesCost)
    return true;
  if (ResourcesCost > other.ResourcesCost)
    return false;

  // Higher SU is otherwise generally better.
  if (SU->getHeight() > other.SU->getHeight())
    return true;
  if (SU->getHeight() < other.SU->getHeight())
    return false;

  // If all same, fall back to original order.
  if (SU->NodeNum < other.SU->NodeNum)
    return true;

  return false;
}

void SystemZPostRASchedStrategy::schedNode(SUnit *SU, bool IsTopNode) {
  DEBUG(dbgs() << "+++ Scheduling SU(" << SU->NodeNum << ")\n";);

  // Remove SU from Available set and update HazardRec.
  Available.erase(SU);
  HazardRec.EmitInstruction(SU);
}

void SystemZPostRASchedStrategy::releaseTopNode(SUnit *SU) {
  // Set isScheduleHigh flag on all SUs that we want to consider first in
  // pickNode().
  const MCSchedClassDesc *SC = DAG->getSchedClass(SU);
  bool AffectsGrouping = (SC->isValid() && (SC->BeginGroup || SC->EndGroup));
  SU->isScheduleHigh = (AffectsGrouping || SU->isUnbuffered);

  // Put all released SUs in the Available set.
  Available.insert(SU);
}
<commit_msg>Fix build.<commit_after>//-- SystemZMachineScheduler.cpp - SystemZ Scheduler Interface -*- C++ -*---==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// -------------------------- Post RA scheduling ---------------------------- //
// SystemZPostRASchedStrategy is a scheduling strategy which is plugged into
// the MachineScheduler. It has a sorted Available set of SUs and a pickNode()
// implementation that looks to optimize decoder grouping and balance the
// usage of processor resources.
//===----------------------------------------------------------------------===//

#include "SystemZMachineScheduler.h"

using namespace llvm;

#define DEBUG_TYPE "misched"

#ifndef NDEBUG
// Print the set of SUs
void SystemZPostRASchedStrategy::SUSet::
dump(SystemZHazardRecognizer &HazardRec) const {
  dbgs() << "{";
  for (auto &SU : *this) {
    HazardRec.dumpSU(SU, dbgs());
    if (SU != *rbegin())
      dbgs() << ",  ";
  }
  dbgs() << "}\n";
}
#endif

SystemZPostRASchedStrategy::
SystemZPostRASchedStrategy(const MachineSchedContext *C)
  : DAG(nullptr), HazardRec(C) {}

void SystemZPostRASchedStrategy::initialize(ScheduleDAGMI *dag) {
  DAG = dag;
  HazardRec.setDAG(dag);
  HazardRec.Reset();
}

// Pick the next node to schedule.
SUnit *SystemZPostRASchedStrategy::pickNode(bool &IsTopNode) {
  // Only scheduling top-down.
  IsTopNode = true;

  if (Available.empty())
    return nullptr;

  // If only one choice, return it.
  if (Available.size() == 1) {
    DEBUG (dbgs() << "+++ Only one: ";
           HazardRec.dumpSU(*Available.begin(), dbgs()); dbgs() << "\n";);
    return *Available.begin();
  }

  // All nodes that are possible to schedule are stored by in the
  // Available set.
  DEBUG(dbgs() << "+++ Available: "; Available.dump(HazardRec););

  Candidate Best;
  for (auto *SU : Available) {

    // SU is the next candidate to be compared against current Best.
    Candidate c(SU, HazardRec);

    // Remeber which SU is the best candidate.
    if (Best.SU == nullptr || c < Best) {
      Best = c;
      DEBUG(dbgs() << "+++ Best sofar: ";
            HazardRec.dumpSU(Best.SU, dbgs());
            if (Best.GroupingCost != 0)
              dbgs() << "\tGrouping cost:" << Best.GroupingCost;
            if (Best.ResourcesCost != 0)
              dbgs() << " Resource cost:" << Best.ResourcesCost;
            dbgs() << " Height:" << Best.SU->getHeight();
            dbgs() << "\n";);
    }

    // Once we know we have seen all SUs that affect grouping or use unbuffered
    // resources, we can stop iterating if Best looks good.
    if (!SU->isScheduleHigh && Best.noCost())
      break;
  }

  assert (Best.SU != nullptr);
  return Best.SU;
}

SystemZPostRASchedStrategy::Candidate::
Candidate(SUnit *SU_, SystemZHazardRecognizer &HazardRec) : Candidate() {
  SU = SU_;

  // Check the grouping cost. For a node that must begin / end a
  // group, it is positive if it would do so prematurely, or negative
  // if it would fit naturally into the schedule.
  GroupingCost = HazardRec.groupingCost(SU);

    // Check the resources cost for this SU.
  ResourcesCost = HazardRec.resourcesCost(SU);
}

bool SystemZPostRASchedStrategy::Candidate::
operator<(const Candidate &other) {

  // Check decoder grouping.
  if (GroupingCost < other.GroupingCost)
    return true;
  if (GroupingCost > other.GroupingCost)
    return false;

  // Compare the use of resources.
  if (ResourcesCost < other.ResourcesCost)
    return true;
  if (ResourcesCost > other.ResourcesCost)
    return false;

  // Higher SU is otherwise generally better.
  if (SU->getHeight() > other.SU->getHeight())
    return true;
  if (SU->getHeight() < other.SU->getHeight())
    return false;

  // If all same, fall back to original order.
  if (SU->NodeNum < other.SU->NodeNum)
    return true;

  return false;
}

void SystemZPostRASchedStrategy::schedNode(SUnit *SU, bool IsTopNode) {
  DEBUG(dbgs() << "+++ Scheduling SU(" << SU->NodeNum << ")\n";);

  // Remove SU from Available set and update HazardRec.
  Available.erase(SU);
  HazardRec.EmitInstruction(SU);
}

void SystemZPostRASchedStrategy::releaseTopNode(SUnit *SU) {
  // Set isScheduleHigh flag on all SUs that we want to consider first in
  // pickNode().
  const MCSchedClassDesc *SC = DAG->getSchedClass(SU);
  bool AffectsGrouping = (SC->isValid() && (SC->BeginGroup || SC->EndGroup));
  SU->isScheduleHigh = (AffectsGrouping || SU->isUnbuffered);

  // Put all released SUs in the Available set.
  Available.insert(SU);
}
<|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 RC 1        *
*                (c) 2006-2011 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library 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 Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#define SOFA_COMPONENT_ENGINE_PROJECTIVETRANSFORMENGINE_CPP
#include <SofaMiscEngine/ProjectiveTransformEngine.inl>
#include <sofa/core/ObjectFactory.h>

namespace sofa
{

namespace component
{

namespace engine
{

  SOFA_DECL_CLASS(ProjectiveTransformEngine)

  int ProjectiveTransformEngineClass = core::RegisterObject("Project the position of 3d points onto a plane according to a projection matrix")
#ifdef SOFA_FLOAT
        .add< ProjectiveTransformEngine<defaulttype::Vec3fTypes> >(true) // default template
#else
        .add< ProjectiveTransformEngine<defaulttype::Vec3dTypes> >(true) // default template
#endif
#ifndef SOFA_DOUBLE
        .add< ProjectiveTransformEngine<defaulttype::Vec3fTypes> >()
#endif
        .add< ProjectiveTransformEngine<defaulttype::ExtVec3fTypes> >()
        ;

#ifndef SOFA_FLOAT
template class SOFA_MISC_ENGINE_API ProjectiveTransformEngine<defaulttype::Vec3dTypes>;
#endif //SOFA_FLOAT
#ifndef SOFA_DOUBLE
template class SOFA_MISC_ENGINE_API ProjectiveTransformEngine<defaulttype::Vec3fTypes>;
#endif //SOFA_DOUBLE
template class SOFA_MISC_ENGINE_API ProjectiveTransformEngine<defaulttype::ExtVec3fTypes>;

} // namespace constraint

} // namespace component

} // namespace sofa

<commit_msg>fix default template when compiled with USE_FLOAT<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 RC 1        *
*                (c) 2006-2011 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library 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 Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#define SOFA_COMPONENT_ENGINE_PROJECTIVETRANSFORMENGINE_CPP
#include <SofaMiscEngine/ProjectiveTransformEngine.inl>
#include <sofa/core/ObjectFactory.h>

namespace sofa
{

namespace component
{

namespace engine
{

  SOFA_DECL_CLASS(ProjectiveTransformEngine)

  int ProjectiveTransformEngineClass = core::RegisterObject("Project the position of 3d points onto a plane according to a projection matrix")
#ifdef SOFA_FLOAT
        .add< ProjectiveTransformEngine<defaulttype::Vec3fTypes> >(true) // default template
#else
        .add< ProjectiveTransformEngine<defaulttype::Vec3dTypes> >(true) // default template
#ifndef SOFA_DOUBLE
        .add< ProjectiveTransformEngine<defaulttype::Vec3fTypes> >()
#endif
#endif

        .add< ProjectiveTransformEngine<defaulttype::ExtVec3fTypes> >()
        ;

#ifndef SOFA_FLOAT
template class SOFA_MISC_ENGINE_API ProjectiveTransformEngine<defaulttype::Vec3dTypes>;
#endif //SOFA_FLOAT
#ifndef SOFA_DOUBLE
template class SOFA_MISC_ENGINE_API ProjectiveTransformEngine<defaulttype::Vec3fTypes>;
#endif //SOFA_DOUBLE
template class SOFA_MISC_ENGINE_API ProjectiveTransformEngine<defaulttype::ExtVec3fTypes>;

} // namespace constraint

} // namespace component

} // namespace sofa

<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit https://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
// Copyright (c) 2014-2018 Francois Beaune, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "dictionary.h"

// appleseed.foundation headers.
#include "foundation/utility/foreach.h"

// Standard headers.
#include <cassert>
#include <map>
#include <string>

namespace foundation
{

typedef std::map<std::string, std::string> StringMap;
typedef std::map<std::string, Dictionary> DictionaryMap;

//
// StringDictionary::const_iterator class implementation.
//

struct StringDictionary::const_iterator::Impl
{
    StringMap::const_iterator m_it;
};

StringDictionary::const_iterator::const_iterator()
  : impl(new Impl())
{
}

StringDictionary::const_iterator::const_iterator(const const_iterator& rhs)
  : impl(new Impl(*rhs.impl))
{
}

StringDictionary::const_iterator::~const_iterator()
{
    delete impl;
}

StringDictionary::const_iterator& StringDictionary::const_iterator::operator=(const const_iterator& rhs)
{
    *impl = *rhs.impl;
    return *this;
}

bool StringDictionary::const_iterator::operator==(const const_iterator& rhs) const
{
    return impl->m_it == rhs.impl->m_it;
}

bool StringDictionary::const_iterator::operator!=(const const_iterator& rhs) const
{
    return impl->m_it != rhs.impl->m_it;
}

StringDictionary::const_iterator& StringDictionary::const_iterator::operator++()
{
    ++impl->m_it;
    return *this;
}

StringDictionary::const_iterator& StringDictionary::const_iterator::operator--()
{
    --impl->m_it;
    return *this;
}

const StringDictionary::const_iterator::value_type& StringDictionary::const_iterator::operator*() const
{
    return *this;
}

const char* StringDictionary::const_iterator::key() const
{
    return impl->m_it->first.c_str();
}

const char* StringDictionary::const_iterator::value() const
{
    return impl->m_it->second.c_str();
}

//
// StringDictionary class implementation.
//

struct StringDictionary::Impl
{
    StringMap m_strings;
};

StringDictionary::StringDictionary()
  : impl(new Impl())
{
}

StringDictionary::StringDictionary(const StringDictionary& rhs)
  : impl(new Impl(*rhs.impl))
{
}

StringDictionary::~StringDictionary()
{
    delete impl;
}

StringDictionary& StringDictionary::operator=(const StringDictionary& rhs)
{
    *impl = *rhs.impl;
    return *this;
}

bool StringDictionary::operator==(const StringDictionary& rhs) const
{
    if (size() != rhs.size())
        return false;

    for (
        StringMap::const_iterator it = impl->m_strings.begin(), rhs_it = rhs.impl->m_strings.begin();
        it != impl->m_strings.end();
        ++it, ++rhs_it)
    {
        if (it->first != rhs_it->first || it->second != rhs_it->second)
            return false;
    }

    return true;
}

bool StringDictionary::operator!=(const StringDictionary& rhs) const
{
    return !(*this == rhs);
}

size_t StringDictionary::size() const
{
    return impl->m_strings.size();
}

bool StringDictionary::empty() const
{
    return impl->m_strings.empty();
}

void StringDictionary::clear()
{
    impl->m_strings.clear();
}

StringDictionary& StringDictionary::insert(const char* key, const char* value)
{
    assert(key);
    assert(value);

    impl->m_strings[key] = value;

    return *this;
}

StringDictionary& StringDictionary::set(const char* key, const char* value)
{
    assert(key);
    assert(value);

    const StringMap::iterator i = impl->m_strings.find(key);

    if (i == impl->m_strings.end())
        throw ExceptionDictionaryKeyNotFound(key);

    i->second = value;

    return *this;
}

const char* StringDictionary::get(const char* key) const
{
    assert(key);

    const StringMap::const_iterator i = impl->m_strings.find(key);

    if (i == impl->m_strings.end())
        throw ExceptionDictionaryKeyNotFound(key);

    return i->second.c_str();
}

bool StringDictionary::exist(const char* key) const
{
    assert(key);

    return impl->m_strings.find(key) != impl->m_strings.end();
}

StringDictionary& StringDictionary::remove(const char* key)
{
    assert(key);

    const StringMap::iterator i = impl->m_strings.find(key);

    if (i != impl->m_strings.end())
        impl->m_strings.erase(i);

    return *this;
}

StringDictionary::const_iterator StringDictionary::begin() const
{
    const_iterator it;
    it.impl->m_it = impl->m_strings.begin();
    return it;
}

StringDictionary::const_iterator StringDictionary::end() const
{
    const_iterator it;
    it.impl->m_it = impl->m_strings.end();
    return it;
}

//
// DictionaryDictionary::iterator class implementation.
//

struct DictionaryDictionary::iterator::Impl
{
    DictionaryMap::iterator m_it;
};

DictionaryDictionary::iterator::iterator()
  : impl(new Impl())
{
}

DictionaryDictionary::iterator::iterator(const iterator& rhs)
  : impl(new Impl(*rhs.impl))
{
}

DictionaryDictionary::iterator::~iterator()
{
    delete impl;
}

DictionaryDictionary::iterator& DictionaryDictionary::iterator::operator=(const iterator& rhs)
{
    *impl = *rhs.impl;
    return *this;
}

bool DictionaryDictionary::iterator::operator==(const iterator& rhs) const
{
    return impl->m_it == rhs.impl->m_it;
}

bool DictionaryDictionary::iterator::operator!=(const iterator& rhs) const
{
    return impl->m_it != rhs.impl->m_it;
}

DictionaryDictionary::iterator& DictionaryDictionary::iterator::operator++()
{
    ++impl->m_it;
    return *this;
}

DictionaryDictionary::iterator& DictionaryDictionary::iterator::operator--()
{
    --impl->m_it;
    return *this;
}

DictionaryDictionary::iterator::value_type& DictionaryDictionary::iterator::operator*()
{
    return *this;
}

const char* DictionaryDictionary::iterator::key() const
{
    return impl->m_it->first.c_str();
}

Dictionary& DictionaryDictionary::iterator::value()
{
    return impl->m_it->second;
}

//
// DictionaryDictionary::const_iterator class implementation.
//

struct DictionaryDictionary::const_iterator::Impl
{
    DictionaryMap::const_iterator m_it;
};

DictionaryDictionary::const_iterator::const_iterator()
  : impl(new Impl())
{
}

DictionaryDictionary::const_iterator::const_iterator(const const_iterator& rhs)
  : impl(new Impl())
{
    impl->m_it = rhs.impl->m_it;
}

DictionaryDictionary::const_iterator::const_iterator(const iterator& rhs)
  : impl(new Impl())
{
    impl->m_it = rhs.impl->m_it;
}

DictionaryDictionary::const_iterator::~const_iterator()
{
    delete impl;
}

DictionaryDictionary::const_iterator& DictionaryDictionary::const_iterator::operator=(const const_iterator& rhs)
{
    *impl = *rhs.impl;
    return *this;
}

bool DictionaryDictionary::const_iterator::operator==(const const_iterator& rhs) const
{
    return impl->m_it == rhs.impl->m_it;
}

bool DictionaryDictionary::const_iterator::operator!=(const const_iterator& rhs) const
{
    return impl->m_it != rhs.impl->m_it;
}

DictionaryDictionary::const_iterator& DictionaryDictionary::const_iterator::operator++()
{
    ++impl->m_it;
    return *this;
}

DictionaryDictionary::const_iterator& DictionaryDictionary::const_iterator::operator--()
{
    --impl->m_it;
    return *this;
}

const DictionaryDictionary::const_iterator::value_type& DictionaryDictionary::const_iterator::operator*() const
{
    return *this;
}

const char* DictionaryDictionary::const_iterator::key() const
{
    return impl->m_it->first.c_str();
}

const Dictionary& DictionaryDictionary::const_iterator::value() const
{
    return impl->m_it->second;
}

//
// DictionaryDictionary class implementation.
//

struct DictionaryDictionary::Impl
{
    DictionaryMap m_dictionaries;
};

DictionaryDictionary::DictionaryDictionary()
  : impl(new Impl())
{
}

DictionaryDictionary::DictionaryDictionary(const DictionaryDictionary& rhs)
  : impl(new Impl(*rhs.impl))
{
}

DictionaryDictionary::~DictionaryDictionary()
{
    delete impl;
}

DictionaryDictionary& DictionaryDictionary::operator=(const DictionaryDictionary& rhs)
{
    *impl = *rhs.impl;
    return *this;
}

bool DictionaryDictionary::operator==(const DictionaryDictionary& rhs) const
{
    if (size() != rhs.size())
        return false;

    for (
        DictionaryMap::const_iterator it = impl->m_dictionaries.begin(), rhs_it = rhs.impl->m_dictionaries.begin();
        it != impl->m_dictionaries.end();
        ++it, ++rhs_it)
    {
        if (it->first != rhs_it->first || it->second != rhs_it->second)
            return false;
    }

    return true;
}

bool DictionaryDictionary::operator!=(const DictionaryDictionary& rhs) const
{
    return !(*this == rhs);
}

size_t DictionaryDictionary::size() const
{
    return impl->m_dictionaries.size();
}

bool DictionaryDictionary::empty() const
{
    return impl->m_dictionaries.empty();
}

void DictionaryDictionary::clear()
{
    impl->m_dictionaries.clear();
}

DictionaryDictionary& DictionaryDictionary::insert(const char* key, const Dictionary& value)
{
    assert(key);

    impl->m_dictionaries[key] = value;

    return *this;
}

DictionaryDictionary& DictionaryDictionary::set(const char* key, const Dictionary& value)
{
    assert(key);

    const DictionaryMap::iterator i = impl->m_dictionaries.find(key);

    if (i == impl->m_dictionaries.end())
        throw ExceptionDictionaryKeyNotFound(key);

    i->second = value;

    return *this;
}

Dictionary& DictionaryDictionary::get(const char* key)
{
    assert(key);

    const DictionaryMap::iterator i = impl->m_dictionaries.find(key);

    if (i == impl->m_dictionaries.end())
        throw ExceptionDictionaryKeyNotFound(key);

    return i->second;
}

const Dictionary& DictionaryDictionary::get(const char* key) const
{
    assert(key);

    const DictionaryMap::const_iterator i = impl->m_dictionaries.find(key);

    if (i == impl->m_dictionaries.end())
        throw ExceptionDictionaryKeyNotFound(key);

    return i->second;
}

bool DictionaryDictionary::exist(const char* key) const
{
    assert(key);

    return impl->m_dictionaries.find(key) != impl->m_dictionaries.end();
}

DictionaryDictionary& DictionaryDictionary::remove(const char* key)
{
    assert(key);

    const DictionaryMap::iterator i = impl->m_dictionaries.find(key);

    if (i != impl->m_dictionaries.end())
        impl->m_dictionaries.erase(i);

    return *this;
}

DictionaryDictionary::iterator DictionaryDictionary::begin()
{
    iterator it;
    it.impl->m_it = impl->m_dictionaries.begin();
    return it;
}

DictionaryDictionary::iterator DictionaryDictionary::end()
{
    iterator it;
    it.impl->m_it = impl->m_dictionaries.end();
    return it;
}

DictionaryDictionary::const_iterator DictionaryDictionary::begin() const
{
    const_iterator it;
    it.impl->m_it = impl->m_dictionaries.begin();
    return it;
}

DictionaryDictionary::const_iterator DictionaryDictionary::end() const
{
    const_iterator it;
    it.impl->m_it = impl->m_dictionaries.end();
    return it;
}

//
// Dictionary class implementation.
//

Dictionary& Dictionary::merge(const Dictionary& rhs)
{
    // Merge strings.
    for (const_each<StringDictionary> i = rhs.strings(); i; ++i)
        insert(i->key(), i->value());

    // Recursively merge dictionaries.
    for (const_each<DictionaryDictionary> i = rhs.dictionaries(); i; ++i)
    {
        if (dictionaries().exist(i->key()))
            dictionary(i->key()).merge(i->value());
        else insert(i->key(), i->value());
    }

    return *this;
}

}   // namespace foundation
<commit_msg>Use interned strings as dictionary keys.<commit_after>
//
// This source file is part of appleseed.
// Visit https://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
// Copyright (c) 2014-2018 Francois Beaune, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "dictionary.h"

// appleseed.foundation headers.
#include "foundation/utility/foreach.h"

// Standard headers.
#include <cassert>
#include <map>
#include <string>

namespace foundation
{

typedef std::map<InternedString, std::string> StringMap;
typedef std::map<InternedString, Dictionary> DictionaryMap;

//
// StringDictionary::const_iterator class implementation.
//

struct StringDictionary::const_iterator::Impl
{
    StringMap::const_iterator m_it;
};

StringDictionary::const_iterator::const_iterator()
  : impl(new Impl())
{
}

StringDictionary::const_iterator::const_iterator(const const_iterator& rhs)
  : impl(new Impl(*rhs.impl))
{
}

StringDictionary::const_iterator::~const_iterator()
{
    delete impl;
}

StringDictionary::const_iterator& StringDictionary::const_iterator::operator=(const const_iterator& rhs)
{
    *impl = *rhs.impl;
    return *this;
}

bool StringDictionary::const_iterator::operator==(const const_iterator& rhs) const
{
    return impl->m_it == rhs.impl->m_it;
}

bool StringDictionary::const_iterator::operator!=(const const_iterator& rhs) const
{
    return impl->m_it != rhs.impl->m_it;
}

StringDictionary::const_iterator& StringDictionary::const_iterator::operator++()
{
    ++impl->m_it;
    return *this;
}

StringDictionary::const_iterator& StringDictionary::const_iterator::operator--()
{
    --impl->m_it;
    return *this;
}

const StringDictionary::const_iterator::value_type& StringDictionary::const_iterator::operator*() const
{
    return *this;
}

const char* StringDictionary::const_iterator::key() const
{
    return impl->m_it->first.c_str();
}

const char* StringDictionary::const_iterator::value() const
{
    return impl->m_it->second.c_str();
}

//
// StringDictionary class implementation.
//

struct StringDictionary::Impl
{
    StringMap m_strings;
};

StringDictionary::StringDictionary()
  : impl(new Impl())
{
}

StringDictionary::StringDictionary(const StringDictionary& rhs)
  : impl(new Impl(*rhs.impl))
{
}

StringDictionary::~StringDictionary()
{
    delete impl;
}

StringDictionary& StringDictionary::operator=(const StringDictionary& rhs)
{
    *impl = *rhs.impl;
    return *this;
}

bool StringDictionary::operator==(const StringDictionary& rhs) const
{
    if (size() != rhs.size())
        return false;

    for (
        StringMap::const_iterator it = impl->m_strings.begin(), rhs_it = rhs.impl->m_strings.begin();
        it != impl->m_strings.end();
        ++it, ++rhs_it)
    {
        if (it->first != rhs_it->first || it->second != rhs_it->second)
            return false;
    }

    return true;
}

bool StringDictionary::operator!=(const StringDictionary& rhs) const
{
    return !(*this == rhs);
}

size_t StringDictionary::size() const
{
    return impl->m_strings.size();
}

bool StringDictionary::empty() const
{
    return impl->m_strings.empty();
}

void StringDictionary::clear()
{
    impl->m_strings.clear();
}

StringDictionary& StringDictionary::insert(const char* key, const char* value)
{
    assert(key);
    assert(value);

    impl->m_strings[InternedString(key)] = value;

    return *this;
}

StringDictionary& StringDictionary::set(const char* key, const char* value)
{
    assert(key);
    assert(value);

    const StringMap::iterator i = impl->m_strings.find(InternedString(key));

    if (i == impl->m_strings.end())
        throw ExceptionDictionaryKeyNotFound(key);

    i->second = value;

    return *this;
}

const char* StringDictionary::get(const char* key) const
{
    assert(key);

    const StringMap::const_iterator i = impl->m_strings.find(InternedString(key));

    if (i == impl->m_strings.end())
        throw ExceptionDictionaryKeyNotFound(key);

    return i->second.c_str();
}

bool StringDictionary::exist(const char* key) const
{
    assert(key);

    return impl->m_strings.find(InternedString(key)) != impl->m_strings.end();
}

StringDictionary& StringDictionary::remove(const char* key)
{
    assert(key);

    const StringMap::iterator i = impl->m_strings.find(InternedString(key));

    if (i != impl->m_strings.end())
        impl->m_strings.erase(i);

    return *this;
}

StringDictionary::const_iterator StringDictionary::begin() const
{
    const_iterator it;
    it.impl->m_it = impl->m_strings.begin();
    return it;
}

StringDictionary::const_iterator StringDictionary::end() const
{
    const_iterator it;
    it.impl->m_it = impl->m_strings.end();
    return it;
}

//
// DictionaryDictionary::iterator class implementation.
//

struct DictionaryDictionary::iterator::Impl
{
    DictionaryMap::iterator m_it;
};

DictionaryDictionary::iterator::iterator()
  : impl(new Impl())
{
}

DictionaryDictionary::iterator::iterator(const iterator& rhs)
  : impl(new Impl(*rhs.impl))
{
}

DictionaryDictionary::iterator::~iterator()
{
    delete impl;
}

DictionaryDictionary::iterator& DictionaryDictionary::iterator::operator=(const iterator& rhs)
{
    *impl = *rhs.impl;
    return *this;
}

bool DictionaryDictionary::iterator::operator==(const iterator& rhs) const
{
    return impl->m_it == rhs.impl->m_it;
}

bool DictionaryDictionary::iterator::operator!=(const iterator& rhs) const
{
    return impl->m_it != rhs.impl->m_it;
}

DictionaryDictionary::iterator& DictionaryDictionary::iterator::operator++()
{
    ++impl->m_it;
    return *this;
}

DictionaryDictionary::iterator& DictionaryDictionary::iterator::operator--()
{
    --impl->m_it;
    return *this;
}

DictionaryDictionary::iterator::value_type& DictionaryDictionary::iterator::operator*()
{
    return *this;
}

const char* DictionaryDictionary::iterator::key() const
{
    return impl->m_it->first.c_str();
}

Dictionary& DictionaryDictionary::iterator::value()
{
    return impl->m_it->second;
}

//
// DictionaryDictionary::const_iterator class implementation.
//

struct DictionaryDictionary::const_iterator::Impl
{
    DictionaryMap::const_iterator m_it;
};

DictionaryDictionary::const_iterator::const_iterator()
  : impl(new Impl())
{
}

DictionaryDictionary::const_iterator::const_iterator(const const_iterator& rhs)
  : impl(new Impl())
{
    impl->m_it = rhs.impl->m_it;
}

DictionaryDictionary::const_iterator::const_iterator(const iterator& rhs)
  : impl(new Impl())
{
    impl->m_it = rhs.impl->m_it;
}

DictionaryDictionary::const_iterator::~const_iterator()
{
    delete impl;
}

DictionaryDictionary::const_iterator& DictionaryDictionary::const_iterator::operator=(const const_iterator& rhs)
{
    *impl = *rhs.impl;
    return *this;
}

bool DictionaryDictionary::const_iterator::operator==(const const_iterator& rhs) const
{
    return impl->m_it == rhs.impl->m_it;
}

bool DictionaryDictionary::const_iterator::operator!=(const const_iterator& rhs) const
{
    return impl->m_it != rhs.impl->m_it;
}

DictionaryDictionary::const_iterator& DictionaryDictionary::const_iterator::operator++()
{
    ++impl->m_it;
    return *this;
}

DictionaryDictionary::const_iterator& DictionaryDictionary::const_iterator::operator--()
{
    --impl->m_it;
    return *this;
}

const DictionaryDictionary::const_iterator::value_type& DictionaryDictionary::const_iterator::operator*() const
{
    return *this;
}

const char* DictionaryDictionary::const_iterator::key() const
{
    return impl->m_it->first.c_str();
}

const Dictionary& DictionaryDictionary::const_iterator::value() const
{
    return impl->m_it->second;
}

//
// DictionaryDictionary class implementation.
//

struct DictionaryDictionary::Impl
{
    DictionaryMap m_dictionaries;
};

DictionaryDictionary::DictionaryDictionary()
  : impl(new Impl())
{
}

DictionaryDictionary::DictionaryDictionary(const DictionaryDictionary& rhs)
  : impl(new Impl(*rhs.impl))
{
}

DictionaryDictionary::~DictionaryDictionary()
{
    delete impl;
}

DictionaryDictionary& DictionaryDictionary::operator=(const DictionaryDictionary& rhs)
{
    *impl = *rhs.impl;
    return *this;
}

bool DictionaryDictionary::operator==(const DictionaryDictionary& rhs) const
{
    if (size() != rhs.size())
        return false;

    for (
        DictionaryMap::const_iterator it = impl->m_dictionaries.begin(), rhs_it = rhs.impl->m_dictionaries.begin();
        it != impl->m_dictionaries.end();
        ++it, ++rhs_it)
    {
        if (it->first != rhs_it->first || it->second != rhs_it->second)
            return false;
    }

    return true;
}

bool DictionaryDictionary::operator!=(const DictionaryDictionary& rhs) const
{
    return !(*this == rhs);
}

size_t DictionaryDictionary::size() const
{
    return impl->m_dictionaries.size();
}

bool DictionaryDictionary::empty() const
{
    return impl->m_dictionaries.empty();
}

void DictionaryDictionary::clear()
{
    impl->m_dictionaries.clear();
}

DictionaryDictionary& DictionaryDictionary::insert(const char* key, const Dictionary& value)
{
    assert(key);

    impl->m_dictionaries[InternedString(key)] = value;

    return *this;
}

DictionaryDictionary& DictionaryDictionary::set(const char* key, const Dictionary& value)
{
    assert(key);

    const DictionaryMap::iterator i = impl->m_dictionaries.find(InternedString(key));

    if (i == impl->m_dictionaries.end())
        throw ExceptionDictionaryKeyNotFound(key);

    i->second = value;

    return *this;
}

Dictionary& DictionaryDictionary::get(const char* key)
{
    assert(key);

    const DictionaryMap::iterator i = impl->m_dictionaries.find(InternedString(key));

    if (i == impl->m_dictionaries.end())
        throw ExceptionDictionaryKeyNotFound(key);

    return i->second;
}

const Dictionary& DictionaryDictionary::get(const char* key) const
{
    assert(key);

    const DictionaryMap::const_iterator i = impl->m_dictionaries.find(InternedString(key));

    if (i == impl->m_dictionaries.end())
        throw ExceptionDictionaryKeyNotFound(key);

    return i->second;
}

bool DictionaryDictionary::exist(const char* key) const
{
    assert(key);

    return impl->m_dictionaries.find(InternedString(key)) != impl->m_dictionaries.end();
}

DictionaryDictionary& DictionaryDictionary::remove(const char* key)
{
    assert(key);

    const DictionaryMap::iterator i = impl->m_dictionaries.find(InternedString(key));

    if (i != impl->m_dictionaries.end())
        impl->m_dictionaries.erase(i);

    return *this;
}

DictionaryDictionary::iterator DictionaryDictionary::begin()
{
    iterator it;
    it.impl->m_it = impl->m_dictionaries.begin();
    return it;
}

DictionaryDictionary::iterator DictionaryDictionary::end()
{
    iterator it;
    it.impl->m_it = impl->m_dictionaries.end();
    return it;
}

DictionaryDictionary::const_iterator DictionaryDictionary::begin() const
{
    const_iterator it;
    it.impl->m_it = impl->m_dictionaries.begin();
    return it;
}

DictionaryDictionary::const_iterator DictionaryDictionary::end() const
{
    const_iterator it;
    it.impl->m_it = impl->m_dictionaries.end();
    return it;
}

//
// Dictionary class implementation.
//

Dictionary& Dictionary::merge(const Dictionary& rhs)
{
    // Merge strings.
    for (const_each<StringDictionary> i = rhs.strings(); i; ++i)
        insert(i->key(), i->value());

    // Recursively merge dictionaries.
    for (const_each<DictionaryDictionary> i = rhs.dictionaries(); i; ++i)
    {
        if (dictionaries().exist(i->key()))
            dictionary(i->key()).merge(i->value());
        else insert(i->key(), i->value());
    }

    return *this;
}

}   // namespace foundation
<|endoftext|>


<commit_before>#include "CGUITitleLabelsWidget.h"

#include "CProgramContext.h"
#include "SciDataManager.h"
#include "CMainMenuState.h"

#include <iomanip>

CGUITitleLabelsWidget::CGUITitleLabelsWidget(SciDataManager * DataManager)
{
	static Range ValueRange = DataManager->GridValues.getValueRange("Avg Oxy", 5.0);

	std::wstringstream s;
	s << std::fixed;
	s << "Range (";
	s << std::setprecision(3);
	s << ValueRange.first;
	s << " - ";
	s << ValueRange.second;
	s << ")";

	// Top Label
	Gwen::Controls::Label * BigLabel = new Gwen::Controls::Label(GUIManager->getCanvas());
	BigLabel->SetFont(GUIManager->getLargeFont());
	BigLabel->SetText(Gwen::UnicodeString(L"Dataset: ") + Gwen::UnicodeString(CMainMenuState::get().DataSetName.begin(), CMainMenuState::get().DataSetName.end()));
	BigLabel->SetBounds(10, 10, 1590, 300);
	BigLabel->SetTextColor(Gwen::Color(235, 255, 235, 215));

	// Second Label
	Gwen::Controls::Label * MediumLabel = new Gwen::Controls::Label(GUIManager->getCanvas());
	MediumLabel->SetFont(GUIManager->getMediumFont());
	MediumLabel->SetText(Gwen::UnicodeString(L"Current Field: Avg Oxy - ") + Gwen::UnicodeString(s.str()));
	MediumLabel->SetBounds(20, 70, 600, 300);
	MediumLabel->SetTextColor(Gwen::Color(235, 235, 255, 215));

	// Volume Range Label
	VolumeRangeIndicator = new Gwen::Controls::Label(GUIManager->getCanvas());
	VolumeRangeIndicator->SetFont(GUIManager->getMediumFont());
	VolumeRangeIndicator->SetBounds(20, 110, 900, 300);
	VolumeRangeIndicator->SetTextColor(Gwen::Color(255, 235, 235, 215));

	// Volume Range Label
	VolumeCalculationIndicator = new Gwen::Controls::Label(GUIManager->getCanvas());
	VolumeCalculationIndicator->SetFont(GUIManager->getMediumFont());
	VolumeCalculationIndicator->SetBounds(20, 150, 900, 300);
	VolumeCalculationIndicator->SetTextColor(Gwen::Color(255, 235, 235, 215));
}

void CGUITitleLabelsWidget::resetVolumeRangeIndicator(SciDataManager * DataManager)
{
	static Range ValueRange = DataManager->GridValues.getValueRange("Avg Oxy", 5.0);

	{
		std::wstringstream s;
		s << std::fixed;
		s << "Value Range: ";
		s << std::setprecision(3);
		s << (CProgramContext::get().Scene.VolumeSceneObject->Control.EmphasisLocation * (ValueRange.second - ValueRange.first) + ValueRange.first);
		s << "  ";
		s << std::setprecision(4);
		s << (CProgramContext::get().Scene.VolumeSceneObject->Control.LocalRange / 2.f * (ValueRange.second - ValueRange.first));
		VolumeRangeIndicator->SetText(s.str());
	}

	{
		std::wstringstream s;
		s << "Volume: ";
		s << std::setprecision(3);
		s << std::scientific;
		s << DataManager->getGridVolume("\"Avg Oxy\"", CProgramContext::get().Scene.VolumeSceneObject->Control.EmphasisLocation * (ValueRange.second - ValueRange.first) + ValueRange.first,
			CProgramContext::get().Scene.VolumeSceneObject->Control.LocalRange / 2.f * (ValueRange.second - ValueRange.first), 2) * 20.0 * 20.0;
		s << " m^3";
		VolumeCalculationIndicator->SetText(s.str());
	}
}

void CGUITitleLabelsWidget::clearVolumeRangeIndicator()
{
	VolumeRangeIndicator->SetText(L"");
}
<commit_msg>+ Fixed title widget<commit_after>#include "CGUITitleLabelsWidget.h"

#include "CProgramContext.h"
#include "SciDataManager.h"
#include "CMainMenuState.h"

#include <iomanip>

CGUITitleLabelsWidget::CGUITitleLabelsWidget(SciDataManager * DataManager)
{
	static Range ValueRange = DataManager->RawValues.getValueRange("Avg Oxy", 5.0);

	std::wstringstream s;
	s << std::fixed;
	s << "Range (";
	s << std::setprecision(3);
	s << ValueRange.first;
	s << ", ";
	s << ValueRange.second;
	s << ")";

	// Top Label
	Gwen::Controls::Label * BigLabel = new Gwen::Controls::Label(GUIManager->getCanvas());
	BigLabel->SetFont(GUIManager->getLargeFont());
	BigLabel->SetText(Gwen::UnicodeString(L"Dataset: ") + Gwen::UnicodeString(CMainMenuState::get().DataSetName.begin(), CMainMenuState::get().DataSetName.end()));
	BigLabel->SetBounds(10, 10, 1590, 300);
	BigLabel->SetTextColor(Gwen::Color(235, 255, 235, 215));

	// Second Label
	Gwen::Controls::Label * MediumLabel = new Gwen::Controls::Label(GUIManager->getCanvas());
	MediumLabel->SetFont(GUIManager->getMediumFont());
	MediumLabel->SetText(Gwen::UnicodeString(L"Current Field: Avg Oxy - ") + Gwen::UnicodeString(s.str()));
	MediumLabel->SetBounds(20, 70, 1000, 300);
	MediumLabel->SetTextColor(Gwen::Color(235, 235, 255, 215));

	// Volume Range Label
	VolumeRangeIndicator = new Gwen::Controls::Label(GUIManager->getCanvas());
	VolumeRangeIndicator->SetFont(GUIManager->getMediumFont());
	VolumeRangeIndicator->SetBounds(20, 110, 1000, 300);
	VolumeRangeIndicator->SetTextColor(Gwen::Color(255, 235, 235, 215));

	// Volume Range Label
	VolumeCalculationIndicator = new Gwen::Controls::Label(GUIManager->getCanvas());
	VolumeCalculationIndicator->SetFont(GUIManager->getMediumFont());
	VolumeCalculationIndicator->SetBounds(20, 150, 1000, 300);
	VolumeCalculationIndicator->SetTextColor(Gwen::Color(255, 235, 235, 215));
}

void CGUITitleLabelsWidget::resetVolumeRangeIndicator(SciDataManager * DataManager)
{
	static Range ValueRange = DataManager->RawValues.getValueRange("Avg Oxy", 5.0);

	{
		std::wstringstream s;
		s << std::fixed;
		s << "Value Range: ";
		s << std::setprecision(3);
		s << (CProgramContext::get().Scene.VolumeSceneObject->Control.EmphasisLocation * (ValueRange.second - ValueRange.first) + ValueRange.first);
		s << "  ";
		s << std::setprecision(4);
		s << (CProgramContext::get().Scene.VolumeSceneObject->Control.LocalRange / 2.f * (ValueRange.second - ValueRange.first));
		VolumeRangeIndicator->SetText(s.str());
	}

	{
		static Range ValueRange = DataManager->GridValues.getValueRange("Avg Oxy", 5.0);
		static Range XValueRange = DataManager->RawValues.getValueRange("x", 5.0);
		static Range YValueRange = DataManager->RawValues.getValueRange("DFS Depth (m)", 5.0);
		YValueRange.first = 0.0;
		static Range ZValueRange = DataManager->RawValues.getValueRange("y", 5.0);

		double EntireVolume = 1.0;
		EntireVolume *= XValueRange.second - XValueRange.first;
		EntireVolume *= YValueRange.second - YValueRange.first;
		EntireVolume *= ZValueRange.second - ZValueRange.first;

		double UnitVolume = EntireVolume / 24.0 / 24.0 / 24.0;
		//printf("Entire Volume: %f UnitVolume %f\n", EntireVolume, UnitVolume);

		std::wstringstream s;
		s << "Volume: ";
		s << std::setprecision(3);
		s << std::scientific;
		s << DataManager->getGridVolume("Avg Oxy", CProgramContext::get().Scene.VolumeSceneObject->Control.EmphasisLocation * (ValueRange.second - ValueRange.first) + ValueRange.first,
			CProgramContext::get().Scene.VolumeSceneObject->Control.LocalRange / 2.f * (ValueRange.second - ValueRange.first), 2) * UnitVolume;
		s << " m^3";
		VolumeCalculationIndicator->SetText(s.str());
	}
}

void CGUITitleLabelsWidget::clearVolumeRangeIndicator()
{
	VolumeRangeIndicator->SetText(L"");
	VolumeCalculationIndicator->SetText(L"");
}
<|endoftext|>


<commit_before>//@author A0114171W
#include "stdafx.h"
#include "operation.h"
#include "operations/post_operation.h"
#include "operations/put_operation.h"
#include "operations/erase_operation.h"
#include "operations/branch_operation.h"
#include "internal_transaction.h"
#include "../exception.h"
#include "internal_datastore.h"

namespace You {
namespace DataStore {
namespace Internal {

const std::string DataStore::FILE_PATH = std::string("data.xml");
const std::wstring DataStore::ROOT_NODE_NAME = std::wstring(L"You");

DataStore& DataStore::get() {
	static DataStore store;
	return store;
}

You::DataStore::Transaction DataStore::begin() {
	You::DataStore::Transaction result;
	transactionStack.push(std::weak_ptr<Internal::Transaction>(result));

	return result;
}

void DataStore::onTransactionCommit(Transaction& transaction) {
	// Only transaction on top of the stack may be committed
	assert(*transactionStack.top().lock() == transaction);
	auto self = transactionStack.top();

	if (transactionStack.size() == 1) {
		// it is the only active transaction, execute the operations and save
		pugi::xml_document temp;
		temp.reset(document);
		executeTransaction(transaction, temp);
		document.reset(temp);
		saveData();
		transactionStack.pop();
	} else {
		// There is a transaction before it that is yet to be committed.
		// Merge with that transaction
		transactionStack.pop();
		auto below = transactionStack.top().lock();
		below->mergeOperationsQueue(transaction.operationsQueue);
		below->mergeOperationsQueue(transaction.mergedOperationsQueue);
	}
}

void DataStore::onTransactionRollback(Transaction& transaction) {
	// Can only rollback the latest transaction
	assert(*(transactionStack.top().lock()) == transaction);
	transactionStack.pop();
}

void DataStore::post(std::wstring branch, std::wstring id,
	const KeyValuePairs& kvp) {
	assert(!transactionStack.empty());

	std::unique_ptr<Internal::Operation> operation =
		std::make_unique<Internal::PostOperation>(branch, id, kvp);

	auto transaction = transactionStack.top().lock();
	assert(transaction);  // Checks if the pointer is valid
	transaction->push(std::move(operation));
}

void DataStore::put(std::wstring branch, std::wstring id,
	const KeyValuePairs& kvp) {
	assert(!transactionStack.empty());

	std::unique_ptr<Internal::Operation> operation =
		std::make_unique<Internal::PutOperation>(branch, id, kvp);

	auto transaction = transactionStack.top().lock();
	assert(transaction);  // Checks if the pointer is valid
	transaction->push(std::move(operation));
}

void DataStore::erase(std::wstring branch, std::wstring id) {
	assert(!transactionStack.empty());

	std::unique_ptr<Internal::Operation> operation =
		std::make_unique<Internal::EraseOperation>(branch, id);

	auto transaction = transactionStack.top().lock();
	assert(transaction);  // Checks if the pointer is valid
	transaction->push(std::move(operation));
}

std::vector<KeyValuePairs> DataStore::getAll(std::wstring nodeName) {
	loadData();
	pugi::xml_node dataNode = BranchOperation::get(root, nodeName);
	std::vector<KeyValuePairs> allData;
	for (auto i = dataNode.begin(); i != dataNode.end(); ++i) {
		allData.push_back(SerializationOperation::deserialize(*i));
	}
	return allData;
}

void DataStore::wipeData() {
	document.reset();
	std::remove(FILE_PATH.c_str());
}

bool DataStore::saveData() {
	bool status = document.save_file(FILE_PATH.c_str());
	return status;
}

void DataStore::loadData() {
	bool isInitialized = !document.first_child().empty();
	if (!isInitialized) {
		pugi::xml_parse_result loadStatus = document.load_file(FILE_PATH.c_str());
		bool loadSuccessful = loadStatus;
		bool isFirstLoad =
			loadStatus.status == pugi::xml_parse_status::status_file_not_found;
		if (!loadSuccessful && !isFirstLoad) {
			// TODO(digawp): find a way to inform user where in the xml
			// the error is located.
			// Possible solution: log
			onXmlParseResult(loadStatus);
		} else {
			root = BranchOperation::get(document, ROOT_NODE_NAME.c_str());
		}
	}
}

void DataStore::executeTransaction(Transaction& transaction,
	pugi::xml_node& node) {
	for (auto operation = transaction.operationsQueue.begin();
		operation != transaction.operationsQueue.end();
		++operation) {
		bool status = operation->run(node);
		if (!status) {
			transaction.rollback();
			assert(false);
		}
	}
	for (auto mergedOperation = transaction.mergedOperationsQueue.begin();
		mergedOperation != transaction.mergedOperationsQueue.end();
		++mergedOperation) {
		bool status = mergedOperation->run(node);
		if (!status) {
			transaction.rollback();
			assert(false);
		}
	}
}

void DataStore::onXmlParseResult(const pugi::xml_parse_result& result) {
	bool isIoError =
		result.status == pugi::xml_parse_status::status_io_error ||
		result.status == pugi::xml_parse_status::status_out_of_memory ||
		result.status == pugi::xml_parse_status::status_internal_error;
	if (isIoError) {
		throw IOException();
	} else {
		throw NotWellFormedXmlException();
	}
}

}  // namespace Internal
}  // namespace DataStore
}  // namespace You
<commit_msg>executeTransaction on temporary root, update root after commit<commit_after>//@author A0114171W
#include "stdafx.h"
#include "operation.h"
#include "operations/post_operation.h"
#include "operations/put_operation.h"
#include "operations/erase_operation.h"
#include "operations/branch_operation.h"
#include "internal_transaction.h"
#include "../exception.h"
#include "internal_datastore.h"

namespace You {
namespace DataStore {
namespace Internal {

const std::string DataStore::FILE_PATH = std::string("data.xml");
const std::wstring DataStore::ROOT_NODE_NAME = std::wstring(L"You");

DataStore& DataStore::get() {
	static DataStore store;
	return store;
}

You::DataStore::Transaction DataStore::begin() {
	You::DataStore::Transaction result;
	transactionStack.push(std::weak_ptr<Internal::Transaction>(result));

	return result;
}

void DataStore::onTransactionCommit(Transaction& transaction) {
	// Only transaction on top of the stack may be committed
	assert(*transactionStack.top().lock() == transaction);
	auto self = transactionStack.top();

	if (transactionStack.size() == 1) {
		// it is the only active transaction, execute the operations and save
		pugi::xml_document temp;
		temp.reset(document);
		pugi::xml_node tempRoot = BranchOperation::get(temp, ROOT_NODE_NAME.c_str());
		executeTransaction(transaction, tempRoot);
		document.reset(temp);
		root = BranchOperation::get(document, ROOT_NODE_NAME.c_str());
		saveData();
		transactionStack.pop();
	} else {
		// There is a transaction before it that is yet to be committed.
		// Merge with that transaction
		transactionStack.pop();
		auto below = transactionStack.top().lock();
		below->mergeOperationsQueue(transaction.operationsQueue);
		below->mergeOperationsQueue(transaction.mergedOperationsQueue);
	}
}

void DataStore::onTransactionRollback(Transaction& transaction) {
	// Can only rollback the latest transaction
	assert(*(transactionStack.top().lock()) == transaction);
	transactionStack.pop();
}

void DataStore::post(std::wstring branch, std::wstring id,
	const KeyValuePairs& kvp) {
	assert(!transactionStack.empty());

	std::unique_ptr<Internal::Operation> operation =
		std::make_unique<Internal::PostOperation>(branch, id, kvp);

	auto transaction = transactionStack.top().lock();
	assert(transaction);  // Checks if the pointer is valid
	transaction->push(std::move(operation));
}

void DataStore::put(std::wstring branch, std::wstring id,
	const KeyValuePairs& kvp) {
	assert(!transactionStack.empty());

	std::unique_ptr<Internal::Operation> operation =
		std::make_unique<Internal::PutOperation>(branch, id, kvp);

	auto transaction = transactionStack.top().lock();
	assert(transaction);  // Checks if the pointer is valid
	transaction->push(std::move(operation));
}

void DataStore::erase(std::wstring branch, std::wstring id) {
	assert(!transactionStack.empty());

	std::unique_ptr<Internal::Operation> operation =
		std::make_unique<Internal::EraseOperation>(branch, id);

	auto transaction = transactionStack.top().lock();
	assert(transaction);  // Checks if the pointer is valid
	transaction->push(std::move(operation));
}

std::vector<KeyValuePairs> DataStore::getAll(std::wstring nodeName) {
	loadData();
	pugi::xml_node dataNode = BranchOperation::get(root, nodeName);
	std::vector<KeyValuePairs> allData;
	for (auto i = dataNode.begin(); i != dataNode.end(); ++i) {
		allData.push_back(SerializationOperation::deserialize(*i));
	}
	return allData;
}

void DataStore::wipeData() {
	document.reset();
	std::remove(FILE_PATH.c_str());
}

bool DataStore::saveData() {
	bool status = document.save_file(FILE_PATH.c_str());
	return status;
}

void DataStore::loadData() {
	bool isInitialized = !document.first_child().empty();
	if (!isInitialized) {
		pugi::xml_parse_result loadStatus = document.load_file(FILE_PATH.c_str());
		bool loadSuccessful = loadStatus;
		bool isFirstLoad =
			loadStatus.status == pugi::xml_parse_status::status_file_not_found;
		if (!loadSuccessful && !isFirstLoad) {
			// TODO(digawp): find a way to inform user where in the xml
			// the error is located.
			// Possible solution: log
			onXmlParseResult(loadStatus);
		} else {
			root = BranchOperation::get(document, ROOT_NODE_NAME.c_str());
		}
	}
}

void DataStore::executeTransaction(Transaction& transaction,
	pugi::xml_node& node) {
	for (auto operation = transaction.operationsQueue.begin();
		operation != transaction.operationsQueue.end();
		++operation) {
		bool status = operation->run(node);
		if (!status) {
			transaction.rollback();
			assert(false);
		}
	}
	for (auto mergedOperation = transaction.mergedOperationsQueue.begin();
		mergedOperation != transaction.mergedOperationsQueue.end();
		++mergedOperation) {
		bool status = mergedOperation->run(node);
		if (!status) {
			transaction.rollback();
			assert(false);
		}
	}
}

void DataStore::onXmlParseResult(const pugi::xml_parse_result& result) {
	bool isIoError =
		result.status == pugi::xml_parse_status::status_io_error ||
		result.status == pugi::xml_parse_status::status_out_of_memory ||
		result.status == pugi::xml_parse_status::status_internal_error;
	if (isIoError) {
		throw IOException();
	} else {
		throw NotWellFormedXmlException();
	}
}

}  // namespace Internal
}  // namespace DataStore
}  // namespace You
<|endoftext|>


<commit_before>// Copyright (c) 2011 - 2019, GS Group, https://github.com/GSGroup
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted,
// provided that the above copyright notice and this permission notice appear in all copies.
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#include <stingraykit/any.h>

#include <stingraykit/serialization/Serialization.h>
#include <stingraykit/assert.h>

namespace stingray
{

	namespace Detail {
	namespace any
	{
		void ObjectHolder<ISerializablePtr>::Serialize(ObjectOStream& ar) const
		{ ar.Serialize("obj", Object); }

		void ObjectHolder<ISerializablePtr>::Deserialize(ObjectIStream& ar)
		{ ar.Deserialize("obj", Object); }
	}}

	void any::Copy(const any& other)
	{
		STINGRAYKIT_ASSERT(_type == Type::Empty);

		switch (other._type)
		{
		case Type::Empty:
		case Type::Bool:
		case Type::Char:
		case Type::UChar:
		case Type::Short:
		case Type::UShort:
		case Type::Int:
		case Type::UInt:
		case Type::Long:
		case Type::ULong:
		case Type::LongLong:
		case Type::ULongLong:
		case Type::Float:
		case Type::Double:
			_data = other._data;
			break;
		case Type::String:
			_data.String.Ctor(other._data.String.Ref());
			break;
		case Type::Object:
		case Type::SerializableObject:
			_data.Object = other._data.Object->Clone();
			break;
		default:
			STINGRAYKIT_THROW(ArgumentException("type", other._type));
		}

		_type = other._type;
	}

	void any::Destroy()
	{
		switch (_type)
		{
		case Type::String:
			_data.String.Dtor();
			break;
		case Type::Object:
		case Type::SerializableObject:
			delete _data.Object;
			break;
		default:
			break;
		}

		_type = Type::Empty;
	}

	bool any::IsSerializable() const
	{ return _type != Type::Object || _data.Object->IsSerializable(); }

#define STRING(NAME) case Type::NAME: return stingray::ToString(_data.NAME)

	std::string any::ToString() const
	{
		switch (_type)
		{
		case Type::Empty:	return "<empty>";
		STRING(Bool);
		STRING(Char);
		STRING(UChar);
		STRING(Short);
		STRING(UShort);
		STRING(Int);
		STRING(UInt);
		STRING(Long);
		STRING(ULong);
		STRING(LongLong);
		STRING(ULongLong);
		STRING(Float);
		STRING(Double);
		case Type::String:
			return _data.String.Ref();
		case Type::Object:
		case Type::SerializableObject:
			return _data.Object->ToString();
		}

		STINGRAYKIT_THROW(StringBuilder() % "Unknown type: " % _type);
	}

#undef STRING

#define SERIALIZE(NAME) case Type::NAME: ar.Serialize("val", _data.NAME); return

	void any::Serialize(ObjectOStream& ar) const
	{
		ar.Serialize("type", _type);

		switch (_type)
		{
		case Type::Empty:	return;
		SERIALIZE(Bool);
		SERIALIZE(Char);
		SERIALIZE(UChar);
		SERIALIZE(Short);
		SERIALIZE(UShort);
		SERIALIZE(Int);
		SERIALIZE(UInt);
		SERIALIZE(Long);
		SERIALIZE(ULong);
		SERIALIZE(LongLong);
		SERIALIZE(ULongLong);
		SERIALIZE(Float);
		SERIALIZE(Double);
		case Type::String: ar.Serialize("val", _data.String.Ref()); return;
		case Type::Object:
		case Type::SerializableObject:
			{
				STINGRAYKIT_CHECK(_data.Object->IsSerializable(),
						StringBuilder() % "'any' object (" % Demangle(typeid(*_data.Object).name()) % ") is not a serializable one!");

				ar.Serialize(".class", _data.Object->GetClassName());
				_data.Object->Serialize(ar);
			}
			return;
		}

		STINGRAYKIT_THROW(StringBuilder() % "Unknown type: " % _type); //you could see warning about unhandled type if leave it here
	}

#undef SERIALIZE

#define DESERIALIZE(NAME) case Type::NAME: ar.Deserialize("val", _data.NAME); break

	void any::Deserialize(ObjectIStream& ar)
	{
		Destroy();

		Type type = Type::Empty;
		ar.Deserialize("type", type);

		switch (type)
		{
		case Type::Empty:	break;
		DESERIALIZE(Bool);
		DESERIALIZE(Char);
		DESERIALIZE(UChar);
		DESERIALIZE(Short);
		DESERIALIZE(UShort);
		DESERIALIZE(Int);
		DESERIALIZE(UInt);
		DESERIALIZE(Long);
		DESERIALIZE(ULong);
		DESERIALIZE(LongLong);
		DESERIALIZE(ULongLong);
		DESERIALIZE(Float);
		DESERIALIZE(Double);
		case Type::String:
			{
				std::string s;
				ar.Deserialize("val", s);
				Init(s);
			}
			break;
		case Type::Object:
		case Type::SerializableObject:
			{
				std::string classname;
				ar.Deserialize(".class", classname);

				_data.Object = Factory::Instance().Create<IObjectHolder>(classname);
				_data.Object->Deserialize(ar);
			}
			break;
		default:
			STINGRAYKIT_THROW(StringBuilder() % "Unknown type: " % _type);
		}

		_type = type;
	}

#undef DESERIALIZE

}
<commit_msg>any: make is-serializable condition more proper<commit_after>// Copyright (c) 2011 - 2019, GS Group, https://github.com/GSGroup
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted,
// provided that the above copyright notice and this permission notice appear in all copies.
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#include <stingraykit/any.h>

#include <stingraykit/serialization/Serialization.h>
#include <stingraykit/assert.h>

namespace stingray
{

	namespace Detail {
	namespace any
	{
		void ObjectHolder<ISerializablePtr>::Serialize(ObjectOStream& ar) const
		{ ar.Serialize("obj", Object); }

		void ObjectHolder<ISerializablePtr>::Deserialize(ObjectIStream& ar)
		{ ar.Deserialize("obj", Object); }
	}}

	void any::Copy(const any& other)
	{
		STINGRAYKIT_ASSERT(_type == Type::Empty);

		switch (other._type)
		{
		case Type::Empty:
		case Type::Bool:
		case Type::Char:
		case Type::UChar:
		case Type::Short:
		case Type::UShort:
		case Type::Int:
		case Type::UInt:
		case Type::Long:
		case Type::ULong:
		case Type::LongLong:
		case Type::ULongLong:
		case Type::Float:
		case Type::Double:
			_data = other._data;
			break;
		case Type::String:
			_data.String.Ctor(other._data.String.Ref());
			break;
		case Type::Object:
		case Type::SerializableObject:
			_data.Object = other._data.Object->Clone();
			break;
		default:
			STINGRAYKIT_THROW(ArgumentException("type", other._type));
		}

		_type = other._type;
	}

	void any::Destroy()
	{
		switch (_type)
		{
		case Type::String:
			_data.String.Dtor();
			break;
		case Type::Object:
		case Type::SerializableObject:
			delete _data.Object;
			break;
		default:
			break;
		}

		_type = Type::Empty;
	}

	bool any::IsSerializable() const
	{ return (_type != Type::Object && _type != Type::SerializableObject) || _data.Object->IsSerializable(); }

#define STRING(NAME) case Type::NAME: return stingray::ToString(_data.NAME)

	std::string any::ToString() const
	{
		switch (_type)
		{
		case Type::Empty:	return "<empty>";
		STRING(Bool);
		STRING(Char);
		STRING(UChar);
		STRING(Short);
		STRING(UShort);
		STRING(Int);
		STRING(UInt);
		STRING(Long);
		STRING(ULong);
		STRING(LongLong);
		STRING(ULongLong);
		STRING(Float);
		STRING(Double);
		case Type::String:
			return _data.String.Ref();
		case Type::Object:
		case Type::SerializableObject:
			return _data.Object->ToString();
		}

		STINGRAYKIT_THROW(StringBuilder() % "Unknown type: " % _type);
	}

#undef STRING

#define SERIALIZE(NAME) case Type::NAME: ar.Serialize("val", _data.NAME); return

	void any::Serialize(ObjectOStream& ar) const
	{
		ar.Serialize("type", _type);

		switch (_type)
		{
		case Type::Empty:	return;
		SERIALIZE(Bool);
		SERIALIZE(Char);
		SERIALIZE(UChar);
		SERIALIZE(Short);
		SERIALIZE(UShort);
		SERIALIZE(Int);
		SERIALIZE(UInt);
		SERIALIZE(Long);
		SERIALIZE(ULong);
		SERIALIZE(LongLong);
		SERIALIZE(ULongLong);
		SERIALIZE(Float);
		SERIALIZE(Double);
		case Type::String: ar.Serialize("val", _data.String.Ref()); return;
		case Type::Object:
		case Type::SerializableObject:
			{
				STINGRAYKIT_CHECK(_data.Object->IsSerializable(),
						StringBuilder() % "'any' object (" % Demangle(typeid(*_data.Object).name()) % ") is not a serializable one!");

				ar.Serialize(".class", _data.Object->GetClassName());
				_data.Object->Serialize(ar);
			}
			return;
		}

		STINGRAYKIT_THROW(StringBuilder() % "Unknown type: " % _type); //you could see warning about unhandled type if leave it here
	}

#undef SERIALIZE

#define DESERIALIZE(NAME) case Type::NAME: ar.Deserialize("val", _data.NAME); break

	void any::Deserialize(ObjectIStream& ar)
	{
		Destroy();

		Type type = Type::Empty;
		ar.Deserialize("type", type);

		switch (type)
		{
		case Type::Empty:	break;
		DESERIALIZE(Bool);
		DESERIALIZE(Char);
		DESERIALIZE(UChar);
		DESERIALIZE(Short);
		DESERIALIZE(UShort);
		DESERIALIZE(Int);
		DESERIALIZE(UInt);
		DESERIALIZE(Long);
		DESERIALIZE(ULong);
		DESERIALIZE(LongLong);
		DESERIALIZE(ULongLong);
		DESERIALIZE(Float);
		DESERIALIZE(Double);
		case Type::String:
			{
				std::string s;
				ar.Deserialize("val", s);
				Init(s);
			}
			break;
		case Type::Object:
		case Type::SerializableObject:
			{
				std::string classname;
				ar.Deserialize(".class", classname);

				_data.Object = Factory::Instance().Create<IObjectHolder>(classname);
				_data.Object->Deserialize(ar);
			}
			break;
		default:
			STINGRAYKIT_THROW(StringBuilder() % "Unknown type: " % _type);
		}

		_type = type;
	}

#undef DESERIALIZE

}
<|endoftext|>


<commit_before>#include "condor_common.h"
#include "condor_config.h"
#include "condor_debug.h"
#include "condor_string.h"
#include "condor_classad.h"
#include "condor_attributes.h"
#include "condor_adtypes.h"
#include "condor_qmgr.h"

/* gshadow is a wrapper around globusrun, meant to be a scheduler universe
 * scheduler. It monitors job status and updates its ClassAd.
 */

#define QUERY_DELAY_SECS_DEFAULT 15 //can be overriden ClassAd
#define QMGMT_TIMEOUT 300 //this is copied per Todd's advice from shadow val.

	//these are global so the sig handlers can use them.
char *contactString = NULL;
char *globusrun = NULL;

/*
  Wait up for one of those nice debuggers which attaches to a running
  process.  These days, most every debugger can do this with a notable
  exception being the ULTRIX version of "dbx".
*/
void wait_for_debugger( int do_wait )
{
   sigset_t sigset;

   // This is not strictly POSIX conforming becuase it uses SIGTRAP, but
   // since it is only used in those environments where is is defined, it
   // will probably pass...
#if defined(SIGTRAP)
      /* Make sure we don't block the signal used by the
      ** debugger to control the debugged process (us).
      */
   sigemptyset( &sigset );
   sigaddset( &sigset, SIGTRAP );
   sigprocmask( SIG_UNBLOCK, &sigset, 0 );
#endif

   while( do_wait )
      ;
}

void
remove_job( int signal ) {
	if ( contactString && globusrun && ( fork() == 0 ) ) {
			//calling globusrun -kill <contact string> is like condor_rm
			//I used exec here rather than popen because pclose blocks
			//until completion, and I figured we wanted a fast shutdown.
		execl( globusrun, globusrun, "-kill", contactString, NULL );

			//if we get here, execl failed...
		fprintf(stderr, "ERROR on execl %s %s -kill %s\n", globusrun,
				globusrun, contactString );
//		dprintf(D_ALWAYS, "ERROR on execl %s %s -kill %s\n", globusrun,
//				globusrun, contactString );
	}
	exit( signal );
}

void
my_exit( int signal ) {
//probably want to change this
	remove_job( signal );
}

int
main( int argc, char *argv[] ) {
	FILE *run = NULL;
	char Gstatus[64] = "";
	char buffer[2048] = "";
	char args[ATTRLIST_MAX_EXPRESSION] = "";
	int delay = QUERY_DELAY_SECS_DEFAULT;

		//install sig handlers
	signal( SIGUSR1, remove_job );
	signal( SIGQUIT, my_exit );
	signal( SIGTERM, my_exit );
	signal( SIGPIPE, SIG_IGN );
//wait_for_debugger( 1 );
		//atoi returns zero on error, so --help, etc. will print usage...
		//(there shouldn't be a cluster # 0....)
	int cluster;
	if ( !( cluster = atoi( argv[1] ) ) )
	{
//		dprintf( D_FULLDEBUG, "%s invalid command invocation\n" );
		fprintf( stderr, "usage: %s <cluster>.<pid> <sinful schedd addr> \\"
				"<globusrunpath> <args>\n", argv[0] );
		exit( 1 );
	}

	int proc = 0;
	char *decimal = strchr( argv[1], '.' );
	proc = atoi( ++decimal ); //move past decimal

		//THIS MUST be a fatal error if we cannot connect, since we
		//start the globus job without getting GlobusArgs...
	Qmgr_connection *schedd = ConnectQ( argv[2], QMGMT_TIMEOUT );
	if ( !schedd ) {
		//wait a bit and try once more...
		sleep( 30 );
		if ( !( schedd = ConnectQ( argv[2], QMGMT_TIMEOUT ) ) ) {
//			dprintf( D_ALWAYS, "%s ERROR, can't connect to schedd (%s)\n",argv[2]);
			fprintf( stderr, "%s ERROR, cannot connect to schedd (%s)\n", argv[2] );
			exit( 2 );
		}
	}

		//these two attributes should always exist in the ClassAd
	if ( GetAttributeString( cluster, proc, "GlobusStatus", Gstatus )
		|| GetAttributeString( cluster, proc, "GlobusArgs", args ) )
	{
//		dprintf(D_ALWAYS,"ERROR, cannot find ClassAd for %d.%d\n", cluster, proc);
		fprintf(stderr,"ERROR, cannot find ClassAd for %d.%d\n", cluster, proc);
		DisconnectQ( schedd );
		exit( 3 );
	}

		//these values *might* be in ClassAd
	GetAttributeString( cluster, proc, "GlobusContactString", buffer );
	if ( buffer[0] ) {
		contactString = strdup( buffer );
	}
	GetAttributeInt( cluster, proc, "GlobusQueryDelay", &delay );
	DisconnectQ( schedd ); //close because popen for globusrun takes long time
	schedd = NULL;

	globusrun = strdup( argv[3] );
	struct stat statbuf;
	if ( ( stat( globusrun, &statbuf ) < 0 )
//	|| (((statbuf.st_mode)&0xF000) != 0x0001)
	)
	{
//		dprintf( D_ALWAYS, "ERROR stat'ing globusrun (%s)\n", globusrun );
		fprintf( stderr, "ERROR stat'ing globusrun (%s)\n", globusrun );
		exit( 4 );
	}

		//if there was no contactString in the ad, it hasn't
		//been submitted to globusrun yet
	if ( !strcmp( contactString, "X" ) )
	{
		sprintf( buffer, "%s %s", globusrun, args );

		if ( !(run = popen( buffer, "r" ) ) ) {
//			dprintf( D_ALWAYS, "unable to popen \"%s\"", buffer );
			fprintf( stderr, "unable to popen \"%s\"", buffer );
			exit( 5 );
		}

		while ( !feof( run ) ) {
			if ( !fgets( buffer, 80, run ) ) {
				fprintf(stderr, "error reading output of globus job\n" );
			}
			if ( !strncasecmp( buffer, "http", 4 ) ) {
				contactString = strdup( chomp( buffer ) );
				break;
			}
		}
		if ( contactString ) {
			if ( schedd = ConnectQ( argv[2], QMGMT_TIMEOUT ) ) {
				SetAttributeString( cluster, proc, "GlobusContactString",
						contactString );
				DisconnectQ( schedd );
			}
			else {
				//FATAL error if we can't set GlobusContactString!
//				dprintf( D_ALWAYS, "Error contacting schedd %s\n", argv[2] );
				fprintf( stderr, "Error contacting schedd %s\n", argv[2] );
				exit( 6 );
			}

		}
		else {
//			dprintf( D_ALWAYS, "Error reading contactString from globusrun\n" );
			fprintf( stderr, "Error reading contactString from globusrun\n" );
			exit( 7 );
		}
	}
	schedd = NULL;

	FILE *statusfp = NULL;
	char status[80] = "";
	sprintf( buffer, "%s -status %s", globusrun, contactString );

		//loop until we're done or killed with a signal
	while ( strcasecmp( Gstatus, "DONE" ) ) {

		if ( !(statusfp = popen( buffer, "r" ) ) ) {
//			dprintf( D_ALWAYS, "cannot popen( %s )\n", buffer );
			fprintf( stderr, "cannot popen( %s )\n", buffer );
			exit( 8 );
		}
		if ( !fgets( status, 80, statusfp ) ) {
//			dprintf( D_ALWAYS, "pipe read errno %d\n", errno );
			fprintf( stderr, "pipe read errno %d\n", errno );
		}
		chomp( status );

		//I might have to close stderr at this point, a bug in globus reports
		//Error to stderr, but nothing to stdout.
		//I am currently using a modified Globusrun until they fix the bug.

		if ( !strncasecmp( status, "ERROR", 5 ) ) {
			strcpy( status, "DONE" );
		}

		pclose( statusfp );
		if ( strcasecmp( Gstatus, status ) ) {
			strcpy( Gstatus, status );

				//this update is NOT fatal, just try again later
			if ( schedd = ConnectQ( argv[2], QMGMT_TIMEOUT ) ) {
				SetAttributeString( cluster, proc, "GlobusStatus", Gstatus );
				DisconnectQ( schedd );
			}
			else {
//				dprintf( D_ALWAYS, "unable to update classAd for %d.%d\n",
//					cluster, proc );
				fprintf( stderr, "unable to update classAd for %d.%d\n",
					cluster, proc );
			}

		}
		sleep( delay );
	}
}
<commit_msg>Added a decl for chomp so that it will compile with gcc 2.95<commit_after>#include "condor_common.h"
#include "condor_config.h"
#include "condor_debug.h"
#include "condor_string.h"
#include "condor_classad.h"
#include "condor_attributes.h"
#include "condor_adtypes.h"
#include "condor_qmgr.h"

/* gshadow is a wrapper around globusrun, meant to be a scheduler universe
 * scheduler. It monitors job status and updates its ClassAd.
 */

#define QUERY_DELAY_SECS_DEFAULT 15 //can be overriden ClassAd
#define QMGMT_TIMEOUT 300 //this is copied per Todd's advice from shadow val.

	//these are global so the sig handlers can use them.
char *contactString = NULL;
char *globusrun = NULL;

extern "C" char * chomp(char*);

/*
  Wait up for one of those nice debuggers which attaches to a running
  process.  These days, most every debugger can do this with a notable
  exception being the ULTRIX version of "dbx".
*/
void wait_for_debugger( int do_wait )
{
   sigset_t sigset;

   // This is not strictly POSIX conforming becuase it uses SIGTRAP, but
   // since it is only used in those environments where is is defined, it
   // will probably pass...
#if defined(SIGTRAP)
      /* Make sure we don't block the signal used by the
      ** debugger to control the debugged process (us).
      */
   sigemptyset( &sigset );
   sigaddset( &sigset, SIGTRAP );
   sigprocmask( SIG_UNBLOCK, &sigset, 0 );
#endif

   while( do_wait )
      ;
}

void
remove_job( int signal ) {
	if ( contactString && globusrun && ( fork() == 0 ) ) {
			//calling globusrun -kill <contact string> is like condor_rm
			//I used exec here rather than popen because pclose blocks
			//until completion, and I figured we wanted a fast shutdown.
		execl( globusrun, globusrun, "-kill", contactString, NULL );

			//if we get here, execl failed...
		fprintf(stderr, "ERROR on execl %s %s -kill %s\n", globusrun,
				globusrun, contactString );
//		dprintf(D_ALWAYS, "ERROR on execl %s %s -kill %s\n", globusrun,
//				globusrun, contactString );
	}
	exit( signal );
}

void
my_exit( int signal ) {
//probably want to change this
	remove_job( signal );
}

int
main( int argc, char *argv[] ) {
	FILE *run = NULL;
	char Gstatus[64] = "";
	char buffer[2048] = "";
	char args[ATTRLIST_MAX_EXPRESSION] = "";
	int delay = QUERY_DELAY_SECS_DEFAULT;

		//install sig handlers
	signal( SIGUSR1, remove_job );
	signal( SIGQUIT, my_exit );
	signal( SIGTERM, my_exit );
	signal( SIGPIPE, SIG_IGN );
//wait_for_debugger( 1 );
		//atoi returns zero on error, so --help, etc. will print usage...
		//(there shouldn't be a cluster # 0....)
	int cluster;
	if ( !( cluster = atoi( argv[1] ) ) )
	{
//		dprintf( D_FULLDEBUG, "%s invalid command invocation\n" );
		fprintf( stderr, "usage: %s <cluster>.<pid> <sinful schedd addr> \\"
				"<globusrunpath> <args>\n", argv[0] );
		exit( 1 );
	}

	int proc = 0;
	char *decimal = strchr( argv[1], '.' );
	proc = atoi( ++decimal ); //move past decimal

		//THIS MUST be a fatal error if we cannot connect, since we
		//start the globus job without getting GlobusArgs...
	Qmgr_connection *schedd = ConnectQ( argv[2], QMGMT_TIMEOUT );
	if ( !schedd ) {
		//wait a bit and try once more...
		sleep( 30 );
		if ( !( schedd = ConnectQ( argv[2], QMGMT_TIMEOUT ) ) ) {
//			dprintf( D_ALWAYS, "%s ERROR, can't connect to schedd (%s)\n",argv[2]);
			fprintf( stderr, "%s ERROR, cannot connect to schedd (%s)\n", argv[2] );
			exit( 2 );
		}
	}

		//these two attributes should always exist in the ClassAd
	if ( GetAttributeString( cluster, proc, "GlobusStatus", Gstatus )
		|| GetAttributeString( cluster, proc, "GlobusArgs", args ) )
	{
//		dprintf(D_ALWAYS,"ERROR, cannot find ClassAd for %d.%d\n", cluster, proc);
		fprintf(stderr,"ERROR, cannot find ClassAd for %d.%d\n", cluster, proc);
		DisconnectQ( schedd );
		exit( 3 );
	}

		//these values *might* be in ClassAd
	GetAttributeString( cluster, proc, "GlobusContactString", buffer );
	if ( buffer[0] ) {
		contactString = strdup( buffer );
	}
	GetAttributeInt( cluster, proc, "GlobusQueryDelay", &delay );
	DisconnectQ( schedd ); //close because popen for globusrun takes long time
	schedd = NULL;

	globusrun = strdup( argv[3] );
	struct stat statbuf;
	if ( ( stat( globusrun, &statbuf ) < 0 )
//	|| (((statbuf.st_mode)&0xF000) != 0x0001)
	)
	{
//		dprintf( D_ALWAYS, "ERROR stat'ing globusrun (%s)\n", globusrun );
		fprintf( stderr, "ERROR stat'ing globusrun (%s)\n", globusrun );
		exit( 4 );
	}

		//if there was no contactString in the ad, it hasn't
		//been submitted to globusrun yet
	if ( !strcmp( contactString, "X" ) )
	{
		sprintf( buffer, "%s %s", globusrun, args );

		if ( !(run = popen( buffer, "r" ) ) ) {
//			dprintf( D_ALWAYS, "unable to popen \"%s\"", buffer );
			fprintf( stderr, "unable to popen \"%s\"", buffer );
			exit( 5 );
		}

		while ( !feof( run ) ) {
			if ( !fgets( buffer, 80, run ) ) {
				fprintf(stderr, "error reading output of globus job\n" );
			}
			if ( !strncasecmp( buffer, "http", 4 ) ) {
				contactString = strdup( chomp( buffer ) );
				break;
			}
		}
		if ( contactString ) {
			if ( schedd = ConnectQ( argv[2], QMGMT_TIMEOUT ) ) {
				SetAttributeString( cluster, proc, "GlobusContactString",
						contactString );
				DisconnectQ( schedd );
			}
			else {
				//FATAL error if we can't set GlobusContactString!
//				dprintf( D_ALWAYS, "Error contacting schedd %s\n", argv[2] );
				fprintf( stderr, "Error contacting schedd %s\n", argv[2] );
				exit( 6 );
			}

		}
		else {
//			dprintf( D_ALWAYS, "Error reading contactString from globusrun\n" );
			fprintf( stderr, "Error reading contactString from globusrun\n" );
			exit( 7 );
		}
	}
	schedd = NULL;

	FILE *statusfp = NULL;
	char status[80] = "";
	sprintf( buffer, "%s -status %s", globusrun, contactString );

		//loop until we're done or killed with a signal
	while ( strcasecmp( Gstatus, "DONE" ) ) {

		if ( !(statusfp = popen( buffer, "r" ) ) ) {
//			dprintf( D_ALWAYS, "cannot popen( %s )\n", buffer );
			fprintf( stderr, "cannot popen( %s )\n", buffer );
			exit( 8 );
		}
		if ( !fgets( status, 80, statusfp ) ) {
//			dprintf( D_ALWAYS, "pipe read errno %d\n", errno );
			fprintf( stderr, "pipe read errno %d\n", errno );
		}
		chomp( status );

		//I might have to close stderr at this point, a bug in globus reports
		//Error to stderr, but nothing to stdout.
		//I am currently using a modified Globusrun until they fix the bug.

		if ( !strncasecmp( status, "ERROR", 5 ) ) {
			strcpy( status, "DONE" );
		}

		pclose( statusfp );
		if ( strcasecmp( Gstatus, status ) ) {
			strcpy( Gstatus, status );

				//this update is NOT fatal, just try again later
			if ( schedd = ConnectQ( argv[2], QMGMT_TIMEOUT ) ) {
				SetAttributeString( cluster, proc, "GlobusStatus", Gstatus );
				DisconnectQ( schedd );
			}
			else {
//				dprintf( D_ALWAYS, "unable to update classAd for %d.%d\n",
//					cluster, proc );
				fprintf( stderr, "unable to update classAd for %d.%d\n",
					cluster, proc );
			}

		}
		sleep( delay );
	}
}
<|endoftext|>