<commit_before>
#include "Globals.h"  // NOTE: MSVC stupidness requires this to be the same across all modules

#include "SandSimulator.h"
#include "../World.h"
#include "../BlockID.h"
#include "../Defines.h"
#include "../FallingBlock.h"
#include "../Chunk.h"

cSandSimulator::cSandSimulator(cWorld & a_World, cIniFile & a_IniFile) :
	cSimulator(a_World),
	m_TotalBlocks(0)
{
	m_IsInstantFall = a_IniFile.GetValueSetB("Physics", "SandInstantFall", false);
}

void cSandSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk)
{
	cSandSimulatorChunkData & ChunkData = a_Chunk->GetSandSimulatorData();
	if (ChunkData.empty())
	{
		return;
	}

	int BaseX = a_Chunk->GetPosX() * cChunkDef::Width;
	int BaseZ = a_Chunk->GetPosZ() * cChunkDef::Width;
	for (cSandSimulatorChunkData::const_iterator itr = ChunkData.begin(), end = ChunkData.end(); itr != end; ++itr)
	{
		BLOCKTYPE BlockType = a_Chunk->GetBlock(itr->x, itr->y, itr->z);
		if (!IsAllowedBlock(BlockType) || (itr->y <= 0))
		{
			continue;
		}

		BLOCKTYPE BlockBelow = (itr->y > 0) ? a_Chunk->GetBlock(itr->x, itr->y - 1, itr->z) : E_BLOCK_AIR;
		if (CanStartFallingThrough(BlockBelow))
		{
			if (m_IsInstantFall)
			{
				DoInstantFall(a_Chunk, itr->x, itr->y, itr->z);
				continue;
			}
			Vector3i Pos;
			Pos.x = itr->x + BaseX;
			Pos.y = itr->y;
			Pos.z = itr->z + BaseZ;
			cFallingBlock * FallingBlock = new cFallingBlock(Pos, BlockType, a_Chunk->GetMeta(itr->x, itr->y, itr->z));
			FallingBlock->Initialize(&m_World);
			a_Chunk->SetBlock(itr->x, itr->y, itr->z, E_BLOCK_AIR, 0);
		}
	}
	m_TotalBlocks -= ChunkData.size();
	ChunkData.clear();
}

bool cSandSimulator::IsAllowedBlock(BLOCKTYPE a_BlockType)
{
	switch (a_BlockType)
	{
		case E_BLOCK_SAND:
		case E_BLOCK_GRAVEL:
		case E_BLOCK_ANVIL:
		{
			return true;
		}
	}
	return false;
}

void cSandSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk)
{
	if (a_Chunk == NULL)
	{
		return;
	}
	int RelX = a_BlockX - a_Chunk->GetPosX() * cChunkDef::Width;
	int RelZ = a_BlockZ - a_Chunk->GetPosZ() * cChunkDef::Width;
	if (!IsAllowedBlock(a_Chunk->GetBlock(RelX, a_BlockY, RelZ)))
	{
		return;
	}

	// Check for duplicates:
	cSandSimulatorChunkData & ChunkData = a_Chunk->GetSandSimulatorData();
	for (cSandSimulatorChunkData::iterator itr = ChunkData.begin(); itr != ChunkData.end(); ++itr)
	{
		if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ))
		{
			return;
		}
	}

	m_TotalBlocks += 1;
	ChunkData.push_back(cCoordWithInt(RelX, a_BlockY, RelZ));
}

bool cSandSimulator::CanStartFallingThrough(BLOCKTYPE a_BlockType)
{
	switch (a_BlockType)
	{
		case E_BLOCK_AIR:
		case E_BLOCK_FIRE:
		case E_BLOCK_LAVA:
		case E_BLOCK_STATIONARY_LAVA:
		case E_BLOCK_STATIONARY_WATER:
		case E_BLOCK_WATER:
		case E_BLOCK_SNOW:
		{
			return true;
		}
	}
	return false;
}

bool cSandSimulator::CanContinueFallThrough(BLOCKTYPE a_BlockType)
{
	switch (a_BlockType)
	{
		case E_BLOCK_AIR:
		case E_BLOCK_BROWN_MUSHROOM:
		case E_BLOCK_COBWEB:
		case E_BLOCK_CROPS:
		case E_BLOCK_DEAD_BUSH:
		case E_BLOCK_DETECTOR_RAIL:
		case E_BLOCK_FIRE:
		case E_BLOCK_FLOWER_POT:
		case E_BLOCK_LAVA:
		case E_BLOCK_LEVER:
		case E_BLOCK_MINECART_TRACKS:
		case E_BLOCK_MELON_STEM:
		case E_BLOCK_POWERED_RAIL:
		case E_BLOCK_PUMPKIN_STEM:
		case E_BLOCK_REDSTONE_REPEATER_OFF:
		case E_BLOCK_REDSTONE_REPEATER_ON:
		case E_BLOCK_REDSTONE_TORCH_OFF:
		case E_BLOCK_REDSTONE_TORCH_ON:
		case E_BLOCK_REDSTONE_WIRE:
		case E_BLOCK_RED_MUSHROOM:
		case E_BLOCK_RED_ROSE:
		case E_BLOCK_SIGN_POST:
		case E_BLOCK_STATIONARY_LAVA:
		case E_BLOCK_STATIONARY_WATER:
		case E_BLOCK_STONE_BUTTON:
		case E_BLOCK_STONE_PRESSURE_PLATE:
		case E_BLOCK_TALL_GRASS:
		case E_BLOCK_TORCH:
		case E_BLOCK_TRAPDOOR:
		case E_BLOCK_TRIPWIRE:
		case E_BLOCK_TRIPWIRE_HOOK:
		case E_BLOCK_WALLSIGN:
		case E_BLOCK_WATER:
		case E_BLOCK_WOODEN_BUTTON:
		case E_BLOCK_WOODEN_PRESSURE_PLATE:
		case E_BLOCK_YELLOW_FLOWER:
		case E_BLOCK_SNOW:
		{
			return true;
		}
	}
	return false;
}

bool cSandSimulator::IsReplacedOnRematerialization(BLOCKTYPE a_BlockType)
{
	switch (a_BlockType)
	{
		case E_BLOCK_AIR:
		case E_BLOCK_DEAD_BUSH:
		case E_BLOCK_FIRE:
		case E_BLOCK_LAVA:
		case E_BLOCK_STATIONARY_LAVA:
		case E_BLOCK_STATIONARY_WATER:
		case E_BLOCK_TALL_GRASS:
		case E_BLOCK_WATER:
		case E_BLOCK_SNOW:
		{
			return true;
		}
	}
	return false;
}

bool cSandSimulator::DoesBreakFallingThrough(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
	switch (a_BlockType)
	{
		case E_BLOCK_STONE_SLAB:
		case E_BLOCK_WOODEN_SLAB:
		{
			return ((a_BlockMeta & 0x08) == 0);  // Only a bottom-slab breaks the block
		}
	}
	return false;
}

void cSandSimulator::FinishFalling(
	cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ,
	BLOCKTYPE a_FallingBlockType, NIBBLETYPE a_FallingBlockMeta
)
{
	ASSERT(a_BlockY < cChunkDef::Height);

	BLOCKTYPE CurrentBlockType = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
	if ((a_FallingBlockType == E_BLOCK_ANVIL) || IsReplacedOnRematerialization(CurrentBlockType))
	{
		// Rematerialize the material here:
		a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, a_FallingBlockType, a_FallingBlockMeta);
		return;
	}

	// Create a pickup instead:
	cItems Pickups;
	Pickups.Add((ENUM_ITEM_ID)a_FallingBlockType, 1, a_FallingBlockMeta);
	a_World->SpawnItemPickups(Pickups, (double)a_BlockX + 0.5, (double)a_BlockY + 0.5, (double)a_BlockZ + 0.5, 0);
}

void cSandSimulator::DoInstantFall(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
{
	// Remove the original block:
	BLOCKTYPE  FallingBlockType;
	NIBBLETYPE FallingBlockMeta;
	a_Chunk->GetBlockTypeMeta(a_RelX, a_RelY, a_RelZ, FallingBlockType, FallingBlockMeta);
	a_Chunk->SetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_AIR, 0);

	// Search for a place to put it:
	for (int y = a_RelY - 1; y >= 0; y--)
	{
		BLOCKTYPE BlockType;
		NIBBLETYPE BlockMeta;
		a_Chunk->GetBlockTypeMeta(a_RelX, y, a_RelZ, BlockType, BlockMeta);
		int BlockY;
		if (DoesBreakFallingThrough(BlockType, BlockMeta))
		{
			BlockY = y;
		}
		else if (!CanContinueFallThrough(BlockType))
		{
			BlockY = y + 1;
		}
		else
		{
			// Can fall further down
			continue;
		}

		// Finish the fall at the found bottom:
		int BlockX = a_RelX + a_Chunk->GetPosX() * cChunkDef::Width;
		int BlockZ = a_RelZ + a_Chunk->GetPosZ() * cChunkDef::Width;
		FinishFalling(&m_World, BlockX, BlockY, BlockZ, FallingBlockType, FallingBlockMeta);
		return;
	}

	// The block just "fell off the world" without leaving a trace
}

<commit_msg>Please keep the lists alpha-sorted<commit_after>
#include "Globals.h"  // NOTE: MSVC stupidness requires this to be the same across all modules

#include "SandSimulator.h"
#include "../World.h"
#include "../BlockID.h"
#include "../Defines.h"
#include "../FallingBlock.h"
#include "../Chunk.h"

cSandSimulator::cSandSimulator(cWorld & a_World, cIniFile & a_IniFile) :
	cSimulator(a_World),
	m_TotalBlocks(0)
{
	m_IsInstantFall = a_IniFile.GetValueSetB("Physics", "SandInstantFall", false);
}

void cSandSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk)
{
	cSandSimulatorChunkData & ChunkData = a_Chunk->GetSandSimulatorData();
	if (ChunkData.empty())
	{
		return;
	}

	int BaseX = a_Chunk->GetPosX() * cChunkDef::Width;
	int BaseZ = a_Chunk->GetPosZ() * cChunkDef::Width;
	for (cSandSimulatorChunkData::const_iterator itr = ChunkData.begin(), end = ChunkData.end(); itr != end; ++itr)
	{
		BLOCKTYPE BlockType = a_Chunk->GetBlock(itr->x, itr->y, itr->z);
		if (!IsAllowedBlock(BlockType) || (itr->y <= 0))
		{
			continue;
		}

		BLOCKTYPE BlockBelow = (itr->y > 0) ? a_Chunk->GetBlock(itr->x, itr->y - 1, itr->z) : E_BLOCK_AIR;
		if (CanStartFallingThrough(BlockBelow))
		{
			if (m_IsInstantFall)
			{
				DoInstantFall(a_Chunk, itr->x, itr->y, itr->z);
				continue;
			}
			Vector3i Pos;
			Pos.x = itr->x + BaseX;
			Pos.y = itr->y;
			Pos.z = itr->z + BaseZ;
			cFallingBlock * FallingBlock = new cFallingBlock(Pos, BlockType, a_Chunk->GetMeta(itr->x, itr->y, itr->z));
			FallingBlock->Initialize(&m_World);
			a_Chunk->SetBlock(itr->x, itr->y, itr->z, E_BLOCK_AIR, 0);
		}
	}
	m_TotalBlocks -= ChunkData.size();
	ChunkData.clear();
}

bool cSandSimulator::IsAllowedBlock(BLOCKTYPE a_BlockType)
{
	switch (a_BlockType)
	{
		case E_BLOCK_SAND:
		case E_BLOCK_GRAVEL:
		case E_BLOCK_ANVIL:
		{
			return true;
		}
	}
	return false;
}

void cSandSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk)
{
	if (a_Chunk == NULL)
	{
		return;
	}
	int RelX = a_BlockX - a_Chunk->GetPosX() * cChunkDef::Width;
	int RelZ = a_BlockZ - a_Chunk->GetPosZ() * cChunkDef::Width;
	if (!IsAllowedBlock(a_Chunk->GetBlock(RelX, a_BlockY, RelZ)))
	{
		return;
	}

	// Check for duplicates:
	cSandSimulatorChunkData & ChunkData = a_Chunk->GetSandSimulatorData();
	for (cSandSimulatorChunkData::iterator itr = ChunkData.begin(); itr != ChunkData.end(); ++itr)
	{
		if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ))
		{
			return;
		}
	}

	m_TotalBlocks += 1;
	ChunkData.push_back(cCoordWithInt(RelX, a_BlockY, RelZ));
}

bool cSandSimulator::CanStartFallingThrough(BLOCKTYPE a_BlockType)
{
	// Please keep the list alpha-sorted
	switch (a_BlockType)
	{
		case E_BLOCK_AIR:
		case E_BLOCK_FIRE:
		case E_BLOCK_LAVA:
		case E_BLOCK_SNOW:
		case E_BLOCK_STATIONARY_LAVA:
		case E_BLOCK_STATIONARY_WATER:
		case E_BLOCK_WATER:
		{
			return true;
		}
	}
	return false;
}

bool cSandSimulator::CanContinueFallThrough(BLOCKTYPE a_BlockType)
{
	// Please keep the list alpha-sorted
	switch (a_BlockType)
	{
		case E_BLOCK_AIR:
		case E_BLOCK_BROWN_MUSHROOM:
		case E_BLOCK_COBWEB:
		case E_BLOCK_CROPS:
		case E_BLOCK_DEAD_BUSH:
		case E_BLOCK_DETECTOR_RAIL:
		case E_BLOCK_FIRE:
		case E_BLOCK_FLOWER_POT:
		case E_BLOCK_LAVA:
		case E_BLOCK_LEVER:
		case E_BLOCK_MINECART_TRACKS:
		case E_BLOCK_MELON_STEM:
		case E_BLOCK_POWERED_RAIL:
		case E_BLOCK_PUMPKIN_STEM:
		case E_BLOCK_REDSTONE_REPEATER_OFF:
		case E_BLOCK_REDSTONE_REPEATER_ON:
		case E_BLOCK_REDSTONE_TORCH_OFF:
		case E_BLOCK_REDSTONE_TORCH_ON:
		case E_BLOCK_REDSTONE_WIRE:
		case E_BLOCK_RED_MUSHROOM:
		case E_BLOCK_RED_ROSE:
		case E_BLOCK_SIGN_POST:
		case E_BLOCK_SNOW:
		case E_BLOCK_STATIONARY_LAVA:
		case E_BLOCK_STATIONARY_WATER:
		case E_BLOCK_STONE_BUTTON:
		case E_BLOCK_STONE_PRESSURE_PLATE:
		case E_BLOCK_TALL_GRASS:
		case E_BLOCK_TORCH:
		case E_BLOCK_TRAPDOOR:
		case E_BLOCK_TRIPWIRE:
		case E_BLOCK_TRIPWIRE_HOOK:
		case E_BLOCK_WALLSIGN:
		case E_BLOCK_WATER:
		case E_BLOCK_WOODEN_BUTTON:
		case E_BLOCK_WOODEN_PRESSURE_PLATE:
		case E_BLOCK_YELLOW_FLOWER:
		{
			return true;
		}
	}
	return false;
}

bool cSandSimulator::IsReplacedOnRematerialization(BLOCKTYPE a_BlockType)
{
	// Please keep the list alpha-sorted
	switch (a_BlockType)
	{
		case E_BLOCK_AIR:
		case E_BLOCK_DEAD_BUSH:
		case E_BLOCK_FIRE:
		case E_BLOCK_LAVA:
		case E_BLOCK_SNOW:
		case E_BLOCK_STATIONARY_LAVA:
		case E_BLOCK_STATIONARY_WATER:
		case E_BLOCK_TALL_GRASS:
		case E_BLOCK_WATER:
		{
			return true;
		}
	}
	return false;
}

bool cSandSimulator::DoesBreakFallingThrough(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
	switch (a_BlockType)
	{
		case E_BLOCK_STONE_SLAB:
		case E_BLOCK_WOODEN_SLAB:
		{
			return ((a_BlockMeta & 0x08) == 0);  // Only a bottom-slab breaks the block
		}
	}
	return false;
}

void cSandSimulator::FinishFalling(
	cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ,
	BLOCKTYPE a_FallingBlockType, NIBBLETYPE a_FallingBlockMeta
)
{
	ASSERT(a_BlockY < cChunkDef::Height);

	BLOCKTYPE CurrentBlockType = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
	if ((a_FallingBlockType == E_BLOCK_ANVIL) || IsReplacedOnRematerialization(CurrentBlockType))
	{
		// Rematerialize the material here:
		a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, a_FallingBlockType, a_FallingBlockMeta);
		return;
	}

	// Create a pickup instead:
	cItems Pickups;
	Pickups.Add((ENUM_ITEM_ID)a_FallingBlockType, 1, a_FallingBlockMeta);
	a_World->SpawnItemPickups(Pickups, (double)a_BlockX + 0.5, (double)a_BlockY + 0.5, (double)a_BlockZ + 0.5, 0);
}

void cSandSimulator::DoInstantFall(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
{
	// Remove the original block:
	BLOCKTYPE  FallingBlockType;
	NIBBLETYPE FallingBlockMeta;
	a_Chunk->GetBlockTypeMeta(a_RelX, a_RelY, a_RelZ, FallingBlockType, FallingBlockMeta);
	a_Chunk->SetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_AIR, 0);

	// Search for a place to put it:
	for (int y = a_RelY - 1; y >= 0; y--)
	{
		BLOCKTYPE BlockType;
		NIBBLETYPE BlockMeta;
		a_Chunk->GetBlockTypeMeta(a_RelX, y, a_RelZ, BlockType, BlockMeta);
		int BlockY;
		if (DoesBreakFallingThrough(BlockType, BlockMeta))
		{
			BlockY = y;
		}
		else if (!CanContinueFallThrough(BlockType))
		{
			BlockY = y + 1;
		}
		else
		{
			// Can fall further down
			continue;
		}

		// Finish the fall at the found bottom:
		int BlockX = a_RelX + a_Chunk->GetPosX() * cChunkDef::Width;
		int BlockZ = a_RelZ + a_Chunk->GetPosZ() * cChunkDef::Width;
		FinishFalling(&m_World, BlockX, BlockY, BlockZ, FallingBlockType, FallingBlockMeta);
		return;
	}

	// The block just "fell off the world" without leaving a trace
}

<|endoftext|>


<commit_before>#include "player.h"
#include "ui_player.h"

#include "controller/commandcontroller.h"
#include "controller/selectioncontroller.h"
#include "geomObject/annotationgraphicsitemfactory.h"
#include "plugins/pluginloader.h"
#include <AnnotatorLib/Algo/InterpolateAnnotation.h>
#include <AnnotatorLib/Commands/NewAnnotation.h>
#include <AnnotatorLib/Commands/UpdateAnnotation.h>
#include <AnnotatorLib/Frame.h>
#include <QDebug>
#include <QFile>
#include <QMessageBox>
#include <geomObject/annotationgraphicsitem.h>

Player::Player(QWidget *parent) : QWidget(parent), ui(new Ui::Player) {
  ui->setupUi(this);
  videoplayer = new Videoplayer; // Creating an instance of class videoplayer

  ui->btnNext->setAutoRepeat(true);
  ui->btnPrev->setAutoRepeat(true);

  videoplayer->setDelay(ui->speedSpinBox->value()); // get default value

  updateStatus(false); // set Status disable
  updateBtn();         // update the button Play & Pause

  connect(videoplayer, SIGNAL(showFrame(cv::Mat)), this,
          SLOT(showFrame(cv::Mat)));
  connect(videoplayer, SIGNAL(updateFrame(long)), this,
          SLOT(updateFrame(long)));
  connect(ui->horizontalSlider, SIGNAL(sendClickPosition(int)), this,
          SLOT(setSliderValue(int)));
  connect(videoplayer, SIGNAL(updateBtn()), this, SLOT(updateBtn()));
  connect(videoplayer, SIGNAL(sleep(int)), this, SLOT(sleep(int)));
  connect(videoplayer, SIGNAL(updateHorizontalSlider()), this,
          SLOT(updateHorizontalSlider()));
  connect(videoplayer, SIGNAL(setInputCoordinate(QPoint)), this,
          SLOT(setInputCoordinate(QPoint)));
  // command controller
  connect(CommandController::instance(), SIGNAL(signal_requestFrameRedraw()),
          this, SLOT(reload()));

  // create graphicsview to be able to draw objects on screen.
  scene = new OwnGraphicScene();
  overlay = new OwnGraphicView(scene, this);
  // overlay->setEnabled(false);
  ui->playerLayout->addWidget(overlay);
  overlay->show();

  connect(scene, SIGNAL(on_btnPause_clicked()), this,
          SLOT(on_btnPause_clicked()));

  connect(
      this, SIGNAL(signal_objectSelection(shared_ptr<AnnotatorLib::Object>)),
      scene, SLOT(on_signal_objectSelection(shared_ptr<AnnotatorLib::Object>)));
}

Player::~Player() {
  clearAnnotationsGraphics();
  delete videoplayer;
  delete scene;
  delete ui;
}

/**
 * setInputCoordinate	-	set image/video coordinate into scene to adjust
 * the coordinate system.
 */
void Player::setInputCoordinate(QPoint point) {
  scene->inputCoordinate = point;
}

void Player::setRateLabel(QLabel *label) { this->rateLabel = label; }

QString Player::getRateValue() {
  return "FPS: " + QString::number(videoplayer->rate);
}

std::shared_ptr<AnnotatorLib::Session> Player::getSession() { return this->session; }

void Player::closeProject() {
  this->currentFrame = cv::Mat();
  setProject(nullptr);
  this->videoplayer->close();
  scene->setSession(nullptr);
  updateStatus(false);           //disable ui
}

void Player::setProject(std::shared_ptr<AnnotatorLib::Project> project) {
  this->project = project;

  this->session = project ? project->getSession() : nullptr;

  ui->horizontalSlider->setMaximum(project ? project->getImageSet()->size() : 0);

  videoplayer->setImageSet(project ? project->getImageSet() : nullptr);
  ui->horizontalSlider->setMaximum(project ? project->getImageSet()->size() : 0);

  cv::Mat firstImage = project ? project->getImageSet()->next() : cv::Mat();
  scene->setSceneRect(0, 0, firstImage.cols, firstImage.rows);
  scene->setSession(project ? session : nullptr);

  this->setEnabled(project.get() != nullptr);

  if (project) {
    overlay->fitInView(scene->sceneRect());
    project->getImageSet()->gotoPosition(0);
  }

  updateStatus(true);
  updateBtn();
  updateTimeLabel();
}

void Player::loadVideo(QString fileName) {
  if (!fileName.isEmpty()) {
    if (LoadFile(fileName)) {
      updateStatus(true);
      updateBtn();
      setEnabled(true);
    }
  }
}

void Player::clearAnnotationsGraphics() {
  while (!annotationGraphics.empty()) {
    delete annotationGraphics.front();
    annotationGraphics.pop_front();
  }
  scene->update();
}

/**
 * LoadFile	-	Open and load a video
 *
 * @param fileName	-	file Path
 *
 * @return true if the file is successfully loaded
 */
bool Player::LoadFile(const QString &fileName) {
  QFile file(fileName);
  if (!file.open(QFile::ReadOnly)) {
    QMessageBox::warning(this, tr("VideoPlayer"),
                         tr("Unable to load file %1:\n%2.")
                             .arg(fileName)
                             .arg(file.errorString()));
    return false;
  }

  // change the cursor
  QApplication::setOverrideCursor(Qt::WaitCursor);

  // input file
  if (!videoplayer->setInput(fileName.toStdString())) {
    QMessageBox::warning(this, tr("VideoPlayer"),
                         tr("Unable to load file %1:\n%2.")
                             .arg(fileName)
                             .arg(file.errorString()));
    return false;
  }

  // restore the cursor
  QApplication::restoreOverrideCursor();

  // update the time label
  updateTimeLabel();

  return true;
}

/**
 * updateStatus	-	Update the enabled property of menu
 *
 * @param var	-	the enable variable
 */
void Player::updateStatus(bool enable) {
  ui->horizontalSlider->setEnabled(enable);
  ui->btnPrev->setEnabled(enable);
  ui->btnNext->setEnabled(enable);
  ui->btnPlay->setEnabled(enable);
  ui->btnStop->setEnabled(enable);
  ui->btnPause->setEnabled(enable);

  if (!enable) {
    ui->horizontalSlider->setValue(0);
  }
}

/**get()
 * updateBtn	-	update the button Play & Pause
 *
 */
void Player::updateBtn() {
  bool isStop = videoplayer->isStop();
  ui->btnPause->setVisible(!isStop);
  ui->btnPlay->setVisible(isStop);
}

/**
 * showFrame	-	show a frame
 *
 * @param image	-	the image to be showed
 *
 */
void Player::showFrame(cv::Mat frame) {
  currentFrame = frame;
  cv::Mat tmp;

  cv::Size size;
  size.width = scene->sceneRect().width();
  size.height = scene->sceneRect().height();

  tmp.convertTo(tmp, CV_8U);
  cv::resize(currentFrame, tmp, size);
  cvtColor(currentFrame, tmp, CV_BGR2RGB);

  QImage img = QImage((const unsigned char *)(tmp.data), tmp.cols, tmp.rows,
                      tmp.step, QImage::Format_RGB888);

  scene->setSceneRect(img.rect());
  overlay->fitInView(img.rect());
  QPixmap pim = QPixmap::fromImage(img);
  scene->setBackgroundBrush(pim);
}

void Player::updateFrame(long frame_nmb) {
  shared_ptr<AnnotatorLib::Frame> f = session->getFrame(frame_nmb);
  if (!f)
    f = std::make_shared<AnnotatorLib::Frame>(
        frame_nmb); // create temporary frame

  if (autoAnnotation) {
    Annotator::Plugin *plugin =
        Annotator::PluginLoader::getInstance().getCurrent();

    if (plugin && SelectionController::instance()->getSelectedObject()) {
      // calculate only if object is not finished.
      shared_ptr<AnnotatorLib::Annotation> previousA = nullptr;
      shared_ptr<AnnotatorLib::Annotation> nextA = nullptr;
      SelectionController::instance()
          ->getSelectedObject()
          ->findClosestKeyFrames(f, previousA, nextA);
      if (previousA !=
          SelectionController::instance()
              ->getSelectedObject()
              ->getLastAnnotation())
        plugin->calculate(SelectionController::instance()->getSelectedObject(),
                          f);
    }
  }

  this->scene->setCurrentFrame(frame_nmb);
  showAnnotationsOfFrame(f);
  this->scene->update();
}

void Player::showAnnotationsOfFrame(shared_ptr<AnnotatorLib::Frame> frame) {
  clearAnnotationsGraphics();

  for (shared_ptr<AnnotatorLib::Annotation> annotation :
       AnnotatorLib::Algo::InterpolateAnnotation::getInterpolations(
           this->session, frame)) {

    AnnotationGraphicsItem *graphicsItem =
        AnnotationGraphicsItemFactory::createItem(annotation);

    connect(SelectionController::instance(),
            SIGNAL(signal_objectSelection(shared_ptr<AnnotatorLib::Object>)),
            graphicsItem,
            SLOT(on_objectSelected(shared_ptr<AnnotatorLib::Object>)));

    graphicsItem->setPlayer(this);
    scene->addItem(graphicsItem);
    annotationGraphics.push_back(graphicsItem);
  }

  // if nothing is selected take first annotation
  if (!SelectionController::instance()->getSelectedObject()) {
    if (annotationGraphics.empty()) {
      SelectionController::instance()->setSelectedObject(nullptr);
    } else {
      SelectionController::instance()->setSelectedObject(
          annotationGraphics.front()->getAnnotation()->getObject());
    }
  }
}

/**
 * updateHorizontalSlider	-	update the progress bar
 *
 */
void Player::updateHorizontalSlider() {
  // update the progress bar
  ui->horizontalSlider->setValue(videoplayer->getCurFrameNr());
  updateTimeLabel();
}

void Player::on_horizontalSlider_sliderMoved(int newpos) {
  long pos =
      newpos * videoplayer->getTotalFrameNr() / ui->horizontalSlider->maximum();
  on_frameSelected(pos);
}

/**
 * setSliderValue	-	set new value on the progress bar
 *
*/
void Player::setSliderValue(int newpos) {
  ui->horizontalSlider->setValue(newpos);
  on_horizontalSlider_sliderMoved(newpos);
}

void Player::on_frameSelected(long index) {
  this->videoplayer->on_frameSelected(index - 1); // why -1?
  updateTimeLabel();
  updateHorizontalSlider();
}

/**
 * updateTimeLabel	-	update Time Label
 */
void Player::updateTimeLabel() {

  double pos_ms = 0;
  double length_ms = 0;
  long cfn = 0;
  long tfn = 0;
  if (this->videoplayer->isOpened()) {
    pos_ms = videoplayer->getPositionMS();
    length_ms = videoplayer->getLengthMS();
    cfn = videoplayer->getCurFrameNr();
    tfn = videoplayer->getTotalFrameNr();
  }
  QString curPos =
      QDateTime::fromMSecsSinceEpoch(pos_ms - 3600000)
          .toString("hh:mm:ss");

  QString length =
      QDateTime::fromMSecsSinceEpoch(length_ms - 3600000)
          .toString("hh:mm:ss");

  ui->timeLabel->setText(tr(""
                            "%1 / %2")
                             .arg(curPos, length));

  ui->frameNrLabel->setText(
      tr(""
         "%1 / %2")
          .arg(QString::number(cfn), QString::number(tfn)));
}

/**
 * play	-	play the video
 *
 */
void Player::play() {
  // video->setDelay(1000.f / video->getFrameRate());
  videoplayer->playIt();
}

/**
 * pause	-	pause the video
 *
 */
void Player::pause() { videoplayer->pauseIt(); }

/**
 * sleep	-	pause the video for several msecs
 *
 * @param msecs
 */
void Player::sleep(int msecs) { videoplayer->wait(msecs); }

///#################################################################################################///

void Player::reload() {
  this->videoplayer->reload();
  // TODO: reload annotations?
}

void Player::enableDrawing(bool enable)
{
  this->ui->scrollArea->setEnabled(enable);
}

/**
 * update the video speed by a factor f in percent
 *
 */
void Player::on_speedSpinBox_valueChanged(int f) {
  // TODO: set proper framerate
  videoplayer->setDelay((100.f * videoplayer->getFrameRate()) / (float)f);
}

///#########################################SLOTS###########################################///

void Player::on_btnPlay_clicked() { play(); }

void Player::on_btnPause_clicked() { pause(); }

void Player::on_btnStop_clicked() { videoplayer->stopIt(); }

void Player::on_btnPrev_clicked() {
  // this->setAutoAnnotation(false);
  videoplayer->prevFrame();
}

void Player::on_btnNext_clicked() { videoplayer->nextFrame(); }

void Player::on_autoAnnotate(bool enabled) {
  if (enabled)
    this->ui->speedSpinBox->setValue(100);
  else
    this->ui->speedSpinBox->setValue(50);
  this->autoAnnotation = enabled;
}
<commit_msg>fix object selection bug at first frame<commit_after>#include "player.h"
#include "ui_player.h"

#include "controller/commandcontroller.h"
#include "controller/selectioncontroller.h"
#include "geomObject/annotationgraphicsitemfactory.h"
#include "plugins/pluginloader.h"
#include <AnnotatorLib/Algo/InterpolateAnnotation.h>
#include <AnnotatorLib/Commands/NewAnnotation.h>
#include <AnnotatorLib/Commands/UpdateAnnotation.h>
#include <AnnotatorLib/Frame.h>
#include <QDebug>
#include <QFile>
#include <QMessageBox>
#include <geomObject/annotationgraphicsitem.h>

Player::Player(QWidget *parent) : QWidget(parent), ui(new Ui::Player) {
  ui->setupUi(this);
  videoplayer = new Videoplayer; // Creating an instance of class videoplayer

  ui->btnNext->setAutoRepeat(true);
  ui->btnPrev->setAutoRepeat(true);

  videoplayer->setDelay(ui->speedSpinBox->value()); // get default value

  updateStatus(false); // set Status disable
  updateBtn();         // update the button Play & Pause

  connect(videoplayer, SIGNAL(showFrame(cv::Mat)), this,
          SLOT(showFrame(cv::Mat)));
  connect(videoplayer, SIGNAL(updateFrame(long)), this,
          SLOT(updateFrame(long)));
  connect(ui->horizontalSlider, SIGNAL(sendClickPosition(int)), this,
          SLOT(setSliderValue(int)));
  connect(videoplayer, SIGNAL(updateBtn()), this, SLOT(updateBtn()));
  connect(videoplayer, SIGNAL(sleep(int)), this, SLOT(sleep(int)));
  connect(videoplayer, SIGNAL(updateHorizontalSlider()), this,
          SLOT(updateHorizontalSlider()));
  connect(videoplayer, SIGNAL(setInputCoordinate(QPoint)), this,
          SLOT(setInputCoordinate(QPoint)));
  // command controller
  connect(CommandController::instance(), SIGNAL(signal_requestFrameRedraw()),
          this, SLOT(reload()));

  // create graphicsview to be able to draw objects on screen.
  scene = new OwnGraphicScene();
  overlay = new OwnGraphicView(scene, this);
  // overlay->setEnabled(false);
  ui->playerLayout->addWidget(overlay);
  overlay->show();

  connect(scene, SIGNAL(on_btnPause_clicked()), this,
          SLOT(on_btnPause_clicked()));

  connect(
      this, SIGNAL(signal_objectSelection(shared_ptr<AnnotatorLib::Object>)),
      scene, SLOT(on_signal_objectSelection(shared_ptr<AnnotatorLib::Object>)));
}

Player::~Player() {
  clearAnnotationsGraphics();
  delete videoplayer;
  delete scene;
  delete ui;
}

/**
 * setInputCoordinate	-	set image/video coordinate into scene to adjust
 * the coordinate system.
 */
void Player::setInputCoordinate(QPoint point) {
  scene->inputCoordinate = point;
}

void Player::setRateLabel(QLabel *label) { this->rateLabel = label; }

QString Player::getRateValue() {
  return "FPS: " + QString::number(videoplayer->rate);
}

std::shared_ptr<AnnotatorLib::Session> Player::getSession() { return this->session; }

void Player::closeProject() {
  this->currentFrame = cv::Mat();
  setProject(nullptr);
  this->videoplayer->close();
  scene->setSession(nullptr);
  updateStatus(false);           //disable ui
}

void Player::setProject(std::shared_ptr<AnnotatorLib::Project> project) {
  this->project = project;

  this->session = project ? project->getSession() : nullptr;

  ui->horizontalSlider->setMaximum(project ? project->getImageSet()->size() : 0);

  videoplayer->setImageSet(project ? project->getImageSet() : nullptr);
  ui->horizontalSlider->setMaximum(project ? project->getImageSet()->size() : 0);

  cv::Mat firstImage = project ? project->getImageSet()->next() : cv::Mat();
  scene->setSceneRect(0, 0, firstImage.cols, firstImage.rows);
  scene->setSession(project ? session : nullptr);

  this->setEnabled(project.get() != nullptr);

  if (project) {
    overlay->fitInView(scene->sceneRect());
    project->getImageSet()->gotoPosition(0);
  }

  updateStatus(true);
  updateBtn();
  updateTimeLabel();
}

void Player::loadVideo(QString fileName) {
  if (!fileName.isEmpty()) {
    if (LoadFile(fileName)) {
      updateStatus(true);
      updateBtn();
      setEnabled(true);
    }
  }
}

void Player::clearAnnotationsGraphics() {
  while (!annotationGraphics.empty()) {
    delete annotationGraphics.front();
    annotationGraphics.pop_front();
  }
  scene->update();
}

/**
 * LoadFile	-	Open and load a video
 *
 * @param fileName	-	file Path
 *
 * @return true if the file is successfully loaded
 */
bool Player::LoadFile(const QString &fileName) {
  QFile file(fileName);
  if (!file.open(QFile::ReadOnly)) {
    QMessageBox::warning(this, tr("VideoPlayer"),
                         tr("Unable to load file %1:\n%2.")
                             .arg(fileName)
                             .arg(file.errorString()));
    return false;
  }

  // change the cursor
  QApplication::setOverrideCursor(Qt::WaitCursor);

  // input file
  if (!videoplayer->setInput(fileName.toStdString())) {
    QMessageBox::warning(this, tr("VideoPlayer"),
                         tr("Unable to load file %1:\n%2.")
                             .arg(fileName)
                             .arg(file.errorString()));
    return false;
  }

  // restore the cursor
  QApplication::restoreOverrideCursor();

  // update the time label
  updateTimeLabel();

  return true;
}

/**
 * updateStatus	-	Update the enabled property of menu
 *
 * @param var	-	the enable variable
 */
void Player::updateStatus(bool enable) {
  ui->horizontalSlider->setEnabled(enable);
  ui->btnPrev->setEnabled(enable);
  ui->btnNext->setEnabled(enable);
  ui->btnPlay->setEnabled(enable);
  ui->btnStop->setEnabled(enable);
  ui->btnPause->setEnabled(enable);

  if (!enable) {
    ui->horizontalSlider->setValue(0);
  }
}

/**get()
 * updateBtn	-	update the button Play & Pause
 *
 */
void Player::updateBtn() {
  bool isStop = videoplayer->isStop();
  ui->btnPause->setVisible(!isStop);
  ui->btnPlay->setVisible(isStop);
}

/**
 * showFrame	-	show a frame
 *
 * @param image	-	the image to be showed
 *
 */
void Player::showFrame(cv::Mat frame) {
  currentFrame = frame;
  cv::Mat tmp;

  cv::Size size;
  size.width = scene->sceneRect().width();
  size.height = scene->sceneRect().height();

  tmp.convertTo(tmp, CV_8U);
  cv::resize(currentFrame, tmp, size);
  cvtColor(currentFrame, tmp, CV_BGR2RGB);

  QImage img = QImage((const unsigned char *)(tmp.data), tmp.cols, tmp.rows,
                      tmp.step, QImage::Format_RGB888);

  scene->setSceneRect(img.rect());
  overlay->fitInView(img.rect());
  QPixmap pim = QPixmap::fromImage(img);
  scene->setBackgroundBrush(pim);
}

void Player::updateFrame(long frame_nmb) {
  shared_ptr<AnnotatorLib::Frame> f = session->getFrame(frame_nmb);
  if (!f)
    f = std::make_shared<AnnotatorLib::Frame>(
        frame_nmb); // create temporary frame

  if (autoAnnotation) {
    Annotator::Plugin *plugin =
        Annotator::PluginLoader::getInstance().getCurrent();

    if (plugin && SelectionController::instance()->getSelectedObject()) {
//      shared_ptr<AnnotatorLib::Annotation> previousA = nullptr;
//      shared_ptr<AnnotatorLib::Annotation> nextA = nullptr;
//      SelectionController::instance()
//          ->getSelectedObject()
//          ->findClosestKeyFrames(f, previousA, nextA);
//      if (previousA !=
//          SelectionController::instance()
//              ->getSelectedObject()
//              ->getLastAnnotation())
        plugin->calculate(SelectionController::instance()->getSelectedObject(), f);
    }
  }

  this->scene->setCurrentFrame(frame_nmb);
  showAnnotationsOfFrame(f);
  this->scene->update();
}

void Player::showAnnotationsOfFrame(shared_ptr<AnnotatorLib::Frame> frame) {
  clearAnnotationsGraphics();

  for (shared_ptr<AnnotatorLib::Annotation> annotation :
       AnnotatorLib::Algo::InterpolateAnnotation::getInterpolations(
           this->session, frame)) {

    AnnotationGraphicsItem *graphicsItem =
        AnnotationGraphicsItemFactory::createItem(annotation);

    connect(SelectionController::instance(),
            SIGNAL(signal_objectSelection(shared_ptr<AnnotatorLib::Object>)),
            graphicsItem,
            SLOT(on_objectSelected(shared_ptr<AnnotatorLib::Object>)));

    graphicsItem->setPlayer(this);
    scene->addItem(graphicsItem);
    annotationGraphics.push_back(graphicsItem);
  }

//  // if nothing is selected take first annotation
//  if (!SelectionController::instance()->getSelectedObject()) {
//    if (annotationGraphics.empty()) {
//      SelectionController::instance()->setSelectedObject(nullptr);
//    }
//  }
}

/**
 * updateHorizontalSlider	-	update the progress bar
 *
 */
void Player::updateHorizontalSlider() {
  // update the progress bar
  ui->horizontalSlider->setValue(videoplayer->getCurFrameNr());
  updateTimeLabel();
}

void Player::on_horizontalSlider_sliderMoved(int newpos) {
  long pos =
      newpos * videoplayer->getTotalFrameNr() / ui->horizontalSlider->maximum();
  on_frameSelected(pos);
}

/**
 * setSliderValue	-	set new value on the progress bar
 *
*/
void Player::setSliderValue(int newpos) {
  ui->horizontalSlider->setValue(newpos);
  on_horizontalSlider_sliderMoved(newpos);
}

void Player::on_frameSelected(long index) {
  this->videoplayer->on_frameSelected(index - 1); // why -1?
  updateTimeLabel();
  updateHorizontalSlider();
}

/**
 * updateTimeLabel	-	update Time Label
 */
void Player::updateTimeLabel() {

  double pos_ms = 0;
  double length_ms = 0;
  long cfn = 0;
  long tfn = 0;
  if (this->videoplayer->isOpened()) {
    pos_ms = videoplayer->getPositionMS();
    length_ms = videoplayer->getLengthMS();
    cfn = videoplayer->getCurFrameNr();
    tfn = videoplayer->getTotalFrameNr();
  }
  QString curPos =
      QDateTime::fromMSecsSinceEpoch(pos_ms - 3600000)
          .toString("hh:mm:ss");

  QString length =
      QDateTime::fromMSecsSinceEpoch(length_ms - 3600000)
          .toString("hh:mm:ss");

  ui->timeLabel->setText(tr(""
                            "%1 / %2")
                             .arg(curPos, length));

  ui->frameNrLabel->setText(
      tr(""
         "%1 / %2")
          .arg(QString::number(cfn), QString::number(tfn)));
}

/**
 * play	-	play the video
 *
 */
void Player::play() {
  // video->setDelay(1000.f / video->getFrameRate());
  videoplayer->playIt();
}

/**
 * pause	-	pause the video
 *
 */
void Player::pause() { videoplayer->pauseIt(); }

/**
 * sleep	-	pause the video for several msecs
 *
 * @param msecs
 */
void Player::sleep(int msecs) { videoplayer->wait(msecs); }

///#################################################################################################///

void Player::reload() {
  this->videoplayer->reload();
  // TODO: reload annotations?
}

void Player::enableDrawing(bool enable)
{
  this->ui->scrollArea->setEnabled(enable);
}

/**
 * update the video speed by a factor f in percent
 *
 */
void Player::on_speedSpinBox_valueChanged(int f) {
  // TODO: set proper framerate
  videoplayer->setDelay((100.f * videoplayer->getFrameRate()) / (float)f);
}

///#########################################SLOTS###########################################///

void Player::on_btnPlay_clicked() { play(); }

void Player::on_btnPause_clicked() { pause(); }

void Player::on_btnStop_clicked() { videoplayer->stopIt(); }

void Player::on_btnPrev_clicked() {
  // this->setAutoAnnotation(false);
  videoplayer->prevFrame();
}

void Player::on_btnNext_clicked() { videoplayer->nextFrame(); }

void Player::on_autoAnnotate(bool enabled) {
  if (enabled)
    this->ui->speedSpinBox->setValue(100);
  else
    this->ui->speedSpinBox->setValue(50);
  this->autoAnnotation = enabled;
}
<|endoftext|>


<commit_before>#include "source/common/http/codec_client.h"

#include <cstdint>
#include <memory>

#include "envoy/http/codec.h"

#include "source/common/common/enum_to_int.h"
#include "source/common/config/utility.h"
#include "source/common/http/exception.h"
#include "source/common/http/http1/codec_impl.h"
#include "source/common/http/http2/codec_impl.h"
#include "source/common/http/status.h"
#include "source/common/http/utility.h"

#ifdef ENVOY_ENABLE_QUIC
#include "source/common/quic/codec_impl.h"
#endif

namespace Envoy {
namespace Http {

CodecClient::CodecClient(CodecType type, Network::ClientConnectionPtr&& connection,
                         Upstream::HostDescriptionConstSharedPtr host,
                         Event::Dispatcher& dispatcher)
    : type_(type), host_(host), connection_(std::move(connection)),
      idle_timeout_(host_->cluster().idleTimeout()) {
  if (type_ != CodecType::HTTP3) {
    // Make sure upstream connections process data and then the FIN, rather than processing
    // TCP disconnects immediately. (see https://github.com/envoyproxy/envoy/issues/1679 for
    // details)
    connection_->detectEarlyCloseWhenReadDisabled(false);
  }
  connection_->addConnectionCallbacks(*this);
  connection_->addReadFilter(Network::ReadFilterSharedPtr{new CodecReadFilter(*this)});

  if (idle_timeout_) {
    idle_timer_ = dispatcher.createTimer([this]() -> void { onIdleTimeout(); });
    enableIdleTimer();
  }

  // We just universally set no delay on connections. Theoretically we might at some point want
  // to make this configurable.
  connection_->noDelay(true);
}

void CodecClient::connect() {
  ASSERT(!connect_called_);
  connect_called_ = true;
  ASSERT(codec_ != nullptr);
  // In general, codecs are handed new not-yet-connected connections, but in the
  // case of ALPN, the codec may be handed an already connected connection.
  if (!connection_->connecting()) {
    ASSERT(connection_->state() == Network::Connection::State::Open);
    connected_ = true;
  } else {
    ENVOY_CONN_LOG(debug, "connecting", *connection_);
    connection_->connect();
  }
}

void CodecClient::close() { connection_->close(Network::ConnectionCloseType::NoFlush); }

void CodecClient::deleteRequest(ActiveRequest& request) {
  connection_->dispatcher().deferredDelete(request.removeFromList(active_requests_));
  if (codec_client_callbacks_) {
    codec_client_callbacks_->onStreamDestroy();
  }
  if (numActiveRequests() == 0) {
    enableIdleTimer();
  }
}

RequestEncoder& CodecClient::newStream(ResponseDecoder& response_decoder) {
  ActiveRequestPtr request(new ActiveRequest(*this, response_decoder));
  request->encoder_ = &codec_->newStream(*request);
  request->encoder_->getStream().addCallbacks(*request);
  LinkedList::moveIntoList(std::move(request), active_requests_);

  auto upstream_info = connection_->streamInfo().upstreamInfo();
  upstream_info->setUpstreamNumStreams(upstream_info->upstreamNumStreams() + 1);

  disableIdleTimer();
  return *active_requests_.front()->encoder_;
}

void CodecClient::onEvent(Network::ConnectionEvent event) {
  if (event == Network::ConnectionEvent::Connected) {
    ENVOY_CONN_LOG(debug, "connected", *connection_);
    connected_ = true;
  }

  if (event == Network::ConnectionEvent::RemoteClose) {
    remote_closed_ = true;
  }

  // HTTP/1 can signal end of response by disconnecting. We need to handle that case.
  if (type_ == CodecType::HTTP1 && event == Network::ConnectionEvent::RemoteClose &&
      !active_requests_.empty()) {
    Buffer::OwnedImpl empty;
    onData(empty);
  }

  if (event == Network::ConnectionEvent::RemoteClose ||
      event == Network::ConnectionEvent::LocalClose) {
    ENVOY_CONN_LOG(debug, "disconnect. resetting {} pending requests", *connection_,
                   active_requests_.size());
    disableIdleTimer();
    idle_timer_.reset();
    StreamResetReason reason = StreamResetReason::ConnectionFailure;
    if (connected_) {
      reason = StreamResetReason::ConnectionTermination;
      if (protocol_error_) {
        reason = StreamResetReason::ProtocolError;
        connection_->streamInfo().setResponseFlag(StreamInfo::ResponseFlag::UpstreamProtocolError);
      }
    }
    while (!active_requests_.empty()) {
      // Fake resetting all active streams so that reset() callbacks get invoked.
      active_requests_.front()->encoder_->getStream().resetStream(reason);
    }
  }
}

void CodecClient::responsePreDecodeComplete(ActiveRequest& request) {
  ENVOY_CONN_LOG(debug, "response complete", *connection_);
  if (codec_client_callbacks_) {
    codec_client_callbacks_->onStreamPreDecodeComplete();
  }
  deleteRequest(request);

  // HTTP/2 can send us a reset after a complete response if the request was not complete. Users
  // of CodecClient will deal with the premature response case and we should not handle any
  // further reset notification.
  request.encoder_->getStream().removeCallbacks(request);
}

void CodecClient::onReset(ActiveRequest& request, StreamResetReason reason) {
  ENVOY_CONN_LOG(debug, "request reset", *connection_);
  if (codec_client_callbacks_) {
    codec_client_callbacks_->onStreamReset(reason);
  }

  deleteRequest(request);
}

void CodecClient::onData(Buffer::Instance& data) {
  const Status status = codec_->dispatch(data);

  if (!status.ok()) {
    ENVOY_CONN_LOG(debug, "Error dispatching received data: {}", *connection_, status.message());

    // Don't count 408 responses where we have no active requests as protocol errors
    if (!isPrematureResponseError(status) ||
        (!active_requests_.empty() ||
         getPrematureResponseHttpCode(status) != Code::RequestTimeout)) {
      host_->cluster().stats().upstream_cx_protocol_error_.inc();
      protocol_error_ = true;
    }
    close();
  }

  // All data should be consumed at this point if the connection remains open.
  ASSERT(data.length() == 0 || connection_->state() != Network::Connection::State::Open,
         absl::StrCat("extraneous bytes after response complete: ", data.length()));
}

CodecClientProd::CodecClientProd(CodecType type, Network::ClientConnectionPtr&& connection,
                                 Upstream::HostDescriptionConstSharedPtr host,
                                 Event::Dispatcher& dispatcher,
                                 Random::RandomGenerator& random_generator)
    : NoConnectCodecClientProd(type, std::move(connection), host, dispatcher, random_generator) {
  connect();
}

NoConnectCodecClientProd::NoConnectCodecClientProd(CodecType type,
                                                   Network::ClientConnectionPtr&& connection,
                                                   Upstream::HostDescriptionConstSharedPtr host,
                                                   Event::Dispatcher& dispatcher,
                                                   Random::RandomGenerator& random_generator)
    : CodecClient(type, std::move(connection), host, dispatcher) {
  switch (type) {
  case CodecType::HTTP1: {
    codec_ = std::make_unique<Http1::ClientConnectionImpl>(
        *connection_, host->cluster().http1CodecStats(), *this, host->cluster().http1Settings(),
        host->cluster().maxResponseHeadersCount());
    break;
  }
  case CodecType::HTTP2: {
    codec_ = std::make_unique<Http2::ClientConnectionImpl>(
        *connection_, *this, host->cluster().http2CodecStats(), random_generator,
        host->cluster().http2Options(), Http::DEFAULT_MAX_REQUEST_HEADERS_KB,
        host->cluster().maxResponseHeadersCount(), Http2::ProdNghttp2SessionFactory::get());
    break;
  }
  case CodecType::HTTP3: {
#ifdef ENVOY_ENABLE_QUIC
    auto& quic_session = dynamic_cast<Quic::EnvoyQuicClientSession&>(*connection_);
    codec_ = std::make_unique<Quic::QuicHttpClientConnectionImpl>(
        quic_session, *this, host->cluster().http3CodecStats(), host->cluster().http3Options(),
        Http::DEFAULT_MAX_REQUEST_HEADERS_KB, host->cluster().maxResponseHeadersCount());
    // Initialize the session after max request header size is changed in above http client
    // connection creation.
    quic_session.Initialize();
    break;
#else
    // Should be blocked by configuration checking at an earlier point.
    PANIC("unexpected");
#endif
  }
  }
}

} // namespace Http
} // namespace Envoy
<commit_msg>http: Skip useless check when get Connected event in CodecClient::onEvent (#21895)<commit_after>#include "source/common/http/codec_client.h"

#include <cstdint>
#include <memory>

#include "envoy/http/codec.h"

#include "source/common/common/enum_to_int.h"
#include "source/common/config/utility.h"
#include "source/common/http/exception.h"
#include "source/common/http/http1/codec_impl.h"
#include "source/common/http/http2/codec_impl.h"
#include "source/common/http/status.h"
#include "source/common/http/utility.h"

#ifdef ENVOY_ENABLE_QUIC
#include "source/common/quic/codec_impl.h"
#endif

namespace Envoy {
namespace Http {

CodecClient::CodecClient(CodecType type, Network::ClientConnectionPtr&& connection,
                         Upstream::HostDescriptionConstSharedPtr host,
                         Event::Dispatcher& dispatcher)
    : type_(type), host_(host), connection_(std::move(connection)),
      idle_timeout_(host_->cluster().idleTimeout()) {
  if (type_ != CodecType::HTTP3) {
    // Make sure upstream connections process data and then the FIN, rather than processing
    // TCP disconnects immediately. (see https://github.com/envoyproxy/envoy/issues/1679 for
    // details)
    connection_->detectEarlyCloseWhenReadDisabled(false);
  }
  connection_->addConnectionCallbacks(*this);
  connection_->addReadFilter(Network::ReadFilterSharedPtr{new CodecReadFilter(*this)});

  if (idle_timeout_) {
    idle_timer_ = dispatcher.createTimer([this]() -> void { onIdleTimeout(); });
    enableIdleTimer();
  }

  // We just universally set no delay on connections. Theoretically we might at some point want
  // to make this configurable.
  connection_->noDelay(true);
}

void CodecClient::connect() {
  ASSERT(!connect_called_);
  connect_called_ = true;
  ASSERT(codec_ != nullptr);
  // In general, codecs are handed new not-yet-connected connections, but in the
  // case of ALPN, the codec may be handed an already connected connection.
  if (!connection_->connecting()) {
    ASSERT(connection_->state() == Network::Connection::State::Open);
    connected_ = true;
  } else {
    ENVOY_CONN_LOG(debug, "connecting", *connection_);
    connection_->connect();
  }
}

void CodecClient::close() { connection_->close(Network::ConnectionCloseType::NoFlush); }

void CodecClient::deleteRequest(ActiveRequest& request) {
  connection_->dispatcher().deferredDelete(request.removeFromList(active_requests_));
  if (codec_client_callbacks_) {
    codec_client_callbacks_->onStreamDestroy();
  }
  if (numActiveRequests() == 0) {
    enableIdleTimer();
  }
}

RequestEncoder& CodecClient::newStream(ResponseDecoder& response_decoder) {
  ActiveRequestPtr request(new ActiveRequest(*this, response_decoder));
  request->encoder_ = &codec_->newStream(*request);
  request->encoder_->getStream().addCallbacks(*request);
  LinkedList::moveIntoList(std::move(request), active_requests_);

  auto upstream_info = connection_->streamInfo().upstreamInfo();
  upstream_info->setUpstreamNumStreams(upstream_info->upstreamNumStreams() + 1);

  disableIdleTimer();
  return *active_requests_.front()->encoder_;
}

void CodecClient::onEvent(Network::ConnectionEvent event) {
  if (event == Network::ConnectionEvent::Connected) {
    ENVOY_CONN_LOG(debug, "connected", *connection_);
    connected_ = true;
    return;
  }

  if (event == Network::ConnectionEvent::RemoteClose) {
    remote_closed_ = true;
  }

  // HTTP/1 can signal end of response by disconnecting. We need to handle that case.
  if (type_ == CodecType::HTTP1 && event == Network::ConnectionEvent::RemoteClose &&
      !active_requests_.empty()) {
    Buffer::OwnedImpl empty;
    onData(empty);
  }

  if (event == Network::ConnectionEvent::RemoteClose ||
      event == Network::ConnectionEvent::LocalClose) {
    ENVOY_CONN_LOG(debug, "disconnect. resetting {} pending requests", *connection_,
                   active_requests_.size());
    disableIdleTimer();
    idle_timer_.reset();
    StreamResetReason reason = StreamResetReason::ConnectionFailure;
    if (connected_) {
      reason = StreamResetReason::ConnectionTermination;
      if (protocol_error_) {
        reason = StreamResetReason::ProtocolError;
        connection_->streamInfo().setResponseFlag(StreamInfo::ResponseFlag::UpstreamProtocolError);
      }
    }
    while (!active_requests_.empty()) {
      // Fake resetting all active streams so that reset() callbacks get invoked.
      active_requests_.front()->encoder_->getStream().resetStream(reason);
    }
  }
}

void CodecClient::responsePreDecodeComplete(ActiveRequest& request) {
  ENVOY_CONN_LOG(debug, "response complete", *connection_);
  if (codec_client_callbacks_) {
    codec_client_callbacks_->onStreamPreDecodeComplete();
  }
  deleteRequest(request);

  // HTTP/2 can send us a reset after a complete response if the request was not complete. Users
  // of CodecClient will deal with the premature response case and we should not handle any
  // further reset notification.
  request.encoder_->getStream().removeCallbacks(request);
}

void CodecClient::onReset(ActiveRequest& request, StreamResetReason reason) {
  ENVOY_CONN_LOG(debug, "request reset", *connection_);
  if (codec_client_callbacks_) {
    codec_client_callbacks_->onStreamReset(reason);
  }

  deleteRequest(request);
}

void CodecClient::onData(Buffer::Instance& data) {
  const Status status = codec_->dispatch(data);

  if (!status.ok()) {
    ENVOY_CONN_LOG(debug, "Error dispatching received data: {}", *connection_, status.message());

    // Don't count 408 responses where we have no active requests as protocol errors
    if (!isPrematureResponseError(status) ||
        (!active_requests_.empty() ||
         getPrematureResponseHttpCode(status) != Code::RequestTimeout)) {
      host_->cluster().stats().upstream_cx_protocol_error_.inc();
      protocol_error_ = true;
    }
    close();
  }

  // All data should be consumed at this point if the connection remains open.
  ASSERT(data.length() == 0 || connection_->state() != Network::Connection::State::Open,
         absl::StrCat("extraneous bytes after response complete: ", data.length()));
}

CodecClientProd::CodecClientProd(CodecType type, Network::ClientConnectionPtr&& connection,
                                 Upstream::HostDescriptionConstSharedPtr host,
                                 Event::Dispatcher& dispatcher,
                                 Random::RandomGenerator& random_generator)
    : NoConnectCodecClientProd(type, std::move(connection), host, dispatcher, random_generator) {
  connect();
}

NoConnectCodecClientProd::NoConnectCodecClientProd(CodecType type,
                                                   Network::ClientConnectionPtr&& connection,
                                                   Upstream::HostDescriptionConstSharedPtr host,
                                                   Event::Dispatcher& dispatcher,
                                                   Random::RandomGenerator& random_generator)
    : CodecClient(type, std::move(connection), host, dispatcher) {
  switch (type) {
  case CodecType::HTTP1: {
    codec_ = std::make_unique<Http1::ClientConnectionImpl>(
        *connection_, host->cluster().http1CodecStats(), *this, host->cluster().http1Settings(),
        host->cluster().maxResponseHeadersCount());
    break;
  }
  case CodecType::HTTP2: {
    codec_ = std::make_unique<Http2::ClientConnectionImpl>(
        *connection_, *this, host->cluster().http2CodecStats(), random_generator,
        host->cluster().http2Options(), Http::DEFAULT_MAX_REQUEST_HEADERS_KB,
        host->cluster().maxResponseHeadersCount(), Http2::ProdNghttp2SessionFactory::get());
    break;
  }
  case CodecType::HTTP3: {
#ifdef ENVOY_ENABLE_QUIC
    auto& quic_session = dynamic_cast<Quic::EnvoyQuicClientSession&>(*connection_);
    codec_ = std::make_unique<Quic::QuicHttpClientConnectionImpl>(
        quic_session, *this, host->cluster().http3CodecStats(), host->cluster().http3Options(),
        Http::DEFAULT_MAX_REQUEST_HEADERS_KB, host->cluster().maxResponseHeadersCount());
    // Initialize the session after max request header size is changed in above http client
    // connection creation.
    quic_session.Initialize();
    break;
#else
    // Should be blocked by configuration checking at an earlier point.
    PANIC("unexpected");
#endif
  }
  }
}

} // namespace Http
} // namespace Envoy
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

//_________________________________________________________________________
// Implementation version v0 of EMCAL Manager class
// An object of this class does not produce hits nor digits
// It is the one to use if you do not want to produce outputs in TREEH or TREED
//
//*-- Author: Yves Schutz (SUBATECH)

// --- ROOT system ---

#include "TTUBS.h"
#include "TNode.h"
#include "TRandom.h"
#include "TGeometry.h"

// --- Standard library ---

#include <iostream.h>

// --- AliRoot header files ---

#include "AliEMCALv0.h"
#include "AliEMCALGeometry.h"
#include "AliRun.h"
#include "AliMC.h"

ClassImp(AliEMCALv0)

//____________________________________________________________________________
AliEMCALv0::AliEMCALv0(const char *name, const char *title):
  AliEMCAL(name,title)
{
  // ctor/* $Id$ */

  cout << " $Id$ " << endl ;

}

//____________________________________________________________________________
void AliEMCALv0::BuildGeometry()
{

  const Int_t kColorEmcal   = kGreen ;
  const Int_t kColorArm1    = kBlue ;
  const Int_t kColorArm2    = kBlue ;
  const Int_t kColorArm1Active   = kRed ;
  const Int_t kColorArm2Active   = kRed ;

  // make the container of entire calorimeter

  new TTUBS("EMCA", "Tubs that contains the calorimeter", "void",
	    fGeom->GetEnvelop(0),     // rmin
	    fGeom->GetEnvelop(1),     // rmax
	    fGeom->GetEnvelop(2)/2.0, // half length in Z
	    0.,
	    360.
	    ) ;

  // make the container of  Arm1

  new TTUBS("Envelop1", "Tubs that contains arm 1", "void",
	    fGeom->GetEnvelop(0),     // rmin
	    fGeom->GetEnvelop(1),     // rmax
	    fGeom->GetEnvelop(2)/2.0, // half length in Z
	    fGeom->GetArm1PhiMin(),   // minimun phi angle
	    fGeom->GetArm1PhiMax()    // maximun phi angle
	    ) ;
   // Active material of  Arm1

  new TTUBS("Arm1", "Active material of  arm 1", "void",
	    fGeom->GetEnvelop(0) + fGeom->GetGap2Active(),                   // rmin
	    fGeom->GetEnvelop(0) + fGeom->GetGap2Active() + fGeom->GetLmat(),// rmax
	    fGeom->GetEnvelop(2)/2.0, // half length in Z
	    fGeom->GetArm1PhiMin(),   // minimun phi angle
	    fGeom->GetArm1PhiMax()    // maximun phi angle
	    ) ;
  // make the container of  Arm2

  new TTUBS("Envelop2", "Tubs that contains arm 2", "void",
	    fGeom->GetEnvelop(0),     // rmin
	    fGeom->GetEnvelop(1),     // rmax
	    fGeom->GetEnvelop(2)/2.0, // half length in Z
	    fGeom->GetArm2PhiMin(),   // minimun phi angle
	    fGeom->GetArm2PhiMax()    // maximun phi angle
	    ) ;

  // Active material of  Arm2

  new TTUBS("Arm2", "Active material of  arm 2", "void",
	    fGeom->GetEnvelop(0) + fGeom->GetGap2Active(),                   // rmin
	    fGeom->GetEnvelop(0) + fGeom->GetGap2Active() + fGeom->GetLmat(),// rmax
	    fGeom->GetEnvelop(2)/2.0, // half length in Z
	    fGeom->GetArm2PhiMin(),   // minimun phi angle
	    fGeom->GetArm2PhiMax()    // maximun phi angle
	    ) ;

  TNode * top = gAlice->GetGeometry()->GetNode("alice") ;
  top->cd();

  // Calorimeter inside alice
  TNode * emcanode = new TNode("EMCAL", "EMCAL Envelop", "EMCAL") ;
  emcanode->SetLineColor(kColorEmcal) ;
  fNodes->Add(emcanode) ;

  // Arm 1 inside Calorimeter
  emcanode->cd();
  TNode * envelop1node = new TNode("Envelop1", "Arm1 Envelop", "Envelop1") ;
  envelop1node->SetLineColor(kColorArm1) ;
  fNodes->Add(envelop1node) ;

  // Arm 2 inside alice
  TNode * envelop2node = new TNode("Envelop2", "Arm2 Envelop", "Envelop2") ;
  envelop2node->SetLineColor(kColorArm2) ;
  fNodes->Add(envelop2node) ;

  // active material inside Arm 1
  envelop1node->cd() ;
  TNode * arm1node = new TNode("Arm1", "Arm1 with Mat", "Arm1") ;
  arm1node->SetLineColor(kColorArm1Active) ;
  fNodes->Add(arm1node) ;

  // active material inside Arm 2
  envelop2node->cd() ;
  TNode * arm2node = new TNode("Arm2", "Arm2 with Mat", "Arm2") ;
  arm2node->SetLineColor(kColorArm2Active) ;
  fNodes->Add(arm2node) ;

}

//____________________________________________________________________________
void AliEMCALv0::CreateGeometry()
{
  // Create the EMCAL geometry for Geant

  AliEMCALv0 *emcaltmp = (AliEMCALv0*)gAlice->GetModule("EMCAL") ;

  if ( emcaltmp == NULL ) {

    fprintf(stderr, "EMCAL detector not found!\n") ;
    return;

  }
  // Get pointer to the array containing media indices
  Int_t *idtmed = fIdtmed->GetArray() - 1599 ;

  // Create the EMCA volume that contains entirely EMCAL

  Float_t envelopA[5] ;
  envelopA[0] = fGeom->GetEnvelop(0) ;         // rmin
  envelopA[1] = fGeom->GetEnvelop(1) ;         // rmax
  envelopA[2] = fGeom->GetEnvelop(2) / 2.0 ;   // dz
  envelopA[3] = 0. ;
  envelopA[4] = 360.;

  gMC->Gsvolu("EMCA", "TUBS ", idtmed[1599], envelopA, 5) ; // filled with air

  // Create tube sectors that contains Arm 1 & 2

  envelopA[3] = fGeom->GetArm1PhiMin() ;       // minimun phi angle
  envelopA[4] = fGeom->GetArm1PhiMax() ;       // maximun phi angle

  gMC->Gsvolu("XEN1", "TUBS ", idtmed[1599], envelopA, 5) ; // filled with air

  envelopA[3] = fGeom->GetArm2PhiMin() ;       // minimun phi angle
  envelopA[4] = fGeom->GetArm2PhiMax() ;       // maximun phi angle

  gMC->Gsvolu("XEN2", "TUBS ", idtmed[1599], envelopA, 5) ; // filled with air

  // Create a tube sector that contains active material Arm 1 & 2

  envelopA[0] = fGeom->GetEnvelop(0) +  fGeom->GetGap2Active() ;
  envelopA[1] = envelopA[0] + fGeom->GetLmat() ;
  envelopA[3] = fGeom->GetArm1PhiMin() ;       // minimun phi angle
  envelopA[4] = fGeom->GetArm1PhiMax() ;       // maximun phi angle

  gMC->Gsvolu("XAR1", "TUBS ", idtmed[1601], envelopA, 5) ; // filled with active material (average)

  envelopA[3] = fGeom->GetArm2PhiMin() ;       // minimun phi angle
  envelopA[4] = fGeom->GetArm2PhiMax() ;       // maximun phi angle

  gMC->Gsvolu("XAR2", "TUBS ", idtmed[1601], envelopA, 5) ; // filled with active material (average)

  Int_t idrotm = 1;
  AliMatrix(idrotm, 90.0, 0., 90.0, 90.0, 0.0, 0.0) ;

  // Position Calorimeter in ALICE
  gMC->Gspos("EMCA", 1, "ALIC", 0.0, 0.0, 0.0, idrotm, "ONLY") ;

  // Position  ENV1 container in EMCA
  gMC->Gspos("XEN1", 1, "EMCA", 0.0, 0.0, 0.0, idrotm, "ONLY") ;

  // Position  ARM1  into ENV1
  gMC->Gspos("XAR1", 1, "XEN1", 0.0, 0.0, 0.0, idrotm, "ONLY") ;

  // Position  ENV2 container in ALIC
  gMC->Gspos("XEN2", 1, "EMCA", 0.0, 0.0, 0.0, idrotm, "ONLY") ;

  // Position  ARM2  into ENV2
  gMC->Gspos("XAR2", 1, "XEN2", 0.0, 0.0, 0.0, idrotm, "ONLY") ;

}

//____________________________________________________________________________
void AliEMCALv0::Init(void)
{
  // Just prints an information message

  Int_t i;

  printf("\n");
  for(i=0;i<35;i++) printf("*");
  printf(" EMCAL_INIT ");
  for(i=0;i<35;i++) printf("*");
  printf("\n");

  // Here the EMCAL initialisation code (if any!)

  if (fGeom!=0)
    cout << "AliEMCAL" << Version() << " : EMCAL geometry intialized for " << fGeom->GetName() << endl ;
  else
    cout << "AliEMCAL" << Version() << " : EMCAL geometry initialization failed !" << endl ;

  for(i=0;i<80;i++) printf("*");
  printf("\n");

}

<commit_msg>corrected typo in the volume name of EMCAL<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

//_________________________________________________________________________
// Implementation version v0 of EMCAL Manager class
// An object of this class does not produce hits nor digits
// It is the one to use if you do not want to produce outputs in TREEH or TREED
//
//*-- Author: Yves Schutz (SUBATECH)

// --- ROOT system ---

#include "TTUBS.h"
#include "TNode.h"
#include "TRandom.h"
#include "TGeometry.h"

// --- Standard library ---

#include <iostream.h>

// --- AliRoot header files ---

#include "AliEMCALv0.h"
#include "AliEMCALGeometry.h"
#include "AliRun.h"
#include "AliMC.h"

ClassImp(AliEMCALv0)

//____________________________________________________________________________
AliEMCALv0::AliEMCALv0(const char *name, const char *title):
  AliEMCAL(name,title)
{
  // ctor/* $Id$ */

  cout << " $Id$ " << endl ;

}

//____________________________________________________________________________
void AliEMCALv0::BuildGeometry()
{

  const Int_t kColorEmcal   = kGreen ;
  const Int_t kColorArm1    = kBlue ;
  const Int_t kColorArm2    = kBlue ;
  const Int_t kColorArm1Active   = kRed ;
  const Int_t kColorArm2Active   = kRed ;

  // make the container of entire calorimeter

  new TTUBS("EMCAL", "Tubs that contains the calorimeter", "void",
	    fGeom->GetEnvelop(0),     // rmin
	    fGeom->GetEnvelop(1),     // rmax
	    fGeom->GetEnvelop(2)/2.0, // half length in Z
	    0.,
	    360.
	    ) ;

  // make the container of  Arm1

  new TTUBS("Envelop1", "Tubs that contains arm 1", "void",
	    fGeom->GetEnvelop(0),     // rmin
	    fGeom->GetEnvelop(1),     // rmax
	    fGeom->GetEnvelop(2)/2.0, // half length in Z
	    fGeom->GetArm1PhiMin(),   // minimun phi angle
	    fGeom->GetArm1PhiMax()    // maximun phi angle
	    ) ;
   // Active material of  Arm1

  new TTUBS("Arm1", "Active material of  arm 1", "void",
	    fGeom->GetEnvelop(0) + fGeom->GetGap2Active(),                   // rmin
	    fGeom->GetEnvelop(0) + fGeom->GetGap2Active() + fGeom->GetLmat(),// rmax
	    fGeom->GetEnvelop(2)/2.0, // half length in Z
	    fGeom->GetArm1PhiMin(),   // minimun phi angle
	    fGeom->GetArm1PhiMax()    // maximun phi angle
	    ) ;
  // make the container of  Arm2

  new TTUBS("Envelop2", "Tubs that contains arm 2", "void",
	    fGeom->GetEnvelop(0),     // rmin
	    fGeom->GetEnvelop(1),     // rmax
	    fGeom->GetEnvelop(2)/2.0, // half length in Z
	    fGeom->GetArm2PhiMin(),   // minimun phi angle
	    fGeom->GetArm2PhiMax()    // maximun phi angle
	    ) ;

  // Active material of  Arm2

  new TTUBS("Arm2", "Active material of  arm 2", "void",
	    fGeom->GetEnvelop(0) + fGeom->GetGap2Active(),                   // rmin
	    fGeom->GetEnvelop(0) + fGeom->GetGap2Active() + fGeom->GetLmat(),// rmax
	    fGeom->GetEnvelop(2)/2.0, // half length in Z
	    fGeom->GetArm2PhiMin(),   // minimun phi angle
	    fGeom->GetArm2PhiMax()    // maximun phi angle
	    ) ;

  TNode * top = gAlice->GetGeometry()->GetNode("alice") ;
  top->cd();

  // Calorimeter inside alice
  TNode * emcanode = new TNode("EMCAL", "EMCAL Envelop", "EMCAL") ;
  emcanode->SetLineColor(kColorEmcal) ;
  fNodes->Add(emcanode) ;

  // Arm 1 inside Calorimeter
  emcanode->cd();
  TNode * envelop1node = new TNode("Envelop1", "Arm1 Envelop", "Envelop1") ;
  envelop1node->SetLineColor(kColorArm1) ;
  fNodes->Add(envelop1node) ;

  // Arm 2 inside alice
  TNode * envelop2node = new TNode("Envelop2", "Arm2 Envelop", "Envelop2") ;
  envelop2node->SetLineColor(kColorArm2) ;
  fNodes->Add(envelop2node) ;

  // active material inside Arm 1
  envelop1node->cd() ;
  TNode * arm1node = new TNode("Arm1", "Arm1 with Mat", "Arm1") ;
  arm1node->SetLineColor(kColorArm1Active) ;
  fNodes->Add(arm1node) ;

  // active material inside Arm 2
  envelop2node->cd() ;
  TNode * arm2node = new TNode("Arm2", "Arm2 with Mat", "Arm2") ;
  arm2node->SetLineColor(kColorArm2Active) ;
  fNodes->Add(arm2node) ;

}

//____________________________________________________________________________
void AliEMCALv0::CreateGeometry()
{
  // Create the EMCAL geometry for Geant

  AliEMCALv0 *emcaltmp = (AliEMCALv0*)gAlice->GetModule("EMCAL") ;

  if ( emcaltmp == NULL ) {

    fprintf(stderr, "EMCAL detector not found!\n") ;
    return;

  }
  // Get pointer to the array containing media indices
  Int_t *idtmed = fIdtmed->GetArray() - 1599 ;

  // Create the EMCA volume that contains entirely EMCAL

  Float_t envelopA[5] ;
  envelopA[0] = fGeom->GetEnvelop(0) ;         // rmin
  envelopA[1] = fGeom->GetEnvelop(1) ;         // rmax
  envelopA[2] = fGeom->GetEnvelop(2) / 2.0 ;   // dz
  envelopA[3] = 0. ;
  envelopA[4] = 360.;

  gMC->Gsvolu("EMCA", "TUBS ", idtmed[1599], envelopA, 5) ; // filled with air

  // Create tube sectors that contains Arm 1 & 2

  envelopA[3] = fGeom->GetArm1PhiMin() ;       // minimun phi angle
  envelopA[4] = fGeom->GetArm1PhiMax() ;       // maximun phi angle

  gMC->Gsvolu("XEN1", "TUBS ", idtmed[1599], envelopA, 5) ; // filled with air

  envelopA[3] = fGeom->GetArm2PhiMin() ;       // minimun phi angle
  envelopA[4] = fGeom->GetArm2PhiMax() ;       // maximun phi angle

  gMC->Gsvolu("XEN2", "TUBS ", idtmed[1599], envelopA, 5) ; // filled with air

  // Create a tube sector that contains active material Arm 1 & 2

  envelopA[0] = fGeom->GetEnvelop(0) +  fGeom->GetGap2Active() ;
  envelopA[1] = envelopA[0] + fGeom->GetLmat() ;
  envelopA[3] = fGeom->GetArm1PhiMin() ;       // minimun phi angle
  envelopA[4] = fGeom->GetArm1PhiMax() ;       // maximun phi angle

  gMC->Gsvolu("XAR1", "TUBS ", idtmed[1601], envelopA, 5) ; // filled with active material (average)

  envelopA[3] = fGeom->GetArm2PhiMin() ;       // minimun phi angle
  envelopA[4] = fGeom->GetArm2PhiMax() ;       // maximun phi angle

  gMC->Gsvolu("XAR2", "TUBS ", idtmed[1601], envelopA, 5) ; // filled with active material (average)

  Int_t idrotm = 1;
  AliMatrix(idrotm, 90.0, 0., 90.0, 90.0, 0.0, 0.0) ;

  // Position Calorimeter in ALICE
  gMC->Gspos("EMCA", 1, "ALIC", 0.0, 0.0, 0.0, idrotm, "ONLY") ;

  // Position  ENV1 container in EMCA
  gMC->Gspos("XEN1", 1, "EMCA", 0.0, 0.0, 0.0, idrotm, "ONLY") ;

  // Position  ARM1  into ENV1
  gMC->Gspos("XAR1", 1, "XEN1", 0.0, 0.0, 0.0, idrotm, "ONLY") ;

  // Position  ENV2 container in ALIC
  gMC->Gspos("XEN2", 1, "EMCA", 0.0, 0.0, 0.0, idrotm, "ONLY") ;

  // Position  ARM2  into ENV2
  gMC->Gspos("XAR2", 1, "XEN2", 0.0, 0.0, 0.0, idrotm, "ONLY") ;

}

//____________________________________________________________________________
void AliEMCALv0::Init(void)
{
  // Just prints an information message

  Int_t i;

  printf("\n");
  for(i=0;i<35;i++) printf("*");
  printf(" EMCAL_INIT ");
  for(i=0;i<35;i++) printf("*");
  printf("\n");

  // Here the EMCAL initialisation code (if any!)

  if (fGeom!=0)
    cout << "AliEMCAL" << Version() << " : EMCAL geometry intialized for " << fGeom->GetName() << endl ;
  else
    cout << "AliEMCAL" << Version() << " : EMCAL geometry initialization failed !" << endl ;

  for(i=0;i<80;i++) printf("*");
  printf("\n");

}

<|endoftext|>


<commit_before>#include "impl.h"

#include <glbinding/glbinding.h>
#include <glbinding/AbstractFunction.h>
#include <glbinding/functions.h>
#include <glbinding/constants.h>
#include <glbinding/meta.h>

#include <iostream>

using namespace gl;

const char* vertexShaderCode = R"(
#version 140
#extension GL_ARB_explicit_attrib_location : require

layout (location = 0) in vec2 corner;

out vec4 color;

void main()
{
    gl_Position = vec4(corner * 2.0 - 1.0, 0.0, 1.0);
    color = vec4(corner, 0.0, 1.0);
}

)";

const char* fragmentShaderCode = R"(
#version 140
#extension GL_ARB_explicit_attrib_location : require

layout (location = 0) out vec4 fragColor;

in vec4 color;

void main()
{
    fragColor = color;
}

)";

void doSomeOpenGLStuff()
{
    std::set<Extension> extensions;
    int num = 0;
    glGetIntegerv(GL_NUM_EXTENSIONS, &num);

    for (int i = 0; i < std::min(num, 5); ++i)
    {
        const unsigned char * name = glGetStringi(GL_EXTENSIONS, i);
        Extension extension = meta::extensionFromString(reinterpret_cast<const char*>(name));
        if (extension != Extension::Unknown)
            extensions.insert(extension);
    }

    std::cout << std::endl;

    GLuint vaoId;
    GLuint cornerBufferId;
    glGenVertexArrays(1, &vaoId);
    glGenBuffers(1, &cornerBufferId);
    GLuint programId = glCreateProgram();

    GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShaderId, 1, &vertexShaderCode, 0);
    glCompileShader(vertexShaderId);

    GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShaderId, 1, &fragmentShaderCode, 0);
    glCompileShader(fragmentShaderId);

    glAttachShader(programId, vertexShaderId);
    glAttachShader(programId, fragmentShaderId);
    glLinkProgram(programId);

    struct vec2 { float x; float y; };

    const vec2 cornerData[4] = {
        vec2{0, 0},
        vec2{1, 0},
        vec2{0, 1},
        vec2{1, 1}
    };

    glBindBuffer(GL_ARRAY_BUFFER, cornerBufferId);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vec2)*4, cornerData, GL_STATIC_DRAW);

    glBindVertexArray(vaoId);

    GLint attributeIndex = glGetAttribLocation(programId, "corner");
    GLint bindingIndex = 0;
    glVertexAttribBinding(attributeIndex, bindingIndex);
    glBindVertexBuffer(bindingIndex, cornerBufferId, 0, sizeof(vec2));
    glVertexAttribFormat(attributeIndex, 2, GL_FLOAT, GL_FALSE, 0);
    glEnableVertexAttribArray(attributeIndex);

    glUseProgram(programId);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glDeleteProgram(programId);
    glDeleteBuffers(1, &cornerBufferId);
    glDeleteVertexArrays(1, &vaoId);
}

void setCallbacks()
{
    AbstractFunction::setCallbackLevelForAll(AbstractFunction::CallbackLevel::All);

    AbstractFunction::setUnresolvedCallback([](const AbstractFunction & f) {
        std::cout << "Calling unresolved function: " << f.name() << std::endl;
    });

    AbstractFunction::setBeforeCallback([](const AbstractFunction & f) {
        std::cout << f.name();
    });
    AbstractFunction::setAfterCallback([](const AbstractFunction &) {
        std::cout << std::endl;
    });
    AbstractFunction::setParametersCallback([](const AbstractFunction &, const std::vector<AbstractValue*> & parameters) {
        std::cout << "(";
        for (unsigned i = 0; i < parameters.size(); ++i)
        {
            parameters[i]->printOn(std::cout);
            if (i < parameters.size()-1)
                std::cout << ", ";
        }
        std::cout << ")";
    });
    AbstractFunction::setReturnValueCallback([](const AbstractFunction &, const AbstractValue* returnValue) {
        if (returnValue)
        {
            std::cout << " -> ";
            returnValue->printOn(std::cout);
        }
    });
}
<commit_msg>Windows fix: missing include<commit_after>#include "impl.h"

#include <glbinding/glbinding.h>
#include <glbinding/AbstractFunction.h>
#include <glbinding/functions.h>
#include <glbinding/constants.h>
#include <glbinding/meta.h>

#include <iostream>
#include <algorithm>

using namespace gl;

const char* vertexShaderCode = R"(
#version 140
#extension GL_ARB_explicit_attrib_location : require

layout (location = 0) in vec2 corner;

out vec4 color;

void main()
{
    gl_Position = vec4(corner * 2.0 - 1.0, 0.0, 1.0);
    color = vec4(corner, 0.0, 1.0);
}

)";

const char* fragmentShaderCode = R"(
#version 140
#extension GL_ARB_explicit_attrib_location : require

layout (location = 0) out vec4 fragColor;

in vec4 color;

void main()
{
    fragColor = color;
}

)";

void doSomeOpenGLStuff()
{
    std::set<Extension> extensions;
    int num = 0;
    glGetIntegerv(GL_NUM_EXTENSIONS, &num);

    for (int i = 0; i < std::min(num, 5); ++i)
    {
        const unsigned char * name = glGetStringi(GL_EXTENSIONS, i);
        Extension extension = meta::extensionFromString(reinterpret_cast<const char*>(name));
        if (extension != Extension::Unknown)
            extensions.insert(extension);
    }

    std::cout << std::endl;

    GLuint vaoId;
    GLuint cornerBufferId;
    glGenVertexArrays(1, &vaoId);
    glGenBuffers(1, &cornerBufferId);
    GLuint programId = glCreateProgram();

    GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShaderId, 1, &vertexShaderCode, 0);
    glCompileShader(vertexShaderId);

    GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShaderId, 1, &fragmentShaderCode, 0);
    glCompileShader(fragmentShaderId);

    glAttachShader(programId, vertexShaderId);
    glAttachShader(programId, fragmentShaderId);
    glLinkProgram(programId);

    struct vec2 { float x; float y; };

    const vec2 cornerData[4] = {
        vec2{0, 0},
        vec2{1, 0},
        vec2{0, 1},
        vec2{1, 1}
    };

    glBindBuffer(GL_ARRAY_BUFFER, cornerBufferId);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vec2)*4, cornerData, GL_STATIC_DRAW);

    glBindVertexArray(vaoId);

    GLint attributeIndex = glGetAttribLocation(programId, "corner");
    GLint bindingIndex = 0;
    glVertexAttribBinding(attributeIndex, bindingIndex);
    glBindVertexBuffer(bindingIndex, cornerBufferId, 0, sizeof(vec2));
    glVertexAttribFormat(attributeIndex, 2, GL_FLOAT, GL_FALSE, 0);
    glEnableVertexAttribArray(attributeIndex);

    glUseProgram(programId);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glDeleteProgram(programId);
    glDeleteBuffers(1, &cornerBufferId);
    glDeleteVertexArrays(1, &vaoId);
}

void setCallbacks()
{
    AbstractFunction::setCallbackLevelForAll(AbstractFunction::CallbackLevel::All);

    AbstractFunction::setUnresolvedCallback([](const AbstractFunction & f) {
        std::cout << "Calling unresolved function: " << f.name() << std::endl;
    });

    AbstractFunction::setBeforeCallback([](const AbstractFunction & f) {
        std::cout << f.name();
    });
    AbstractFunction::setAfterCallback([](const AbstractFunction &) {
        std::cout << std::endl;
    });
    AbstractFunction::setParametersCallback([](const AbstractFunction &, const std::vector<AbstractValue*> & parameters) {
        std::cout << "(";
        for (unsigned i = 0; i < parameters.size(); ++i)
        {
            parameters[i]->printOn(std::cout);
            if (i < parameters.size()-1)
                std::cout << ", ";
        }
        std::cout << ")";
    });
    AbstractFunction::setReturnValueCallback([](const AbstractFunction &, const AbstractValue* returnValue) {
        if (returnValue)
        {
            std::cout << " -> ";
            returnValue->printOn(std::cout);
        }
    });
}
<|endoftext|>


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

#include "FileIndex.h"
#include "../Interface/Server.h"

const size_t max_buffer_size=1000;
#ifdef _DEBUG
const unsigned int max_wait_time=1000;
#else
const unsigned int max_wait_time=120000;
#endif
const size_t min_size_no_wait=100;

std::map<FileIndex::SIndexKey, int64> FileIndex::cache_buffer_1;
std::map<FileIndex::SIndexKey, int64> FileIndex::cache_buffer_2;
std::map<FileIndex::SIndexKey, int64>* FileIndex::active_cache_buffer=&cache_buffer_1;
std::map<FileIndex::SIndexKey, int64>* FileIndex::other_cache_buffer=&cache_buffer_2;

IMutex *FileIndex::mutex=NULL;
ICondition *FileIndex::cond=NULL;
bool FileIndex::do_shutdown=false;
bool FileIndex::do_flush=false;

void FileIndex::operator()(void)
{
	mutex=Server->createMutex();
	cond=Server->createCondition();

	while(true)
	{
		std::map<FileIndex::SIndexKey, int64>* local_buf;

		{
			IScopedLock lock(mutex);

			if(do_shutdown &&
				cache_buffer_1.empty() &&
				cache_buffer_2.empty() )
			{
				break;
			}

			while(active_cache_buffer->empty() && !do_shutdown)
			{
				do_flush=false;
				int64 starttime=Server->getTimeMS();

				while(active_cache_buffer->size()<min_size_no_wait
					&& Server->getTimeMS()-starttime<max_wait_time
					&& !do_shutdown && !do_flush)
				{
					cond->wait(&lock, max_wait_time);
				}
			}

			local_buf=active_cache_buffer;

			if(active_cache_buffer==&cache_buffer_1)
			{
				active_cache_buffer=&cache_buffer_2;
				other_cache_buffer=&cache_buffer_1;
			}
			else
			{
				active_cache_buffer=&cache_buffer_1;
				other_cache_buffer=&cache_buffer_2;
			}
		}

		start_transaction();

		for(std::map<FileIndex::SIndexKey, int64>::iterator it=local_buf->begin();
			it!=local_buf->end();++it)
		{
			if(it->second!=0)
			{
				put(it->first, it->second);
			}
			else
			{
				del(it->first);
			}
		}

		commit_transaction();

		{
			IScopedLock lock(mutex);
			local_buf->clear();
			do_flush=false;
		}
	}

	delete this;
}

void FileIndex::put_delayed(const SIndexKey& key, int64 value)
{
	IScopedLock lock(mutex);

	while(active_cache_buffer->size()>=max_buffer_size)
	{
		lock.relock(NULL);
		Server->wait(1000);
		lock.relock(mutex);
	}

	(*active_cache_buffer)[key]=value;
	cond->notify_all();
}

void FileIndex::del_delayed(const SIndexKey& key)
{
	put_delayed(key, 0);
}

int64 FileIndex::get_with_cache(const FileIndex::SIndexKey& key)
{
	{
		IScopedLock lock(mutex);

		int64 ret;
		if(get_from_cache(key, *active_cache_buffer, ret))
		{
			return ret;
		}

		if(get_from_cache(key, *other_cache_buffer, ret))
		{
			return ret;
		}

	}

	return get_any_client(key);
}

int64 FileIndex::get_with_cache_prefer_client(const SIndexKey& key)
{
	{
		IScopedLock lock(mutex);

		int64 ret;
		if(get_from_cache_prefer_client(key, *active_cache_buffer, ret))
		{
			return ret;
		}

		if(get_from_cache_prefer_client(key, *other_cache_buffer, ret))
		{
			return ret;
		}
	}

	return get_prefer_client(key);
}

std::map<int, int64> FileIndex::get_all_clients_with_cache( const SIndexKey& key, bool with_del)
{
	std::map<int, int64> ret = get_all_clients(key);

	{
		IScopedLock lock(mutex);

		get_from_cache_all_clients(key, *other_cache_buffer, ret);

		get_from_cache_all_clients(key, *active_cache_buffer, ret);
	}

	if(!with_del)
	{
		for(std::map<int, int64>::iterator it=ret.begin();it!=ret.end();)
		{
			if(it->second == 0)
			{
				std::map<int, int64>::iterator del_it = it;
				++it;
				ret.erase(del_it);
			}
			else
			{
				++it;
			}
		}
	}

	return ret;
}

int64 FileIndex::get_with_cache_exact( const SIndexKey& key )
{
	{
		IScopedLock lock(mutex);

		int64 ret;
		if(get_from_cache_exact(key, *active_cache_buffer, ret))
		{
			return ret;
		}

		if(get_from_cache_exact(key, *other_cache_buffer, ret))
		{
			return ret;
		}
	}

	return get(key);
}

void FileIndex::shutdown()
{
	IScopedLock lock(mutex);

	do_shutdown=true;
	cond->notify_all();
}

bool FileIndex::get_from_cache( const FileIndex::SIndexKey &key, const std::map<SIndexKey, int64>& cache, int64& res )
{
	std::map<FileIndex::SIndexKey, int64>::const_iterator it=cache.lower_bound(key);

	if(it!=cache.end() &&
		it->first.isEqualWithoutClientid(key))
	{
		res = it->second;
		return true;
	}

	return false;
}

bool FileIndex::get_from_cache_prefer_client( const SIndexKey &key, const std::map<SIndexKey, int64>& cache, int64& res)
{
	std::map<FileIndex::SIndexKey, int64>::const_iterator start_it=cache.lower_bound(key);

	if(start_it!=cache.end()
		&& start_it->first.isEqualWithoutClientid(key) )
	{
		res=start_it->second;
		return true;
	}

	if(start_it!=cache.end() &&
		start_it!=cache.begin())
	{
		--start_it;

		if( start_it->first.isEqualWithoutClientid(key) )
		{
			res=start_it->second;
			return true;
		}
	}

	return false;
}

void FileIndex::get_from_cache_all_clients( const SIndexKey &key, const std::map<SIndexKey, int64>& cache, std::map<int, int64> &ret )
{
	std::map<FileIndex::SIndexKey, int64>::const_iterator it=cache.lower_bound(key);

	for(;it!=cache.end()
		&& it->first.isEqualWithoutClientid(key); ++it)
	{
		ret[it->first.getClientid()]=it->second;
	}
}

bool FileIndex::get_from_cache_exact( const SIndexKey& key, const std::map<SIndexKey, int64>& cache, int64& res )
{
	std::map<FileIndex::SIndexKey, int64>::const_iterator it=cache.find(key);

	if(it!=cache.end())
	{
		res=it->second;
		return true;
	}

	return false;
}

void FileIndex::flush()
{
	IScopedLock lock(mutex);

	do_flush=true;

	while(do_flush)
	{
		cond->notify_all();
		lock.relock(NULL);
		Server->wait(100);
		lock.relock(mutex);
	}
}
<commit_msg>Increased file index buffer size<commit_after>/*************************************************************************
*    UrBackup - Client/Server backup system
*    Copyright (C) 2011-2016 Martin Raiber
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU Affero General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU Affero General Public License for more details.
*
*    You should have received a copy of the GNU Affero General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/

#include "FileIndex.h"
#include "../Interface/Server.h"

const size_t max_buffer_size=100000;
#ifdef _DEBUG
const unsigned int max_wait_time=1000;
#else
const unsigned int max_wait_time=30000;
#endif
const size_t min_size_no_wait=10000;

std::map<FileIndex::SIndexKey, int64> FileIndex::cache_buffer_1;
std::map<FileIndex::SIndexKey, int64> FileIndex::cache_buffer_2;
std::map<FileIndex::SIndexKey, int64>* FileIndex::active_cache_buffer=&cache_buffer_1;
std::map<FileIndex::SIndexKey, int64>* FileIndex::other_cache_buffer=&cache_buffer_2;

IMutex *FileIndex::mutex=NULL;
ICondition *FileIndex::cond=NULL;
bool FileIndex::do_shutdown=false;
bool FileIndex::do_flush=false;

void FileIndex::operator()(void)
{
	mutex=Server->createMutex();
	cond=Server->createCondition();

	while(true)
	{
		std::map<FileIndex::SIndexKey, int64>* local_buf;

		{
			IScopedLock lock(mutex);

			if(do_shutdown &&
				cache_buffer_1.empty() &&
				cache_buffer_2.empty() )
			{
				break;
			}

			while(active_cache_buffer->empty() && !do_shutdown)
			{
				do_flush=false;
				int64 starttime=Server->getTimeMS();

				while(active_cache_buffer->size()<min_size_no_wait
					&& Server->getTimeMS()-starttime<max_wait_time
					&& !do_shutdown && !do_flush)
				{
					cond->wait(&lock, max_wait_time);
				}
			}

			local_buf=active_cache_buffer;

			if(active_cache_buffer==&cache_buffer_1)
			{
				active_cache_buffer=&cache_buffer_2;
				other_cache_buffer=&cache_buffer_1;
			}
			else
			{
				active_cache_buffer=&cache_buffer_1;
				other_cache_buffer=&cache_buffer_2;
			}
		}

		start_transaction();

		for(std::map<FileIndex::SIndexKey, int64>::iterator it=local_buf->begin();
			it!=local_buf->end();++it)
		{
			if(it->second!=0)
			{
				put(it->first, it->second);
			}
			else
			{
				del(it->first);
			}
		}

		commit_transaction();

		{
			IScopedLock lock(mutex);
			local_buf->clear();
			do_flush=false;
		}
	}

	delete this;
}

void FileIndex::put_delayed(const SIndexKey& key, int64 value)
{
	IScopedLock lock(mutex);

	while(active_cache_buffer->size()>=max_buffer_size)
	{
		lock.relock(NULL);
		Server->wait(10);
		lock.relock(mutex);
	}

	(*active_cache_buffer)[key]=value;
	cond->notify_all();
}

void FileIndex::del_delayed(const SIndexKey& key)
{
	put_delayed(key, 0);
}

int64 FileIndex::get_with_cache(const FileIndex::SIndexKey& key)
{
	{
		IScopedLock lock(mutex);

		int64 ret;
		if(get_from_cache(key, *active_cache_buffer, ret))
		{
			return ret;
		}

		if(get_from_cache(key, *other_cache_buffer, ret))
		{
			return ret;
		}

	}

	return get_any_client(key);
}

int64 FileIndex::get_with_cache_prefer_client(const SIndexKey& key)
{
	{
		IScopedLock lock(mutex);

		int64 ret;
		if(get_from_cache_prefer_client(key, *active_cache_buffer, ret))
		{
			return ret;
		}

		if(get_from_cache_prefer_client(key, *other_cache_buffer, ret))
		{
			return ret;
		}
	}

	return get_prefer_client(key);
}

std::map<int, int64> FileIndex::get_all_clients_with_cache( const SIndexKey& key, bool with_del)
{
	std::map<int, int64> ret = get_all_clients(key);

	{
		IScopedLock lock(mutex);

		get_from_cache_all_clients(key, *other_cache_buffer, ret);

		get_from_cache_all_clients(key, *active_cache_buffer, ret);
	}

	if(!with_del)
	{
		for(std::map<int, int64>::iterator it=ret.begin();it!=ret.end();)
		{
			if(it->second == 0)
			{
				std::map<int, int64>::iterator del_it = it;
				++it;
				ret.erase(del_it);
			}
			else
			{
				++it;
			}
		}
	}

	return ret;
}

int64 FileIndex::get_with_cache_exact( const SIndexKey& key )
{
	{
		IScopedLock lock(mutex);

		int64 ret;
		if(get_from_cache_exact(key, *active_cache_buffer, ret))
		{
			return ret;
		}

		if(get_from_cache_exact(key, *other_cache_buffer, ret))
		{
			return ret;
		}
	}

	return get(key);
}

void FileIndex::shutdown()
{
	IScopedLock lock(mutex);

	do_shutdown=true;
	cond->notify_all();
}

bool FileIndex::get_from_cache( const FileIndex::SIndexKey &key, const std::map<SIndexKey, int64>& cache, int64& res )
{
	std::map<FileIndex::SIndexKey, int64>::const_iterator it=cache.lower_bound(key);

	if(it!=cache.end() &&
		it->first.isEqualWithoutClientid(key))
	{
		res = it->second;
		return true;
	}

	return false;
}

bool FileIndex::get_from_cache_prefer_client( const SIndexKey &key, const std::map<SIndexKey, int64>& cache, int64& res)
{
	std::map<FileIndex::SIndexKey, int64>::const_iterator start_it=cache.lower_bound(key);

	if(start_it!=cache.end()
		&& start_it->first.isEqualWithoutClientid(key) )
	{
		res=start_it->second;
		return true;
	}

	if(start_it!=cache.end() &&
		start_it!=cache.begin())
	{
		--start_it;

		if( start_it->first.isEqualWithoutClientid(key) )
		{
			res=start_it->second;
			return true;
		}
	}

	return false;
}

void FileIndex::get_from_cache_all_clients( const SIndexKey &key, const std::map<SIndexKey, int64>& cache, std::map<int, int64> &ret )
{
	std::map<FileIndex::SIndexKey, int64>::const_iterator it=cache.lower_bound(key);

	for(;it!=cache.end()
		&& it->first.isEqualWithoutClientid(key); ++it)
	{
		ret[it->first.getClientid()]=it->second;
	}
}

bool FileIndex::get_from_cache_exact( const SIndexKey& key, const std::map<SIndexKey, int64>& cache, int64& res )
{
	std::map<FileIndex::SIndexKey, int64>::const_iterator it=cache.find(key);

	if(it!=cache.end())
	{
		res=it->second;
		return true;
	}

	return false;
}

void FileIndex::flush()
{
	IScopedLock lock(mutex);

	do_flush=true;

	while(do_flush)
	{
		cond->notify_all();
		lock.relock(NULL);
		Server->wait(100);
		lock.relock(mutex);
	}
}
<|endoftext|>