<commit_before>
#include "stdafx.h"
#include "vertexbuffer.h"

using namespace graphic;

cVertexBuffer::cVertexBuffer()
	: m_sizeOfVertex(0)
	, m_vertexCount(0)
	, m_vtxBuff(NULL)
{
}

// Copy Constructor
cVertexBuffer::cVertexBuffer(const cVertexBuffer &rhs)
{
	operator = (rhs);
}

cVertexBuffer::~cVertexBuffer()
{
	Clear();
}

bool cVertexBuffer::Create(cRenderer &renderer, const int vertexCount, const int sizeofVertex
	, const D3D11_USAGE usage //= D3D11_USAGE_DEFAULT
)
{
	SAFE_RELEASE(m_vtxBuff);

	D3D11_BUFFER_DESC bd;
	ZeroMemory(&bd, sizeof(bd));
	bd.Usage = usage;
	bd.ByteWidth = sizeofVertex * vertexCount;
	bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	switch (usage)
	{
	case D3D11_USAGE_DEFAULT:
		bd.CPUAccessFlags = 0;
		break;
	case D3D11_USAGE_DYNAMIC:
		bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
		break;
	case D3D11_USAGE_STAGING:
		assert(0); // very slow flag
		break;
	}

	if (FAILED(renderer.GetDevice()->CreateBuffer(&bd, NULL, &m_vtxBuff)))
	{
		assert(0);
		return false;
	}

	m_vertexCount = vertexCount;
	m_sizeOfVertex = sizeofVertex;
	return true;
}

bool cVertexBuffer::Create(cRenderer &renderer, const int vertexCount, const int sizeofVertex
	, const void *vertices
	, const D3D11_USAGE usage //= D3D11_USAGE_DEFAULT
)
{
	SAFE_RELEASE(m_vtxBuff);

	D3D11_BUFFER_DESC bd;
	ZeroMemory(&bd, sizeof(bd));
	bd.Usage = usage;
	bd.ByteWidth = sizeofVertex * vertexCount;
	bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	switch (usage)
	{
	case D3D11_USAGE_DEFAULT:
		bd.CPUAccessFlags = 0;
		break;
	case D3D11_USAGE_DYNAMIC:
		bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
		break;
	case D3D11_USAGE_STAGING:
		assert(0); // very slow flag
		break;
	}

	D3D11_SUBRESOURCE_DATA InitData;
	ZeroMemory(&InitData, sizeof(InitData));
	InitData.pSysMem = vertices;

	if (FAILED(renderer.GetDevice()->CreateBuffer(&bd, &InitData, &m_vtxBuff)))
	{
		assert(0);
		return false;
	}

	m_vertexCount = vertexCount;
	m_sizeOfVertex = sizeofVertex;
	return true;
}

void* cVertexBuffer::Lock(cRenderer &renderer
	, const D3D11_MAP flag //= D3D11_MAP_WRITE_DISCARD
)
{
	RETV(!m_vtxBuff, NULL);

	D3D11_MAPPED_SUBRESOURCE res;
	ZeroMemory(&res, sizeof(res));
	HRESULT hr = renderer.GetDevContext()->Map(m_vtxBuff, 0, flag, 0, &res);
	if (FAILED(hr))
		return NULL;
	return res.pData;
}

void cVertexBuffer::Unlock(cRenderer &renderer)
{
	RET(!m_vtxBuff);
	renderer.GetDevContext()->Unmap(m_vtxBuff, 0);
}

void cVertexBuffer::Bind(cRenderer &renderer) const
{
	const UINT offset = 0;
	const UINT stride = (UINT)m_sizeOfVertex;
	renderer.GetDevContext()->IASetVertexBuffers(0, 1, &m_vtxBuff, &stride, &offset);
}

inline DWORD FtoDW(FLOAT f) { return *((DWORD*)&f); }
void cVertexBuffer::RenderLineStrip(cRenderer &renderer)
{
	//RET(!m_vtxBuff);

	//renderer.GetDevice()->SetTransform(D3DTS_WORLD, (D3DXMATRIX*)&Matrix44::Identity);

	//DWORD lighting;
	//renderer.GetDevice()->GetRenderState(D3DRS_LIGHTING, &lighting);
	//renderer.GetDevice()->SetRenderState(D3DRS_LIGHTING, FALSE);
	//renderer.GetDevice()->SetRenderState(D3DRS_ZENABLE, FALSE);

	//renderer.GetDevice()->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
	//renderer.GetDevice()->SetRenderState(D3DRS_POINTSCALEENABLE, TRUE);
	//renderer.GetDevice()->SetRenderState(D3DRS_POINTSIZE_MAX, FtoDW(10));
	//renderer.GetDevice()->SetRenderState(D3DRS_POINTSIZE_MIN, FtoDW(1.0f));
	//renderer.GetDevice()->SetRenderState(D3DRS_POINTSCALE_A, FtoDW(0.0f));
	//renderer.GetDevice()->SetRenderState(D3DRS_POINTSCALE_B, FtoDW(0.0f));
	//renderer.GetDevice()->SetRenderState(D3DRS_POINTSCALE_C, FtoDW(1.0f));

	//Bind(renderer);
	//renderer.GetDevice()->DrawPrimitive(D3DPT_LINESTRIP, 0, m_vertexCount - 1);
	//renderer.GetDevice()->SetRenderState(D3DRS_LIGHTING, lighting);
	//renderer.GetDevice()->SetRenderState(D3DRS_ZENABLE, TRUE);
}

void cVertexBuffer::RenderLineList(cRenderer &renderer)
{
	//RET(!m_vtxBuff);

	//renderer.GetDevice()->SetTransform(D3DTS_WORLD, (D3DXMATRIX*)&Matrix44::Identity);

	//DWORD lighting;
	//renderer.GetDevice()->GetRenderState(D3DRS_LIGHTING, &lighting);
	//renderer.GetDevice()->SetRenderState(D3DRS_LIGHTING, FALSE);
	//renderer.GetDevice()->SetRenderState(D3DRS_ZENABLE, FALSE);
	//Bind(renderer);
	//renderer.GetDevice()->DrawPrimitive(D3DPT_LINELIST, 0, m_vertexCount /2);
	//renderer.GetDevice()->SetRenderState(D3DRS_LIGHTING, lighting);
	//renderer.GetDevice()->SetRenderState(D3DRS_ZENABLE, TRUE);
}

// ZBuffer Enable
void cVertexBuffer::RenderLineList2(cRenderer &renderer)
{
	//RET(!m_vtxBuff);

	//DWORD lighting;
	//renderer.GetDevice()->GetRenderState(D3DRS_LIGHTING, &lighting);
	//renderer.GetDevice()->SetRenderState(D3DRS_LIGHTING, FALSE);
	//Bind(renderer);
	//renderer.GetDevice()->DrawPrimitive(D3DPT_LINELIST, 0, m_vertexCount / 2);
	//renderer.GetDevice()->SetRenderState(D3DRS_LIGHTING, lighting);
}

void cVertexBuffer::RenderPointList2(cRenderer &renderer, const int count) // count=0
{
	//RET(!m_vtxBuff);

	//DWORD lighting;
	//renderer.GetDevice()->GetRenderState(D3DRS_LIGHTING, &lighting);
	//renderer.GetDevice()->SetRenderState(D3DRS_LIGHTING, FALSE);
	//renderer.GetDevice()->SetRenderState(D3DRS_ZENABLE, FALSE);

	//renderer.GetDevice()->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
	//renderer.GetDevice()->SetRenderState(D3DRS_POINTSCALEENABLE, TRUE);
	//renderer.GetDevice()->SetRenderState(D3DRS_POINTSIZE_MAX, FtoDW(10));
	//renderer.GetDevice()->SetRenderState(D3DRS_POINTSIZE_MIN, FtoDW(1.0f));
	//renderer.GetDevice()->SetRenderState(D3DRS_POINTSCALE_A, FtoDW(0.0f));
	//renderer.GetDevice()->SetRenderState(D3DRS_POINTSCALE_B, FtoDW(0.0f));
	//renderer.GetDevice()->SetRenderState(D3DRS_POINTSCALE_C, FtoDW(1.0f));

	////renderer.GetDevice()->SetTransform(D3DTS_WORLD, (D3DXMATRIX*)&Matrix44::Identity);

	//Bind(renderer);
	//renderer.GetDevice()->DrawPrimitive(D3DPT_POINTLIST, 0, (count == 0) ? m_vertexCount : count);

	//renderer.GetDevice()->SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE);
	//renderer.GetDevice()->SetRenderState(D3DRS_POINTSCALEENABLE, FALSE);
	//renderer.GetDevice()->SetRenderState(D3DRS_LIGHTING, lighting);
	//renderer.GetDevice()->SetRenderState(D3DRS_ZENABLE, TRUE);
}

void cVertexBuffer::RenderPointList(cRenderer &renderer, const int count) // count=0
{
	//RET(!m_vtxBuff);

	//renderer.GetDevice()->SetTransform( D3DTS_WORLD, (D3DXMATRIX*)&Matrix44::Identity );

	//Bind(renderer);
	//renderer.GetDevice()->DrawPrimitive(D3DPT_POINTLIST, 0, (count == 0) ? m_vertexCount : count);
}

void cVertexBuffer::RenderTriangleStrip(cRenderer &renderer)
{
	//RET(!m_vtxBuff);
	Bind(renderer);
	//renderer.GetDevice()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, m_vertexCount - 2);
}

void cVertexBuffer::RenderTriangleList(cRenderer &renderer)
{
	//RET(!m_vtxBuff);
	Bind(renderer);
	//renderer.GetDevice()->DrawPrimitive(D3DPT_TRIANGLELIST, 0, m_vertexCount/3);
}

void cVertexBuffer::Clear()
{
	m_vertexCount = 0;
	m_sizeOfVertex = 0;
	SAFE_RELEASE(m_vtxBuff);
}

void cVertexBuffer::Set(cRenderer &renderer, const cVertexBuffer &rhs)
{
	if (this != &rhs)
	{
		Clear();

		m_sizeOfVertex = rhs.m_sizeOfVertex;
		m_vertexCount = rhs.m_vertexCount;
		Create(renderer, rhs.m_vertexCount, rhs.m_sizeOfVertex);
		renderer.GetDevContext()->CopyResource(m_vtxBuff, rhs.m_vtxBuff);
	}
}

cVertexBuffer& cVertexBuffer::operator=(const cVertexBuffer &rhs)
{
	if (this != &rhs)
	{
		Clear();

		m_sizeOfVertex = rhs.m_sizeOfVertex;
		m_vertexCount = rhs.m_vertexCount;
		m_vtxBuff = NULL; // No Copy
	}
	return *this;
}
<commit_msg>update graphic refactoring<commit_after>
#include "stdafx.h"
#include "vertexbuffer.h"

using namespace graphic;

cVertexBuffer::cVertexBuffer()
	: m_sizeOfVertex(0)
	, m_vertexCount(0)
	, m_vtxBuff(NULL)
{
}

// Copy Constructor
cVertexBuffer::cVertexBuffer(const cVertexBuffer &rhs)
{
	operator = (rhs);
}

cVertexBuffer::~cVertexBuffer()
{
	Clear();
}

bool cVertexBuffer::Create(cRenderer &renderer, const int vertexCount, const int sizeofVertex
	, const D3D11_USAGE usage //= D3D11_USAGE_DEFAULT
)
{
	SAFE_RELEASE(m_vtxBuff);

	D3D11_BUFFER_DESC bd;
	ZeroMemory(&bd, sizeof(bd));
	bd.Usage = usage;
	bd.ByteWidth = sizeofVertex * vertexCount;
	bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	switch (usage)
	{
	case D3D11_USAGE_DEFAULT:
		bd.CPUAccessFlags = 0;
		break;
	case D3D11_USAGE_DYNAMIC:
		bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
		break;
	case D3D11_USAGE_STAGING:
		assert(0); // very slow flag
		break;
	}

	if (FAILED(renderer.GetDevice()->CreateBuffer(&bd, NULL, &m_vtxBuff)))
	{
		assert(0);
		return false;
	}

	m_vertexCount = vertexCount;
	m_sizeOfVertex = sizeofVertex;
	return true;
}

bool cVertexBuffer::Create(cRenderer &renderer, const int vertexCount, const int sizeofVertex
	, const void *vertices
	, const D3D11_USAGE usage //= D3D11_USAGE_DEFAULT
)
{
	SAFE_RELEASE(m_vtxBuff);

	D3D11_BUFFER_DESC bd;
	ZeroMemory(&bd, sizeof(bd));
	bd.Usage = usage;
	bd.ByteWidth = sizeofVertex * vertexCount;
	bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	switch (usage)
	{
	case D3D11_USAGE_DEFAULT:
		bd.CPUAccessFlags = 0;
		break;
	case D3D11_USAGE_DYNAMIC:
		bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
		break;
	case D3D11_USAGE_STAGING:
		assert(0); // very slow flag
		break;
	}

	D3D11_SUBRESOURCE_DATA InitData;
	ZeroMemory(&InitData, sizeof(InitData));
	InitData.pSysMem = vertices;

	if (FAILED(renderer.GetDevice()->CreateBuffer(&bd, &InitData, &m_vtxBuff)))
	{
		assert(0);
		return false;
	}

	m_vertexCount = vertexCount;
	m_sizeOfVertex = sizeofVertex;
	return true;
}

void* cVertexBuffer::Lock(cRenderer &renderer
	, const D3D11_MAP flag //= D3D11_MAP_WRITE_DISCARD
)
{
	RETV(!m_vtxBuff, NULL);

	D3D11_MAPPED_SUBRESOURCE res;
	ZeroMemory(&res, sizeof(res));
	HRESULT hr = renderer.GetDevContext()->Map(m_vtxBuff, 0, flag, 0, &res);
	if (FAILED(hr))
		return NULL;
	return res.pData;
}

void cVertexBuffer::Unlock(cRenderer &renderer)
{
	RET(!m_vtxBuff);
	renderer.GetDevContext()->Unmap(m_vtxBuff, 0);
}

void cVertexBuffer::Bind(cRenderer &renderer) const
{
	const UINT offset = 0;
	const UINT stride = (UINT)m_sizeOfVertex;
	renderer.GetDevContext()->IASetVertexBuffers(0, 1, &m_vtxBuff, &stride, &offset);
}

inline DWORD FtoDW(FLOAT f) { return *((DWORD*)&f); }
void cVertexBuffer::RenderLineStrip(cRenderer &renderer)
{
}

void cVertexBuffer::RenderLineList(cRenderer &renderer)
{
}

// ZBuffer Enable
void cVertexBuffer::RenderLineList2(cRenderer &renderer)
{
}

void cVertexBuffer::RenderPointList2(cRenderer &renderer, const int count) // count=0
{
}

void cVertexBuffer::RenderPointList(cRenderer &renderer, const int count) // count=0
{
}

void cVertexBuffer::RenderTriangleStrip(cRenderer &renderer)
{
}

void cVertexBuffer::RenderTriangleList(cRenderer &renderer)
{
}

void cVertexBuffer::Clear()
{
	m_vertexCount = 0;
	m_sizeOfVertex = 0;
	SAFE_RELEASE(m_vtxBuff);
}

void cVertexBuffer::Set(cRenderer &renderer, const cVertexBuffer &rhs)
{
	if (this != &rhs)
	{
		Clear();

		m_sizeOfVertex = rhs.m_sizeOfVertex;
		m_vertexCount = rhs.m_vertexCount;
		Create(renderer, rhs.m_vertexCount, rhs.m_sizeOfVertex);
		renderer.GetDevContext()->CopyResource(m_vtxBuff, rhs.m_vtxBuff);
	}
}

cVertexBuffer& cVertexBuffer::operator=(const cVertexBuffer &rhs)
{
	if (this != &rhs)
	{
		Clear();

		m_sizeOfVertex = rhs.m_sizeOfVertex;
		m_vertexCount = rhs.m_vertexCount;
		m_vtxBuff = NULL; // No Copy
	}
	return *this;
}
<|endoftext|>


<commit_before>/*
 * OneToManyProcessor.cpp
 */

#include "OneToManyProcessor.h"

#include <map>
#include <string>

#include "./MediaStream.h"
#include "rtp/RtpHeaders.h"
#include "rtp/RtpUtils.h"

namespace erizo {
  DEFINE_LOGGER(OneToManyProcessor, "OneToManyProcessor");
  OneToManyProcessor::OneToManyProcessor() : feedbackSink_{nullptr} {
    ELOG_DEBUG("OneToManyProcessor constructor");
  }

  OneToManyProcessor::~OneToManyProcessor() {
  }

  int OneToManyProcessor::deliverAudioData_(std::shared_ptr<DataPacket> audio_packet) {
    if (audio_packet->length <= 0)
      return 0;

    boost::unique_lock<boost::mutex> lock(monitor_mutex_);
    if (subscribers.empty())
      return 0;

    std::map<std::string, std::shared_ptr<MediaSink>>::iterator it;
    RtpHeader* head = reinterpret_cast<RtpHeader*>(audio_packet->data);
    RtcpHeader* chead = reinterpret_cast<RtcpHeader*>(audio_packet->data);
    for (it = subscribers.begin(); it != subscribers.end(); ++it) {
      if ((*it).second != nullptr) {
        if (chead->isRtcp()) {
          chead->setSSRC((*it).second->getAudioSinkSSRC());
        } else {
          head->setSSRC((*it).second->getAudioSinkSSRC());
        }
        // Note: deliverAudioData must copy the packet inmediately
        (*it).second->deliverAudioData(audio_packet);
      }
    }

    return 0;
  }

  bool OneToManyProcessor::isSSRCFromAudio(uint32_t ssrc) {
    std::map<std::string, std::shared_ptr<MediaSink>>::iterator it;
    for (it = subscribers.begin(); it != subscribers.end(); ++it) {
      if ((*it).second->getAudioSinkSSRC() == ssrc) {
        return true;
      }
    }
    return false;
  }

  int OneToManyProcessor::deliverVideoData_(std::shared_ptr<DataPacket> video_packet) {
    if (video_packet->length <= 0)
      return 0;
    RtcpHeader* head = reinterpret_cast<RtcpHeader*>(video_packet->data);
    if (head->isFeedback()) {
      ELOG_WARN("Receiving Feedback in wrong path: %d", head->packettype);
      deliverFeedback_(video_packet);
      return 0;
    }
    boost::unique_lock<boost::mutex> lock(monitor_mutex_);
    if (subscribers.empty())
      return 0;
    std::map<std::string, std::shared_ptr<MediaSink>>::iterator it;
    RtpHeader* rhead = reinterpret_cast<RtpHeader*>(video_packet->data);
    uint32_t ssrc = head->isRtcp() ? head->getSSRC() : rhead->getSSRC();
    uint32_t ssrc_offset = translateAndMaybeAdaptForSimulcast(ssrc);
    for (it = subscribers.begin(); it != subscribers.end(); ++it) {
      if ((*it).second != nullptr) {
        uint32_t base_ssrc = (*it).second->getVideoSinkSSRC();
        if (head->isRtcp()) {
          head->setSSRC(base_ssrc + ssrc_offset);
        } else {
          rhead->setSSRC(base_ssrc + ssrc_offset);
        }
        // Note: deliverVideoData must copy the packet inmediately
        (*it).second->deliverVideoData(video_packet);
      }
    }
    return 0;
  }

  uint32_t OneToManyProcessor::translateAndMaybeAdaptForSimulcast(uint32_t orig_ssrc) {
    return orig_ssrc - publisher->getVideoSourceSSRC();
  }

  void OneToManyProcessor::setPublisher(std::shared_ptr<MediaSource> publisher_stream) {
    boost::mutex::scoped_lock lock(monitor_mutex_);
    this->publisher = publisher_stream;
    feedbackSink_ = publisher->getFeedbackSink();
  }

  int OneToManyProcessor::deliverFeedback_(std::shared_ptr<DataPacket> fb_packet) {
    if (feedbackSink_ != nullptr) {
      RtpUtils::forEachRtcpBlock(fb_packet, [this](RtcpHeader *chead) {
        if (chead->isREMB()) {
          for (uint8_t index = 0; index < chead->getREMBNumSSRC(); index++) {
            if (isSSRCFromAudio(chead->getREMBFeedSSRC(index))) {
              chead->setREMBFeedSSRC(index, publisher->getAudioSourceSSRC());
            } else {
              chead->setREMBFeedSSRC(index, publisher->getVideoSourceSSRC());
            }
          }
        }
        if (isSSRCFromAudio(chead->getSourceSSRC())) {
          chead->setSourceSSRC(publisher->getAudioSourceSSRC());
        } else {
          chead->setSourceSSRC(publisher->getVideoSourceSSRC());
        }
      });
      feedbackSink_->deliverFeedback(fb_packet);
    }
    return 0;
  }

  int OneToManyProcessor::deliverEvent_(MediaEventPtr event) {
    boost::unique_lock<boost::mutex> lock(monitor_mutex_);
    if (subscribers.empty())
      return 0;
    std::map<std::string, std::shared_ptr<MediaSink>>::iterator it;
    for (it = subscribers.begin(); it != subscribers.end(); ++it) {
      if ((*it).second != nullptr) {
        (*it).second->deliverEvent(event);
      }
    }
    return 0;
  }

  void OneToManyProcessor::addSubscriber(std::shared_ptr<MediaSink> subscriber_stream,
      const std::string& peer_id) {
    ELOG_DEBUG("Adding subscriber");
    boost::mutex::scoped_lock lock(monitor_mutex_);
    ELOG_DEBUG("From %u, %u ", publisher->getAudioSourceSSRC(), publisher->getVideoSourceSSRC());
    ELOG_DEBUG("Subscribers ssrcs: Audio %u, video, %u from %u, %u ",
               subscriber_stream->getAudioSinkSSRC(), subscriber_stream->getVideoSinkSSRC(),
               this->publisher->getAudioSourceSSRC() , this->publisher->getVideoSourceSSRC());
    FeedbackSource* fbsource = subscriber_stream->getFeedbackSource();

    if (fbsource != nullptr) {
      ELOG_DEBUG("adding fbsource");
      fbsource->setFeedbackSink(this);
    }
    if (this->subscribers.find(peer_id) != subscribers.end()) {
        ELOG_WARN("This OTM already has a subscriber with peer_id %s, substituting it", peer_id.c_str());
        this->subscribers.erase(peer_id);
    }
    this->subscribers[peer_id] = subscriber_stream;
  }

  void OneToManyProcessor::removeSubscriber(const std::string& peer_id) {
    ELOG_DEBUG("Remove subscriber %s", peer_id.c_str());
    boost::mutex::scoped_lock lock(monitor_mutex_);
    if (this->subscribers.find(peer_id) != subscribers.end()) {
      this->subscribers.erase(peer_id);
    }
  }

  boost::future<void> OneToManyProcessor::close() {
    return closeAll();
  }

  boost::future<void> OneToManyProcessor::closeAll() {
    ELOG_DEBUG("OneToManyProcessor closeAll");
    std::shared_ptr<boost::promise<void>> p = std::make_shared<boost::promise<void>>();
    boost::future<void> f = p->get_future();
    feedbackSink_ = nullptr;
    publisher.reset();
    boost::unique_lock<boost::mutex> lock(monitor_mutex_);
    std::map<std::string, std::shared_ptr<MediaSink>>::iterator it = subscribers.begin();
    while (it != subscribers.end()) {
      if ((*it).second != nullptr) {
        FeedbackSource* fbsource = (*it).second->getFeedbackSource();
        if (fbsource != nullptr) {
          fbsource->setFeedbackSink(nullptr);
        }
      }
      subscribers.erase(it++);
    }
    subscribers.clear();
    p->set_value();
    ELOG_DEBUG("ClosedAll media in this OneToMany");
    return f;
  }

}  // namespace erizo
<commit_msg>Avoid audio drifting by updating audio SRs (#1487)<commit_after>/*
 * OneToManyProcessor.cpp
 */

#include "OneToManyProcessor.h"

#include <map>
#include <string>

#include "./MediaStream.h"
#include "rtp/RtpHeaders.h"
#include "rtp/RtpUtils.h"

namespace erizo {
  DEFINE_LOGGER(OneToManyProcessor, "OneToManyProcessor");
  OneToManyProcessor::OneToManyProcessor() : feedbackSink_{nullptr} {
    ELOG_DEBUG("OneToManyProcessor constructor");
  }

  OneToManyProcessor::~OneToManyProcessor() {
  }

  int OneToManyProcessor::deliverAudioData_(std::shared_ptr<DataPacket> audio_packet) {
    if (audio_packet->length <= 0)
      return 0;

    boost::unique_lock<boost::mutex> lock(monitor_mutex_);
    if (subscribers.empty())
      return 0;

    std::map<std::string, std::shared_ptr<MediaSink>>::iterator it;
    RtpHeader* head = reinterpret_cast<RtpHeader*>(audio_packet->data);
    RtcpHeader* chead = reinterpret_cast<RtcpHeader*>(audio_packet->data);
    for (it = subscribers.begin(); it != subscribers.end(); ++it) {
      if ((*it).second != nullptr) {
        // Hack to avoid audio drifting in Chrome.
        if (chead->isRtcp() && chead->isSDES()) {
          chead->setSSRC((*it).second->getAudioSinkSSRC());
        } else {
          head->setSSRC((*it).second->getAudioSinkSSRC());
        }
        // Note: deliverAudioData must copy the packet inmediately
        (*it).second->deliverAudioData(audio_packet);
      }
    }

    return 0;
  }

  bool OneToManyProcessor::isSSRCFromAudio(uint32_t ssrc) {
    std::map<std::string, std::shared_ptr<MediaSink>>::iterator it;
    for (it = subscribers.begin(); it != subscribers.end(); ++it) {
      if ((*it).second->getAudioSinkSSRC() == ssrc) {
        return true;
      }
    }
    return false;
  }

  int OneToManyProcessor::deliverVideoData_(std::shared_ptr<DataPacket> video_packet) {
    if (video_packet->length <= 0)
      return 0;
    RtcpHeader* head = reinterpret_cast<RtcpHeader*>(video_packet->data);
    if (head->isFeedback()) {
      ELOG_WARN("Receiving Feedback in wrong path: %d", head->packettype);
      deliverFeedback_(video_packet);
      return 0;
    }
    boost::unique_lock<boost::mutex> lock(monitor_mutex_);
    if (subscribers.empty())
      return 0;
    std::map<std::string, std::shared_ptr<MediaSink>>::iterator it;
    RtpHeader* rhead = reinterpret_cast<RtpHeader*>(video_packet->data);
    uint32_t ssrc = head->isRtcp() ? head->getSSRC() : rhead->getSSRC();
    uint32_t ssrc_offset = translateAndMaybeAdaptForSimulcast(ssrc);
    for (it = subscribers.begin(); it != subscribers.end(); ++it) {
      if ((*it).second != nullptr) {
        uint32_t base_ssrc = (*it).second->getVideoSinkSSRC();
        if (head->isRtcp()) {
          head->setSSRC(base_ssrc + ssrc_offset);
        } else {
          rhead->setSSRC(base_ssrc + ssrc_offset);
        }
        // Note: deliverVideoData must copy the packet inmediately
        (*it).second->deliverVideoData(video_packet);
      }
    }
    return 0;
  }

  uint32_t OneToManyProcessor::translateAndMaybeAdaptForSimulcast(uint32_t orig_ssrc) {
    return orig_ssrc - publisher->getVideoSourceSSRC();
  }

  void OneToManyProcessor::setPublisher(std::shared_ptr<MediaSource> publisher_stream) {
    boost::mutex::scoped_lock lock(monitor_mutex_);
    this->publisher = publisher_stream;
    feedbackSink_ = publisher->getFeedbackSink();
  }

  int OneToManyProcessor::deliverFeedback_(std::shared_ptr<DataPacket> fb_packet) {
    if (feedbackSink_ != nullptr) {
      RtpUtils::forEachRtcpBlock(fb_packet, [this](RtcpHeader *chead) {
        if (chead->isREMB()) {
          for (uint8_t index = 0; index < chead->getREMBNumSSRC(); index++) {
            if (isSSRCFromAudio(chead->getREMBFeedSSRC(index))) {
              chead->setREMBFeedSSRC(index, publisher->getAudioSourceSSRC());
            } else {
              chead->setREMBFeedSSRC(index, publisher->getVideoSourceSSRC());
            }
          }
        }
        if (isSSRCFromAudio(chead->getSourceSSRC())) {
          chead->setSourceSSRC(publisher->getAudioSourceSSRC());
        } else {
          chead->setSourceSSRC(publisher->getVideoSourceSSRC());
        }
      });
      feedbackSink_->deliverFeedback(fb_packet);
    }
    return 0;
  }

  int OneToManyProcessor::deliverEvent_(MediaEventPtr event) {
    boost::unique_lock<boost::mutex> lock(monitor_mutex_);
    if (subscribers.empty())
      return 0;
    std::map<std::string, std::shared_ptr<MediaSink>>::iterator it;
    for (it = subscribers.begin(); it != subscribers.end(); ++it) {
      if ((*it).second != nullptr) {
        (*it).second->deliverEvent(event);
      }
    }
    return 0;
  }

  void OneToManyProcessor::addSubscriber(std::shared_ptr<MediaSink> subscriber_stream,
      const std::string& peer_id) {
    ELOG_DEBUG("Adding subscriber");
    boost::mutex::scoped_lock lock(monitor_mutex_);
    ELOG_DEBUG("From %u, %u ", publisher->getAudioSourceSSRC(), publisher->getVideoSourceSSRC());
    ELOG_DEBUG("Subscribers ssrcs: Audio %u, video, %u from %u, %u ",
               subscriber_stream->getAudioSinkSSRC(), subscriber_stream->getVideoSinkSSRC(),
               this->publisher->getAudioSourceSSRC() , this->publisher->getVideoSourceSSRC());
    FeedbackSource* fbsource = subscriber_stream->getFeedbackSource();

    if (fbsource != nullptr) {
      ELOG_DEBUG("adding fbsource");
      fbsource->setFeedbackSink(this);
    }
    if (this->subscribers.find(peer_id) != subscribers.end()) {
        ELOG_WARN("This OTM already has a subscriber with peer_id %s, substituting it", peer_id.c_str());
        this->subscribers.erase(peer_id);
    }
    this->subscribers[peer_id] = subscriber_stream;
  }

  void OneToManyProcessor::removeSubscriber(const std::string& peer_id) {
    ELOG_DEBUG("Remove subscriber %s", peer_id.c_str());
    boost::mutex::scoped_lock lock(monitor_mutex_);
    if (this->subscribers.find(peer_id) != subscribers.end()) {
      this->subscribers.erase(peer_id);
    }
  }

  boost::future<void> OneToManyProcessor::close() {
    return closeAll();
  }

  boost::future<void> OneToManyProcessor::closeAll() {
    ELOG_DEBUG("OneToManyProcessor closeAll");
    std::shared_ptr<boost::promise<void>> p = std::make_shared<boost::promise<void>>();
    boost::future<void> f = p->get_future();
    feedbackSink_ = nullptr;
    publisher.reset();
    boost::unique_lock<boost::mutex> lock(monitor_mutex_);
    std::map<std::string, std::shared_ptr<MediaSink>>::iterator it = subscribers.begin();
    while (it != subscribers.end()) {
      if ((*it).second != nullptr) {
        FeedbackSource* fbsource = (*it).second->getFeedbackSource();
        if (fbsource != nullptr) {
          fbsource->setFeedbackSink(nullptr);
        }
      }
      subscribers.erase(it++);
    }
    subscribers.clear();
    p->set_value();
    ELOG_DEBUG("ClosedAll media in this OneToMany");
    return f;
  }

}  // namespace erizo
<|endoftext|>


<commit_before>/**
 *  testApp.cpp is part of ofxXmlDefaultSettings.
 *
 *  Copyright (c) 2012, Paul Vollmer http://www.wrong-entertainment.com
 *  All rights reserved.
 *
 *
 *  The MIT License
 *
 *  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.
 *
 *
 *  @testet_oF          0071
 *  @testet_plattform   MacOs 10.6+
 *                      ??? Win
 *                      ??? Linux
 *  @dependencies       ofxXmlSettings
 *  @contributor(s)     Paul Vollmer <paul.vollmer@fh-potsdam.de>
 *  @modified           2012.09.20
 *  @version            0.1.2b
 */

#include "testApp.h"

//--------------------------------------------------------------
void testApp::setup(){
	/* Load our default xml file.
	 */
	XML.load();

	/* Get a status message
	 */
	cout << "STATUS: " << XML.statusMessage << endl;

	/* and set the openFrameworks core settings from it.
	 */
	XML.setSettings();
	cout << "STATUS: " << XML.statusMessage << endl;
}

//--------------------------------------------------------------
void testApp::update(){

}

//--------------------------------------------------------------
void testApp::draw(){

}

//--------------------------------------------------------------
void testApp::keyPressed(int key){
	switch (key) {
		/* if key 'f' is pressed, toffle fullscreen mode.
		 */
		case 'f':
			ofToggleFullscreen();
			break;
	}
}

//--------------------------------------------------------------
void testApp::exit(){
	/* Save the current settings to xml.
	 */
	XML.saveSettings();
	cout << "STATUS: " << XML.statusMessage << endl;
}
<commit_msg>small syntax fix, changes at description<commit_after>/**
 *  testApp.cpp is part of ofxXmlDefaultSettings.
 *
 *  Copyright (c) 2012, Paul Vollmer http://www.wrong-entertainment.com
 *  All rights reserved.
 *
 *
 *  The MIT License
 *
 *  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.
 *
 *
 *  @testet_oF          0071
 *  @testet_plattform   MacOs 10.6+
 *                      ??? Win
 *                      ??? Linux
 *  @dependencies       ofxXmlSettings
 *  @contributor(s)     Paul Vollmer <paul.vollmer@fh-potsdam.de>
 *  @modified           2012.09.20
 *  @version            0.1.2b
 */

#include "testApp.h"

//--------------------------------------------------------------
void testApp::setup(){
	/* Load the xml file from default path.
	 */
	XML.load();

	/* Get a status message from last method.
	 */
	cout << "STATUS: " << XML.getStatusMessage() << endl;

	/* Set the openFrameworks app settings.
	 */
	XML.setSettings();
	cout << "STATUS: " << XML.getStatusMessage() << endl;
}

//--------------------------------------------------------------
void testApp::update(){

}

//--------------------------------------------------------------
void testApp::draw(){

}

//--------------------------------------------------------------
void testApp::keyPressed(int key){
	switch (key) {
		/* If key 'f' is pressed, toggle fullscreen mode.
		 */
		case 'f':
			ofToggleFullscreen();
			break;
	}
}

//--------------------------------------------------------------
void testApp::exit(){
	/* Save the current settings to xml file.
	 */
	XML.save();
	cout << "STATUS: " << XML.getStatusMessage() << endl;
}
<|endoftext|>


<commit_before><commit_msg>fix a memory leak in the custom unpacker in the merger<commit_after><|endoftext|>


<commit_before>#include "zmq.h"
#include <iostream>
#include "AliHLTDataTypes.h"
#include "AliHLTComponent.h"
#include "AliHLTMessage.h"
#include "TClass.h"
#include "TCanvas.h"
#include "TMap.h"
#include "TPRegexp.h"
#include "TObjString.h"
#include "TDirectory.h"
#include "TList.h"
#include "AliZMQhelpers.h"
#include "TMessage.h"
#include "TSystem.h"
#include "TApplication.h"
#include "TH1.h"
#include "TH1F.h"
#include <time.h>
#include <string>
#include <map>
#include "TFile.h"
#include "TSystem.h"
#include "TStyle.h"
#include "signal.h"
class MySignalHandler;

//this is meant to become a class, hence the structure with global vars etc.
//Also the code is rather flat - it is a bit of a playground to test ideas.
//TODO structure this at some point, e.g. introduce a SIMPLE unified way of handling
//zmq payloads, maybe a AliZMQmessage class which would by default be multipart and provide
//easy access to payloads based on topic or so (a la HLT GetFirstInputObject() etc...)

//methods
int ProcessOptionString(TString arguments);
int UpdatePad(TObject*);
int DumpToFile(TObject* object);
void* run(void* arg);

//configuration vars
Bool_t fVerbose = kFALSE;
TString fZMQconfigIN  = "PULL>tcp://localhost:60211";
int fZMQsocketModeIN=-1;
TString fZMQsubscriptionIN = "";
TString fFilter = "";

TString fFileName="";
TFile* fFile=NULL;

int fPollInterval = 0;
int fPollTimeout = 1000; //1s
Bool_t fSort = kTRUE;

//internal state
void* fZMQcontext = NULL;             //ze zmq context
void* fZMQin  = NULL;                 //the in socket - entry point for the data to be merged.

TApplication* gApp;
TCanvas* fCanvas;
TObjArray fDrawables;

TString fStatus = "";
Int_t fRunNumber = 0;
TPRegexp* fSelectionRegexp = NULL;
TPRegexp* fUnSelectionRegexp = NULL;
TString fDrawOptions;
Bool_t fScaleLogX = kFALSE;
Bool_t fScaleLogY = kFALSE;
Bool_t fScaleLogZ = kFALSE;
Bool_t fResetOnRequest = kFALSE;
Int_t fHistStats = 0;

Bool_t fAllowResetAtSOR = kTRUE;

ULong64_t iterations=0;

const char* fUSAGE =
    "ZMQhstViewer: Draw() all ROOT drawables in a message\n"
    "options: \n"
    " -in : data in\n"
    " -sleep : how long to sleep in between requests for data in s (if applicable)\n"
    " -timeout : how long to wait for the server to reply (s)\n"
    " -Verbose : be verbose\n"
    " -select : only show selected histograms (by regexp)\n"
    " -unselect : as select, only inverted\n"
    " -drawoptions : what draw option to use\n"
    " -file : dump input to file and exit\n"
    " -log[xyz] : use log scale on [xyz] dimension\n"
    " -histstats : histogram stat box options (default 0)\n"
    " -AllowResetAtSOR : 0/1 to reset at change of run\n"
    ;
//_______________________________________________________________________________________
class MySignalHandler : public TSignalHandler
{
  public:
	MySignalHandler(ESignals sig) : TSignalHandler(sig) {}
	Bool_t Notify()
	{
    Printf("signal received, exiting");
		fgTerminationSignaled = true;
		return TSignalHandler::Notify();
	}
	static bool TerminationSignaled() { return fgTerminationSignaled; }
	static bool fgTerminationSignaled;
};
bool MySignalHandler::fgTerminationSignaled = false;

void sig_handler(int signo)
{
  if (signo == SIGINT)
    printf("received SIGINT\n");
  MySignalHandler::fgTerminationSignaled=true;
}

//_______________________________________________________________________________________
void* run(void* arg)
{
  //main loop
  while(!MySignalHandler::TerminationSignaled())
  {
    errno=0;
    //send a request if we are using REQ
    if (fZMQsocketModeIN==ZMQ_REQ)
    {
      string request;

      if (fSelectionRegexp || fUnSelectionRegexp)
      {
        if (fSelectionRegexp) request += " select="+fSelectionRegexp->GetPattern();
        if (fUnSelectionRegexp) request += " unselect="+fUnSelectionRegexp->GetPattern();
        if (fResetOnRequest) request += " ResetOnRequest";
        alizmq_msg_send("CONFIG", request, fZMQin, ZMQ_SNDMORE);
      }

      if (fVerbose) Printf("sending request CONFIG %s", request.c_str());
      alizmq_msg_send("", "", fZMQin, 0);
    }

    //wait for the data
    zmq_pollitem_t sockets[] = {
                                 { fZMQin, 0, ZMQ_POLLIN, 0 },
                               };
    int rc = zmq_poll(sockets, 1, (fZMQsocketModeIN==ZMQ_REQ)?fPollTimeout:-1);

    if (rc==-1 && errno==ETERM)
    {
      Printf("jumping out of main loop");
      break;
    }

    if (!(sockets[0].revents & ZMQ_POLLIN))
    {
      //server died
      Printf("connection timed out, server %s died?", fZMQconfigIN.Data());
      fZMQsocketModeIN = alizmq_socket_init(fZMQin, fZMQcontext, fZMQconfigIN.Data());
      if (fZMQsocketModeIN < 0) return NULL;
      continue;
    }
    else
    {
      //get all data (topic+body), possibly many of them
      aliZMQmsg message;
      alizmq_msg_recv(&message, fZMQin, 0);
      for (aliZMQmsg::iterator i=message.begin(); i!=message.end(); ++i)
      {
        if (alizmq_msg_iter_check(i, "INFO")==0)
        {
            //check if we have a runnumber in the string
            string info;
            alizmq_msg_iter_data(i,info);
            if (fVerbose) Printf("processing INFO %s", info.c_str());

            fCanvas->SetTitle(info.c_str());
            size_t runTagPos = info.find("run");
            if (runTagPos != std::string::npos)
            {
              size_t runStartPos = info.find("=",runTagPos);
              size_t runEndPos = info.find(" ");
              string runString = info.substr(runStartPos+1,runEndPos-runStartPos-1);
              if (fVerbose) printf("received run=%s\n",runString.c_str());

              int runnumber = atoi(runString.c_str());

              if (runnumber!=fRunNumber && fAllowResetAtSOR)
              {
                  if (fVerbose) printf("Run changed, resetting!\n");
                  fDrawables.Delete();
                  fCanvas->Clear();
              }
              fRunNumber = runnumber;
            }
            continue;
        }

        TObject* object;
        alizmq_msg_iter_data(i, object);
        if (object) UpdatePad(object);

        if (!fFileName.IsNull())
        {
          if (object) DumpToFile(object);
        }
      }
      alizmq_msg_close(&message);

    }//socket 0
    gSystem->ProcessEvents();
    usleep(fPollInterval);
  }//main loop
  return NULL;
}

//_______________________________________________________________________________________
int main(int argc, char** argv)
{
  //process args
  int noptions = ProcessOptionString(AliOptionParser::GetFullArgString(argc,argv));
  if (noptions<=0)
  {
    printf("%s",fUSAGE);
    return 1;
  }

  TH1::AddDirectory(kFALSE);
  TDirectory::AddDirectory(kFALSE);
  gApp = new TApplication("viewer", &argc, argv);
  gApp->SetReturnFromRun(true);
  //gApp->Run();

  gStyle->SetOptStat(fHistStats);
  fCanvas = new TCanvas();
  gSystem->ProcessEvents();

  int mainReturnCode=0;

  //init stuff
  //globally enable schema evolution for serializing ROOT objects
  TMessage::EnableSchemaEvolutionForAll(kTRUE);
  //ZMQ init
  fZMQcontext = zmq_ctx_new();
  fZMQsocketModeIN = alizmq_socket_init(fZMQin, fZMQcontext, fZMQconfigIN.Data(), -1, 2);
  if (fZMQsocketModeIN < 0) return 1;

  gSystem->ResetSignal(kSigPipe);
  gSystem->ResetSignal(kSigQuit);
  gSystem->ResetSignal(kSigInterrupt);
  gSystem->ResetSignal(kSigTermination);
  //gSystem->AddSignalHandler(new MySignalHandler(kSigPipe));
  //gSystem->AddSignalHandler(new MySignalHandler(kSigQuit));
  //gSystem->AddSignalHandler(new MySignalHandler(kSigInterrupt));
  //gSystem->AddSignalHandler(new MySignalHandler(kSigTermination));

  if (signal(SIGINT, sig_handler) == SIG_ERR)
  printf("\ncan't catch SIGINT\n");

  run(NULL);

  Printf("exiting...");
  if (fFile) fFile->Close();
  delete fFile; fFile=0;

  //destroy ZMQ sockets

  int linger=0;
  zmq_setsockopt(fZMQin, ZMQ_LINGER, &linger, sizeof(linger));
  zmq_close(fZMQin);
  zmq_ctx_term(fZMQcontext);
  return mainReturnCode;
}

//______________________________________________________________________________
int DumpToFile(TObject* object)
{
  Option_t* fileMode="RECREATE";
  if (!fFile) fFile = new TFile(fFileName,fileMode);
  if (fVerbose) Printf("writing object %s to %s",object->GetName(), fFileName.Data());
  int rc = object->Write(object->GetName(),TObject::kOverwrite);
  MySignalHandler::fgTerminationSignaled=true;
  return rc;
}

//______________________________________________________________________________
int UpdatePad(TObject* object)
{
  if (!object) return -1;
  const char* name = object->GetName();

  TObject* drawable = fDrawables.FindObject(name);
  int padIndex = fDrawables.IndexOf(drawable);

  if (fVerbose) Printf("in: %s (%s)", name, object->ClassName());
  Bool_t selected = kTRUE;
  Bool_t unselected = kFALSE;
  if (fSelectionRegexp) selected = fSelectionRegexp->Match(name);
  if (fUnSelectionRegexp) unselected = fUnSelectionRegexp->Match(name);
  if (!selected || unselected)
  {
      delete object;
      return 0;
  }

  if (drawable)
  {
    //only redraw the one thing
    if (fVerbose) Printf("  redrawing %s in pad %i", name, padIndex);
    fCanvas->cd(padIndex+1);
    gPad->GetListOfPrimitives()->Remove(drawable);
    gPad->Clear();
    fDrawables.RemoveAt(padIndex);
    delete drawable;
    fDrawables.AddAt(object, padIndex);
    object->Draw(fDrawOptions);
    gPad->Modified(kTRUE);
  }
  else
  {
    if (fVerbose) Printf("  new object %s", name);
    //add the new object to the collection, restructure the canvas
    //and redraw everything
    fDrawables.AddLast(object);

    if (fSort)
    {
      TObjArray sortedTitles(fDrawables.GetEntries());
      for (int i=0; i<fDrawables.GetEntries(); i++)
      { sortedTitles.AddAt(new TNamed(fDrawables[i]->GetTitle(),fDrawables[i]->GetName()),i); }
      sortedTitles.Sort();
      TObjArray sortedDrawables(fDrawables.GetEntries());
      for (int i=0; i<fDrawables.GetEntries(); i++)
      {
        const char* name = sortedTitles[i]->GetTitle();
        TObject* tmp = fDrawables.FindObject(name);
        int index = fDrawables.IndexOf(tmp);
        sortedDrawables.AddAt(fDrawables[index],i);
      }
      for (int i=0; i<sortedDrawables.GetEntries(); i++)
      { fDrawables.AddAt(sortedDrawables[i],i); }
      sortedTitles.Delete();
    }

    //after we clear the canvas, the pads are gone, clear the pad cache as well
    fCanvas->Clear();
    fCanvas->DivideSquare(fDrawables.GetLast()+1);

    //redraw all objects at their old places and the new one as last
    for (int i=0; i<fDrawables.GetLast()+1; i++)
    {
      TObject* obj = fDrawables[i];
      fCanvas->cd(i+1);
      if (fScaleLogX) gPad->SetLogx();
      if (fScaleLogY) gPad->SetLogy();
      if (fScaleLogZ) gPad->SetLogz();
      if (fVerbose) Printf("  drawing %s in pad %i", obj->GetName(), i);
      if (obj) obj->Draw(fDrawOptions);
    }
  }
  gSystem->ProcessEvents();
  fCanvas->Update();
  return 0;
}

//______________________________________________________________________________
int ProcessOptionString(TString arguments)
{
  //process passed options
  aliStringVec* options = AliOptionParser::TokenizeOptionString(arguments);
  int nOptions = 0;
  for (aliStringVec::iterator i=options->begin(); i!=options->end(); ++i)
  {
    //Printf("  %s : %s", i->first.data(), i->second.data());
    const TString& option = i->first;
    const TString& value = i->second;
    if (option.EqualTo("PollInterval") || option.EqualTo("sleep"))
    {
      fPollInterval = round(value.Atof()*1e6);
    }
    else if (option.EqualTo("PollTimeout") || option.EqualTo("timeout"))
    {
      fPollTimeout = round(value.Atof()*1e3);
    }
    else if (option.EqualTo("ZMQconfigIN") || option.EqualTo("in") )
    {
      fZMQconfigIN = value;
    }
    else if (option.EqualTo("Verbose"))
    {
      fVerbose=kTRUE;
    }
    else if (option.EqualTo("select"))
    {
      delete fSelectionRegexp;
      fSelectionRegexp=new TPRegexp(value);
    }
    else if (option.EqualTo("unselect"))
    {
      delete fUnSelectionRegexp;
      fUnSelectionRegexp=new TPRegexp(value);
    }
    else if (option.EqualTo("ResetOnRequest"))
    {
      fResetOnRequest = kTRUE;
    }
    else if (option.EqualTo("drawoptions"))
    {
      fDrawOptions = value;
    }
    else if (option.EqualTo("logx"))
    {
      fScaleLogX=kTRUE;
    }
    else if (option.EqualTo("logy"))
    {
      fScaleLogY=kTRUE;
    }
    else if (option.EqualTo("logz"))
    {
      fScaleLogZ=kTRUE;
    }
    else if (option.EqualTo("file"))
    {
      fFileName = value;
    }
    else if (option.EqualTo("sort"))
    {
      fSort=value.Contains(0)?kFALSE:kTRUE;
    }
    else if (option.EqualTo("histstats"))
    {
      fHistStats = value.Atoi();
    }
    else if (option.EqualTo("AllowResetAtSOR"))
    {
      fAllowResetAtSOR = (option.Contains("0")||option.Contains("no"))?kFALSE:kTRUE;
    }
    else
    {
      nOptions=-1;
      break;
    }
    nOptions++;
  }
  delete options; //tidy up

  return nOptions;
}

<commit_msg>process events after reset<commit_after>#include "zmq.h"
#include <iostream>
#include "AliHLTDataTypes.h"
#include "AliHLTComponent.h"
#include "AliHLTMessage.h"
#include "TClass.h"
#include "TCanvas.h"
#include "TMap.h"
#include "TPRegexp.h"
#include "TObjString.h"
#include "TDirectory.h"
#include "TList.h"
#include "AliZMQhelpers.h"
#include "TMessage.h"
#include "TSystem.h"
#include "TApplication.h"
#include "TH1.h"
#include "TH1F.h"
#include <time.h>
#include <string>
#include <map>
#include "TFile.h"
#include "TSystem.h"
#include "TStyle.h"
#include "signal.h"
class MySignalHandler;

//this is meant to become a class, hence the structure with global vars etc.
//Also the code is rather flat - it is a bit of a playground to test ideas.
//TODO structure this at some point, e.g. introduce a SIMPLE unified way of handling
//zmq payloads, maybe a AliZMQmessage class which would by default be multipart and provide
//easy access to payloads based on topic or so (a la HLT GetFirstInputObject() etc...)

//methods
int ProcessOptionString(TString arguments);
int UpdatePad(TObject*);
int DumpToFile(TObject* object);
void* run(void* arg);

//configuration vars
Bool_t fVerbose = kFALSE;
TString fZMQconfigIN  = "PULL>tcp://localhost:60211";
int fZMQsocketModeIN=-1;
TString fZMQsubscriptionIN = "";
TString fFilter = "";

TString fFileName="";
TFile* fFile=NULL;

int fPollInterval = 0;
int fPollTimeout = 1000; //1s
Bool_t fSort = kTRUE;

//internal state
void* fZMQcontext = NULL;             //ze zmq context
void* fZMQin  = NULL;                 //the in socket - entry point for the data to be merged.

TApplication* gApp;
TCanvas* fCanvas;
TObjArray fDrawables;

TString fStatus = "";
Int_t fRunNumber = 0;
TPRegexp* fSelectionRegexp = NULL;
TPRegexp* fUnSelectionRegexp = NULL;
TString fDrawOptions;
Bool_t fScaleLogX = kFALSE;
Bool_t fScaleLogY = kFALSE;
Bool_t fScaleLogZ = kFALSE;
Bool_t fResetOnRequest = kFALSE;
Int_t fHistStats = 0;

Bool_t fAllowResetAtSOR = kTRUE;

ULong64_t iterations=0;

const char* fUSAGE =
    "ZMQhstViewer: Draw() all ROOT drawables in a message\n"
    "options: \n"
    " -in : data in\n"
    " -sleep : how long to sleep in between requests for data in s (if applicable)\n"
    " -timeout : how long to wait for the server to reply (s)\n"
    " -Verbose : be verbose\n"
    " -select : only show selected histograms (by regexp)\n"
    " -unselect : as select, only inverted\n"
    " -drawoptions : what draw option to use\n"
    " -file : dump input to file and exit\n"
    " -log[xyz] : use log scale on [xyz] dimension\n"
    " -histstats : histogram stat box options (default 0)\n"
    " -AllowResetAtSOR : 0/1 to reset at change of run\n"
    ;
//_______________________________________________________________________________________
class MySignalHandler : public TSignalHandler
{
  public:
	MySignalHandler(ESignals sig) : TSignalHandler(sig) {}
	Bool_t Notify()
	{
    Printf("signal received, exiting");
		fgTerminationSignaled = true;
		return TSignalHandler::Notify();
	}
	static bool TerminationSignaled() { return fgTerminationSignaled; }
	static bool fgTerminationSignaled;
};
bool MySignalHandler::fgTerminationSignaled = false;

void sig_handler(int signo)
{
  if (signo == SIGINT)
    printf("received SIGINT\n");
  MySignalHandler::fgTerminationSignaled=true;
}

//_______________________________________________________________________________________
void* run(void* arg)
{
  //main loop
  while(!MySignalHandler::TerminationSignaled())
  {
    errno=0;
    //send a request if we are using REQ
    if (fZMQsocketModeIN==ZMQ_REQ)
    {
      string request;

      if (fSelectionRegexp || fUnSelectionRegexp)
      {
        if (fSelectionRegexp) request += " select="+fSelectionRegexp->GetPattern();
        if (fUnSelectionRegexp) request += " unselect="+fUnSelectionRegexp->GetPattern();
        if (fResetOnRequest) request += " ResetOnRequest";
        alizmq_msg_send("CONFIG", request, fZMQin, ZMQ_SNDMORE);
      }

      if (fVerbose) Printf("sending request CONFIG %s", request.c_str());
      alizmq_msg_send("", "", fZMQin, 0);
    }

    //wait for the data
    zmq_pollitem_t sockets[] = {
                                 { fZMQin, 0, ZMQ_POLLIN, 0 },
                               };
    int rc = zmq_poll(sockets, 1, (fZMQsocketModeIN==ZMQ_REQ)?fPollTimeout:-1);

    if (rc==-1 && errno==ETERM)
    {
      Printf("jumping out of main loop");
      break;
    }

    if (!(sockets[0].revents & ZMQ_POLLIN))
    {
      //server died
      Printf("connection timed out, server %s died?", fZMQconfigIN.Data());
      fZMQsocketModeIN = alizmq_socket_init(fZMQin, fZMQcontext, fZMQconfigIN.Data());
      if (fZMQsocketModeIN < 0) return NULL;
      continue;
    }
    else
    {
      //get all data (topic+body), possibly many of them
      aliZMQmsg message;
      alizmq_msg_recv(&message, fZMQin, 0);
      for (aliZMQmsg::iterator i=message.begin(); i!=message.end(); ++i)
      {
        if (alizmq_msg_iter_check(i, "INFO")==0)
        {
            //check if we have a runnumber in the string
            string info;
            alizmq_msg_iter_data(i,info);
            if (fVerbose) Printf("processing INFO %s", info.c_str());

            fCanvas->SetTitle(info.c_str());
            size_t runTagPos = info.find("run");
            if (runTagPos != std::string::npos)
            {
              size_t runStartPos = info.find("=",runTagPos);
              size_t runEndPos = info.find(" ");
              string runString = info.substr(runStartPos+1,runEndPos-runStartPos-1);
              if (fVerbose) printf("received run=%s\n",runString.c_str());

              int runnumber = atoi(runString.c_str());

              if (runnumber!=fRunNumber && fAllowResetAtSOR)
              {
                  if (fVerbose) printf("Run changed, resetting!\n");
                  fDrawables.Delete();
                  fCanvas->Clear();
                  gSystem->ProcessEvents();
              }
              fRunNumber = runnumber;
            }
            continue;
        }

        TObject* object;
        alizmq_msg_iter_data(i, object);
        if (object) UpdatePad(object);

        if (!fFileName.IsNull())
        {
          if (object) DumpToFile(object);
        }
      }
      alizmq_msg_close(&message);

    }//socket 0
    gSystem->ProcessEvents();
    usleep(fPollInterval);
  }//main loop
  return NULL;
}

//_______________________________________________________________________________________
int main(int argc, char** argv)
{
  //process args
  int noptions = ProcessOptionString(AliOptionParser::GetFullArgString(argc,argv));
  if (noptions<=0)
  {
    printf("%s",fUSAGE);
    return 1;
  }

  TH1::AddDirectory(kFALSE);
  TDirectory::AddDirectory(kFALSE);
  gApp = new TApplication("viewer", &argc, argv);
  gApp->SetReturnFromRun(true);
  //gApp->Run();

  gStyle->SetOptStat(fHistStats);
  fCanvas = new TCanvas();
  gSystem->ProcessEvents();

  int mainReturnCode=0;

  //init stuff
  //globally enable schema evolution for serializing ROOT objects
  TMessage::EnableSchemaEvolutionForAll(kTRUE);
  //ZMQ init
  fZMQcontext = zmq_ctx_new();
  fZMQsocketModeIN = alizmq_socket_init(fZMQin, fZMQcontext, fZMQconfigIN.Data(), -1, 2);
  if (fZMQsocketModeIN < 0) return 1;

  gSystem->ResetSignal(kSigPipe);
  gSystem->ResetSignal(kSigQuit);
  gSystem->ResetSignal(kSigInterrupt);
  gSystem->ResetSignal(kSigTermination);
  //gSystem->AddSignalHandler(new MySignalHandler(kSigPipe));
  //gSystem->AddSignalHandler(new MySignalHandler(kSigQuit));
  //gSystem->AddSignalHandler(new MySignalHandler(kSigInterrupt));
  //gSystem->AddSignalHandler(new MySignalHandler(kSigTermination));

  if (signal(SIGINT, sig_handler) == SIG_ERR)
  printf("\ncan't catch SIGINT\n");

  run(NULL);

  Printf("exiting...");
  if (fFile) fFile->Close();
  delete fFile; fFile=0;

  //destroy ZMQ sockets

  int linger=0;
  zmq_setsockopt(fZMQin, ZMQ_LINGER, &linger, sizeof(linger));
  zmq_close(fZMQin);
  zmq_ctx_term(fZMQcontext);
  return mainReturnCode;
}

//______________________________________________________________________________
int DumpToFile(TObject* object)
{
  Option_t* fileMode="RECREATE";
  if (!fFile) fFile = new TFile(fFileName,fileMode);
  if (fVerbose) Printf("writing object %s to %s",object->GetName(), fFileName.Data());
  int rc = object->Write(object->GetName(),TObject::kOverwrite);
  MySignalHandler::fgTerminationSignaled=true;
  return rc;
}

//______________________________________________________________________________
int UpdatePad(TObject* object)
{
  if (!object) return -1;
  const char* name = object->GetName();

  TObject* drawable = fDrawables.FindObject(name);
  int padIndex = fDrawables.IndexOf(drawable);

  if (fVerbose) Printf("in: %s (%s)", name, object->ClassName());
  Bool_t selected = kTRUE;
  Bool_t unselected = kFALSE;
  if (fSelectionRegexp) selected = fSelectionRegexp->Match(name);
  if (fUnSelectionRegexp) unselected = fUnSelectionRegexp->Match(name);
  if (!selected || unselected)
  {
      delete object;
      return 0;
  }

  if (drawable)
  {
    //only redraw the one thing
    if (fVerbose) Printf("  redrawing %s in pad %i", name, padIndex);
    fCanvas->cd(padIndex+1);
    gPad->GetListOfPrimitives()->Remove(drawable);
    gPad->Clear();
    fDrawables.RemoveAt(padIndex);
    delete drawable;
    fDrawables.AddAt(object, padIndex);
    object->Draw(fDrawOptions);
    gPad->Modified(kTRUE);
  }
  else
  {
    if (fVerbose) Printf("  new object %s", name);
    //add the new object to the collection, restructure the canvas
    //and redraw everything
    fDrawables.AddLast(object);

    if (fSort)
    {
      TObjArray sortedTitles(fDrawables.GetEntries());
      for (int i=0; i<fDrawables.GetEntries(); i++)
      { sortedTitles.AddAt(new TNamed(fDrawables[i]->GetTitle(),fDrawables[i]->GetName()),i); }
      sortedTitles.Sort();
      TObjArray sortedDrawables(fDrawables.GetEntries());
      for (int i=0; i<fDrawables.GetEntries(); i++)
      {
        const char* name = sortedTitles[i]->GetTitle();
        TObject* tmp = fDrawables.FindObject(name);
        int index = fDrawables.IndexOf(tmp);
        sortedDrawables.AddAt(fDrawables[index],i);
      }
      for (int i=0; i<sortedDrawables.GetEntries(); i++)
      { fDrawables.AddAt(sortedDrawables[i],i); }
      sortedTitles.Delete();
    }

    //after we clear the canvas, the pads are gone, clear the pad cache as well
    fCanvas->Clear();
    fCanvas->DivideSquare(fDrawables.GetLast()+1);

    //redraw all objects at their old places and the new one as last
    for (int i=0; i<fDrawables.GetLast()+1; i++)
    {
      TObject* obj = fDrawables[i];
      fCanvas->cd(i+1);
      if (fScaleLogX) gPad->SetLogx();
      if (fScaleLogY) gPad->SetLogy();
      if (fScaleLogZ) gPad->SetLogz();
      if (fVerbose) Printf("  drawing %s in pad %i", obj->GetName(), i);
      if (obj) obj->Draw(fDrawOptions);
    }
  }
  gSystem->ProcessEvents();
  fCanvas->Update();
  return 0;
}

//______________________________________________________________________________
int ProcessOptionString(TString arguments)
{
  //process passed options
  aliStringVec* options = AliOptionParser::TokenizeOptionString(arguments);
  int nOptions = 0;
  for (aliStringVec::iterator i=options->begin(); i!=options->end(); ++i)
  {
    //Printf("  %s : %s", i->first.data(), i->second.data());
    const TString& option = i->first;
    const TString& value = i->second;
    if (option.EqualTo("PollInterval") || option.EqualTo("sleep"))
    {
      fPollInterval = round(value.Atof()*1e6);
    }
    else if (option.EqualTo("PollTimeout") || option.EqualTo("timeout"))
    {
      fPollTimeout = round(value.Atof()*1e3);
    }
    else if (option.EqualTo("ZMQconfigIN") || option.EqualTo("in") )
    {
      fZMQconfigIN = value;
    }
    else if (option.EqualTo("Verbose"))
    {
      fVerbose=kTRUE;
    }
    else if (option.EqualTo("select"))
    {
      delete fSelectionRegexp;
      fSelectionRegexp=new TPRegexp(value);
    }
    else if (option.EqualTo("unselect"))
    {
      delete fUnSelectionRegexp;
      fUnSelectionRegexp=new TPRegexp(value);
    }
    else if (option.EqualTo("ResetOnRequest"))
    {
      fResetOnRequest = kTRUE;
    }
    else if (option.EqualTo("drawoptions"))
    {
      fDrawOptions = value;
    }
    else if (option.EqualTo("logx"))
    {
      fScaleLogX=kTRUE;
    }
    else if (option.EqualTo("logy"))
    {
      fScaleLogY=kTRUE;
    }
    else if (option.EqualTo("logz"))
    {
      fScaleLogZ=kTRUE;
    }
    else if (option.EqualTo("file"))
    {
      fFileName = value;
    }
    else if (option.EqualTo("sort"))
    {
      fSort=value.Contains(0)?kFALSE:kTRUE;
    }
    else if (option.EqualTo("histstats"))
    {
      fHistStats = value.Atoi();
    }
    else if (option.EqualTo("AllowResetAtSOR"))
    {
      fAllowResetAtSOR = (option.Contains("0")||option.Contains("no"))?kFALSE:kTRUE;
    }
    else
    {
      nOptions=-1;
      break;
    }
    nOptions++;
  }
  delete options; //tidy up

  return nOptions;
}

<|endoftext|>


<commit_before>/* Copyright (c) 2010-2012 Stanford University
 *
 * Permission to use, copy, modify, and 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(S) DISCLAIM ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS 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 "ClientException.h"
#include "Cycles.h"
#include "Logger.h"
#include "MasterService.h"
#include "Memory.h"
#include "SegmentIterator.h"
#include "Seglet.h"
#include "Tablets.pb.h"

namespace RAMCloud {

class RecoverSegmentBenchmark {

  public:
    Context context;
    ServerConfig config;
    ServerList serverList;
    MasterService* service;

    RecoverSegmentBenchmark(string logSize, string hashTableSize,
        int numSegments)
        : context()
        , config(ServerConfig::forTesting())
        , serverList(&context)
        , service(NULL)
    {
        Logger::get().setLogLevels(SILENT_LOG_LEVEL);
        config.localLocator = "bogus";
        config.coordinatorLocator = "bogus";
        config.setLogAndHashTableSize(logSize, hashTableSize);
        config.services = {WireFormat::MASTER_SERVICE};
        config.master.numReplicas = 0;
        config.segmentSize = Segment::DEFAULT_SEGMENT_SIZE;
        config.segletSize = Seglet::DEFAULT_SEGLET_SIZE;
        service = new MasterService(&context, config);
        service->init({1, 0});
    }

    ~RecoverSegmentBenchmark()
    {
        delete service;
    }

    void
    run(int numSegments, int dataBytes)
    {
        /*
         * Allocate numSegments Segments and fill them up with objects of
         * size dataBytes. These will be the Segments that we recover.
         */
        uint64_t numObjects = 0;
        uint64_t nextKeyVal = 0;
        Segment *segments[numSegments];
        for (int i = 0; i < numSegments; i++) {
            segments[i] = new Segment();
            while (1) {
                Key key(0, &nextKeyVal, sizeof(nextKeyVal));

                char objectData[dataBytes];
                Object object(key, objectData, dataBytes, 0, 0);
                Buffer buffer;
                object.serializeToBuffer(buffer);
                if (!segments[i]->append(LOG_ENTRY_TYPE_OBJ, buffer))
                    break;
                nextKeyVal++;
                numObjects++;
            }
            segments[i]->close();
        }

        /* Update the list of Tablets */
        ProtoBuf::Tablets_Tablet tablet;
        tablet.set_table_id(0);
        tablet.set_start_key_hash(0);
        tablet.set_end_key_hash(~0UL);
        tablet.set_state(ProtoBuf::Tablets_Tablet_State_NORMAL);
        tablet.set_server_id(service->serverId.getId());
        *service->tablets.add_tablet() = tablet;

        /*
         * Now run a fake recovery.
         */
        uint64_t before = Cycles::rdtsc();
        for (int i = 0; i < numSegments; i++) {
            Segment* s = segments[i];
            Buffer buffer;
            s->appendToBuffer(buffer);
            Segment::Certificate certificate;
            s->getAppendedLength(certificate);
            const void* contigSeg = buffer.getRange(0, buffer.getTotalLength());
            SegmentIterator it(contigSeg, buffer.getTotalLength(), certificate);
            service->recoverSegment(it);
        }
        uint64_t ticks = Cycles::rdtsc() - before;

        uint64_t totalObjectBytes = numObjects * dataBytes;
        uint64_t totalSegmentBytes = numSegments *
                                     Segment::DEFAULT_SEGMENT_SIZE;
        printf("Recovery of %d %dKB Segments with %d byte Objects took %lu "
            "milliseconds\n", numSegments, Segment::DEFAULT_SEGMENT_SIZE / 1024,
            dataBytes, RAMCloud::Cycles::toNanoseconds(ticks) / 1000 / 1000);
        printf("Actual total object count: %lu (%lu bytes in Objects, %.2f%% "
            "overhead)\n", numObjects, totalObjectBytes,
            100.0 *
            static_cast<double>(totalSegmentBytes - totalObjectBytes) /
            static_cast<double>(totalSegmentBytes));

        // clean up
        for (int i = 0; i < numSegments; i++) {
            delete segments[i];
        }
    }

    DISALLOW_COPY_AND_ASSIGN(RecoverSegmentBenchmark);
};

}  // namespace RAMCloud

int
main()
{
    int numSegments = 80;
    int dataBytes[] = { 64, 128, 256, 512, 1024, 2048, 8192, 0 };

    for (int i = 0; dataBytes[i] != 0; i++) {
        printf("==========================\n");
        RAMCloud::RecoverSegmentBenchmark rsb("2048", "10%", numSegments);
        rsb.run(numSegments, dataBytes[i]);
    }

    return 0;
}
<commit_msg>Temp metrics support for RecoverSegmentBenchmark.<commit_after>/* Copyright (c) 2010-2012 Stanford University
 *
 * Permission to use, copy, modify, and 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(S) DISCLAIM ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS 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 "ClientException.h"
#include "Cycles.h"
#include "Logger.h"
#include "MasterService.h"
#include "Memory.h"
#include "SegmentIterator.h"
#include "Seglet.h"
#include "Tablets.pb.h"

namespace RAMCloud {

class RecoverSegmentBenchmark {

  public:
    Context context;
    ServerConfig config;
    ServerList serverList;
    MasterService* service;

    RecoverSegmentBenchmark(string logSize, string hashTableSize,
        int numSegments)
        : context()
        , config(ServerConfig::forTesting())
        , serverList(&context)
        , service(NULL)
    {
        Logger::get().setLogLevels(WARNING);
        config.localLocator = "bogus";
        config.coordinatorLocator = "bogus";
        config.setLogAndHashTableSize(logSize, hashTableSize);
        config.services = {WireFormat::MASTER_SERVICE};
        config.master.numReplicas = 0;
        config.segmentSize = Segment::DEFAULT_SEGMENT_SIZE;
        config.segletSize = Seglet::DEFAULT_SEGLET_SIZE;
        service = new MasterService(&context, config);
        service->init({1, 0});
    }

    ~RecoverSegmentBenchmark()
    {
        delete service;
    }

    void
    run(int numSegments, int dataBytes)
    {
        /*
         * Allocate numSegments Segments and fill them up with objects of
         * size dataBytes. These will be the Segments that we recover.
         */
        uint64_t numObjects = 0;
        uint64_t nextKeyVal = 0;
        Segment *segments[numSegments];
        for (int i = 0; i < numSegments; i++) {
            segments[i] = new Segment();
            while (1) {
                Key key(0, &nextKeyVal, sizeof(nextKeyVal));

                char objectData[dataBytes];
                Object object(key, objectData, dataBytes, 0, 0);
                Buffer buffer;
                object.serializeToBuffer(buffer);
                if (!segments[i]->append(LOG_ENTRY_TYPE_OBJ, buffer))
                    break;
                nextKeyVal++;
                numObjects++;
            }
            segments[i]->close();
        }

        /* Update the list of Tablets */
        ProtoBuf::Tablets_Tablet tablet;
        tablet.set_table_id(0);
        tablet.set_start_key_hash(0);
        tablet.set_end_key_hash(~0UL);
        tablet.set_state(ProtoBuf::Tablets_Tablet_State_NORMAL);
        tablet.set_server_id(service->serverId.getId());
        *service->tablets.add_tablet() = tablet;

        metrics->temp.ticks0 =
        metrics->temp.ticks1 =
        metrics->temp.ticks2 =
        metrics->temp.ticks3 =
        metrics->temp.ticks4 =
        metrics->temp.ticks5 =
        metrics->temp.ticks6 =
        metrics->temp.ticks7 =
        metrics->temp.ticks8 =
        metrics->temp.ticks9 = 0;

        metrics->temp.count0 =
        metrics->temp.count1 =
        metrics->temp.count2 =
        metrics->temp.count3 =
        metrics->temp.count4 =
        metrics->temp.count5 =
        metrics->temp.count6 =
        metrics->temp.count7 =
        metrics->temp.count8 =
        metrics->temp.count9 = 0;

        /*
         * Now run a fake recovery.
         */
        uint64_t before = Cycles::rdtsc();
        for (int i = 0; i < numSegments; i++) {
            Segment* s = segments[i];
            Buffer buffer;
            s->appendToBuffer(buffer);
            Segment::Certificate certificate;
            s->getAppendedLength(certificate);
            const void* contigSeg = buffer.getRange(0, buffer.getTotalLength());
            SegmentIterator it(contigSeg, buffer.getTotalLength(), certificate);
            service->recoverSegment(it);
        }
        uint64_t ticks = Cycles::rdtsc() - before;

        uint64_t totalObjectBytes = numObjects * dataBytes;
        uint64_t totalSegmentBytes = numSegments *
                                     Segment::DEFAULT_SEGMENT_SIZE;
        printf("Recovery of %d %dKB Segments with %d byte Objects took %lu "
            "ms\n", numSegments, Segment::DEFAULT_SEGMENT_SIZE / 1024,
            dataBytes, RAMCloud::Cycles::toNanoseconds(ticks) / 1000 / 1000);
        printf("Actual total object count: %lu (%lu bytes in Objects, %.2f%% "
            "overhead)\n", numObjects, totalObjectBytes,
            100.0 *
            static_cast<double>(totalSegmentBytes - totalObjectBytes) /
            static_cast<double>(totalSegmentBytes));

        printf("\n");
        printf("Verify object checksums: %.2f ms\n",
               Cycles::toSeconds(metrics->master.verifyChecksumTicks.load()) *
               1000.);
        metrics->master.verifyChecksumTicks = 0;

#define DUMP_TEMP_TICKS(i)  \
if (metrics->temp.ticks##i.load()) { \
    printf("temp.ticks%d: %.2f ms\n", i, \
           Cycles::toSeconds(metrics->temp.ticks##i.load()) * \
           1000.); \
    metrics->temp.ticks##i = 0; \
}

#define DUMP_TEMP_COUNT(i)  \
if (metrics->temp.count##i.load()) { \
    printf("temp.count%d: %lu\n", i, \
           metrics->temp.count##i.load()); \
    metrics->temp.count##i = 0; \
}

        DUMP_TEMP_TICKS(0);
        DUMP_TEMP_TICKS(1);
        DUMP_TEMP_TICKS(2);
        DUMP_TEMP_TICKS(3);
        DUMP_TEMP_TICKS(4);
        DUMP_TEMP_TICKS(5);
        DUMP_TEMP_TICKS(6);
        DUMP_TEMP_TICKS(7);
        DUMP_TEMP_TICKS(8);
        DUMP_TEMP_TICKS(9);

        DUMP_TEMP_COUNT(0);
        DUMP_TEMP_COUNT(1);
        DUMP_TEMP_COUNT(2);
        DUMP_TEMP_COUNT(3);
        DUMP_TEMP_COUNT(4);
        DUMP_TEMP_COUNT(5);
        DUMP_TEMP_COUNT(6);
        DUMP_TEMP_COUNT(7);
        DUMP_TEMP_COUNT(8);
        DUMP_TEMP_COUNT(9);

        // clean up
        for (int i = 0; i < numSegments; i++) {
            delete segments[i];
        }
    }

    DISALLOW_COPY_AND_ASSIGN(RecoverSegmentBenchmark);
};

}  // namespace RAMCloud

int
main()
{
    int numSegments = 80;
    int dataBytes[] = { 64, 128, 256, 512, 1024, 2048, 8192, 0 };

    for (int i = 0; dataBytes[i] != 0; i++) {
        printf("==========================\n");
        RAMCloud::RecoverSegmentBenchmark rsb("2048", "10%", numSegments);
        rsb.run(numSegments, dataBytes[i]);
    }

    return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2011, 2012 Esrille Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "StackingContext.h"

// TODO: Do not inlcude GL in this file
#include <GL/gl.h>
#include <GL/glu.h>

#include <new>
#include <iostream>

#include "Box.h"
#include "ViewCSSImp.h"

namespace org { namespace w3c { namespace dom { namespace bootstrap {

StackingContext* StackingContext::removeChild(StackingContext* item)
{
    StackingContext* next = item->nextSibling;
    StackingContext* prev = item->previousSibling;
    if (!next)
        lastChild = prev;
    else
        next->previousSibling = prev;
    if (!prev)
        firstChild = next;
    else
        prev->nextSibling = next;
    item->parent = item->nextSibling = item->previousSibling = 0;
    --childCount;
    return item;
}

StackingContext* StackingContext::insertBefore(StackingContext* item, StackingContext* after)
{
    if (!after)
        return appendChild(item);
    item->previousSibling = after->previousSibling;
    item->nextSibling = after;
    after->previousSibling = item;
    if (!item->previousSibling)
        firstChild = item;
    else
        item->previousSibling->nextSibling = item;
    item->parent = this;
    ++childCount;
    return item;
}

StackingContext* StackingContext::appendChild(StackingContext* item)
{
    StackingContext* prev = lastChild;
    if (!prev)
        firstChild = item;
    else
        prev->nextSibling = item;
    item->previousSibling = prev;
    item->nextSibling = 0;
    lastChild = item;
    item->parent = this;
    ++childCount;
    return item;
}

StackingContext::StackingContext(bool auto_, int zIndex, CSSStyleDeclarationImp* style) :
    count(0),
    style(style),
    needStaticPosition(false),
    auto_(auto_),
    zIndex(zIndex),
    parent(0),
    firstChild(0),
    lastChild(0),
    previousSibling(0),
    nextSibling(0),
    childCount(0),
    positioned(0),
    firstBase(0),
    lastBase(0),
    clipBox(0),
    firstFloat(0),
    lastFloat(0),
    currentFloat(0),
    relativeX(0.0f),
    relativeY(0.0f)
{
}

StackingContext::~StackingContext()
{
    if (parent)
        parent->removeChild(this);
    while (0 < childCount) {
        StackingContext* child = removeChild(firstChild);
        delete child;
    }
}

StackingContext* StackingContext::addContext(bool auto_, int zIndex, CSSStyleDeclarationImp* style)
{
    StackingContext* item = new(std::nothrow) StackingContext(auto_, zIndex, style);
    if (item)
        insertContext(item);
    return item;
}

void StackingContext::insertContext(StackingContext* item)
{
    assert(item);
    if (isAuto()) {
        parent->insertContext(item);
        item->positioned = this;
        return;
    }
    // TODO: Preserve the order in the DOM tree
    StackingContext* after = 0;
    for (auto i = getFirstChild(); i; i = i->getNextSibling()) {
        if (item->zIndex < i->zIndex) {
            after = i;
            break;
        }
    }
    insertBefore(item, after);
    item->positioned = this;
}

void StackingContext::reparent(StackingContext* target)
{
    auto child = parent->getFirstChild();
    while (child) {
        auto next = child->getNextSibling();
        if (child->positioned == target) {
            parent->removeChild(child);
            target->insertContext(child);
            if (child->isAuto())
                reparent(child);
        }
        child = next;
    }
}

void StackingContext::setZIndex(bool auto_, int index)
{
    if (isAuto() == auto_ && zIndex == index)
        return;
    bool updateChildren = (this->auto_ != auto_);
    this->auto_ = auto_;
    zIndex = index;
    if (parent) {
        parent->removeChild(this);
        positioned->insertContext(this);
        if (updateChildren) {
            if (isAuto()) {
                while (StackingContext* child = getFirstChild()) {
                    removeChild(child);
                    child->positioned->insertContext(child);
                }
            } else
                reparent(this);
        }
    }
}

void StackingContext::resetScrollSize()
{
    for (Box* base = firstBase; base; base = base->nextBase)
        base->resetScrollSize();
    for (StackingContext* childContext = getFirstChild(); childContext; childContext = childContext->getNextSibling())
        childContext->resetScrollSize();
}

void StackingContext::resolveScrollSize(ViewCSSImp* view)
{
    relativeX = relativeY = 0.0f;
    for (StackingContext* s = this; s != parent; s = s->positioned) {
        assert(s->style);
        CSSStyleDeclarationImp* style = s->style;
        if (!style->isResolved()) {
            if (Box* b = style->getBox()) {
                if (auto c = b->getContainingBlock(view)) {
                    style->left.resolve(view, style, c->width);
                    style->right.resolve(view, style, c->width);
                    style->top.resolve(view, style, c->height);
                    style->bottom.resolve(view, style, c->height);
                }
            }
        }
        style->resolveRelativeOffset(relativeX, relativeY);
    }
    if (parent) {
        relativeX += parent->relativeX;
        relativeY += parent->relativeY;
    }
    for (Box* base = firstBase; base; base = base->nextBase)
        base->updateScrollSize();
    for (StackingContext* childContext = getFirstChild(); childContext; childContext = childContext->getNextSibling())
        childContext->resolveScrollSize(view);
}

void StackingContext::updateClipBox(StackingContext* s)
{
    float scrollLeft = 0.0f;
    float scrollTop = 0.0f;
    for (Block* clip = s->clipBox; clip && clip != s->positioned->clipBox; clip = clip->clipBox) {
        if (clip->stackingContext == s || !clip->getParentBox())
            continue;
        Element element = interface_cast<Element>(clip->node);
        scrollLeft += element.getScrollLeft();
        scrollTop += element.getScrollTop();
        if (clipWidth == HUGE_VALF) {
            clipLeft = scrollLeft + clip->x + clip->marginLeft + clip->borderLeft + clip->stackingContext->relativeX;
            clipTop = scrollTop + clip->y + clip->marginTop + clip->borderTop + clip->stackingContext->relativeY;
            clipWidth = clip->getPaddingWidth();
            clipHeight = clip->getPaddingHeight();
        } else {
            Box::unionRect(clipLeft, clipTop, clipWidth, clipHeight,
                           scrollLeft + clip->x + clip->marginLeft + clip->borderLeft + clip->stackingContext->relativeX,
                           scrollTop + clip->y + clip->marginTop + clip->borderTop + clip->stackingContext->relativeY,
                           clip->getPaddingWidth(), clip->getPaddingHeight());
        }
    }
    glTranslatef(-scrollLeft, -scrollTop, 0.0f);
}

bool StackingContext::hasClipBox()
{
    clipLeft = clipTop = 0.0f;
    clipWidth = clipHeight = HUGE_VALF;
    for (StackingContext* s = this; s != parent; s = s->positioned)
        updateClipBox(s);
    return clipWidth != HUGE_VALF && clipHeight != HUGE_VALF;
}

void StackingContext::render(ViewCSSImp* view)
{
    glPushMatrix();
    if (hasClipBox())
        view->clip(clipLeft, clipTop, clipWidth, clipHeight);
    if (parent)
        glTranslatef(relativeX - parent->relativeX, relativeY - parent->relativeY, 0.0f);
    else
        glTranslatef(relativeX, relativeY, 0.0f);
    if (firstBase) {
        currentFloat = firstFloat = lastFloat = 0;
        GLfloat mtx[16];
        glGetFloatv(GL_MODELVIEW_MATRIX, mtx);
        for (Box* base = firstBase; base; base = base->nextBase) {
            glPushMatrix();
            Block* block = dynamic_cast<Block*>(base);
            unsigned overflow = CSSOverflowValueImp::Visible;
            if (block)
                overflow = block->renderBegin(view);

            StackingContext* childContext = getFirstChild();
            for (; childContext && childContext->zIndex < 0; childContext = childContext->getNextSibling()) {
                glPushMatrix();
                glLoadMatrixf(mtx);
                childContext->render(view);
                glPopMatrix();
            }

            if (block) {
                block->renderNonInline(view, this);
                renderFloats(view, 0, 0);
                block->renderInline(view, this);
            } else
                base->render(view, this);

            for (; childContext; childContext = childContext->getNextSibling()) {
                glPushMatrix();
                glLoadMatrixf(mtx);
                childContext->render(view);
                glPopMatrix();
            }

            if (block) {
                if (0.0f < block->getOutlineWidth())
                    block->renderOutline(view, block->x, block->y + block->getTopBorderEdge());
                block->renderEnd(view, overflow);
            }
            glPopMatrix();
        }
    } else {
        glPushMatrix();
        for (StackingContext* childContext = getFirstChild(); childContext; childContext = childContext->getNextSibling())
            childContext->render(view);
        glPopMatrix();
    }

    if (clipWidth != HUGE_VALF && clipHeight != HUGE_VALF)
        view->unclip(clipLeft, clipTop, clipWidth, clipHeight);
    glPopMatrix();
}

void StackingContext::renderFloats(ViewCSSImp* view, Box* last, Box* current)
{
    if (current && current == currentFloat)
        return;
    if (!last)
        currentFloat = firstFloat;
    else if (last->nextFloat)
        currentFloat = last->nextFloat;
    else
        return;
    while (currentFloat) {
        currentFloat->render(view, this);;
        currentFloat = currentFloat->nextFloat;
    }
    if (!last)
        firstFloat = lastFloat = 0;
    else {
        last->nextFloat = 0;
        lastFloat = last;
    }
    currentFloat = 0;
}

void StackingContext::addBase(Box* box)
{
#ifndef NDEBUG
    for (Box* i = firstBase; i; i = i->nextBase)
        assert(box != i);
#endif
    if (!firstBase)
        firstBase = lastBase = box;
    else {
        lastBase->nextBase = box;
        lastBase = box;
    }
    box->nextBase = 0;
}

void StackingContext::addBox(Box* box, Box* parentBox)
{
    assert(parentBox);
    if (parentBox->stackingContext != this)
        addBase(box);
}

void StackingContext::addFloat(Box* box)
{
#ifndef NDEBUG
    for (Box* i = firstFloat; i; i = i->nextFloat) {
        assert(box != i);
    }
#endif
    if (currentFloat) {
        box->nextFloat = currentFloat->nextFloat;
        currentFloat->nextFloat = box;
        return;
    }
    if (!firstFloat)
        firstFloat = lastFloat = box;
    else {
        lastFloat->nextFloat = box;
        lastFloat = box;
    }
    box->nextFloat = 0;
}

void StackingContext::removeBox(Box* box)
{
    Box* p = 0;
    for (Box* i = firstBase; i ; p = i, i = i->nextBase) {
        if (i == box) {
            if (!p)
                firstBase = i->nextBase;
            else
                p->nextBase = i->nextBase;
            if (lastBase == box)
                lastBase = p;
            break;
        }
    }
}

void StackingContext::layOutAbsolute(ViewCSSImp* view)
{
    for (Box* base = firstBase; base; base = base->nextBase) {
        Block* block = dynamic_cast<Block*>(base);
        if (!block || !block->isAbsolutelyPositioned())
            continue;
        block->layOutAbsolute(view);
        block->resolveXY(view, block->x, block->y, block->clipBox ? block->clipBox : ((view->getTree() == block) ? 0 : view->getTree()));
    }
    needStaticPosition = false;

    for (StackingContext* childContext = getFirstChild(); childContext; childContext = childContext->getNextSibling())
        childContext->needStaticPosition = true;
    bool repeat;
    do {
        repeat = false;
        for (StackingContext* childContext = getFirstChild(); childContext; childContext = childContext->getNextSibling()) {
            if (childContext->needStaticPosition) {
                if (!childContext->positioned->needStaticPosition)
                    childContext->layOutAbsolute(view);
                else
                    repeat = true;
            }
        }
    } while (repeat);
}

void StackingContext::dump(std::string indent)
{
    std::cout << indent << "z-index: ";
    if (isAuto())
        std::cout << "auto";
    else
        std::cout << zIndex;
    std::cout << '\n';
    indent += "  ";
    for (auto child = getFirstChild(); child; child = child->getNextSibling())
        child->dump(indent);
}

}}}}  // org::w3c::dom::bootstrap
<commit_msg>(StackingContext::renderFloats) : Fix a bug<commit_after>/*
 * Copyright 2011, 2012 Esrille Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "StackingContext.h"

// TODO: Do not inlcude GL in this file
#include <GL/gl.h>
#include <GL/glu.h>

#include <new>
#include <iostream>

#include "Box.h"
#include "ViewCSSImp.h"

namespace org { namespace w3c { namespace dom { namespace bootstrap {

StackingContext* StackingContext::removeChild(StackingContext* item)
{
    StackingContext* next = item->nextSibling;
    StackingContext* prev = item->previousSibling;
    if (!next)
        lastChild = prev;
    else
        next->previousSibling = prev;
    if (!prev)
        firstChild = next;
    else
        prev->nextSibling = next;
    item->parent = item->nextSibling = item->previousSibling = 0;
    --childCount;
    return item;
}

StackingContext* StackingContext::insertBefore(StackingContext* item, StackingContext* after)
{
    if (!after)
        return appendChild(item);
    item->previousSibling = after->previousSibling;
    item->nextSibling = after;
    after->previousSibling = item;
    if (!item->previousSibling)
        firstChild = item;
    else
        item->previousSibling->nextSibling = item;
    item->parent = this;
    ++childCount;
    return item;
}

StackingContext* StackingContext::appendChild(StackingContext* item)
{
    StackingContext* prev = lastChild;
    if (!prev)
        firstChild = item;
    else
        prev->nextSibling = item;
    item->previousSibling = prev;
    item->nextSibling = 0;
    lastChild = item;
    item->parent = this;
    ++childCount;
    return item;
}

StackingContext::StackingContext(bool auto_, int zIndex, CSSStyleDeclarationImp* style) :
    count(0),
    style(style),
    needStaticPosition(false),
    auto_(auto_),
    zIndex(zIndex),
    parent(0),
    firstChild(0),
    lastChild(0),
    previousSibling(0),
    nextSibling(0),
    childCount(0),
    positioned(0),
    firstBase(0),
    lastBase(0),
    clipBox(0),
    firstFloat(0),
    lastFloat(0),
    currentFloat(0),
    relativeX(0.0f),
    relativeY(0.0f)
{
}

StackingContext::~StackingContext()
{
    if (parent)
        parent->removeChild(this);
    while (0 < childCount) {
        StackingContext* child = removeChild(firstChild);
        delete child;
    }
}

StackingContext* StackingContext::addContext(bool auto_, int zIndex, CSSStyleDeclarationImp* style)
{
    StackingContext* item = new(std::nothrow) StackingContext(auto_, zIndex, style);
    if (item)
        insertContext(item);
    return item;
}

void StackingContext::insertContext(StackingContext* item)
{
    assert(item);
    if (isAuto()) {
        parent->insertContext(item);
        item->positioned = this;
        return;
    }
    // TODO: Preserve the order in the DOM tree
    StackingContext* after = 0;
    for (auto i = getFirstChild(); i; i = i->getNextSibling()) {
        if (item->zIndex < i->zIndex) {
            after = i;
            break;
        }
    }
    insertBefore(item, after);
    item->positioned = this;
}

void StackingContext::reparent(StackingContext* target)
{
    auto child = parent->getFirstChild();
    while (child) {
        auto next = child->getNextSibling();
        if (child->positioned == target) {
            parent->removeChild(child);
            target->insertContext(child);
            if (child->isAuto())
                reparent(child);
        }
        child = next;
    }
}

void StackingContext::setZIndex(bool auto_, int index)
{
    if (isAuto() == auto_ && zIndex == index)
        return;
    bool updateChildren = (this->auto_ != auto_);
    this->auto_ = auto_;
    zIndex = index;
    if (parent) {
        parent->removeChild(this);
        positioned->insertContext(this);
        if (updateChildren) {
            if (isAuto()) {
                while (StackingContext* child = getFirstChild()) {
                    removeChild(child);
                    child->positioned->insertContext(child);
                }
            } else
                reparent(this);
        }
    }
}

void StackingContext::resetScrollSize()
{
    for (Box* base = firstBase; base; base = base->nextBase)
        base->resetScrollSize();
    for (StackingContext* childContext = getFirstChild(); childContext; childContext = childContext->getNextSibling())
        childContext->resetScrollSize();
}

void StackingContext::resolveScrollSize(ViewCSSImp* view)
{
    relativeX = relativeY = 0.0f;
    for (StackingContext* s = this; s != parent; s = s->positioned) {
        assert(s->style);
        CSSStyleDeclarationImp* style = s->style;
        if (!style->isResolved()) {
            if (Box* b = style->getBox()) {
                if (auto c = b->getContainingBlock(view)) {
                    style->left.resolve(view, style, c->width);
                    style->right.resolve(view, style, c->width);
                    style->top.resolve(view, style, c->height);
                    style->bottom.resolve(view, style, c->height);
                }
            }
        }
        style->resolveRelativeOffset(relativeX, relativeY);
    }
    if (parent) {
        relativeX += parent->relativeX;
        relativeY += parent->relativeY;
    }
    for (Box* base = firstBase; base; base = base->nextBase)
        base->updateScrollSize();
    for (StackingContext* childContext = getFirstChild(); childContext; childContext = childContext->getNextSibling())
        childContext->resolveScrollSize(view);
}

void StackingContext::updateClipBox(StackingContext* s)
{
    float scrollLeft = 0.0f;
    float scrollTop = 0.0f;
    for (Block* clip = s->clipBox; clip && clip != s->positioned->clipBox; clip = clip->clipBox) {
        if (clip->stackingContext == s || !clip->getParentBox())
            continue;
        Element element = interface_cast<Element>(clip->node);
        scrollLeft += element.getScrollLeft();
        scrollTop += element.getScrollTop();
        if (clipWidth == HUGE_VALF) {
            clipLeft = scrollLeft + clip->x + clip->marginLeft + clip->borderLeft + clip->stackingContext->relativeX;
            clipTop = scrollTop + clip->y + clip->marginTop + clip->borderTop + clip->stackingContext->relativeY;
            clipWidth = clip->getPaddingWidth();
            clipHeight = clip->getPaddingHeight();
        } else {
            Box::unionRect(clipLeft, clipTop, clipWidth, clipHeight,
                           scrollLeft + clip->x + clip->marginLeft + clip->borderLeft + clip->stackingContext->relativeX,
                           scrollTop + clip->y + clip->marginTop + clip->borderTop + clip->stackingContext->relativeY,
                           clip->getPaddingWidth(), clip->getPaddingHeight());
        }
    }
    glTranslatef(-scrollLeft, -scrollTop, 0.0f);
}

bool StackingContext::hasClipBox()
{
    clipLeft = clipTop = 0.0f;
    clipWidth = clipHeight = HUGE_VALF;
    for (StackingContext* s = this; s != parent; s = s->positioned)
        updateClipBox(s);
    return clipWidth != HUGE_VALF && clipHeight != HUGE_VALF;
}

void StackingContext::render(ViewCSSImp* view)
{
    glPushMatrix();
    if (hasClipBox())
        view->clip(clipLeft, clipTop, clipWidth, clipHeight);
    if (parent)
        glTranslatef(relativeX - parent->relativeX, relativeY - parent->relativeY, 0.0f);
    else
        glTranslatef(relativeX, relativeY, 0.0f);
    if (firstBase) {
        currentFloat = firstFloat = lastFloat = 0;
        GLfloat mtx[16];
        glGetFloatv(GL_MODELVIEW_MATRIX, mtx);
        for (Box* base = firstBase; base; base = base->nextBase) {
            glPushMatrix();
            Block* block = dynamic_cast<Block*>(base);
            unsigned overflow = CSSOverflowValueImp::Visible;
            if (block)
                overflow = block->renderBegin(view);

            StackingContext* childContext = getFirstChild();
            for (; childContext && childContext->zIndex < 0; childContext = childContext->getNextSibling()) {
                glPushMatrix();
                glLoadMatrixf(mtx);
                childContext->render(view);
                glPopMatrix();
            }

            if (block) {
                block->renderNonInline(view, this);
                renderFloats(view, 0, 0);
                block->renderInline(view, this);
            } else
                base->render(view, this);

            for (; childContext; childContext = childContext->getNextSibling()) {
                glPushMatrix();
                glLoadMatrixf(mtx);
                childContext->render(view);
                glPopMatrix();
            }

            if (block) {
                if (0.0f < block->getOutlineWidth())
                    block->renderOutline(view, block->x, block->y + block->getTopBorderEdge());
                block->renderEnd(view, overflow);
            }
            glPopMatrix();
        }
    } else {
        glPushMatrix();
        for (StackingContext* childContext = getFirstChild(); childContext; childContext = childContext->getNextSibling())
            childContext->render(view);
        glPopMatrix();
    }

    if (clipWidth != HUGE_VALF && clipHeight != HUGE_VALF)
        view->unclip(clipLeft, clipTop, clipWidth, clipHeight);
    glPopMatrix();
}

void StackingContext::renderFloats(ViewCSSImp* view, Box* last, Box* current)
{
    if (current && current == currentFloat)
        return;

    Box* saved = currentFloat;
    if (!current || !last)
        currentFloat = firstFloat;
    else if (last->nextFloat)
        currentFloat = last->nextFloat;
    else
        return;
    while (currentFloat) {
        currentFloat->render(view, this);
        assert(currentFloat);
        currentFloat = currentFloat->nextFloat;
    }
    if (!current || !last)
        firstFloat = lastFloat = 0;
    else {
        last->nextFloat = 0;
        lastFloat = last;
    }
    currentFloat = saved;
}

void StackingContext::addBase(Box* box)
{
#ifndef NDEBUG
    for (Box* i = firstBase; i; i = i->nextBase)
        assert(box != i);
#endif
    if (!firstBase)
        firstBase = lastBase = box;
    else {
        lastBase->nextBase = box;
        lastBase = box;
    }
    box->nextBase = 0;
}

void StackingContext::addBox(Box* box, Box* parentBox)
{
    assert(parentBox);
    if (parentBox->stackingContext != this)
        addBase(box);
}

void StackingContext::addFloat(Box* box)
{
#ifndef NDEBUG
    for (Box* i = firstFloat; i; i = i->nextFloat) {
        assert(box != i);
    }
#endif
    if (currentFloat) {
        box->nextFloat = currentFloat->nextFloat;
        currentFloat->nextFloat = box;
        return;
    }
    if (!firstFloat)
        firstFloat = lastFloat = box;
    else {
        lastFloat->nextFloat = box;
        lastFloat = box;
    }
    box->nextFloat = 0;
}

void StackingContext::removeBox(Box* box)
{
    Box* p = 0;
    for (Box* i = firstBase; i ; p = i, i = i->nextBase) {
        if (i == box) {
            if (!p)
                firstBase = i->nextBase;
            else
                p->nextBase = i->nextBase;
            if (lastBase == box)
                lastBase = p;
            break;
        }
    }
}

void StackingContext::layOutAbsolute(ViewCSSImp* view)
{
    for (Box* base = firstBase; base; base = base->nextBase) {
        Block* block = dynamic_cast<Block*>(base);
        if (!block || !block->isAbsolutelyPositioned())
            continue;
        block->layOutAbsolute(view);
        block->resolveXY(view, block->x, block->y, block->clipBox ? block->clipBox : ((view->getTree() == block) ? 0 : view->getTree()));
    }
    needStaticPosition = false;

    for (StackingContext* childContext = getFirstChild(); childContext; childContext = childContext->getNextSibling())
        childContext->needStaticPosition = true;
    bool repeat;
    do {
        repeat = false;
        for (StackingContext* childContext = getFirstChild(); childContext; childContext = childContext->getNextSibling()) {
            if (childContext->needStaticPosition) {
                if (!childContext->positioned->needStaticPosition)
                    childContext->layOutAbsolute(view);
                else
                    repeat = true;
            }
        }
    } while (repeat);
}

void StackingContext::dump(std::string indent)
{
    std::cout << indent << "z-index: ";
    if (isAuto())
        std::cout << "auto";
    else
        std::cout << zIndex;
    std::cout << '\n';
    indent += "  ";
    for (auto child = getFirstChild(); child; child = child->getNextSibling())
        child->dump(indent);
}

}}}}  // org::w3c::dom::bootstrap
<|endoftext|>


<commit_before>#ifndef _SNARKFRONT_HPP_
#define _SNARKFRONT_HPP_

////////////////////////////////////////////////////////////////////////////////
// this header file includes everything applications need
//

// not part of the EDSL but convenient for command line applications
#include "CompilePPZK_query.hpp"
#include "CompilePPZK_witness.hpp"
#include "CompileQAP.hpp"
#include "Getopt.hpp"

// the basic language
#include "DSL_base.hpp"
#include "DSL_bless.hpp"
#include "DSL_identity.hpp"
#include "DSL_ppzk.hpp"
#include "DSL_utility.hpp"

// progress bar for proof generation and verification
#include "GenericProgressBar.hpp"

// input and printing of hexadecimal text
#include "HexUtil.hpp"

// initialize elliptic curves
#include "InitPairing.hpp"

// Merkle tree
#include "MerkleAuthPath.hpp"
#include "MerkleBundle.hpp"
#include "MerkleTree.hpp"

// Secure Hash Algorithms
#include "SHA_1.hpp"
#include "SHA_224.hpp"
#include "SHA_256.hpp"
#include "SHA_384.hpp"
#include "SHA_512.hpp"
#include "SHA_512_224.hpp"
#include "SHA_512_256.hpp"

// Advanced Encryption Algorithm
#include "AES_Cipher.hpp"
#include "AES_InvCipher.hpp"
#include "AES_InvSBox.hpp"
#include "AES_KeyExpansion.hpp"
#include "AES_SBox.hpp"

#endif
<commit_msg>scope header file paths<commit_after>#ifndef _SNARKFRONT_HPP_
#define _SNARKFRONT_HPP_

////////////////////////////////////////////////////////////////////////////////
// this header file includes everything applications need
//

// not part of the EDSL but convenient for command line applications
#include <snarkfront/CompilePPZK_query.hpp>
#include <snarkfront/CompilePPZK_witness.hpp>
#include <snarkfront/CompileQAP.hpp>
#include <snarkfront/Getopt.hpp>

// the basic language
#include <snarkfront/DSL_base.hpp>
#include <snarkfront/DSL_bless.hpp>
#include <snarkfront/DSL_identity.hpp>
#include <snarkfront/DSL_ppzk.hpp>
#include <snarkfront/DSL_utility.hpp>

// progress bar for proof generation and verification
#include <snarkfront/GenericProgressBar.hpp>

// input and printing of hexadecimal text
#include <snarkfront/HexUtil.hpp>

// initialize elliptic curves
#include <snarkfront/InitPairing.hpp>

// Merkle tree
#include <snarkfront/MerkleAuthPath.hpp>
#include <snarkfront/MerkleBundle.hpp>
#include <snarkfront/MerkleTree.hpp>

// Secure Hash Algorithms
#include <snarkfront/SHA_1.hpp>
#include <snarkfront/SHA_224.hpp>
#include <snarkfront/SHA_256.hpp>
#include <snarkfront/SHA_384.hpp>
#include <snarkfront/SHA_512.hpp>
#include <snarkfront/SHA_512_224.hpp>
#include <snarkfront/SHA_512_256.hpp>

// Advanced Encryption Algorithm
#include <snarkfront/AES_Cipher.hpp>
#include <snarkfront/AES_InvCipher.hpp>
#include <snarkfront/AES_InvSBox.hpp>
#include <snarkfront/AES_KeyExpansion.hpp>
#include <snarkfront/AES_SBox.hpp>

#endif
<|endoftext|>