<commit_before>#include "SAMdisk.h"
#include "Sector.h"

Sector::Sector (DataRate datarate_, Encoding encoding_, const Header &header_, int gap3_)
	: header(header_), datarate(datarate_), encoding(encoding_), gap3(gap3_)
{
}

bool Sector::operator== (const Sector &sector) const
{
	// Headers must match
	if (sector.header != header)
		return false;

	// If neither has data it's a match
	if (sector.m_data.size() == 0 && m_data.size() == 0)
		return true;

	// Both sectors must have some data
	if (sector.copies() == 0 || copies() == 0)
		return false;

	// Both first sectors must have at least the natural size to compare
	if (sector.data_size() < sector.size() || data_size() < size())
		return false;

	// The natural data contents must match
	return std::equal(data_copy().begin(), data_copy().begin() + size(), sector.data_copy().begin());
}

int Sector::size () const
{
	return header.sector_size();
}

int Sector::data_size () const
{
	return copies() ? static_cast<int>(m_data[0].size()) : 0;
}

const DataList &Sector::datas () const
{
	return m_data;
}

DataList &Sector::datas ()
{
	return m_data;
}

const Data &Sector::data_copy (int copy/*=0*/) const
{
	copy = std::max(std::min(copy, static_cast<int>(m_data.size()) - 1), 0);
	return m_data[copy];
}

Data &Sector::data_copy (int copy/*=0*/)
{
	assert(m_data.size() != 0);
	copy = std::max(std::min(copy, static_cast<int>(m_data.size()) - 1), 0);
	return m_data[copy];
}

int Sector::copies () const
{
	return static_cast<int>(m_data.size());
}

Sector::Merge Sector::add (Data &&data, bool bad_crc, uint8_t new_dam)
{
	Merge ret = Merge::NewData;
	assert(!copies() || dam == new_dam);

	// If the sector has a bad header CRC, it can't have any data
	if (has_badidcrc())
		return Merge::Unchanged;

#ifdef _DEBUG
	// If there's enough data, check the CRC
	if ((encoding == Encoding::MFM || encoding == Encoding::FM) &&
		static_cast<int>(data.size()) >= (size() + 2))
	{
		CRC16 crc;
		if (encoding == Encoding::MFM) crc.init(CRC16::A1A1A1);
		crc.add(new_dam);
		auto bad_data_crc = crc.add(data.data(), size() + 2) != 0;
		assert(bad_crc == bad_data_crc);
	}
#endif

	// If the exising sector has good data, ignore supplied data if it's bad
	if (bad_crc && has_good_data())
		return Merge::Unchanged;

	// If the existing sector is bad, new good data will replace it all
	if (!bad_crc && has_baddatacrc())
	{
		remove_data();
		ret = Merge::Improved;
	}

	// 8K sectors always have a CRC error, but may include a secondary checksum
	if (is_8k_sector())
	{
		// Attempt to identify the 8K checksum method used by the new data
		// If it's recognised, replace any existing data with it
		if (!ChecksumMethods(data.data(), data.size()).empty())
		{
			remove_data();
			ret = Merge::Improved;
		}
		// Do we already have a copy?
		else if (copies() == 1)
		{
			// Can we identify the method used by the existing copy?
			if (!ChecksumMethods(m_data[0].data(), m_data[0].size()).empty())
			{
				// Keep the existing, ignoring the new data
				return Merge::Unchanged;
			}
		}
	}

	// Look for existing data that is a superset of what we're adding
	auto it = std::find_if(m_data.begin(), m_data.end(), [&] (const Data &d) {
		return d.size() >= data.size() && std::equal(data.begin(), data.end(), d.begin());
	});

	// Return if we already have a better copy
	if (it != m_data.end())
		return Merge::Unchanged;

	// Look for existing data that is a subset of what we're adding
	it = std::find_if(m_data.begin(), m_data.end(), [&] (const Data &d) {
		return d.size() <= data.size() && std::equal(d.begin(), d.end(), data.begin());
	});

	// Remove the inferior copy
	if (it != m_data.end())
	{
		ret = (it->size() < size()) ? Merge::Improved : Merge::NewData;
		m_data.erase(it);
	}

	// DD 8K sectors are considered complete at 6K, everything else at natural size
	auto complete_size = is_8k_sector() ? 0x1800 : data.size();

	// Is the supplied data enough for a complete sector?
	if (data.size() >= complete_size)
	{
		// Look for existing data that contains the same normal sector data
		it = std::find_if(m_data.begin(), m_data.end(), [&] (const Data &d) {
			return d.size() >= complete_size && std::equal(d.begin(), d.begin() + complete_size, data.begin());
		});

		// Found a match?
		if (it != m_data.end())
		{
			// Return if the new one isn't larger
			if (data.size() <= it->size())
				return Merge::Unchanged;

			// Remove the existing smaller copy
			m_data.erase(it);
		}

		// Will we now have multiple copies?
		if (copies() > 0)
		{
			// We should never see different good copies of the same sector.
			assert(has_baddatacrc());
			if (!has_baddatacrc())
				return Merge::Unchanged;

			// Keep multiple copies the same size, whichever is shortest
			auto new_size = std::min(data.size(), m_data[0].size());
			data.resize(new_size);

			// Resize any existing copies to match
			for (auto &d : m_data)
				d.resize(new_size);
		}
	}

	// Insert the new data copy.
	m_data.emplace_back(std::move(data));
	limit_copies(opt.maxcopies);

	// Update the data CRC state and DAM
	m_bad_data_crc = bad_crc;
	dam = new_dam;

	return ret;
}

Sector::Merge Sector::merge (Sector &&sector)
{
	Merge ret = Merge::Unchanged;

	// If the new header CRC is bad there's nothing we can use
	if (sector.has_badidcrc())
		return Merge::Unchanged;

	// Something is wrong if the new details don't match the existing one
	assert(sector.header == header);
	assert(sector.datarate == datarate);
	assert(sector.encoding == encoding);

	// If the existing header is bad, repair it
	if (has_badidcrc())
	{
		header = sector.header;
		set_badidcrc(false);
		ret = Merge::Improved;
	}

	// We can't repair good data with bad
	if (!has_baddatacrc() && sector.has_baddatacrc())
		return ret;

	// Add the new data snapshots
	for (Data &data : sector.m_data)
	{
		// Move the data into place, passing on the existing data CRC status and DAM
		auto add_ret = add(std::move(data), sector.has_baddatacrc(), sector.dam);
		if (add_ret == Merge::Improved || (ret == Merge::Unchanged))
			ret = add_ret;
	}
	sector.m_data.clear();

	return ret;
}

bool Sector::has_data () const
{
	return copies() != 0;
}

bool Sector::has_good_data() const
{
	return has_data() && !has_baddatacrc();
}

bool Sector::has_gapdata () const
{
	return data_size() > size();
}

bool Sector::has_shortdata () const
{
	return data_size() < size();
}

bool Sector::has_badidcrc () const
{
	return m_bad_id_crc;
}

bool Sector::has_baddatacrc () const
{
	return m_bad_data_crc;
}

bool Sector::is_deleted () const
{
	return dam == 0xf8 || dam == 0xf9;
}

bool Sector::is_altdam () const
{
	return dam == 0xfa;
}

bool Sector::is_rx02dam () const
{
	return dam == 0xfd;
}

bool Sector::is_8k_sector () const
{
	// +3 and CPC disks treat this as a virtual complete sector
	return datarate == DataRate::_250K && encoding == Encoding::MFM &&
		header.size == 6 && has_data();
}

void Sector::set_badidcrc (bool bad)
{
	m_bad_id_crc = bad;

	if (bad)
		remove_data();
}

void Sector::set_baddatacrc (bool bad)
{
	m_bad_data_crc = bad;

	if (!bad)
	{
		auto fill_byte = static_cast<uint8_t>((opt.fill >= 0) ? opt.fill : 0);

		if (!has_data())
			m_data.push_back(Data(size(), fill_byte));
		else if (copies() > 1)
		{
			m_data.resize(1);

			if (data_size() < size())
			{
				auto pad{ Data(size() - data_size(), fill_byte) };
				m_data[0].insert(m_data[0].begin(), pad.begin(), pad.end());
			}
		}
	}
}

void Sector::remove_data ()
{
	m_data.clear();
	m_bad_data_crc = false;
	dam = 0xfb;
}

void Sector::limit_copies (int max_copies)
{
	if (copies() > max_copies)
		m_data.resize(max_copies);
}

void Sector::remove_gapdata (bool keep_crc/*=false*/)
{
	if (!has_gapdata())
		return;

	for (auto &data : m_data)
	{
		// If requested, attempt to preserve CRC bytes on bad sectors.
		if (keep_crc && has_baddatacrc() && data.size() >= (size() + 2))
			data.resize(size() + 2);
		else
			data.resize(size());
	}
}

// Map a size code to how it's treated by the uPD765 FDC on the PC
int Sector::SizeCodeToRealSizeCode (int size)
{
	// Sizes above 8 are treated as 8 (32K)
	return (size <= 7) ? size : 8;
}

// Return the sector length for a given sector size code
int Sector::SizeCodeToLength (int size)
{
	// 2 ^ (7 + size)
	return 128 << SizeCodeToRealSizeCode(size);
}
<commit_msg>Ignore bad data fields with different DAM<commit_after>#include "SAMdisk.h"
#include "Sector.h"

Sector::Sector (DataRate datarate_, Encoding encoding_, const Header &header_, int gap3_)
	: header(header_), datarate(datarate_), encoding(encoding_), gap3(gap3_)
{
}

bool Sector::operator== (const Sector &sector) const
{
	// Headers must match
	if (sector.header != header)
		return false;

	// If neither has data it's a match
	if (sector.m_data.size() == 0 && m_data.size() == 0)
		return true;

	// Both sectors must have some data
	if (sector.copies() == 0 || copies() == 0)
		return false;

	// Both first sectors must have at least the natural size to compare
	if (sector.data_size() < sector.size() || data_size() < size())
		return false;

	// The natural data contents must match
	return std::equal(data_copy().begin(), data_copy().begin() + size(), sector.data_copy().begin());
}

int Sector::size () const
{
	return header.sector_size();
}

int Sector::data_size () const
{
	return copies() ? static_cast<int>(m_data[0].size()) : 0;
}

const DataList &Sector::datas () const
{
	return m_data;
}

DataList &Sector::datas ()
{
	return m_data;
}

const Data &Sector::data_copy (int copy/*=0*/) const
{
	copy = std::max(std::min(copy, static_cast<int>(m_data.size()) - 1), 0);
	return m_data[copy];
}

Data &Sector::data_copy (int copy/*=0*/)
{
	assert(m_data.size() != 0);
	copy = std::max(std::min(copy, static_cast<int>(m_data.size()) - 1), 0);
	return m_data[copy];
}

int Sector::copies () const
{
	return static_cast<int>(m_data.size());
}

Sector::Merge Sector::add (Data &&data, bool bad_crc, uint8_t new_dam)
{
	Merge ret = Merge::NewData;

	// If the sector has a bad header CRC, it can't have any data
	if (has_badidcrc())
		return Merge::Unchanged;

#ifdef _DEBUG
	// If there's enough data, check the CRC
	if ((encoding == Encoding::MFM || encoding == Encoding::FM) &&
		static_cast<int>(data.size()) >= (size() + 2))
	{
		CRC16 crc;
		if (encoding == Encoding::MFM) crc.init(CRC16::A1A1A1);
		crc.add(new_dam);
		auto bad_data_crc = crc.add(data.data(), size() + 2) != 0;
		assert(bad_crc == bad_data_crc);
	}
#endif

	// If both are bad, ignore additional copies with a different DAM
	if (bad_crc && has_baddatacrc() && new_dam != dam)
		return Merge::Unchanged;

	// If the exising sector has good data, ignore supplied data if it's bad
	if (bad_crc && has_good_data())
		return Merge::Unchanged;

	// If the existing sector is bad, new good data will replace it all
	if (!bad_crc && has_baddatacrc())
	{
		remove_data();
		ret = Merge::Improved;
	}

	// 8K sectors always have a CRC error, but may include a secondary checksum
	if (is_8k_sector())
	{
		// Attempt to identify the 8K checksum method used by the new data
		// If it's recognised, replace any existing data with it
		if (!ChecksumMethods(data.data(), data.size()).empty())
		{
			remove_data();
			ret = Merge::Improved;
		}
		// Do we already have a copy?
		else if (copies() == 1)
		{
			// Can we identify the method used by the existing copy?
			if (!ChecksumMethods(m_data[0].data(), m_data[0].size()).empty())
			{
				// Keep the existing, ignoring the new data
				return Merge::Unchanged;
			}
		}
	}

	// Look for existing data that is a superset of what we're adding
	auto it = std::find_if(m_data.begin(), m_data.end(), [&] (const Data &d) {
		return d.size() >= data.size() && std::equal(data.begin(), data.end(), d.begin());
	});

	// Return if we already have a better copy
	if (it != m_data.end())
		return Merge::Unchanged;

	// Look for existing data that is a subset of what we're adding
	it = std::find_if(m_data.begin(), m_data.end(), [&] (const Data &d) {
		return d.size() <= data.size() && std::equal(d.begin(), d.end(), data.begin());
	});

	// Remove the inferior copy
	if (it != m_data.end())
	{
		ret = (it->size() < size()) ? Merge::Improved : Merge::NewData;
		m_data.erase(it);
	}

	// DD 8K sectors are considered complete at 6K, everything else at natural size
	auto complete_size = is_8k_sector() ? 0x1800 : data.size();

	// Is the supplied data enough for a complete sector?
	if (data.size() >= complete_size)
	{
		// Look for existing data that contains the same normal sector data
		it = std::find_if(m_data.begin(), m_data.end(), [&] (const Data &d) {
			return d.size() >= complete_size && std::equal(d.begin(), d.begin() + complete_size, data.begin());
		});

		// Found a match?
		if (it != m_data.end())
		{
			// Return if the new one isn't larger
			if (data.size() <= it->size())
				return Merge::Unchanged;

			// Remove the existing smaller copy
			m_data.erase(it);
		}

		// Will we now have multiple copies?
		if (copies() > 0)
		{
			// We should never see different good copies of the same sector.
			assert(has_baddatacrc());
			if (!has_baddatacrc())
				return Merge::Unchanged;

			// Keep multiple copies the same size, whichever is shortest
			auto new_size = std::min(data.size(), m_data[0].size());
			data.resize(new_size);

			// Resize any existing copies to match
			for (auto &d : m_data)
				d.resize(new_size);
		}
	}

	// Insert the new data copy.
	m_data.emplace_back(std::move(data));
	limit_copies(opt.maxcopies);

	// Update the data CRC state and DAM
	m_bad_data_crc = bad_crc;
	dam = new_dam;

	return ret;
}

Sector::Merge Sector::merge (Sector &&sector)
{
	Merge ret = Merge::Unchanged;

	// If the new header CRC is bad there's nothing we can use
	if (sector.has_badidcrc())
		return Merge::Unchanged;

	// Something is wrong if the new details don't match the existing one
	assert(sector.header == header);
	assert(sector.datarate == datarate);
	assert(sector.encoding == encoding);

	// If the existing header is bad, repair it
	if (has_badidcrc())
	{
		header = sector.header;
		set_badidcrc(false);
		ret = Merge::Improved;
	}

	// We can't repair good data with bad
	if (!has_baddatacrc() && sector.has_baddatacrc())
		return ret;

	// Add the new data snapshots
	for (Data &data : sector.m_data)
	{
		// Move the data into place, passing on the existing data CRC status and DAM
		auto add_ret = add(std::move(data), sector.has_baddatacrc(), sector.dam);
		if (add_ret == Merge::Improved || (ret == Merge::Unchanged))
			ret = add_ret;
	}
	sector.m_data.clear();

	return ret;
}

bool Sector::has_data () const
{
	return copies() != 0;
}

bool Sector::has_good_data() const
{
	return has_data() && !has_baddatacrc();
}

bool Sector::has_gapdata () const
{
	return data_size() > size();
}

bool Sector::has_shortdata () const
{
	return data_size() < size();
}

bool Sector::has_badidcrc () const
{
	return m_bad_id_crc;
}

bool Sector::has_baddatacrc () const
{
	return m_bad_data_crc;
}

bool Sector::is_deleted () const
{
	return dam == 0xf8 || dam == 0xf9;
}

bool Sector::is_altdam () const
{
	return dam == 0xfa;
}

bool Sector::is_rx02dam () const
{
	return dam == 0xfd;
}

bool Sector::is_8k_sector () const
{
	// +3 and CPC disks treat this as a virtual complete sector
	return datarate == DataRate::_250K && encoding == Encoding::MFM &&
		header.size == 6 && has_data();
}

void Sector::set_badidcrc (bool bad)
{
	m_bad_id_crc = bad;

	if (bad)
		remove_data();
}

void Sector::set_baddatacrc (bool bad)
{
	m_bad_data_crc = bad;

	if (!bad)
	{
		auto fill_byte = static_cast<uint8_t>((opt.fill >= 0) ? opt.fill : 0);

		if (!has_data())
			m_data.push_back(Data(size(), fill_byte));
		else if (copies() > 1)
		{
			m_data.resize(1);

			if (data_size() < size())
			{
				auto pad{ Data(size() - data_size(), fill_byte) };
				m_data[0].insert(m_data[0].begin(), pad.begin(), pad.end());
			}
		}
	}
}

void Sector::remove_data ()
{
	m_data.clear();
	m_bad_data_crc = false;
	dam = 0xfb;
}

void Sector::limit_copies (int max_copies)
{
	if (copies() > max_copies)
		m_data.resize(max_copies);
}

void Sector::remove_gapdata (bool keep_crc/*=false*/)
{
	if (!has_gapdata())
		return;

	for (auto &data : m_data)
	{
		// If requested, attempt to preserve CRC bytes on bad sectors.
		if (keep_crc && has_baddatacrc() && data.size() >= (size() + 2))
			data.resize(size() + 2);
		else
			data.resize(size());
	}
}

// Map a size code to how it's treated by the uPD765 FDC on the PC
int Sector::SizeCodeToRealSizeCode (int size)
{
	// Sizes above 8 are treated as 8 (32K)
	return (size <= 7) ? size : 8;
}

// Return the sector length for a given sector size code
int Sector::SizeCodeToLength (int size)
{
	// 2 ^ (7 + size)
	return 128 << SizeCodeToRealSizeCode(size);
}
<|endoftext|>


<commit_before>/*  cbr
 *  Server.cpp
 *
 *  Copyright (c) 2009, Ewen Cheslack-Postava
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of cbr nor the names of its contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "Network.hpp"
#include "Server.hpp"
#include "Proximity.hpp"
#include "Object.hpp"
#include "ObjectFactory.hpp"
#include "ServerMap.hpp"
#include "Message.hpp"
#include "ServerIDMap.hpp"
#include "SendQueue.hpp"
namespace CBR {

Server::Server(ServerID id, ObjectFactory* obj_factory, LocationService* loc_service, ServerMap* server_map, Proximity* prox, Network* net, SendQueue * sq)
 : mID(id),
   mObjectFactory(obj_factory),
   mLocationService(loc_service),
   mServerMap(server_map),
   mProximity(prox),
   mNetwork(net),
   mSendQueue(sq)
{
    // setup object which are initially residing on this server
    for(ObjectFactory::iterator it = mObjectFactory->begin(); it != mObjectFactory->end(); it++) {
        UUID obj_id = *it;
        MotionVector3f start_motion = loc_service->location(obj_id);
        Vector3f start_pos = loc_service->currentPosition(obj_id);

        mProximity->addObject(obj_id, start_motion);

        if (mServerMap->lookup(start_pos) == mID) {
            // Instantiate object
            Object* obj = mObjectFactory->object(obj_id, this);
            mObjects[obj_id] = obj;
            // Register proximity query
            mProximity->addQuery(obj_id, 100.f); // FIXME how to set proximity radius?
        }
    }
}

const ServerID& Server::id() const {
    return mID;
}

void Server::route(ObjectToObjectMessage* msg) {
    assert(msg != NULL);

    UUID src_uuid = msg->sourceObject();
    UUID dest_uuid = msg->destObject();
    ServerID destServerID=mServerMap->lookup(dest_uuid);
    ServerMessageHeader server_header(
        this->id(),
        destServerID
    );

    uint32 offset = 0;
    Network::Chunk msg_serialized;
    offset=server_header.serialize(msg_serialized, offset);
    offset = msg->serialize(msg_serialized, offset);
    if (destServerID==id()) {
        mSelfMessages.push_back(msg_serialized);
    }else {
        bool failed=!mSendQueue->addMessage(destServerID,msg_serialized,src_uuid);
        assert(!failed);
    }
    delete msg;
}

void Server::route(Message* msg, const ServerID& dest_server) {
    assert(msg != NULL);

    ServerMessageHeader server_header(this->id(), dest_server);

    uint32 offset = 0;
    Network::Chunk msg_serialized;
    offset=server_header.serialize(msg_serialized, offset);
    offset = msg->serialize(msg_serialized, offset);
    if (dest_server==id()) {
        mSelfMessages.push_back(msg_serialized);
    }else {
        bool failed=!mSendQueue->addMessage(dest_server,msg_serialized);
        assert(!failed);
    }
    delete msg;
}

void Server::route(Message* msg, const UUID& dest_obj) {
    route(msg, mServerMap->lookup(dest_obj));
}

void Server::deliver(Message* msg) {
    switch(msg->type()) {
      case MESSAGE_TYPE_PROXIMITY:
          {
              ProximityMessage* prox_msg = static_cast<ProximityMessage*>(msg);
              Object* dest_obj = object(prox_msg->destObject());
              if (dest_obj == NULL)
                  forward(prox_msg, prox_msg->destObject());
              else
                  dest_obj->proximityMessage(prox_msg);
          }
          break;
      case MESSAGE_TYPE_LOCATION:
          {
              LocationMessage* loc_msg = static_cast<LocationMessage*>(msg);
              Object* dest_obj = object(loc_msg->destObject());
              if (dest_obj == NULL)
                  forward(loc_msg, loc_msg->destObject());
              else
                  dest_obj->locationMessage(loc_msg);
          }
          break;
      case MESSAGE_TYPE_SUBSCRIPTION:
          {
              SubscriptionMessage* subs_msg = static_cast<SubscriptionMessage*>(msg);
              Object* dest_obj = object(subs_msg->destObject());
              if (dest_obj == NULL)
                  forward(subs_msg, subs_msg->destObject());
              else
                  dest_obj->subscriptionMessage(subs_msg);
          }
        break;
      case MESSAGE_TYPE_MIGRATE:
          {
              MigrateMessage* migrate_msg = static_cast<MigrateMessage*>(msg);
              // FIXME
              delete migrate_msg;
          }
          break;
      default:
#if NDEBUG
        assert(false);
#endif
        break;
    }

}

Object* Server::object(const UUID& dest) const {
    ObjectMap::const_iterator it = mObjects.find(dest);
    if (it == mObjects.end())
        return NULL;
    return it->second;
}

void Server::forward(Message* msg, const UUID& dest) {
    route(msg, dest);
}

void Server::processChunk(const Network::Chunk&chunk) {
    Message* result;
    unsigned int offset=0;
    do {
        ServerMessageHeader hdr=ServerMessageHeader::deserialize(chunk,offset);
        offset=Message::deserialize(chunk,offset,&result);
        deliver(result);
    }while (offset<chunk.size());
}
void Server::networkTick(const Time&t) {
    mSendQueue->service();
    while (!mSelfMessages.empty()) {
        processChunk(mSelfMessages.front());
        mSelfMessages.pop_front();
    }
    Sirikata::Network::Chunk *c=NULL;
    while((c=mNetwork->receiveOne())) {
        processChunk(*c);
        delete c;
    }
}
void Server::tick(const Time& t) {
    // Update object locations
    mLocationService->tick(t);

    // Check proximity updates
    proximityTick(t);
    networkTick(t);
    // Check for object migrations
    checkObjectMigrations();
}

void Server::proximityTick(const Time& t) {
    // Check for proximity updates
    std::queue<ProximityEvent> proximity_events;
    mProximity->evaluate(t, proximity_events);

    while(!proximity_events.empty()) {
        ProximityEvent& evt = proximity_events.front();
        ProximityMessage* msg =
            new ProximityMessage(
                evt.query(),
                evt.object(),
                (evt.type() == ProximityEvent::Entered) ? ProximityMessage::Entered : ProximityMessage::Exited
            );
        route(msg, evt.query());
        proximity_events.pop();
    }
}

void Server::checkObjectMigrations() {
    // * check for objects crossing server boundaries
    //   * wrap up state and send message to other server
    //     to reinstantiate the object there
    //   * delete object on this side
}

} // namespace CBR
<commit_msg>Have Server give active Objects tick events.<commit_after>/*  cbr
 *  Server.cpp
 *
 *  Copyright (c) 2009, Ewen Cheslack-Postava
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of cbr nor the names of its contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "Network.hpp"
#include "Server.hpp"
#include "Proximity.hpp"
#include "Object.hpp"
#include "ObjectFactory.hpp"
#include "ServerMap.hpp"
#include "Message.hpp"
#include "ServerIDMap.hpp"
#include "SendQueue.hpp"
namespace CBR {

Server::Server(ServerID id, ObjectFactory* obj_factory, LocationService* loc_service, ServerMap* server_map, Proximity* prox, Network* net, SendQueue * sq)
 : mID(id),
   mObjectFactory(obj_factory),
   mLocationService(loc_service),
   mServerMap(server_map),
   mProximity(prox),
   mNetwork(net),
   mSendQueue(sq)
{
    // setup object which are initially residing on this server
    for(ObjectFactory::iterator it = mObjectFactory->begin(); it != mObjectFactory->end(); it++) {
        UUID obj_id = *it;
        MotionVector3f start_motion = loc_service->location(obj_id);
        Vector3f start_pos = loc_service->currentPosition(obj_id);

        mProximity->addObject(obj_id, start_motion);

        if (mServerMap->lookup(start_pos) == mID) {
            // Instantiate object
            Object* obj = mObjectFactory->object(obj_id, this);
            mObjects[obj_id] = obj;
            // Register proximity query
            mProximity->addQuery(obj_id, 100.f); // FIXME how to set proximity radius?
        }
    }
}

const ServerID& Server::id() const {
    return mID;
}

void Server::route(ObjectToObjectMessage* msg) {
    assert(msg != NULL);

    UUID src_uuid = msg->sourceObject();
    UUID dest_uuid = msg->destObject();
    ServerID destServerID=mServerMap->lookup(dest_uuid);
    ServerMessageHeader server_header(
        this->id(),
        destServerID
    );

    uint32 offset = 0;
    Network::Chunk msg_serialized;
    offset=server_header.serialize(msg_serialized, offset);
    offset = msg->serialize(msg_serialized, offset);
    if (destServerID==id()) {
        mSelfMessages.push_back(msg_serialized);
    }else {
        bool failed=!mSendQueue->addMessage(destServerID,msg_serialized,src_uuid);
        assert(!failed);
    }
    delete msg;
}

void Server::route(Message* msg, const ServerID& dest_server) {
    assert(msg != NULL);

    ServerMessageHeader server_header(this->id(), dest_server);

    uint32 offset = 0;
    Network::Chunk msg_serialized;
    offset=server_header.serialize(msg_serialized, offset);
    offset = msg->serialize(msg_serialized, offset);
    if (dest_server==id()) {
        mSelfMessages.push_back(msg_serialized);
    }else {
        bool failed=!mSendQueue->addMessage(dest_server,msg_serialized);
        assert(!failed);
    }
    delete msg;
}

void Server::route(Message* msg, const UUID& dest_obj) {
    route(msg, mServerMap->lookup(dest_obj));
}

void Server::deliver(Message* msg) {
    switch(msg->type()) {
      case MESSAGE_TYPE_PROXIMITY:
          {
              ProximityMessage* prox_msg = static_cast<ProximityMessage*>(msg);
              Object* dest_obj = object(prox_msg->destObject());
              if (dest_obj == NULL)
                  forward(prox_msg, prox_msg->destObject());
              else
                  dest_obj->proximityMessage(prox_msg);
          }
          break;
      case MESSAGE_TYPE_LOCATION:
          {
              LocationMessage* loc_msg = static_cast<LocationMessage*>(msg);
              Object* dest_obj = object(loc_msg->destObject());
              if (dest_obj == NULL)
                  forward(loc_msg, loc_msg->destObject());
              else
                  dest_obj->locationMessage(loc_msg);
          }
          break;
      case MESSAGE_TYPE_SUBSCRIPTION:
          {
              SubscriptionMessage* subs_msg = static_cast<SubscriptionMessage*>(msg);
              Object* dest_obj = object(subs_msg->destObject());
              if (dest_obj == NULL)
                  forward(subs_msg, subs_msg->destObject());
              else
                  dest_obj->subscriptionMessage(subs_msg);
          }
        break;
      case MESSAGE_TYPE_MIGRATE:
          {
              MigrateMessage* migrate_msg = static_cast<MigrateMessage*>(msg);
              // FIXME
              delete migrate_msg;
          }
          break;
      default:
#if NDEBUG
        assert(false);
#endif
        break;
    }

}

Object* Server::object(const UUID& dest) const {
    ObjectMap::const_iterator it = mObjects.find(dest);
    if (it == mObjects.end())
        return NULL;
    return it->second;
}

void Server::forward(Message* msg, const UUID& dest) {
    route(msg, dest);
}

void Server::processChunk(const Network::Chunk&chunk) {
    Message* result;
    unsigned int offset=0;
    do {
        ServerMessageHeader hdr=ServerMessageHeader::deserialize(chunk,offset);
        offset=Message::deserialize(chunk,offset,&result);
        deliver(result);
    }while (offset<chunk.size());
}
void Server::networkTick(const Time&t) {
    mSendQueue->service();
    while (!mSelfMessages.empty()) {
        processChunk(mSelfMessages.front());
        mSelfMessages.pop_front();
    }
    Sirikata::Network::Chunk *c=NULL;
    while((c=mNetwork->receiveOne())) {
        processChunk(*c);
        delete c;
    }
}
void Server::tick(const Time& t) {
    // Update object locations
    mLocationService->tick(t);

    // Check proximity updates
    proximityTick(t);
    networkTick(t);
    // Check for object migrations
    checkObjectMigrations();

    // Give objects a chance to process
    for(ObjectMap::iterator it = mObjects.begin(); it != mObjects.end(); it++) {
        Object* obj = it->second;
        obj->tick(t);
    }
}

void Server::proximityTick(const Time& t) {
    // Check for proximity updates
    std::queue<ProximityEvent> proximity_events;
    mProximity->evaluate(t, proximity_events);

    while(!proximity_events.empty()) {
        ProximityEvent& evt = proximity_events.front();
        ProximityMessage* msg =
            new ProximityMessage(
                evt.query(),
                evt.object(),
                (evt.type() == ProximityEvent::Entered) ? ProximityMessage::Entered : ProximityMessage::Exited
            );
        route(msg, evt.query());
        proximity_events.pop();
    }
}

void Server::checkObjectMigrations() {
    // * check for objects crossing server boundaries
    //   * wrap up state and send message to other server
    //     to reinstantiate the object there
    //   * delete object on this side
}

} // namespace CBR
<|endoftext|>


<commit_before>#include "core.hpp"
#include "logger.hpp"

#include <mutex>

#include <curl/curl.h>

namespace libkeen {
namespace internal {

class LibCurl
{
public:
    LibCurl() { curl_global_init(CURL_GLOBAL_DEFAULT); }
    ~LibCurl() { curl_global_cleanup(); }
    static LibCurlRef ref() { static LibCurlRef instance{ new LibCurl }; return instance; }
};

CoreRef Core::instance(AccessType type)
{
    static CoreRef      core;
    static std::mutex   mutex;

    std::lock_guard<decltype(mutex)> lock(mutex);

    if (type == AccessType::Current)
    {
        /* no-op */
    }
    else if (type == AccessType::Release)
    {
        if (core) core.reset();
    }
    else if (type == AccessType::Renew)
    {
        if (!core) core.reset(new Core);
    }

    return core;
}

CoreRef Core::instance()
{
    if (!instance(AccessType::Current))
        return instance(AccessType::Renew);
    else
        return instance(AccessType::Current);
}

void Core::release()
{
    instance(AccessType::Release);
}

Core::Core()
    : mWork(mIoService)
    , mLibCurlRef(LibCurl::ref())
{
    Logger::pull(mLoggerRefs);

    unsigned num_threads = std::thread::hardware_concurrency();
    if (num_threads == 0)
    {
        LOG_WARN("hardware_concurrency returned 0. Forcing one thread.");
        num_threads = 1;
    }

    for (unsigned t = 0; t < num_threads; ++t)
    {
        mThreadPool.push_back(std::thread([this]{ mIoService.run(); }));
        LOG_INFO("Spawned thread " << mThreadPool.back().get_id());
    }

    LOG_INFO("Thread pool size: " << mThreadPool.size());
}

Core::~Core()
{
    LOG_INFO("Stopping IO service");
    mIoService.stop();

    for (std::thread& thread : mThreadPool)
    {
        LOG_INFO("Shutting down thread " << thread.get_id());
        thread.join();
    }
}

void Core::postEvent(const std::string& name, const std::string& data)
{

}

unsigned Core::useCount()
{
    if (!instance(AccessType::Current)) return 0;
    // minus one to take current method's ref into account
    else return static_cast<unsigned>(instance(AccessType::Current).use_count()) - 1;
}

}}
<commit_msg>removed cURL specific code from core<commit_after>#include "core.hpp"
#include "curl.hpp"
#include "logger.hpp"

#include <mutex>

namespace libkeen {
namespace internal {

CoreRef Core::instance(AccessType type)
{
    static CoreRef      core;
    static std::mutex   mutex;

    std::lock_guard<decltype(mutex)> lock(mutex);

    if (type == AccessType::Current)
    {
        /* no-op */
    }
    else if (type == AccessType::Release)
    {
        if (core) core.reset();
    }
    else if (type == AccessType::Renew)
    {
        if (!core) core.reset(new Core);
    }

    return core;
}

CoreRef Core::instance()
{
    if (!instance(AccessType::Current))
        return instance(AccessType::Renew);
    else
        return instance(AccessType::Current);
}

void Core::release()
{
    instance(AccessType::Release);
}

Core::Core()
    : mWork(mIoService)
    , mLibCurlRef(LibCurl::ref())
{
    Logger::pull(mLoggerRefs);

    unsigned num_threads = std::thread::hardware_concurrency();
    if (num_threads == 0)
    {
        LOG_WARN("hardware_concurrency returned 0. Forcing one thread.");
        num_threads = 1;
    }

    for (unsigned t = 0; t < num_threads; ++t)
    {
        mThreadPool.push_back(std::thread([this]{ mIoService.run(); }));
        LOG_INFO("Spawned thread " << mThreadPool.back().get_id());
    }

    LOG_INFO("Thread pool size: " << mThreadPool.size());
}

Core::~Core()
{
    LOG_INFO("Stopping IO service");
    mIoService.stop();

    for (std::thread& thread : mThreadPool)
    {
        LOG_INFO("Shutting down thread " << thread.get_id());
        thread.join();
    }
}

void Core::postEvent(const std::string& name, const std::string& data)
{

}

unsigned Core::useCount()
{
    if (!instance(AccessType::Current)) return 0;
    // minus one to take current method's ref into account
    else return static_cast<unsigned>(instance(AccessType::Current).use_count()) - 1;
}

}}
<|endoftext|>


<commit_before>#include "Stream.h"
#include <cstdarg>

void IStream::Printf(const char* format, ...)
{
	static char buffer[2048];
	va_list args;
	va_start( args, format );
	int bytesWritten = _vsnprintf(buffer, sizeof(buffer), format, args);
	va_end(args);

	assert(bytesWritten < sizeof(buffer));

	ReadImpl(buffer, bytesWritten, 1);
}
<commit_msg>Fix IStream::Printf not writing to stream<commit_after>#include "Stream.h"
#include <cstdarg>

void IStream::Printf(const char* format, ...)
{
	static char buffer[2048];
	va_list args;
	va_start( args, format );
	int bytesWritten = _vsnprintf(buffer, sizeof(buffer), format, args);
	va_end(args);

	assert(bytesWritten < sizeof(buffer));

	WriteImpl(buffer, bytesWritten, 1);
}
<|endoftext|>


<commit_before>/*******************************************************************************
GPU OPTIMIZED MONTE CARLO (GOMC) 2.70
Copyright (C) 2018  GOMC Group
A copy of the GNU General Public License can be found in the COPYRIGHT.txt
along with this program, also can be found at <http://www.gnu.org/licenses/>.
********************************************************************************/
#include "EnsemblePreprocessor.h"
#include "System.h"
#include "CalculateEnergy.h"
#include "EwaldCached.h"
#include "Ewald.h"
#include "NoEwald.h"
#include "EnergyTypes.h"
#include "Setup.h"               //For source of setup data.
#include "ConfigSetup.h"         //For types directly read from config. file
#include "StaticVals.h"
#include "Molecules.h"           //For indexing molecules.
#include "MoveConst.h"           //For array of move objects.
#include "MoveBase.h"            //For move bases....
#include "Rotation.h"
#include "Translate.h"
#include "VolumeTransfer.h"
#include "MoleculeTransfer.h"
#include "IntraSwap.h"
#include "MultiParticle.h"
#include "Regrowth.h"
#include "MoleculeExchange1.h"
#include "MoleculeExchange2.h"
#include "MoleculeExchange3.h"
#include "IntraMoleculeExchange1.h"
#include "IntraMoleculeExchange2.h"
#include "IntraMoleculeExchange3.h"
#include "CrankShaft.h"
#include "CFCMC.h"

System::System(StaticVals& statics, Setup const& set,
               MultiSim const*const& multisim) :
  statV(statics),
  boxDimRef(*BoxDim(statics.isOrthogonal)),
#ifdef VARIABLE_PARTICLE_NUMBER
  molLookupRef(molLookup),
#else
  molLookupRef(statics.molLookup),
#endif
  prng(molLookupRef),
#if GOMC_LIB_MPI
  ms(multisim),
#endif
  moveSettings(boxDimRef), cellList(statics.mol, boxDimRef),
  coordinates(boxDimRef, com, molLookupRef, prng, statics.mol),
  com(boxDimRef, coordinates, molLookupRef, statics.mol),
  calcEnergy(statics, *this), checkpointSet(*this, statics, set)
{
  calcEwald = NULL;
#if GOMC_LIB_MPI
  if(ms->parallelTemperingEnabled)
    prngParallelTemp = new PRNG(molLookupRef);
#endif
}

System::~System()
{
  if (boxDimensions != NULL)
    delete boxDimensions;

  if (calcEwald != NULL)
    delete calcEwald;
  delete moves[mv::DISPLACE];
  delete moves[mv::ROTATE];
  delete moves[mv::INTRA_SWAP];
  delete moves[mv::REGROWTH];
  delete moves[mv::INTRA_MEMC];
  delete moves[mv::CRANKSHAFT];
  delete moves[mv::MULTIPARTICLE];
#if ENSEMBLE == GEMC || ENSEMBLE == NPT
  delete moves[mv::VOL_TRANSFER];
#endif
#if ENSEMBLE == GEMC || ENSEMBLE == GCMC
  delete moves[mv::MOL_TRANSFER];
  delete moves[mv::MEMC];
  delete moves[mv::CFCMC];
#endif
#if GOMC_LIB_MPI
  if(ms->parallelTemperingEnabled)
    delete prngParallelTemp;
#endif
}

void System::Init(Setup & set, ulong & startStep)
{
  prng.Init(set.prng.prngMaker.prng);
  r123wrapper.SetRandomSeed(set.config.in.prng.seed);
#if GOMC_LIB_MPI
  if(ms->parallelTemperingEnabled)
    prngParallelTemp->Init(set.prngParallelTemp.prngMaker.prng);
#endif
#ifdef VARIABLE_PARTICLE_NUMBER
  molLookup.Init(statV.mol, set.pdb.atoms);
#endif
  moveSettings.Init(statV, set.pdb.remarks, molLookupRef.GetNumKind());

  // At this point see if checkpoint is enabled. if so re-initialize
  // coordinates, prng, mollookup, step, boxdim, and movesettings
  if(set.config.in.restart.restartFromCheckpoint) {
    checkpointSet.ReadAll();
    checkpointSet.SetStepNumber(startStep);
    checkpointSet.SetPRNGVariables(prng);
    checkpointSet.SetMoleculeLookup(molLookupRef);
    checkpointSet.SetMoveSettings(moveSettings);
    checkpointSet.SetMolecules(statV.mol);
#if GOMC_LIB_MPI
    if(checkpointSet.CheckIfParallelTemperingWasEnabled() && ms->parallelTemperingEnabled)
      checkpointSet.SetPRNGVariablesPT(*prngParallelTemp);
#endif
  }

  xsc.Init(set.pdb, set.config.in, molLookupRef, statV.mol);
  boxDimensions->Init(set.config.in.restart,
                      set.config.sys.volume, set.pdb.cryst,
                      statV.forcefield);
  coordinates.InitFromPDB(set.pdb.atoms);

  com.CalcCOM();
  // Allocate space for atom forces
  atomForceRef.Init(set.pdb.atoms.beta.size());
  molForceRef.Init(com.Count());
  // Allocate space for reciprocate force
  atomForceRecRef.Init(set.pdb.atoms.beta.size());
  molForceRecRef.Init(com.Count());
  cellList.SetCutoff();
  cellList.GridAll(boxDimRef, coordinates, molLookupRef);

  //check if we have to use cached version of Ewald or not.
  bool ewald = set.config.sys.elect.ewald;
  bool cached = set.config.sys.elect.cache;

#ifdef GOMC_CUDA
  if(ewald)
    calcEwald = new Ewald(statV, *this);
  else
    calcEwald = new NoEwald(statV, *this);
#else
  if (ewald && cached)
    calcEwald = new EwaldCached(statV, *this);
  else if (ewald && !cached)
    calcEwald = new Ewald(statV, *this);
  else
    calcEwald = new NoEwald(statV, *this);
#endif

  //Initial the lambda before calling SystemTotal
  InitLambda();
  calcEnergy.Init(*this);
  calcEwald->Init();
  potential = calcEnergy.SystemTotal();
  InitMoves(set);
  for(uint m = 0; m < mv::MOVE_KINDS_TOTAL; m++)
    moveTime[m] = 0.0;
}

void System::InitMoves(Setup const& set)
{
  moves[mv::DISPLACE] = new Translate(*this, statV);
  moves[mv::MULTIPARTICLE] = new MultiParticle(*this, statV);
  moves[mv::ROTATE] = new Rotate(*this, statV);
  moves[mv::INTRA_SWAP] = new IntraSwap(*this, statV);
  moves[mv::REGROWTH] = new Regrowth(*this, statV);
  moves[mv::CRANKSHAFT] = new CrankShaft(*this, statV);
  if(set.config.sys.intraMemcVal.MEMC1) {
    moves[mv::INTRA_MEMC] = new IntraMoleculeExchange1(*this, statV);
  } else if (set.config.sys.intraMemcVal.MEMC2) {
    moves[mv::INTRA_MEMC] = new IntraMoleculeExchange2(*this, statV);
  } else {
    moves[mv::INTRA_MEMC] = new IntraMoleculeExchange3(*this, statV);
  }

#if ENSEMBLE == GEMC || ENSEMBLE == NPT
  moves[mv::VOL_TRANSFER] = new VolumeTransfer(*this, statV);
#endif
#if ENSEMBLE == GEMC || ENSEMBLE == GCMC
  moves[mv::MOL_TRANSFER] = new MoleculeTransfer(*this, statV);
  if(set.config.sys.memcVal.MEMC1) {
    moves[mv::MEMC] = new MoleculeExchange1(*this, statV);
  } else if (set.config.sys.memcVal.MEMC2) {
    moves[mv::MEMC] = new MoleculeExchange2(*this, statV);
  } else {
    moves[mv::MEMC] = new MoleculeExchange3(*this, statV);
  }
  moves[mv::CFCMC] = new CFCMC(*this, statV);
#endif
}

void System::InitLambda()
{
#ifdef GOMC_CUDA
  int temp_molIndex[BOX_TOTAL], temp_kindIndex[BOX_TOTAL];
  double temp_lambdaVDW[BOX_TOTAL], temp_lambdaCoulomb[BOX_TOTAL];
  bool temp_isFraction[BOX_TOTAL];
  for(int i = 0; i < BOX_TOTAL; i++) {
    temp_isFraction[i] = false;
  }
#endif
  if(statV.freeEnVal.enable) {
    bool found = false;
    for(uint k = 0; k < statV.mol.GetKindsCount(); k++) {
      std::string kindName = statV.mol.kinds[k].name;
      if(statV.freeEnVal.molType == kindName) {
        found = true;
        uint totalMol = molLookupRef.NumKindInBox(k, mv::BOX0);
        //In PDB file, molIndex start from 1.
        uint FEmolIndex = statV.freeEnVal.molIndex - 1;
        if(totalMol == 0) {
          found = false;
        } else if(totalMol <= FEmolIndex) {
          std::cout << "Error: Molecule index " << statV.freeEnVal.molIndex <<
                    " of kind " << kindName << " does not exist in the simulation box!\n";
          exit(EXIT_FAILURE);
        } else {
          uint m = molLookupRef.GetMolNum(FEmolIndex, k, mv::BOX0);
          uint state = statV.freeEnVal.iState;
          double lambdaCoulomb = statV.freeEnVal.lambdaCoulomb[state];
          double lambdaVDW = statV.freeEnVal.lambdaVDW[state];
          lambdaRef.Set(lambdaVDW, lambdaCoulomb, m, k, mv::BOX0);

#ifdef GOMC_CUDA
          // initialize arrays to copy to GPU
          temp_molIndex[mv::BOX0] = m;
          temp_kindIndex[mv::BOX0] = k;
          temp_lambdaVDW[mv::BOX0] = lambdaVDW;
          temp_lambdaCoulomb[mv::BOX0] = lambdaCoulomb;
          temp_isFraction[mv::BOX0] = true;
#endif
        }
        break;
      }
    }

    if(!found) {
      std::cout << "Error: No molecule of kind " << statV.freeEnVal.molType <<
                " in the simulation box! \n";
      exit(EXIT_FAILURE);
    }
  }
#ifdef GOMC_CUDA
  InitGPULambda(statV.forcefield.particles->getCUDAVars(), temp_molIndex,
                temp_kindIndex, temp_lambdaVDW, temp_lambdaCoulomb,
                temp_isFraction);
#endif
}

void System::RecalculateTrajectory(Setup &set, uint frameNum)
{
  set.pdb.Init(set.config.in.restart, set.config.in.files.pdb.name, frameNum);
  statV.InitOver(set, *this);
#ifdef VARIABLE_PARTICLE_NUMBER
  molLookup.Init(statV.mol, set.pdb.atoms);
#endif
  coordinates.InitFromPDB(set.pdb.atoms);
  com.CalcCOM();
  cellList.GridAll(boxDimRef, coordinates, molLookupRef);
  calcEnergy.Init(*this);
  calcEwald->Init();
  potential = calcEnergy.SystemTotal();
}

void System::ChooseAndRunMove(const uint step)
{
  r123wrapper.SetStep(step);
  double draw = 0;
  uint majKind = 0;
  PickMove(majKind, draw);
  time.SetStart();
  RunMove(majKind, draw, step);
  time.SetStop();
  moveTime[majKind] += time.GetTimDiff();
}
void System::PickMove(uint & kind, double & draw)
{
  prng.PickArbDist(kind, draw, statV.movePerc, statV.totalPerc,
                   mv::MOVE_KINDS_TOTAL);
}

void System::RunMove(uint majKind, double draw, const uint step)
{
  //return now if move targets molecule and there's none in that box.
  uint rejectState = SetParams(majKind, draw);
  //If single atom, redo move as displacement
  if (rejectState == mv::fail_state::ROTATE_ON_SINGLE_ATOM) {
    majKind = mv::DISPLACE;
    Translate * disp = static_cast<Translate *>(moves[mv::DISPLACE]);
    Rotate * rot = static_cast<Rotate *>(moves[mv::ROTATE]);
    rejectState = disp->ReplaceRot(*rot);
  }
  if (rejectState == mv::fail_state::NO_FAIL)
    rejectState = Transform(majKind);
  if (rejectState == mv::fail_state::NO_FAIL)
    CalcEn(majKind);
  Accept(majKind, rejectState, step);
}

uint System::SetParams(const uint kind, const double draw)
{
  return moves[kind]->Prep(draw, statV.movePerc[kind]);
}

uint System::Transform(const uint kind)
{
  return moves[kind]->Transform();
}

void System::CalcEn(const uint kind)
{
  moves[kind]->CalcEn();
}

void System::Accept(const uint kind, const uint rejectState, const uint step)
{
  moves[kind]->Accept(rejectState, step);
}

void System::PrintAcceptance()
{
  std::cout << std::endl;
  printf("%-24s %-15s", "Move Type", "Mol. Kind");
  for(uint b = 0; b < BOX_TOTAL; b++) {
    sstrm::Converter toStr;
    std::string numStr = "";
    toStr << b;
    toStr >> numStr;
    numStr = "BOX_" + numStr;
    printf("%-11s", numStr.c_str());
  }
  std::cout << std::endl;

  for(uint m = 0; m < mv::MOVE_KINDS_TOTAL; m++) {
    if(statV.movePerc[m] > 0.0)
      moves[m]->PrintAcceptKind();
  }
  std::cout << std::endl;
}

void System::PrintTime()
{
  //std::cout << "MC moves Execution time:\n";
  printf("%-36s %10.4f    sec.\n", "Displacement:", moveTime[mv::DISPLACE]);
  printf("%-36s %10.4f    sec.\n", "Rotation:", moveTime[mv::ROTATE]);
  printf("%-36s %10.4f    sec.\n", "MultiParticle:", moveTime[mv::MULTIPARTICLE]);
  printf("%-36s %10.4f    sec.\n", "Intra-Swap:", moveTime[mv::INTRA_SWAP]);
  printf("%-36s %10.4f    sec.\n", "Regrowth:", moveTime[mv::REGROWTH]);
  printf("%-36s %10.4f    sec.\n", "Intra-MEMC:", moveTime[mv::INTRA_MEMC]);
  printf("%-36s %10.4f    sec.\n", "Crank-Shaft:", moveTime[mv::CRANKSHAFT]);

#if ENSEMBLE == GEMC || ENSEMBLE == GCMC
  printf("%-36s %10.4f    sec.\n", "Mol-Transfer:",
         moveTime[mv::MOL_TRANSFER]);
  printf("%-36s %10.4f    sec.\n", "MEMC:", moveTime[mv::MEMC]);
  printf("%-36s %10.4f    sec.\n", "CFCMC:", moveTime[mv::CFCMC]);
#endif
#if ENSEMBLE == GEMC || ENSEMBLE == NPT
  printf("%-36s %10.4f    sec.\n", "Vol-Transfer:", moveTime[mv::VOL_TRANSFER]);
#endif
  std::cout << std::endl;
}
<commit_msg>Add xsc parser to NVTX marker<commit_after>/*******************************************************************************
GPU OPTIMIZED MONTE CARLO (GOMC) 2.70
Copyright (C) 2018  GOMC Group
A copy of the GNU General Public License can be found in the COPYRIGHT.txt
along with this program, also can be found at <http://www.gnu.org/licenses/>.
********************************************************************************/
#include "EnsemblePreprocessor.h"
#include "System.h"
#include "CalculateEnergy.h"
#include "EwaldCached.h"
#include "Ewald.h"
#include "NoEwald.h"
#include "EnergyTypes.h"
#include "Setup.h"               //For source of setup data.
#include "ConfigSetup.h"         //For types directly read from config. file
#include "StaticVals.h"
#include "Molecules.h"           //For indexing molecules.
#include "MoveConst.h"           //For array of move objects.
#include "MoveBase.h"            //For move bases....
#include "Rotation.h"
#include "Translate.h"
#include "VolumeTransfer.h"
#include "MoleculeTransfer.h"
#include "IntraSwap.h"
#include "MultiParticle.h"
#include "Regrowth.h"
#include "MoleculeExchange1.h"
#include "MoleculeExchange2.h"
#include "MoleculeExchange3.h"
#include "IntraMoleculeExchange1.h"
#include "IntraMoleculeExchange2.h"
#include "IntraMoleculeExchange3.h"
#include "CrankShaft.h"
#include "CFCMC.h"
#include "GOMCEventsProfile.h"

System::System(StaticVals& statics, Setup const& set,
               MultiSim const*const& multisim) :
  statV(statics),
  boxDimRef(*BoxDim(statics.isOrthogonal)),
#ifdef VARIABLE_PARTICLE_NUMBER
  molLookupRef(molLookup),
#else
  molLookupRef(statics.molLookup),
#endif
  prng(molLookupRef),
#if GOMC_LIB_MPI
  ms(multisim),
#endif
  moveSettings(boxDimRef), cellList(statics.mol, boxDimRef),
  coordinates(boxDimRef, com, molLookupRef, prng, statics.mol),
  com(boxDimRef, coordinates, molLookupRef, statics.mol),
  calcEnergy(statics, *this), checkpointSet(*this, statics, set)
{
  calcEwald = NULL;
#if GOMC_LIB_MPI
  if(ms->parallelTemperingEnabled)
    prngParallelTemp = new PRNG(molLookupRef);
#endif
}

System::~System()
{
  if (boxDimensions != NULL)
    delete boxDimensions;

  if (calcEwald != NULL)
    delete calcEwald;
  delete moves[mv::DISPLACE];
  delete moves[mv::ROTATE];
  delete moves[mv::INTRA_SWAP];
  delete moves[mv::REGROWTH];
  delete moves[mv::INTRA_MEMC];
  delete moves[mv::CRANKSHAFT];
  delete moves[mv::MULTIPARTICLE];
#if ENSEMBLE == GEMC || ENSEMBLE == NPT
  delete moves[mv::VOL_TRANSFER];
#endif
#if ENSEMBLE == GEMC || ENSEMBLE == GCMC
  delete moves[mv::MOL_TRANSFER];
  delete moves[mv::MEMC];
  delete moves[mv::CFCMC];
#endif
#if GOMC_LIB_MPI
  if(ms->parallelTemperingEnabled)
    delete prngParallelTemp;
#endif
}

void System::Init(Setup & set, ulong & startStep)
{
  prng.Init(set.prng.prngMaker.prng);
  r123wrapper.SetRandomSeed(set.config.in.prng.seed);
#if GOMC_LIB_MPI
  if(ms->parallelTemperingEnabled)
    prngParallelTemp->Init(set.prngParallelTemp.prngMaker.prng);
#endif
#ifdef VARIABLE_PARTICLE_NUMBER
  molLookup.Init(statV.mol, set.pdb.atoms);
#endif
  moveSettings.Init(statV, set.pdb.remarks, molLookupRef.GetNumKind());

  // At this point see if checkpoint is enabled. if so re-initialize
  // coordinates, prng, mollookup, step, boxdim, and movesettings
  if(set.config.in.restart.restartFromCheckpoint) {
    checkpointSet.ReadAll();
    checkpointSet.SetStepNumber(startStep);
    checkpointSet.SetPRNGVariables(prng);
    checkpointSet.SetMoleculeLookup(molLookupRef);
    checkpointSet.SetMoveSettings(moveSettings);
    checkpointSet.SetMolecules(statV.mol);
#if GOMC_LIB_MPI
    if(checkpointSet.CheckIfParallelTemperingWasEnabled() && ms->parallelTemperingEnabled)
      checkpointSet.SetPRNGVariablesPT(*prngParallelTemp);
#endif
  }

  GOMC_EVENT_START(1, GomcProfileEvent::READ_INPUT_FILES);
  xsc.Init(set.pdb, set.config.in, molLookupRef, statV.mol);
  GOMC_EVENT_STOP(1, GomcProfileEvent::READ_INPUT_FILES);
  boxDimensions->Init(set.config.in.restart,
                      set.config.sys.volume, set.pdb.cryst,
                      statV.forcefield);
  coordinates.InitFromPDB(set.pdb.atoms);

  com.CalcCOM();
  // Allocate space for atom forces
  atomForceRef.Init(set.pdb.atoms.beta.size());
  molForceRef.Init(com.Count());
  // Allocate space for reciprocate force
  atomForceRecRef.Init(set.pdb.atoms.beta.size());
  molForceRecRef.Init(com.Count());
  cellList.SetCutoff();
  cellList.GridAll(boxDimRef, coordinates, molLookupRef);

  //check if we have to use cached version of Ewald or not.
  bool ewald = set.config.sys.elect.ewald;
  bool cached = set.config.sys.elect.cache;

#ifdef GOMC_CUDA
  if(ewald)
    calcEwald = new Ewald(statV, *this);
  else
    calcEwald = new NoEwald(statV, *this);
#else
  if (ewald && cached)
    calcEwald = new EwaldCached(statV, *this);
  else if (ewald && !cached)
    calcEwald = new Ewald(statV, *this);
  else
    calcEwald = new NoEwald(statV, *this);
#endif

  //Initial the lambda before calling SystemTotal
  InitLambda();
  calcEnergy.Init(*this);
  calcEwald->Init();
  potential = calcEnergy.SystemTotal();
  InitMoves(set);
  for(uint m = 0; m < mv::MOVE_KINDS_TOTAL; m++)
    moveTime[m] = 0.0;
}

void System::InitMoves(Setup const& set)
{
  moves[mv::DISPLACE] = new Translate(*this, statV);
  moves[mv::MULTIPARTICLE] = new MultiParticle(*this, statV);
  moves[mv::ROTATE] = new Rotate(*this, statV);
  moves[mv::INTRA_SWAP] = new IntraSwap(*this, statV);
  moves[mv::REGROWTH] = new Regrowth(*this, statV);
  moves[mv::CRANKSHAFT] = new CrankShaft(*this, statV);
  if(set.config.sys.intraMemcVal.MEMC1) {
    moves[mv::INTRA_MEMC] = new IntraMoleculeExchange1(*this, statV);
  } else if (set.config.sys.intraMemcVal.MEMC2) {
    moves[mv::INTRA_MEMC] = new IntraMoleculeExchange2(*this, statV);
  } else {
    moves[mv::INTRA_MEMC] = new IntraMoleculeExchange3(*this, statV);
  }

#if ENSEMBLE == GEMC || ENSEMBLE == NPT
  moves[mv::VOL_TRANSFER] = new VolumeTransfer(*this, statV);
#endif
#if ENSEMBLE == GEMC || ENSEMBLE == GCMC
  moves[mv::MOL_TRANSFER] = new MoleculeTransfer(*this, statV);
  if(set.config.sys.memcVal.MEMC1) {
    moves[mv::MEMC] = new MoleculeExchange1(*this, statV);
  } else if (set.config.sys.memcVal.MEMC2) {
    moves[mv::MEMC] = new MoleculeExchange2(*this, statV);
  } else {
    moves[mv::MEMC] = new MoleculeExchange3(*this, statV);
  }
  moves[mv::CFCMC] = new CFCMC(*this, statV);
#endif
}

void System::InitLambda()
{
#ifdef GOMC_CUDA
  int temp_molIndex[BOX_TOTAL], temp_kindIndex[BOX_TOTAL];
  double temp_lambdaVDW[BOX_TOTAL], temp_lambdaCoulomb[BOX_TOTAL];
  bool temp_isFraction[BOX_TOTAL];
  for(int i = 0; i < BOX_TOTAL; i++) {
    temp_isFraction[i] = false;
  }
#endif
  if(statV.freeEnVal.enable) {
    bool found = false;
    for(uint k = 0; k < statV.mol.GetKindsCount(); k++) {
      std::string kindName = statV.mol.kinds[k].name;
      if(statV.freeEnVal.molType == kindName) {
        found = true;
        uint totalMol = molLookupRef.NumKindInBox(k, mv::BOX0);
        //In PDB file, molIndex start from 1.
        uint FEmolIndex = statV.freeEnVal.molIndex - 1;
        if(totalMol == 0) {
          found = false;
        } else if(totalMol <= FEmolIndex) {
          std::cout << "Error: Molecule index " << statV.freeEnVal.molIndex <<
                    " of kind " << kindName << " does not exist in the simulation box!\n";
          exit(EXIT_FAILURE);
        } else {
          uint m = molLookupRef.GetMolNum(FEmolIndex, k, mv::BOX0);
          uint state = statV.freeEnVal.iState;
          double lambdaCoulomb = statV.freeEnVal.lambdaCoulomb[state];
          double lambdaVDW = statV.freeEnVal.lambdaVDW[state];
          lambdaRef.Set(lambdaVDW, lambdaCoulomb, m, k, mv::BOX0);

#ifdef GOMC_CUDA
          // initialize arrays to copy to GPU
          temp_molIndex[mv::BOX0] = m;
          temp_kindIndex[mv::BOX0] = k;
          temp_lambdaVDW[mv::BOX0] = lambdaVDW;
          temp_lambdaCoulomb[mv::BOX0] = lambdaCoulomb;
          temp_isFraction[mv::BOX0] = true;
#endif
        }
        break;
      }
    }

    if(!found) {
      std::cout << "Error: No molecule of kind " << statV.freeEnVal.molType <<
                " in the simulation box! \n";
      exit(EXIT_FAILURE);
    }
  }
#ifdef GOMC_CUDA
  InitGPULambda(statV.forcefield.particles->getCUDAVars(), temp_molIndex,
                temp_kindIndex, temp_lambdaVDW, temp_lambdaCoulomb,
                temp_isFraction);
#endif
}

void System::RecalculateTrajectory(Setup &set, uint frameNum)
{
  set.pdb.Init(set.config.in.restart, set.config.in.files.pdb.name, frameNum);
  statV.InitOver(set, *this);
#ifdef VARIABLE_PARTICLE_NUMBER
  molLookup.Init(statV.mol, set.pdb.atoms);
#endif
  coordinates.InitFromPDB(set.pdb.atoms);
  com.CalcCOM();
  cellList.GridAll(boxDimRef, coordinates, molLookupRef);
  calcEnergy.Init(*this);
  calcEwald->Init();
  potential = calcEnergy.SystemTotal();
}

void System::ChooseAndRunMove(const uint step)
{
  r123wrapper.SetStep(step);
  double draw = 0;
  uint majKind = 0;
  PickMove(majKind, draw);
  time.SetStart();
  RunMove(majKind, draw, step);
  time.SetStop();
  moveTime[majKind] += time.GetTimDiff();
}
void System::PickMove(uint & kind, double & draw)
{
  prng.PickArbDist(kind, draw, statV.movePerc, statV.totalPerc,
                   mv::MOVE_KINDS_TOTAL);
}

void System::RunMove(uint majKind, double draw, const uint step)
{
  //return now if move targets molecule and there's none in that box.
  uint rejectState = SetParams(majKind, draw);
  //If single atom, redo move as displacement
  if (rejectState == mv::fail_state::ROTATE_ON_SINGLE_ATOM) {
    majKind = mv::DISPLACE;
    Translate * disp = static_cast<Translate *>(moves[mv::DISPLACE]);
    Rotate * rot = static_cast<Rotate *>(moves[mv::ROTATE]);
    rejectState = disp->ReplaceRot(*rot);
  }
  if (rejectState == mv::fail_state::NO_FAIL)
    rejectState = Transform(majKind);
  if (rejectState == mv::fail_state::NO_FAIL)
    CalcEn(majKind);
  Accept(majKind, rejectState, step);
}

uint System::SetParams(const uint kind, const double draw)
{
  return moves[kind]->Prep(draw, statV.movePerc[kind]);
}

uint System::Transform(const uint kind)
{
  return moves[kind]->Transform();
}

void System::CalcEn(const uint kind)
{
  moves[kind]->CalcEn();
}

void System::Accept(const uint kind, const uint rejectState, const uint step)
{
  moves[kind]->Accept(rejectState, step);
}

void System::PrintAcceptance()
{
  std::cout << std::endl;
  printf("%-24s %-15s", "Move Type", "Mol. Kind");
  for(uint b = 0; b < BOX_TOTAL; b++) {
    sstrm::Converter toStr;
    std::string numStr = "";
    toStr << b;
    toStr >> numStr;
    numStr = "BOX_" + numStr;
    printf("%-11s", numStr.c_str());
  }
  std::cout << std::endl;

  for(uint m = 0; m < mv::MOVE_KINDS_TOTAL; m++) {
    if(statV.movePerc[m] > 0.0)
      moves[m]->PrintAcceptKind();
  }
  std::cout << std::endl;
}

void System::PrintTime()
{
  //std::cout << "MC moves Execution time:\n";
  printf("%-36s %10.4f    sec.\n", "Displacement:", moveTime[mv::DISPLACE]);
  printf("%-36s %10.4f    sec.\n", "Rotation:", moveTime[mv::ROTATE]);
  printf("%-36s %10.4f    sec.\n", "MultiParticle:", moveTime[mv::MULTIPARTICLE]);
  printf("%-36s %10.4f    sec.\n", "Intra-Swap:", moveTime[mv::INTRA_SWAP]);
  printf("%-36s %10.4f    sec.\n", "Regrowth:", moveTime[mv::REGROWTH]);
  printf("%-36s %10.4f    sec.\n", "Intra-MEMC:", moveTime[mv::INTRA_MEMC]);
  printf("%-36s %10.4f    sec.\n", "Crank-Shaft:", moveTime[mv::CRANKSHAFT]);

#if ENSEMBLE == GEMC || ENSEMBLE == GCMC
  printf("%-36s %10.4f    sec.\n", "Mol-Transfer:",
         moveTime[mv::MOL_TRANSFER]);
  printf("%-36s %10.4f    sec.\n", "MEMC:", moveTime[mv::MEMC]);
  printf("%-36s %10.4f    sec.\n", "CFCMC:", moveTime[mv::CFCMC]);
#endif
#if ENSEMBLE == GEMC || ENSEMBLE == NPT
  printf("%-36s %10.4f    sec.\n", "Vol-Transfer:", moveTime[mv::VOL_TRANSFER]);
#endif
  std::cout << std::endl;
}
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

#include "Terrain.h"
#include "QGCMapEngine.h"
#include "QGeoMapReplyQGC.h"

#include <QUrl>
#include <QUrlQuery>
#include <QNetworkRequest>
#include <QNetworkProxy>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QTimer>
#include <QtLocation/private/qgeotilespec_p.h>

QGC_LOGGING_CATEGORY(ElevationProviderLog, "ElevationProviderLog")

Q_GLOBAL_STATIC(TerrainBatchManager, _terrainBatchManager)

TerrainBatchManager::TerrainBatchManager(void)
{
}

void TerrainBatchManager::addQuery(ElevationProvider* elevationProvider, const QList<QGeoCoordinate>& coordinates)
{
    if (coordinates.length() > 0) {
        QList<float> altitudes;

        if (!_getAltitudesForCoordinates(coordinates, altitudes)) {
            QueuedRequestInfo_t queuedRequestInfo = { elevationProvider, coordinates };
            _requestQueue.append(queuedRequestInfo);
        }

        qCDebug(ElevationProviderLog) << "All altitudes taken from cached data";
        elevationProvider->_signalTerrainData(coordinates.count() == altitudes.count(), altitudes);
    }
}

bool TerrainBatchManager::_getAltitudesForCoordinates(const QList<QGeoCoordinate>& coordinates, QList<float>& altitudes)
{
    foreach (const QGeoCoordinate& coordinate, coordinates) {
        QString tileHash = _getTileHash(coordinate);
        _tilesMutex.lock();
        if (!_tiles.contains(tileHash)) {
            qCDebug(ElevationProviderLog) << "Need to download tile " << tileHash;

            if (!_tileDownloadQueue.contains(tileHash)) {
                // Schedule the fetch task

                if (_state != State::Downloading) {
                    QNetworkRequest request = getQGCMapEngine()->urlFactory()->getTileURL(UrlFactory::AirmapElevation, QGCMapEngine::long2elevationTileX(coordinate.longitude(), 1), QGCMapEngine::lat2elevationTileY(coordinate.latitude(), 1), 1, &_networkManager);
                    QGeoTileSpec spec;
                    spec.setX(QGCMapEngine::long2elevationTileX(coordinate.longitude(), 1));
                    spec.setY(QGCMapEngine::lat2elevationTileY(coordinate.latitude(), 1));
                    spec.setZoom(1);
                    spec.setMapId(UrlFactory::AirmapElevation);
                    QGeoTiledMapReplyQGC* reply = new QGeoTiledMapReplyQGC(&_networkManager, request, spec);
                    connect(reply, &QGeoTiledMapReplyQGC::finished, this, &TerrainBatchManager::_fetchedTile);
                    connect(reply, &QGeoTiledMapReplyQGC::aborted, this, &TerrainBatchManager::_fetchedTile);
                    _state = State::Downloading;
                }

                _tileDownloadQueue.append(tileHash);
            }
            _tilesMutex.unlock();

            return false;
        } else {
            if (_tiles[tileHash].isIn(coordinate)) {
                altitudes.push_back(_tiles[tileHash].elevation(coordinate));
            } else {
                qCDebug(ElevationProviderLog) << "Error: coordinate not in tile region";
                altitudes.push_back(-1.0);
            }
        }
        _tilesMutex.unlock();
    }
    return true;
}

void TerrainBatchManager::_tileFailed(void)
{
    QList<float>    noAltitudes;

    foreach (const QueuedRequestInfo_t& requestInfo, _requestQueue) {
        requestInfo.elevationProvider->_signalTerrainData(false, noAltitudes);
    }
    _requestQueue.clear();
}

void TerrainBatchManager::_fetchedTile()
{
    QGeoTiledMapReplyQGC* reply = qobject_cast<QGeoTiledMapReplyQGC*>(QObject::sender());

    if (!reply) {
        qCDebug(ElevationProviderLog) << "Elevation tile fetched but invalid reply data type.";
        return;
    }

    // remove from download queue
    QGeoTileSpec spec = reply->tileSpec();
    QString hash = QGCMapEngine::getTileHash(UrlFactory::AirmapElevation, spec.x(), spec.y(), spec.zoom());
    _tilesMutex.lock();
    if (_tileDownloadQueue.contains(hash)) {
        _tileDownloadQueue.removeOne(hash);
    } else {
        qCDebug(ElevationProviderLog) << "Loaded elevation tile, but not found in download queue.";
    }
    _tilesMutex.unlock();

    // handle potential errors
    if (reply->error() != QGeoTiledMapReply::NoError) {
        if (reply->error() == QGeoTiledMapReply::CommunicationError) {
            qCDebug(ElevationProviderLog) << "Elevation tile fetching returned communication error. " << reply->errorString();
        } else {
            qCDebug(ElevationProviderLog) << "Elevation tile fetching returned error. " << reply->errorString();
        }
        _tileFailed();
        reply->deleteLater();
        return;
    }
    if (!reply->isFinished()) {
        qCDebug(ElevationProviderLog) << "Error in fetching elevation tile. Not finished. " << reply->errorString();
        _tileFailed();
        reply->deleteLater();
        return;
    }

    // parse received data and insert into hash table
    QByteArray responseBytes = reply->mapImageData();

    QJsonParseError parseError;
    QJsonDocument responseJson = QJsonDocument::fromJson(responseBytes, &parseError);
    if (parseError.error != QJsonParseError::NoError) {
        qCDebug(ElevationProviderLog) << "Could not parse terrain tile " << parseError.errorString();
        qCDebug(ElevationProviderLog) << responseBytes;
        _tileFailed();
        reply->deleteLater();
        return;
    }

    TerrainTile* terrainTile = new TerrainTile(responseJson);
    if (terrainTile->isValid()) {
        _tilesMutex.lock();
        if (!_tiles.contains(hash)) {
            _tiles.insert(hash, *terrainTile);
        } else {
            delete terrainTile;
        }
        _tilesMutex.unlock();
    } else {
        qCDebug(ElevationProviderLog) << "Received invalid tile";
    }
    reply->deleteLater();

    // now try to query the data again
    for (int i = _requestQueue.count() - 1; i >= 0; i--) {
        QList<float> altitudes;
        if (_getAltitudesForCoordinates(_requestQueue[i].coordinates, altitudes)) {
            _requestQueue[i].elevationProvider->_signalTerrainData(_requestQueue[i].coordinates.count() == altitudes.count(), altitudes);
            _requestQueue.removeAt(i);
        }
    }
}

QString TerrainBatchManager::_getTileHash(const QGeoCoordinate& coordinate)
{
    QString ret = QGCMapEngine::getTileHash(UrlFactory::AirmapElevation, QGCMapEngine::long2elevationTileX(coordinate.longitude(), 1), QGCMapEngine::lat2elevationTileY(coordinate.latitude(), 1), 1);
    qCDebug(ElevationProviderLog) << "Computing unique tile hash for " << coordinate << ret;

    return ret;
}

ElevationProvider::ElevationProvider(QObject* parent)
    : QObject(parent)
{

}

bool ElevationProvider::queryTerrainData(const QList<QGeoCoordinate>& coordinates)
{
    if (coordinates.length() == 0) {
        return false;
    }

    _terrainBatchManager->addQuery(this, coordinates);

    return false;
}

void ElevationProvider::_signalTerrainData(bool success, QList<float>& altitudes)
{
    emit terrainData(success, altitudes);
}
<commit_msg>download fix<commit_after>/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

#include "Terrain.h"
#include "QGCMapEngine.h"
#include "QGeoMapReplyQGC.h"

#include <QUrl>
#include <QUrlQuery>
#include <QNetworkRequest>
#include <QNetworkProxy>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QTimer>
#include <QtLocation/private/qgeotilespec_p.h>

QGC_LOGGING_CATEGORY(ElevationProviderLog, "ElevationProviderLog")

Q_GLOBAL_STATIC(TerrainBatchManager, _terrainBatchManager)

TerrainBatchManager::TerrainBatchManager(void)
{
}

void TerrainBatchManager::addQuery(ElevationProvider* elevationProvider, const QList<QGeoCoordinate>& coordinates)
{
    if (coordinates.length() > 0) {
        QList<float> altitudes;

        if (!_getAltitudesForCoordinates(coordinates, altitudes)) {
            QueuedRequestInfo_t queuedRequestInfo = { elevationProvider, coordinates };
            _requestQueue.append(queuedRequestInfo);
            return;
        }

        qCDebug(ElevationProviderLog) << "All altitudes taken from cached data";
        elevationProvider->_signalTerrainData(coordinates.count() == altitudes.count(), altitudes);
    }
}

bool TerrainBatchManager::_getAltitudesForCoordinates(const QList<QGeoCoordinate>& coordinates, QList<float>& altitudes)
{
    foreach (const QGeoCoordinate& coordinate, coordinates) {
        QString tileHash = _getTileHash(coordinate);
        _tilesMutex.lock();
        if (!_tiles.contains(tileHash)) {
            qCDebug(ElevationProviderLog) << "Need to download tile " << tileHash;

            if (!_tileDownloadQueue.contains(tileHash)) {
                // Schedule the fetch task

                if (_state != State::Downloading) {
                    QNetworkRequest request = getQGCMapEngine()->urlFactory()->getTileURL(UrlFactory::AirmapElevation, QGCMapEngine::long2elevationTileX(coordinate.longitude(), 1), QGCMapEngine::lat2elevationTileY(coordinate.latitude(), 1), 1, &_networkManager);
                    QGeoTileSpec spec;
                    spec.setX(QGCMapEngine::long2elevationTileX(coordinate.longitude(), 1));
                    spec.setY(QGCMapEngine::lat2elevationTileY(coordinate.latitude(), 1));
                    spec.setZoom(1);
                    spec.setMapId(UrlFactory::AirmapElevation);
                    QGeoTiledMapReplyQGC* reply = new QGeoTiledMapReplyQGC(&_networkManager, request, spec);
                    connect(reply, &QGeoTiledMapReplyQGC::finished, this, &TerrainBatchManager::_fetchedTile);
                    connect(reply, &QGeoTiledMapReplyQGC::aborted, this, &TerrainBatchManager::_fetchedTile);
                    _state = State::Downloading;
                }

                _tileDownloadQueue.append(tileHash);
            }
            _tilesMutex.unlock();

            return false;
        } else {
            if (_tiles[tileHash].isIn(coordinate)) {
                altitudes.push_back(_tiles[tileHash].elevation(coordinate));
            } else {
                qCDebug(ElevationProviderLog) << "Error: coordinate not in tile region";
                altitudes.push_back(-1.0);
            }
        }
        _tilesMutex.unlock();
    }
    return true;
}

void TerrainBatchManager::_tileFailed(void)
{
    QList<float>    noAltitudes;

    foreach (const QueuedRequestInfo_t& requestInfo, _requestQueue) {
        requestInfo.elevationProvider->_signalTerrainData(false, noAltitudes);
    }
    _requestQueue.clear();
}

void TerrainBatchManager::_fetchedTile()
{
    QGeoTiledMapReplyQGC* reply = qobject_cast<QGeoTiledMapReplyQGC*>(QObject::sender());
    _state = State::Idle;

    if (!reply) {
        qCDebug(ElevationProviderLog) << "Elevation tile fetched but invalid reply data type.";
        return;
    }

    // remove from download queue
    QGeoTileSpec spec = reply->tileSpec();
    QString hash = QGCMapEngine::getTileHash(UrlFactory::AirmapElevation, spec.x(), spec.y(), spec.zoom());
    _tilesMutex.lock();
    if (_tileDownloadQueue.contains(hash)) {
        _tileDownloadQueue.removeOne(hash);
    } else {
        qCDebug(ElevationProviderLog) << "Loaded elevation tile, but not found in download queue.";
    }
    _tilesMutex.unlock();

    // handle potential errors
    if (reply->error() != QGeoTiledMapReply::NoError) {
        if (reply->error() == QGeoTiledMapReply::CommunicationError) {
            qCDebug(ElevationProviderLog) << "Elevation tile fetching returned communication error. " << reply->errorString();
        } else {
            qCDebug(ElevationProviderLog) << "Elevation tile fetching returned error. " << reply->errorString();
        }
        _tileFailed();
        reply->deleteLater();
        return;
    }
    if (!reply->isFinished()) {
        qCDebug(ElevationProviderLog) << "Error in fetching elevation tile. Not finished. " << reply->errorString();
        _tileFailed();
        reply->deleteLater();
        return;
    }

    // parse received data and insert into hash table
    QByteArray responseBytes = reply->mapImageData();

    QJsonParseError parseError;
    QJsonDocument responseJson = QJsonDocument::fromJson(responseBytes, &parseError);
    if (parseError.error != QJsonParseError::NoError) {
        qCDebug(ElevationProviderLog) << "Could not parse terrain tile " << parseError.errorString();
        qCDebug(ElevationProviderLog) << responseBytes;
        _tileFailed();
        reply->deleteLater();
        return;
    }

    TerrainTile* terrainTile = new TerrainTile(responseJson);
    if (terrainTile->isValid()) {
        _tilesMutex.lock();
        if (!_tiles.contains(hash)) {
            _tiles.insert(hash, *terrainTile);
        } else {
            delete terrainTile;
        }
        _tilesMutex.unlock();
    } else {
        qCDebug(ElevationProviderLog) << "Received invalid tile";
    }
    reply->deleteLater();

    // now try to query the data again
    for (int i = _requestQueue.count() - 1; i >= 0; i--) {
        QList<float> altitudes;
        if (_getAltitudesForCoordinates(_requestQueue[i].coordinates, altitudes)) {
            _requestQueue[i].elevationProvider->_signalTerrainData(_requestQueue[i].coordinates.count() == altitudes.count(), altitudes);
            _requestQueue.removeAt(i);
        }
    }
}

QString TerrainBatchManager::_getTileHash(const QGeoCoordinate& coordinate)
{
    QString ret = QGCMapEngine::getTileHash(UrlFactory::AirmapElevation, QGCMapEngine::long2elevationTileX(coordinate.longitude(), 1), QGCMapEngine::lat2elevationTileY(coordinate.latitude(), 1), 1);
    qCDebug(ElevationProviderLog) << "Computing unique tile hash for " << coordinate << ret;

    return ret;
}

ElevationProvider::ElevationProvider(QObject* parent)
    : QObject(parent)
{

}

bool ElevationProvider::queryTerrainData(const QList<QGeoCoordinate>& coordinates)
{
    if (coordinates.length() == 0) {
        return false;
    }

    _terrainBatchManager->addQuery(this, coordinates);

    return false;
}

void ElevationProvider::_signalTerrainData(bool success, QList<float>& altitudes)
{
    emit terrainData(success, altitudes);
}
<|endoftext|>


<commit_before>#include <cstdio>
#include <sys/time.h>

#include "engine.h"
#include "entity.h"
#include "gamestate.h"
#include "global_constants.h"

Engine::Engine()
{
    lasttimeupdated = getmillisec();
    millisecperframe = 1000.0 / PHYSICS_FPS;
    Gamestate currentstate = Gamestate();
}

Engine::~Engine()
{
    //destructor
}

void Engine::run()
{
    int timediff = getmillisec() - lasttimeupdated;
    while (timediff - millisecperframe >= 0)
    {
        currentstate.update(millisecperframe);
        lasttimeupdated += millisecperframe;
        timediff -= millisecperframe;
    }
}

long int Engine::getmillisec()
{
    static struct timeval tp;
    gettimeofday(&tp, 0);
    return ((long) tp.tv_sec) * 1000 + ((long) tp.tv_usec) / 1000;
}
<commit_msg>Removed member shadow.<commit_after>#include <cstdio>
#include <sys/time.h>

#include "engine.h"
#include "entity.h"
#include "gamestate.h"
#include "global_constants.h"

Engine::Engine()
{
    lasttimeupdated = getmillisec();
    millisecperframe = 1000.0 / PHYSICS_FPS;
    currentstate = Gamestate();
}

Engine::~Engine()
{
    //destructor
}

void Engine::run()
{
    int timediff = getmillisec() - lasttimeupdated;
    while (timediff - millisecperframe >= 0)
    {
        currentstate.update(millisecperframe);
        lasttimeupdated += millisecperframe;
        timediff -= millisecperframe;
    }
}

long int Engine::getmillisec()
{
    static struct timeval tp;
    gettimeofday(&tp, 0);
    return ((long) tp.tv_sec) * 1000 + ((long) tp.tv_usec) / 1000;
}
<|endoftext|>


<commit_before>#include "config.hpp"

#if defined(PLATFORM_WINDOWS)
    #define WIN32_LEAN_AND_MEAN
    #include <windows.h>
#elif defined(PLATFORM_LINUX)
    #include <time.h>
#elif defined(PLATFORM_OSX)
    #include <mach/clock.h>
    #include <mach/mach.h>
#endif
namespace MgCore
{
    class FpsTimer
    {
    private:
        int m_frames;
        double m_currentTime;
        double m_previousTime;
        double m_delta;
        double m_fpsTime;
        float m_fps;

#if defined(PLATFORM_WINDOWS)
        LARGE_INTEGER m_frequency;
        double get_time()
        {
            LARGE_INTEGER startingTime;
            QueryPerformanceCounter(&startingTime);
            return startingTime.QuadPart / m_frequency.QuadPart;
        }

#elif defined(PLATFORM_LINUX)
        double get_time()
        {
            timespec mt;
            clock_gettime(CLOCK_MONOTONIC, &mt);
            return mt.tv_sec + (mt.tv_nsec * 0.000000001);
        }

#elif defined(PLATFORM_OSX)
        clock_serv_t m_cclock;
        double get_time()
        {
            mach_timespec_t mts;
            clock_get_time(m_cclock, &mts);
            return mts.tv_sec + (mts.tv_nsec * 0.000000001);
        }

#else
        double get_time()
        {
            return 1.0;
        }

#endif

    public:
        FpsTimer();
        ~FpsTimer();
        double tick();
        float get_fps();
    };
}<commit_msg>Fix potential issue with the window fpstimer.<commit_after>#include "config.hpp"

#if defined(PLATFORM_WINDOWS)
    #define WIN32_LEAN_AND_MEAN
    #include <windows.h>
#elif defined(PLATFORM_LINUX)
    #include <time.h>
#elif defined(PLATFORM_OSX)
    #include <mach/clock.h>
    #include <mach/mach.h>
#endif
namespace MgCore
{
    class FpsTimer
    {
    private:
        int m_frames;
        double m_currentTime;
        double m_previousTime;
        double m_delta;
        double m_fpsTime;
        float m_fps;

#if defined(PLATFORM_WINDOWS)
        LARGE_INTEGER m_frequency;
        double get_time()
        {
            LARGE_INTEGER startingTime;
            QueryPerformanceCounter(&startingTime);
            return startingTime.QuadPart / static_cast<double>(m_frequency.QuadPart);
        }

#elif defined(PLATFORM_LINUX)
        double get_time()
        {
            timespec mt;
            clock_gettime(CLOCK_MONOTONIC, &mt);
            return mt.tv_sec + (mt.tv_nsec * 0.000000001);
        }

#elif defined(PLATFORM_OSX)
        clock_serv_t m_cclock;
        double get_time()
        {
            mach_timespec_t mts;
            clock_get_time(m_cclock, &mts);
            return mts.tv_sec + (mts.tv_nsec * 0.000000001);
        }

#else
        double get_time()
        {
            return 1.0;
        }

#endif

    public:
        FpsTimer();
        ~FpsTimer();
        double tick();
        float get_fps();
    };
}<|endoftext|>