<commit_before>/****************************************************************************
 *
 * Copyright (C) 2016 Ramakrishna Kintada. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 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 <time.h>
#include <unistd.h>
#include <fcntl.h>
#include "px4muorb_KraitRpcWrapper.hpp"
#include <rpcmem.h>
#include "px4muorb.h"
#include "px4_log.h"

using namespace px4muorb;

/* Flags applied to the allocation of the shared memory for RPC */
#define MUORB_KRAIT_FASTRPC_MEM_FLAGS         0

/* The ID of the HEAP to be used when allocating shared memory */
//TODO This heap id is used for test purposes. We need to find out the correct one.
#define MUORB_KRAIT_FASTRPC_HEAP_ID           22

static char *_TopicNameBuffer = 0;
static const int32_t _MAX_TOPIC_NAME_BUFFER = 256;

static uint8_t *_DataBuffer  = 0;
static const uint32_t _MAX_DATA_BUFFER_SIZE = 2048;

static bool _Initialized = false;

// These numbers are based off the fact each fastrpc call for 64K packet is 94us.
// hence we are trying to allocation 64K of byte buffers.
static const uint32_t _MAX_TOPIC_DATA_BUFFER_SIZE = 1024;
static const uint32_t _MAX_TOPICS = 64;
static const uint32_t _MAX_BULK_TRANSFER_BUFFER_SIZE = _MAX_TOPIC_DATA_BUFFER_SIZE * _MAX_TOPICS;
static uint8_t *_BulkTransferBuffer = 0;

// The DSP timer can be read from this file.
#define DSP_TIMER_FILE "/sys/kernel/boot_adsp/qdsp_qtimer"

/**
 * Helper function to get timer difference between time on DSP and appsproc side.
 * Usually the DSP gets started around 2s before the appsproc (Linux) side and
 * therefore the clocks are not in sync. We change the clock on the DSP side but
 * for this we need to find the offset first and then tell code on the DSP side.
 *
 * @param time_diff_us: pointer to time offset to set.
 * @return: 0 on success, < 0 on error.
 */
int calc_timer_diff_to_dsp_us(int32_t *time_diff_us);

int calc_timer_diff_to_dsp_us(int32_t *time_diff_us)
{
	int fd = open(DSP_TIMER_FILE, O_RDONLY);

	if (fd < 0) {
		PX4_ERR("Could not open DSP timer file %s.", DSP_TIMER_FILE);
		return -1;
	}

	char buffer[21];
	memset(buffer, 0, sizeof(buffer));
	int bytes_read = read(fd, buffer, sizeof(buffer));

	if (bytes_read < 0) {
		PX4_ERR("Could not read DSP timer file %s.", DSP_TIMER_FILE);
		close(fd);
		return -2;
	}

	// Do this call right after reading to avoid latency here.W
	timespec ts;
	clock_gettime(CLOCK_MONOTONIC, &ts);
	uint64_t time_appsproc = ((uint64_t)ts.tv_sec) * 1000000llu + (ts.tv_nsec / 1000);

	close(fd);

	uint64_t time_dsp;
	int ret  = sscanf(buffer, "%llx", &time_dsp);

	if (ret < 0) {
		PX4_ERR("Could not parse DSP timer.");
		return -3;
	}

	time_dsp /= 19.2;

	// Before casting to in32_t, check if it fits.
	uint64_t abs_diff = (time_appsproc > time_dsp)
			    ? (time_appsproc - time_dsp) : (time_dsp - time_appsproc);

	if (abs_diff > INT32_MAX) {
		PX4_ERR("Timer difference too big");
		return -4;
	}

	*time_diff_us = time_appsproc - time_dsp;

	PX4_DEBUG("found time_dsp: %llu us, time_appsproc: %llu us", time_dsp, time_appsproc);
	PX4_DEBUG("found time_diff: %li us, %.6f s", *time_diff_us, ((double)*time_diff_us) / 1e6);

	return 0;
}

px4muorb::KraitRpcWrapper::KraitRpcWrapper()
{
}

px4muorb::KraitRpcWrapper::~KraitRpcWrapper()
{
}

bool px4muorb::KraitRpcWrapper::Initialize()
{
	bool rc = true;

	PX4_DEBUG("%s Now calling rpcmem_init...", __FUNCTION__);
	rpcmem_init();

	PX4_DEBUG("%s Now calling rpcmem_alloc...", __FUNCTION__);

	_BulkTransferBuffer = (uint8_t *) rpcmem_alloc(MUORB_KRAIT_FASTRPC_HEAP_ID, MUORB_KRAIT_FASTRPC_MEM_FLAGS,
			      _MAX_BULK_TRANSFER_BUFFER_SIZE * sizeof(uint8_t));
	rc = (_BulkTransferBuffer != NULL) ? true : false;

	if (!rc) {
		PX4_ERR("%s rpcmem_alloc failed! for bulk transfer buffers", __FUNCTION__);
		return rc;

	} else {
		PX4_DEBUG("%s rpcmem_alloc passed for Bulk transfer buffers buffer_size: %d addr: %p",
			  __FUNCTION__, (_MAX_BULK_TRANSFER_BUFFER_SIZE * sizeof(uint8_t)), _BulkTransferBuffer);
	}

	_TopicNameBuffer = (char *) rpcmem_alloc(MUORB_KRAIT_FASTRPC_HEAP_ID,
			   MUORB_KRAIT_FASTRPC_MEM_FLAGS, _MAX_TOPIC_NAME_BUFFER * sizeof(char));

	rc = (_TopicNameBuffer != NULL) ? true : false;

	if (!rc) {
		PX4_ERR("%s rpcmem_alloc failed! for topic_name_buffer", __FUNCTION__);
		rpcmem_free(_BulkTransferBuffer);
		return rc;

	} else {
		PX4_DEBUG("%s rpcmem_alloc passed for topic_name_buffer", __FUNCTION__);
	}

	// now allocate the data buffer.
	_DataBuffer = (uint8_t *) rpcmem_alloc(MUORB_KRAIT_FASTRPC_HEAP_ID,
					       MUORB_KRAIT_FASTRPC_MEM_FLAGS, _MAX_DATA_BUFFER_SIZE * sizeof(uint8_t));

	rc = (_DataBuffer != NULL) ? true : false;

	if (!rc) {
		PX4_ERR("%s rpcmem_alloc failed! for DataBuffer", __FUNCTION__);
		// free the topic name buffer;
		rpcmem_free(_BulkTransferBuffer);
		rpcmem_free(_TopicNameBuffer);
		_TopicNameBuffer = 0;
		return rc;

	} else {
		PX4_DEBUG("%s rpcmem_alloc passed for data_buffer", __FUNCTION__);
	}

	int32_t time_diff_us;

	if (calc_timer_diff_to_dsp_us(&time_diff_us) != 0) {
		rc = false;
		return rc;
	}

	// call muorb initialize routine.
	if (px4muorb_orb_initialize() != 0) {
		PX4_ERR("%s Error calling the uorb fastrpc initalize method..", __FUNCTION__);
		rc = false;
		return rc;
	}

	// TODO FIXME: remove this check or make it less verbose later
	px4muorb_set_absolute_time_offset(time_diff_us);

	uint64_t time_dsp;
	px4muorb_get_absolute_time(&time_dsp);

	uint64_t time_appsproc = hrt_absolute_time();

	int diff = (time_dsp - time_appsproc);

	PX4_INFO("time_dsp: %llu us, time appsproc: %llu us, diff: %d us", time_dsp, time_appsproc, diff);

	_Initialized = true;
	return rc;
}

bool px4muorb::KraitRpcWrapper::Terminate()
{
	if (_BulkTransferBuffer != NULL) {
		rpcmem_free(_BulkTransferBuffer);
		_BulkTransferBuffer = 0;
	}

	if (_TopicNameBuffer != NULL) {
		rpcmem_free(_TopicNameBuffer);
		_TopicNameBuffer = 0;
	}

	if (_DataBuffer != NULL) {
		rpcmem_free(_DataBuffer);
		_DataBuffer = 0;
	}

	_Initialized = false;
	return true;
}

int32_t px4muorb::KraitRpcWrapper::AddSubscriber(const char *topic)
{
	return ((_Initialized) ? px4muorb_add_subscriber(topic) : -1);
}

int32_t px4muorb::KraitRpcWrapper::RemoveSubscriber(const char *topic)
{
	return (_Initialized ? px4muorb_remove_subscriber(topic) : -1);
}

int32_t px4muorb::KraitRpcWrapper::IsSubscriberPresent(const char *topic, int32_t *status)
{
	return (_Initialized ? px4muorb_is_subscriber_present(topic, status) : -1);
}

int32_t px4muorb::KraitRpcWrapper::SendData(const char *topic, int32_t length_in_bytes, const uint8_t *data)
{
	return (_Initialized ? px4muorb_send_topic_data(topic, data, length_in_bytes) : -1);
}

int32_t px4muorb::KraitRpcWrapper::ReceiveData(int32_t *msg_type, char **topic, int32_t *length_in_bytes,
		uint8_t **data)
{
	int32_t rc = -1;

	if (_Initialized) {
		rc = px4muorb_receive_msg(msg_type, _TopicNameBuffer, _MAX_TOPIC_NAME_BUFFER, _DataBuffer, _MAX_DATA_BUFFER_SIZE,
					  length_in_bytes);

		if (rc == 0) {
			*topic = _TopicNameBuffer;
			*data  = _DataBuffer;

		} else {
			PX4_ERR("ERROR: Getting data from fastRPC link");
		}

	} else {
		PX4_ERR("ERROR: FastRpcWrapper Not Initialized");
	}

	return rc;
}

int32_t px4muorb::KraitRpcWrapper::ReceiveBulkData(uint8_t **bulk_data, int32_t *length_in_bytes, int32_t *topic_count)
{
	int32_t rc = -1;

	if (_Initialized) {
		//rc = px4muorb_receive_msg( msg_type, _TopicNameBuffer, _MAX_TOPIC_NAME_BUFFER, _DataBuffer, _MAX_DATA_BUFFER_SIZE, length_in_bytes  );
		rc = px4muorb_receive_bulk_data(_BulkTransferBuffer, _MAX_BULK_TRANSFER_BUFFER_SIZE,  length_in_bytes, topic_count);

		if (rc == 0) {
			*bulk_data = _BulkTransferBuffer;

		} else {
			PX4_ERR("ERROR: Getting Bulk data from fastRPC link");
		}

	} else {
		PX4_ERR("ERROR: FastRpcWrapper Not Initialized");
	}

	return rc;
}

int32_t px4muorb::KraitRpcWrapper::UnblockReceiveData()
{
	return (_Initialized ? px4muorb_unblock_recieve_msg() : -1);
}
<commit_msg>muorb: typo and added comment for magic number<commit_after>/****************************************************************************
 *
 * Copyright (C) 2016 Ramakrishna Kintada. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 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 <time.h>
#include <unistd.h>
#include <fcntl.h>
#include "px4muorb_KraitRpcWrapper.hpp"
#include <rpcmem.h>
#include "px4muorb.h"
#include "px4_log.h"

using namespace px4muorb;

/* Flags applied to the allocation of the shared memory for RPC */
#define MUORB_KRAIT_FASTRPC_MEM_FLAGS         0

/* The ID of the HEAP to be used when allocating shared memory */
//TODO This heap id is used for test purposes. We need to find out the correct one.
#define MUORB_KRAIT_FASTRPC_HEAP_ID           22

static char *_TopicNameBuffer = 0;
static const int32_t _MAX_TOPIC_NAME_BUFFER = 256;

static uint8_t *_DataBuffer  = 0;
static const uint32_t _MAX_DATA_BUFFER_SIZE = 2048;

static bool _Initialized = false;

// These numbers are based off the fact each fastrpc call for 64K packet is 94us.
// hence we are trying to allocation 64K of byte buffers.
static const uint32_t _MAX_TOPIC_DATA_BUFFER_SIZE = 1024;
static const uint32_t _MAX_TOPICS = 64;
static const uint32_t _MAX_BULK_TRANSFER_BUFFER_SIZE = _MAX_TOPIC_DATA_BUFFER_SIZE * _MAX_TOPICS;
static uint8_t *_BulkTransferBuffer = 0;

// The DSP timer can be read from this file.
#define DSP_TIMER_FILE "/sys/kernel/boot_adsp/qdsp_qtimer"

/**
 * Helper function to get timer difference between time on DSP and appsproc side.
 * Usually the DSP gets started around 2s before the appsproc (Linux) side and
 * therefore the clocks are not in sync. We change the clock on the DSP side but
 * for this we need to find the offset first and then tell code on the DSP side.
 *
 * @param time_diff_us: pointer to time offset to set.
 * @return: 0 on success, < 0 on error.
 */
int calc_timer_diff_to_dsp_us(int32_t *time_diff_us);

int calc_timer_diff_to_dsp_us(int32_t *time_diff_us)
{
	int fd = open(DSP_TIMER_FILE, O_RDONLY);

	if (fd < 0) {
		PX4_ERR("Could not open DSP timer file %s.", DSP_TIMER_FILE);
		return -1;
	}

	char buffer[21];
	memset(buffer, 0, sizeof(buffer));
	int bytes_read = read(fd, buffer, sizeof(buffer));

	if (bytes_read < 0) {
		PX4_ERR("Could not read DSP timer file %s.", DSP_TIMER_FILE);
		close(fd);
		return -2;
	}

	// Do this call right after reading to avoid latency here.
	timespec ts;
	clock_gettime(CLOCK_MONOTONIC, &ts);
	uint64_t time_appsproc = ((uint64_t)ts.tv_sec) * 1000000llu + (ts.tv_nsec / 1000);

	close(fd);

	uint64_t time_dsp;
	int ret  = sscanf(buffer, "%llx", &time_dsp);

	if (ret < 0) {
		PX4_ERR("Could not parse DSP timer.");
		return -3;
	}

	// The clock count needs to get converted to us. The clock supposedly
	// runs at just under 20 MHz. The magic value of 19.2 was provided by
	// Qualcomm.
	time_dsp /= 19.2;

	// Before casting to in32_t, check if it fits.
	uint64_t abs_diff = (time_appsproc > time_dsp)
			    ? (time_appsproc - time_dsp) : (time_dsp - time_appsproc);

	if (abs_diff > INT32_MAX) {
		PX4_ERR("Timer difference too big");
		return -4;
	}

	*time_diff_us = time_appsproc - time_dsp;

	PX4_DEBUG("found time_dsp: %llu us, time_appsproc: %llu us", time_dsp, time_appsproc);
	PX4_DEBUG("found time_diff: %li us, %.6f s", *time_diff_us, ((double)*time_diff_us) / 1e6);

	return 0;
}

px4muorb::KraitRpcWrapper::KraitRpcWrapper()
{
}

px4muorb::KraitRpcWrapper::~KraitRpcWrapper()
{
}

bool px4muorb::KraitRpcWrapper::Initialize()
{
	bool rc = true;

	PX4_DEBUG("%s Now calling rpcmem_init...", __FUNCTION__);
	rpcmem_init();

	PX4_DEBUG("%s Now calling rpcmem_alloc...", __FUNCTION__);

	_BulkTransferBuffer = (uint8_t *) rpcmem_alloc(MUORB_KRAIT_FASTRPC_HEAP_ID, MUORB_KRAIT_FASTRPC_MEM_FLAGS,
			      _MAX_BULK_TRANSFER_BUFFER_SIZE * sizeof(uint8_t));
	rc = (_BulkTransferBuffer != NULL) ? true : false;

	if (!rc) {
		PX4_ERR("%s rpcmem_alloc failed! for bulk transfer buffers", __FUNCTION__);
		return rc;

	} else {
		PX4_DEBUG("%s rpcmem_alloc passed for Bulk transfer buffers buffer_size: %d addr: %p",
			  __FUNCTION__, (_MAX_BULK_TRANSFER_BUFFER_SIZE * sizeof(uint8_t)), _BulkTransferBuffer);
	}

	_TopicNameBuffer = (char *) rpcmem_alloc(MUORB_KRAIT_FASTRPC_HEAP_ID,
			   MUORB_KRAIT_FASTRPC_MEM_FLAGS, _MAX_TOPIC_NAME_BUFFER * sizeof(char));

	rc = (_TopicNameBuffer != NULL) ? true : false;

	if (!rc) {
		PX4_ERR("%s rpcmem_alloc failed! for topic_name_buffer", __FUNCTION__);
		rpcmem_free(_BulkTransferBuffer);
		return rc;

	} else {
		PX4_DEBUG("%s rpcmem_alloc passed for topic_name_buffer", __FUNCTION__);
	}

	// now allocate the data buffer.
	_DataBuffer = (uint8_t *) rpcmem_alloc(MUORB_KRAIT_FASTRPC_HEAP_ID,
					       MUORB_KRAIT_FASTRPC_MEM_FLAGS, _MAX_DATA_BUFFER_SIZE * sizeof(uint8_t));

	rc = (_DataBuffer != NULL) ? true : false;

	if (!rc) {
		PX4_ERR("%s rpcmem_alloc failed! for DataBuffer", __FUNCTION__);
		// free the topic name buffer;
		rpcmem_free(_BulkTransferBuffer);
		rpcmem_free(_TopicNameBuffer);
		_TopicNameBuffer = 0;
		return rc;

	} else {
		PX4_DEBUG("%s rpcmem_alloc passed for data_buffer", __FUNCTION__);
	}

	int32_t time_diff_us;

	if (calc_timer_diff_to_dsp_us(&time_diff_us) != 0) {
		rc = false;
		return rc;
	}

	// call muorb initialize routine.
	if (px4muorb_orb_initialize() != 0) {
		PX4_ERR("%s Error calling the uorb fastrpc initalize method..", __FUNCTION__);
		rc = false;
		return rc;
	}

	// TODO FIXME: remove this check or make it less verbose later
	px4muorb_set_absolute_time_offset(time_diff_us);

	uint64_t time_dsp;
	px4muorb_get_absolute_time(&time_dsp);

	uint64_t time_appsproc = hrt_absolute_time();

	int diff = (time_dsp - time_appsproc);

	PX4_INFO("time_dsp: %llu us, time appsproc: %llu us, diff: %d us", time_dsp, time_appsproc, diff);

	_Initialized = true;
	return rc;
}

bool px4muorb::KraitRpcWrapper::Terminate()
{
	if (_BulkTransferBuffer != NULL) {
		rpcmem_free(_BulkTransferBuffer);
		_BulkTransferBuffer = 0;
	}

	if (_TopicNameBuffer != NULL) {
		rpcmem_free(_TopicNameBuffer);
		_TopicNameBuffer = 0;
	}

	if (_DataBuffer != NULL) {
		rpcmem_free(_DataBuffer);
		_DataBuffer = 0;
	}

	_Initialized = false;
	return true;
}

int32_t px4muorb::KraitRpcWrapper::AddSubscriber(const char *topic)
{
	return ((_Initialized) ? px4muorb_add_subscriber(topic) : -1);
}

int32_t px4muorb::KraitRpcWrapper::RemoveSubscriber(const char *topic)
{
	return (_Initialized ? px4muorb_remove_subscriber(topic) : -1);
}

int32_t px4muorb::KraitRpcWrapper::IsSubscriberPresent(const char *topic, int32_t *status)
{
	return (_Initialized ? px4muorb_is_subscriber_present(topic, status) : -1);
}

int32_t px4muorb::KraitRpcWrapper::SendData(const char *topic, int32_t length_in_bytes, const uint8_t *data)
{
	return (_Initialized ? px4muorb_send_topic_data(topic, data, length_in_bytes) : -1);
}

int32_t px4muorb::KraitRpcWrapper::ReceiveData(int32_t *msg_type, char **topic, int32_t *length_in_bytes,
		uint8_t **data)
{
	int32_t rc = -1;

	if (_Initialized) {
		rc = px4muorb_receive_msg(msg_type, _TopicNameBuffer, _MAX_TOPIC_NAME_BUFFER, _DataBuffer, _MAX_DATA_BUFFER_SIZE,
					  length_in_bytes);

		if (rc == 0) {
			*topic = _TopicNameBuffer;
			*data  = _DataBuffer;

		} else {
			PX4_ERR("ERROR: Getting data from fastRPC link");
		}

	} else {
		PX4_ERR("ERROR: FastRpcWrapper Not Initialized");
	}

	return rc;
}

int32_t px4muorb::KraitRpcWrapper::ReceiveBulkData(uint8_t **bulk_data, int32_t *length_in_bytes, int32_t *topic_count)
{
	int32_t rc = -1;

	if (_Initialized) {
		//rc = px4muorb_receive_msg( msg_type, _TopicNameBuffer, _MAX_TOPIC_NAME_BUFFER, _DataBuffer, _MAX_DATA_BUFFER_SIZE, length_in_bytes  );
		rc = px4muorb_receive_bulk_data(_BulkTransferBuffer, _MAX_BULK_TRANSFER_BUFFER_SIZE,  length_in_bytes, topic_count);

		if (rc == 0) {
			*bulk_data = _BulkTransferBuffer;

		} else {
			PX4_ERR("ERROR: Getting Bulk data from fastRPC link");
		}

	} else {
		PX4_ERR("ERROR: FastRpcWrapper Not Initialized");
	}

	return rc;
}

int32_t px4muorb::KraitRpcWrapper::UnblockReceiveData()
{
	return (_Initialized ? px4muorb_unblock_recieve_msg() : -1);
}
<|endoftext|>


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

// *
// *
// *
// * this class defines the TOF object to be stored
// * in OCDB on a run-by-run basis in order to have the status
// * of TOF trigger inputs. it stores 32 bit masks for each crate
// *
// *
// *
// *

#include "AliTOFTriggerMask.h"

Int_t AliTOFTriggerMask::fPowerMask[24];

ClassImp(AliTOFTriggerMask)
//_________________________________________________________

AliTOFTriggerMask::AliTOFTriggerMask() :
  TObject(),
  fTriggerMask()
{
  /*
   * default constructor
   */

  for (Int_t iddl = 0; iddl < 72; iddl++) fTriggerMask[iddl] = 0;

  fPowerMask[0] = 1;
  for(Int_t i=1;i <= 23;i++){
      fPowerMask[i] = fPowerMask[i-1]*2;
  }

}

//_________________________________________________________

AliTOFTriggerMask::~AliTOFTriggerMask()
{
  /*
   * default destructor
   */

}

//_________________________________________________________

AliTOFTriggerMask::AliTOFTriggerMask(const AliTOFTriggerMask &source) :
  TObject(source),
  fTriggerMask()
{
  /*
   * copy constructor
   */

  for (Int_t iddl = 0; iddl < 72; iddl++) fTriggerMask[iddl] = source.fTriggerMask[iddl];
}

//_________________________________________________________

AliTOFTriggerMask &
AliTOFTriggerMask::operator=(const AliTOFTriggerMask &source)
{
  /*
   * operator=
   */

  if (this == &source) return *this;
  TObject::operator=(source);

  for (Int_t iddl = 0; iddl < 72; iddl++) fTriggerMask[iddl] = source.fTriggerMask[iddl];

  return *this;
}

//_________________________________________________________

void
AliTOFTriggerMask::SetTriggerMaskArray(UInt_t *array)
{
  /*
   * set trigger mask array
   */

  for (Int_t iddl = 0; iddl < 72; iddl++) fTriggerMask[iddl] = array[iddl];
}
//_________________________________________________________

Int_t AliTOFTriggerMask::GetNumberMaxiPadOn() {
  Int_t n=0;
  for(Int_t j=0;j<72;j++)
    for(Int_t i=22;i>=0;i--)
      n += (fTriggerMask[j]%fPowerMask[i+1])/fPowerMask[i];
  return n;
};
//_________________________________________________________
void AliTOFTriggerMask::SetON(Int_t icrate,Int_t ich){
  if(ich < 24 && icrate < 73) fTriggerMask[icrate] += fPowerMask[ich];
}
//_________________________________________________________
Bool_t AliTOFTriggerMask::IsON(Int_t icrate,Int_t ich){
  if(ich < 24 && icrate < 73) return (fTriggerMask[icrate] & fPowerMask[ich]);
  else return kFALSE;
}
//_________________________________________________________

TH2F *AliTOFTriggerMask::GetHistoMask() {
  TH2F *h = new TH2F("hTOFTriggerMask","TOF trigger mask;crate;MaxiPad",72,0,72,23,0,23);
  for(Int_t j=0;j<72;j++)
    for(Int_t i=22;i>=0;i--)
      h->SetBinContent(j+1,i+1,(fTriggerMask[j]%fPowerMask[i+1])/fPowerMask[i]);
  return h;
};
//_________________________________________________________
void AliTOFTriggerMask::ResetMask() {
  for (Int_t iddl = 0; iddl < 72; iddl++) fTriggerMask[iddl] = 0;
}
<commit_msg>Fixes for out-of-bounds read/write (Coverity 21070,21071)<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

// *
// *
// *
// * this class defines the TOF object to be stored
// * in OCDB on a run-by-run basis in order to have the status
// * of TOF trigger inputs. it stores 32 bit masks for each crate
// *
// *
// *
// *

#include "AliTOFTriggerMask.h"

Int_t AliTOFTriggerMask::fPowerMask[24];

ClassImp(AliTOFTriggerMask)
//_________________________________________________________

AliTOFTriggerMask::AliTOFTriggerMask() :
  TObject(),
  fTriggerMask()
{
  /*
   * default constructor
   */

  for (Int_t iddl = 0; iddl < 72; iddl++) fTriggerMask[iddl] = 0;

  fPowerMask[0] = 1;
  for(Int_t i=1;i <= 23;i++){
      fPowerMask[i] = fPowerMask[i-1]*2;
  }

}

//_________________________________________________________

AliTOFTriggerMask::~AliTOFTriggerMask()
{
  /*
   * default destructor
   */

}

//_________________________________________________________

AliTOFTriggerMask::AliTOFTriggerMask(const AliTOFTriggerMask &source) :
  TObject(source),
  fTriggerMask()
{
  /*
   * copy constructor
   */

  for (Int_t iddl = 0; iddl < 72; iddl++) fTriggerMask[iddl] = source.fTriggerMask[iddl];
}

//_________________________________________________________

AliTOFTriggerMask &
AliTOFTriggerMask::operator=(const AliTOFTriggerMask &source)
{
  /*
   * operator=
   */

  if (this == &source) return *this;
  TObject::operator=(source);

  for (Int_t iddl = 0; iddl < 72; iddl++) fTriggerMask[iddl] = source.fTriggerMask[iddl];

  return *this;
}

//_________________________________________________________

void
AliTOFTriggerMask::SetTriggerMaskArray(UInt_t *array)
{
  /*
   * set trigger mask array
   */

  for (Int_t iddl = 0; iddl < 72; iddl++) fTriggerMask[iddl] = array[iddl];
}
//_________________________________________________________

Int_t AliTOFTriggerMask::GetNumberMaxiPadOn() {
  Int_t n=0;
  for(Int_t j=0;j<72;j++)
    for(Int_t i=22;i>=0;i--)
      n += (fTriggerMask[j]%fPowerMask[i+1])/fPowerMask[i];
  return n;
};
//_________________________________________________________
void AliTOFTriggerMask::SetON(Int_t icrate,Int_t ich){
  if(ich < 24 && icrate < 72) fTriggerMask[icrate] += fPowerMask[ich];
}
//_________________________________________________________
Bool_t AliTOFTriggerMask::IsON(Int_t icrate,Int_t ich){
  if(ich < 24 && icrate < 72) return (fTriggerMask[icrate] & fPowerMask[ich]);
  else return kFALSE;
}
//_________________________________________________________

TH2F *AliTOFTriggerMask::GetHistoMask() {
  TH2F *h = new TH2F("hTOFTriggerMask","TOF trigger mask;crate;MaxiPad",72,0,72,23,0,23);
  for(Int_t j=0;j<72;j++)
    for(Int_t i=22;i>=0;i--)
      h->SetBinContent(j+1,i+1,(fTriggerMask[j]%fPowerMask[i+1])/fPowerMask[i]);
  return h;
};
//_________________________________________________________
void AliTOFTriggerMask::ResetMask() {
  for (Int_t iddl = 0; iddl < 72; iddl++) fTriggerMask[iddl] = 0;
}
<|endoftext|>


<commit_before>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Microsoft Corporation
 *
 * -=- Robust Distributed System Nucleus (rDSN) -=-
 *
 * 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.
 */

/*
 * Description:
 *     What is this file about?
 *
 * Revision history:
 *     xxxx-xx-xx, author, first version
 *     xxxx-xx-xx, author, fix bug about xxx
 */

#include "meta_server_failure_detector.h"
#include "server_state.h"
#include "meta_service.h"
#include <dsn/internal/factory_store.h>

# ifdef __TITLE__
# undef __TITLE__
# endif
# define __TITLE__ "meta.server.FD"

meta_server_failure_detector::meta_server_failure_detector(server_state* state, meta_service* svc)
{
    _is_primary = false;
    _state = state;
    _svc = svc;

    const char* distributed_lock_service_type = dsn_config_get_value_string(
        "meta_server",
        "distributed_lock_service_type",
        "distributed_lock_service_simple",
        "distributed_lock_service provider type"
        );
    const char* distributed_lock_service_parameters = dsn_config_get_value_string(
        "meta_server",
        "distributed_lock_service_parameters",
        "",
        "distributed_lock_service provider parameters"
        );

    // prepare parameters
    std::vector<std::string> args;
    dsn::utils::split_args(distributed_lock_service_parameters, args);
    int argc = static_cast<int>(args.size());
    std::vector<const char*> args_ptr;
    args_ptr.resize(argc);
    for (int i = argc - 1; i >= 0; i--)
    {
        args_ptr[i] = args[i].c_str();
    }

    // create lock service
    _lock_svc = dsn::utils::factory_store< ::dsn::dist::distributed_lock_service>::create(
        distributed_lock_service_type,
        PROVIDER_TYPE_MAIN
        );
    error_code err = _lock_svc->initialize(argc, argc > 0 ? &args_ptr[0] : nullptr);
    dassert(err == ERR_OK, "init distributed_lock_service failed, err = %s", err.to_string());
    _primary_lock_id = "dsn.meta.server.leader";

    ddebug("init meta_server_failure_detector succeed");
}

meta_server_failure_detector::~meta_server_failure_detector()
{
    auto t = _lock_grant_task;
    if (t) t->cancel(true);
    t = _lock_expire_task;
    if (t) t->cancel(true);

    if ( _lock_svc )
        delete _lock_svc;
}

void meta_server_failure_detector::on_worker_disconnected(const std::vector< ::dsn::rpc_address>& nodes)
{
    if (!is_primary())
    {
        return;
    }

    if (!_svc->_started)
    {
        for (auto& node: nodes)
            _state->remove_dead_node_from_cache(node);
        return;
    }

    node_states states;
    for (auto& n : nodes)
    {
        states.push_back(std::make_pair(n, false));
        dwarn("client expired: %s", n.to_string());
    }

    machine_fail_updates pris;
    _state->set_node_state(states, &pris);

    for (auto& pri : pris)
    {
        dinfo("%d.%d primary node for %s is gone, update configuration on meta server",
            pri.first.app_id,
            pri.first.pidx,
            pri.second->node.to_string()
            );
        _svc->update_configuration_on_machine_failure(pri.second);
    }
}

void meta_server_failure_detector::on_worker_connected(::dsn::rpc_address node)
{
    if (!is_primary())
    {
        return;
    }

    if (!_svc->_started)
    {
        _state->add_alive_node_to_cache(node);
        return;
    }
    node_states states;
    states.push_back(std::make_pair(node, true));

    dwarn("Client reconnected",
        "Client %s", node.to_string());

    _state->set_node_state(states, nullptr);
}

DEFINE_TASK_CODE(LPC_META_SERVER_LEADER_LOCK_CALLBACK, TASK_PRIORITY_COMMON, THREAD_POOL_FD)

void meta_server_failure_detector::acquire_leader_lock()
{
    //
    // try to get the leader lock until it is done
    //
    dsn::dist::distributed_lock_service::lock_options opt = {true, true};
    std::string local_owner_id;
    while (true)
    {
        error_code err;
        auto tasks =
            _lock_svc->lock(
            _primary_lock_id,
            primary_address().to_std_string(),
            // lock granted
            LPC_META_SERVER_LEADER_LOCK_CALLBACK,
            [this, &err, &local_owner_id](error_code ec, const std::string& owner, uint64_t version)
            {
                err = ec;
                local_owner_id = owner;
            },

            // lease expire
            LPC_META_SERVER_LEADER_LOCK_CALLBACK,
            [this](error_code ec, const std::string& owner, uint64_t version)
            {
                // let's take the easy way right now
                dsn_exit(0);
            },
            opt
        );

        _lock_grant_task = tasks.first;
        _lock_expire_task = tasks.second;

        _lock_grant_task->wait();
        if (err == ERR_OK)
        {
            rpc_address addr;
            if (addr.from_string_ipv4(local_owner_id.c_str()))
            {
                dassert(primary_address() == addr, "");
                set_primary(addr);
                break;
            }
        }
    }
}

void meta_server_failure_detector::sync_node_state_and_start_service()
{
    /*
     * we do need the failure_detector::_lock to protect,
     * because we want to keep the states of server_state::_nodes
     * and _cache_alive_nodes consistent
     */
    zauto_lock l(failure_detector::_lock);

    //first add new nodes to the server_state
    _state->apply_cache_nodes();

    //then we register all workers from server_state
    node_states alive_list;
    _state->get_node_state(alive_list);

    for(auto& node_pair: alive_list) {
        dassert(node_pair.second, "in initializing we don't add dead nodes to server_state");

        // a worker may have been dead in the fd, so we must reactive it
        unregister_worker(node_pair.first);
        register_worker(node_pair.first, true);
    }

    //now nodes in server_state and in fd are in consistent state
    _svc->start_load_balance();
}

void meta_server_failure_detector::set_primary(rpc_address primary)
{
    /*
    * we don't do register worker things in set_primary
    * as only nodes sync from meta_state_service are useful,
    * but currently, we haven't do sync yet
    */
    bool old = _is_primary;
    {
        utils::auto_lock<zlock> l(_primary_address_lock);
        _primary_address = primary;
        _is_primary = (primary == primary_address());
    }

    if (old && !_is_primary)
    {
        clear_workers();
    }
}

void meta_server_failure_detector::on_ping(const fd::beacon_msg& beacon, ::dsn::rpc_replier<fd::beacon_ack>& reply)
{
    fd::beacon_ack ack;
    ack.time = beacon.time;
    ack.this_node = beacon.to_addr;
    ack.allowed = true;

    if ( !is_primary() )
    {
        ack.is_master = false;
        ack.primary_node = get_primary();
    }
    else
    {
        ack.is_master = true;
        ack.primary_node = beacon.to_addr;
        failure_detector::on_ping_internal(beacon, ack);
    }

    dinfo("on_ping, is_master(%s), this_node(%s), primary_node(%s)", ack.is_master?"true":"false",
          ack.this_node.to_string(), ack.primary_node.to_string());
    reply(ack);
}

/*the following functions are only for test*/
meta_server_failure_detector::meta_server_failure_detector(rpc_address leader_address, bool is_myself_leader)
{
    _lock_svc = nullptr;
    _primary_address = leader_address;
    _is_primary = is_myself_leader;
}

void meta_server_failure_detector::set_leader_for_test(rpc_address leader_address, bool is_myself_leader)
{
    utils::auto_lock<zlock> l(_primary_address_lock);
    _primary_address = leader_address;
    _is_primary = is_myself_leader;
}

<commit_msg>bug fix in extensible_object & fd & delay<commit_after>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Microsoft Corporation
 *
 * -=- Robust Distributed System Nucleus (rDSN) -=-
 *
 * 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.
 */

/*
 * Description:
 *     What is this file about?
 *
 * Revision history:
 *     xxxx-xx-xx, author, first version
 *     xxxx-xx-xx, author, fix bug about xxx
 */

#include "meta_server_failure_detector.h"
#include "server_state.h"
#include "meta_service.h"
#include <dsn/internal/factory_store.h>

# ifdef __TITLE__
# undef __TITLE__
# endif
# define __TITLE__ "meta.server.FD"

meta_server_failure_detector::meta_server_failure_detector(server_state* state, meta_service* svc)
{
    _is_primary = false;
    _state = state;
    _svc = svc;

    const char* distributed_lock_service_type = dsn_config_get_value_string(
        "meta_server",
        "distributed_lock_service_type",
        "distributed_lock_service_simple",
        "distributed_lock_service provider type"
        );
    const char* distributed_lock_service_parameters = dsn_config_get_value_string(
        "meta_server",
        "distributed_lock_service_parameters",
        "",
        "distributed_lock_service provider parameters"
        );

    // prepare parameters
    std::vector<std::string> args;
    dsn::utils::split_args(distributed_lock_service_parameters, args);
    int argc = static_cast<int>(args.size());
    std::vector<const char*> args_ptr;
    args_ptr.resize(argc);
    for (int i = argc - 1; i >= 0; i--)
    {
        args_ptr[i] = args[i].c_str();
    }

    // create lock service
    _lock_svc = dsn::utils::factory_store< ::dsn::dist::distributed_lock_service>::create(
        distributed_lock_service_type,
        PROVIDER_TYPE_MAIN
        );
    error_code err = _lock_svc->initialize(argc, argc > 0 ? &args_ptr[0] : nullptr);
    dassert(err == ERR_OK, "init distributed_lock_service failed, err = %s", err.to_string());
    _primary_lock_id = "dsn.meta.server.leader";

    ddebug("init meta_server_failure_detector succeed");
}

meta_server_failure_detector::~meta_server_failure_detector()
{
    auto t = _lock_grant_task;
    if (t) t->cancel(true);
    t = _lock_expire_task;
    if (t) t->cancel(true);

    if ( _lock_svc )
        delete _lock_svc;
}

void meta_server_failure_detector::on_worker_disconnected(const std::vector< ::dsn::rpc_address>& nodes)
{
    if (!is_primary())
    {
        return;
    }

    if (!_svc->_started)
    {
        for (auto& node: nodes)
            _state->remove_dead_node_from_cache(node);
        return;
    }

    node_states states;
    for (auto& n : nodes)
    {
        states.push_back(std::make_pair(n, false));
        dwarn("client expired: %s", n.to_string());
    }

    machine_fail_updates pris;
    _state->set_node_state(states, &pris);

    for (auto& pri : pris)
    {
        dinfo("%d.%d primary node for %s is gone, update configuration on meta server",
            pri.first.app_id,
            pri.first.pidx,
            pri.second->node.to_string()
            );
        _svc->update_configuration_on_machine_failure(pri.second);
    }
}

void meta_server_failure_detector::on_worker_connected(::dsn::rpc_address node)
{
    if (!is_primary())
    {
        return;
    }

    if (!_svc->_started)
    {
        _state->add_alive_node_to_cache(node);
        return;
    }
    node_states states;
    states.push_back(std::make_pair(node, true));

    dwarn("Client reconnected",
        "Client %s", node.to_string());

    _state->set_node_state(states, nullptr);
}

DEFINE_TASK_CODE(LPC_META_SERVER_LEADER_LOCK_CALLBACK, TASK_PRIORITY_COMMON, THREAD_POOL_FD)

void meta_server_failure_detector::acquire_leader_lock()
{
    //
    // try to get the leader lock until it is done
    //
    dsn::dist::distributed_lock_service::lock_options opt = {true, true};
    std::string local_owner_id;
    while (true)
    {
        error_code err;
        auto tasks =
            _lock_svc->lock(
            _primary_lock_id,
            primary_address().to_std_string(),
            // lock granted
            LPC_META_SERVER_LEADER_LOCK_CALLBACK,
            [this, &err, &local_owner_id](error_code ec, const std::string& owner, uint64_t version)
            {
                err = ec;
                local_owner_id = owner;
            },

            // lease expire
            LPC_META_SERVER_LEADER_LOCK_CALLBACK,
            [this](error_code ec, const std::string& owner, uint64_t version)
            {
                // let's take the easy way right now
                dsn_exit(0);
            },
            opt
        );

        _lock_grant_task = tasks.first;
        _lock_expire_task = tasks.second;

        _lock_grant_task->wait();
        if (err == ERR_OK)
        {
            rpc_address addr;
            if (addr.from_string_ipv4(local_owner_id.c_str()))
            {
                dassert(primary_address() == addr, "");
                set_primary(addr);
                break;
            }
        }
    }
}

void meta_server_failure_detector::sync_node_state_and_start_service()
{
    /*
     * we do need the failure_detector::_lock to protect,
     * because we want to keep the states of server_state::_nodes
     * and _cache_alive_nodes consistent
     */
    zauto_lock l(failure_detector::_lock);

    //first add new nodes to the server_state
    _state->apply_cache_nodes();

    //then we register all workers from server_state
    node_states alive_list;
    _state->get_node_state(alive_list);

    for(auto& node_pair: alive_list) {
        dassert(node_pair.second, "in initializing we don't add dead nodes to server_state");

        // a worker may have been dead in the fd, so we must reactive it
        unregister_worker(node_pair.first);
        register_worker(node_pair.first, true);
    }

    //now nodes in server_state and in fd are in consistent state
    _svc->start_load_balance();
}

void meta_server_failure_detector::set_primary(rpc_address primary)
{
    /*
    * we don't do register worker things in set_primary
    * as only nodes sync from meta_state_service are useful,
    * but currently, we haven't do sync yet
    */
    bool old = _is_primary;
    {
        utils::auto_lock<zlock> l(_primary_address_lock);
        _primary_address = primary;
        _is_primary = (primary == primary_address());
    }

    if (old && !_is_primary)
    {
        clear_workers();
    }
}

void meta_server_failure_detector::on_ping(const fd::beacon_msg& beacon, ::dsn::rpc_replier<fd::beacon_ack>& reply)
{
    fd::beacon_ack ack;
    ack.time = beacon.time;
    ack.this_node = beacon.to_addr;
    ack.allowed = true;

    if ( !is_primary() )
    {
        ack.is_master = false;
        ack.primary_node = get_primary();
        {
            zauto_lock l(_lock);
            _state->add_alive_node_to_cache(beacon.from_addr);
        }
    }
    else
    {
        ack.is_master = true;
        ack.primary_node = beacon.to_addr;
        failure_detector::on_ping_internal(beacon, ack);
    }

    dinfo("on_ping, is_master(%s), from_node(%s), this_node(%s), primary_node(%s)", ack.is_master?"true":"false",
          beacon.from_addr.to_string(), ack.this_node.to_string(), ack.primary_node.to_string());
    reply(ack);
}

/*the following functions are only for test*/
meta_server_failure_detector::meta_server_failure_detector(rpc_address leader_address, bool is_myself_leader)
{
    _lock_svc = nullptr;
    _primary_address = leader_address;
    _is_primary = is_myself_leader;
    _state = new server_state();
}

void meta_server_failure_detector::set_leader_for_test(rpc_address leader_address, bool is_myself_leader)
{
    utils::auto_lock<zlock> l(_primary_address_lock);
    _primary_address = leader_address;
    _is_primary = is_myself_leader;
    _state = new server_state();
}

<|endoftext|>


<commit_before>#include "Process.hpp"

void Process::initFileNamePath()
{
	if (this->handle == NULL)
	{
		this->name = NULL;
		this->path = NULL;
		return;
	}

	int nResult = 1;

	TCHAR szProcessPath[MAX_PATH];
	TCHAR szProcessName[MAX_PATH];

	if (this->handle != NULL)
	{
		HMODULE hMod;
		DWORD cbNeeded;

		if (!EnumProcessModulesEx(this->handle, &hMod, sizeof(hMod), &cbNeeded, LIST_MODULES_ALL))
			nResult = -1;

		// Get Process Path
		if (GetModuleFileNameEx(this->handle, hMod, szProcessPath, sizeof(szProcessPath) / sizeof(TCHAR)) == 0)
			nResult = -2;

		// Get Process Name
		if (GetModuleBaseName(this->handle, hMod, szProcessName, sizeof(szProcessName) / sizeof(TCHAR)) == 0)
			nResult = -3;
	}
	else
		nResult = -4;

	if (nResult != 1)
		return;

	this->name = new TCHAR[MAX_PATH];
	this->path = new TCHAR[MAX_PATH];
	memset(this->name, NULL, MAX_PATH);
	memset(this->path, NULL, MAX_PATH);
	strcpy_s(this->name, MAX_PATH, szProcessName);
	strcpy_s(this->path, MAX_PATH, szProcessPath);
}

void Process::initCommandLine()
{
	if (this->handle == NULL)
		return;

	int nResult = 1;
	PVOID pebAddress;
	PVOID rtlUserProcParamsAddress;
	UNICODE_STRING commandLine;

	_NtQueryInformationProcess NtQueryInformationProcess = (_NtQueryInformationProcess)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryInformationProcess");
	PROCESS_BASIC_INFORMATION processBasicInformation;
	NtQueryInformationProcess(this->handle, 0, &processBasicInformation, sizeof(processBasicInformation), NULL);
	pebAddress = processBasicInformation.PebBaseAddress;

	if (!ReadProcessMemory(this->handle, &(((_PEB*)pebAddress)->ProcessParameters), &rtlUserProcParamsAddress, sizeof(PVOID), NULL))
		nResult = -1;

	if (!ReadProcessMemory(this->handle, &(((_RTL_USER_PROCESS_PARAMETERS*)rtlUserProcParamsAddress)->CommandLine), &commandLine, sizeof(commandLine), NULL))
		nResult = -2;

	TCHAR *commandLineContents = new TCHAR[commandLine.Length];
	if (!ReadProcessMemory(this->handle, commandLine.Buffer, commandLineContents, commandLine.Length, NULL))
		nResult = -3;

	int size = commandLine.Length / 2;
	TCHAR *strCommandLine = new TCHAR[size + 1];
	memset(strCommandLine, NULL, size + 1);

	// char <-> w_char compatibility
	for (int i = 0; i < commandLine.Length; i++)
	{
		if (commandLineContents[i] != NULL)
			strCommandLine[i / 2] = commandLineContents[i];
	}

	if (commandLineContents)
	{
		delete[] commandLineContents;
		commandLineContents = nullptr;
	}

	if (nResult != 1)
		return;
	//	throw nResult;

	this->commandLine = strCommandLine;
}

void Process::initOwner()
{
	if (this->handle == NULL)
	{
		this->owner = NULL;
		return;
	}

	int nResult = 1;

	HANDLE tokenHandle = 0;
	TCHAR name[MAX_PATH], dom[MAX_PATH], tubuf[MAX_PATH];
	DWORD nlen = MAX_PATH, dlen = MAX_PATH;
	TOKEN_USER *tokenUser = (TOKEN_USER*)tubuf;

	//open the processes token
	if (!OpenProcessToken(this->handle, TOKEN_QUERY, &tokenHandle))
		nResult = -1;

	//get the SID of the token
	if (!GetTokenInformation(tokenHandle, TokenUser, tokenUser, MAX_PATH, &nlen))
		nResult = -2;

	// domain name of the SID
	int iUse;
	if (!LookupAccountSidA(0, tokenUser->User.Sid, name, &nlen, dom, &dlen, (PSID_NAME_USE)&iUse))
		nResult = -3;

	int len = dlen + nlen + 2; // Last Null char + '/'
	this->owner = new TCHAR[len];
	memset(this->owner, NULL, len);

	// copy info to our static buffer
	strcpy_s(this->owner, len, dom);
	strcat_s(this->owner, len, "/");
	strcat_s(this->owner, len, name);

	if (tokenHandle)
		CloseHandle(tokenHandle);
}

void Process::initCreateTime()
{
	FILETIME createTime, exitTime, kernelTime, userTime;
	FILETIME localFileTime;
	SYSTEMTIME sysTime;

	GetProcessTimes(this->handle, &createTime, &exitTime, &kernelTime, &userTime);
	FileTimeToLocalFileTime(&createTime, &localFileTime);
	FileTimeToSystemTime(&localFileTime, &sysTime);

	struct tm tmTime = { 0 };
	tmTime.tm_year = sysTime.wYear - 1900;
	tmTime.tm_mon = sysTime.wMonth - 1;
	tmTime.tm_mday = sysTime.wDay;
	tmTime.tm_hour = sysTime.wHour;
	tmTime.tm_min = sysTime.wMinute;
	tmTime.tm_sec = sysTime.wSecond;
	tmTime.tm_wday = 0;
	tmTime.tm_yday = 0;
	tmTime.tm_isdst = -1;

	this->createTime = tmTime;
}

HWND Process::getHwndFromPid()
{
	HWND hWnd = FindWindow(NULL, NULL);
	while (hWnd != NULL)
	{
		if (GetParent(hWnd) == NULL) {
			DWORD dwProcId;
			GetWindowThreadProcessId(hWnd, &dwProcId);

			if (this->pid == dwProcId)
				return hWnd;
		}
		hWnd = GetWindow(hWnd, GW_HWNDNEXT);
	}
	return NULL;
}

// When you are finished with the handle, be sure to close it using the CloseHandle function.
HANDLE Process::getHandleFromPid()
{
	HANDLE handle;
	if ((handle = OpenProcess(MAXIMUM_ALLOWED, false, this->pid)) == NULL)
		return NULL;

	return handle;
}

DWORD Process::getPid()
{
	return this->pid;
}

TCHAR * Process::getName()
{
	if (this->name)
		return this->name;
	else
		return "";
}

TCHAR * Process::getPath()
{
	if (this->path)
		return this->path;
	else
		return "";
}

TCHAR * Process::getCommandLine()
{
	if (this->commandLine)
		return this->commandLine;
	else
		return "";
}

TCHAR * Process::getOwner()
{
	if (this->owner)
		return this->owner;
	else
		return "";
}

HICON Process::getIcon(BOOLEAN LargeIcon)
{
	/*
		Get High Resolution ICON
		Vista and higer, 256 * 256
		lower 48 * 48
	*/

	SHFILEINFO sfi;
	if (!SHGetFileInfo(this->path, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX))
		return NULL;

	// Retrieve the system image list.
	// To get the 48x48 icons, use SHIL_EXTRALARGE
	// To get the 256x256 icons (Vista only), use SHIL_JUMBO
	HIMAGELIST* imageList;
	if (SHGetImageList(SHIL_JUMBO, IID_IImageList, (void**)&imageList) != S_OK)
		return NULL;

	// Get the icon we need from the list. Note that the HIMAGELIST we retrieved
	// earlier needs to be casted to the IImageList interface before use.
	HICON hIcon;
	HRESULT hResult = ((IImageList*)imageList)->GetIcon(sfi.iIcon, ILD_TRANSPARENT, &hIcon);

	if (hResult == S_OK)
		return hIcon;

	return NULL;
}

BOOLEAN Process::isRunning()
{
	DWORD_PTR dw = 0;
	HWND hWnd = getHwndFromPid();

	// TimeOut 2sec
	if (SendMessageTimeout(hWnd, NULL, NULL, NULL, SMTO_NORMAL, 2000, &dw))
	{
		return TRUE; // process is running
	}
	else
	{
		if (GetLastError() == ERROR_TIMEOUT) {
			return FALSE; // process is not responsed
		}
	}
	return TRUE;
}

int Process::getHandleCount(DWORD &val)
{
	DWORD pCount;

	if (GetProcessHandleCount(this->handle, &pCount) == 0)
		return 0;

	val = pCount;

	return 1;
}

int Process::getNetworkUsage(double &val)
{
	// TODO :
	return 1;
}

/*
	val = kbyte
	Not working properly in operate on 64bit system
*/
int Process::getMemoryUsage(DWORD &val)
{
	/*#if _WIN32 || _WIN64
	#if _WIN64
		// TODO : 64Bit Compile
	#else
		// TODO : 32Bit Compile
	#endif
	#endif*/

	DWORD workingSetPages[1024 * 128]; // 512KB
	DWORD pageSize = 0x1000;

	DWORD sharedPages = 0;
	DWORD privatePages = 0;
	DWORD pageTablePages = 0;

	if (this->handle == NULL)
		return -1;

	if (!QueryWorkingSet(this->handle, workingSetPages, sizeof(workingSetPages)))
		return -2;

	DWORD pages = workingSetPages[0];
	qsort(&workingSetPages[1], pages, sizeof(DWORD), Compare);

	for (DWORD i = 1; i <= pageSize; i++)
	{
		DWORD currentPageStatus = 0;
		DWORD currentPageAddress;
		DWORD nextPageAddress;
		DWORD nextPageFlags;
		ULONGLONG pageAddress = workingSetPages[i] & 0xFFFFF000;
		ULONGLONG pageFlags = workingSetPages[i] & 0x00000FFF;

		while (i <= pages) // iterate all pages
		{
			currentPageStatus++;

			if (i == pages) //if last page
				break;

			currentPageAddress = workingSetPages[i] & 0xFFFFF000;
			nextPageAddress = workingSetPages[i + 1] & 0xFFFFF000;
			nextPageFlags = workingSetPages[i + 1] & 0x00000FFF;

			//decide whether iterate further or exit
			//(this is non-contiguous page or have different flags)
			if ((nextPageAddress == (currentPageAddress + pageSize)) && (nextPageFlags == pageFlags))
				i++;
			else
				break;
		}

		if ((pageAddress < 0xC0000000) || (pageAddress > 0xE0000000))
		{
			if (pageFlags & 0x100) // this is shared one
				sharedPages += currentPageStatus;

			else // private one
				privatePages += currentPageStatus;
		}
		else
			pageTablePages += currentPageStatus; //page table region
	}

	DWORD totalMemory = pages * 4;
	DWORD sharedMemory = sharedPages * 4;
	DWORD privateMemory = totalMemory - sharedMemory;

	val = privateMemory; //ref

	return 1;
}

int Process::getCpuUsage(double &val)
{
	int nResult = 1;

	ULONGLONG LastCycleTime = NULL;
	LARGE_INTEGER LastPCounter;
	LastPCounter.QuadPart = 0; // LARGE_INTEGER Init

							   // cpu get core number
	SYSTEM_INFO sysInfo;
	GetSystemInfo(&sysInfo);
	int numProcessors = sysInfo.dwNumberOfProcessors;

	int count = 0;
	while (true)
	{
		ULONG64	CycleTime;
		LARGE_INTEGER qpcLastInt;

		if (!QueryProcessCycleTime(this->handle, &CycleTime))
			nResult = 0;

		ULONG64 cycle = CycleTime - LastCycleTime;

		if (!QueryPerformanceCounter(&qpcLastInt))
			nResult = 0;

		double Usage = cycle / ((double)(qpcLastInt.QuadPart - LastPCounter.QuadPart));

		// Scaling
		Usage *= 1.0 / numProcessors;
		Usage *= 0.1;

		LastPCounter = qpcLastInt;
		LastCycleTime = CycleTime;

		if (count >= 2)
		{
			val = Usage;
			break;
		}

		Util::microDelay(30); // QueryPerformanceCounter Function Resolution is 1 microsecond

		count++;
	}

	return nResult;
}

int Compare(const void * val1, const void * val2)
{
	if (*(PDWORD)val1 == *(PDWORD)val2)
		return 0;

	return *(PDWORD)val1 > *(PDWORD)val2 ? 1 : -1;
}<commit_msg>:hammer: Code refactoring, :ambulance: Memory Leak Solved<commit_after>#include "Process.hpp"

void Process::initFileNamePath()
{
	if (this->handle == NULL)
	{
		this->name = NULL;
		this->path = NULL;
		return;
	}

	int nResult = 1;

	TCHAR szProcessPath[MAX_PATH];
	TCHAR szProcessName[MAX_PATH];

	if (this->handle != NULL)
	{
		HMODULE hMod;
		DWORD cbNeeded;

		if (!EnumProcessModulesEx(this->handle, &hMod, sizeof(hMod), &cbNeeded, LIST_MODULES_ALL))
			nResult = -1;

		// Get Process Path
		if (GetModuleFileNameEx(this->handle, hMod, szProcessPath, sizeof(szProcessPath) / sizeof(TCHAR)) == 0)
			nResult = -2;

		// Get Process Name
		if (GetModuleBaseName(this->handle, hMod, szProcessName, sizeof(szProcessName) / sizeof(TCHAR)) == 0)
			nResult = -3;
	}
	else
		nResult = -4;

	if (nResult != 1)
		return;

	this->name = new TCHAR[MAX_PATH];
	this->path = new TCHAR[MAX_PATH];
	memset(this->name, NULL, MAX_PATH);
	memset(this->path, NULL, MAX_PATH);
	strcpy_s(this->name, MAX_PATH, szProcessName);
	strcpy_s(this->path, MAX_PATH, szProcessPath);
}

void Process::initCommandLine()
{
	if (this->handle == NULL)
		return;

	int nResult = 1;
	PVOID pebAddress;
	PVOID rtlUserProcParamsAddress;
	UNICODE_STRING commandLine;

	_NtQueryInformationProcess NtQueryInformationProcess = (_NtQueryInformationProcess)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryInformationProcess");
	PROCESS_BASIC_INFORMATION processBasicInformation;
	NtQueryInformationProcess(this->handle, 0, &processBasicInformation, sizeof(processBasicInformation), NULL);
	pebAddress = processBasicInformation.PebBaseAddress;

	if (!ReadProcessMemory(this->handle, &(((_PEB*)pebAddress)->ProcessParameters), &rtlUserProcParamsAddress, sizeof(PVOID), NULL))
		nResult = -1;

	if (!ReadProcessMemory(this->handle, &(((_RTL_USER_PROCESS_PARAMETERS*)rtlUserProcParamsAddress)->CommandLine), &commandLine, sizeof(commandLine), NULL))
		nResult = -2;

	TCHAR *commandLineContents = new TCHAR[commandLine.Length];
	if (!ReadProcessMemory(this->handle, commandLine.Buffer, commandLineContents, commandLine.Length, NULL))
		nResult = -3;

	if (nResult == 1)
	{
		int size = (commandLine.Length / 2) + 1; // Last Null Char
		this->commandLine = new TCHAR[size];
		memset(this->commandLine, NULL, size);

		// char <-> w_char compatibility
		for (int i = 0; i < commandLine.Length; i++)
		{
			if (commandLineContents[i] != NULL)
				this->commandLine[i / 2] = commandLineContents[i];
		}
	}

	if (commandLineContents)
	{
		delete[] commandLineContents;
		commandLineContents = nullptr;
	}
}

void Process::initOwner()
{
	if (this->handle == NULL)
	{
		this->owner = NULL;
		return;
	}

	int nResult = 1;

	HANDLE tokenHandle = 0;
	TCHAR name[MAX_PATH], dom[MAX_PATH], tubuf[MAX_PATH];
	DWORD nlen = MAX_PATH, dlen = MAX_PATH;
	TOKEN_USER *tokenUser = (TOKEN_USER*)tubuf;

	//open the processes token
	if (!OpenProcessToken(this->handle, TOKEN_QUERY, &tokenHandle))
		nResult = -1;

	//get the SID of the token
	if (!GetTokenInformation(tokenHandle, TokenUser, tokenUser, MAX_PATH, &nlen))
		nResult = -2;

	// domain name of the SID
	int iUse;
	if (!LookupAccountSidA(0, tokenUser->User.Sid, name, &nlen, dom, &dlen, (PSID_NAME_USE)&iUse))
		nResult = -3;

	int len = dlen + nlen + 2; // Last Null char + '/'
	this->owner = new TCHAR[len];
	memset(this->owner, NULL, len);

	// copy info to our static buffer
	strcpy_s(this->owner, len, dom);
	strcat_s(this->owner, len, "/");
	strcat_s(this->owner, len, name);

	if (tokenHandle)
		CloseHandle(tokenHandle);
}

void Process::initCreateTime()
{
	FILETIME createTime, exitTime, kernelTime, userTime;
	FILETIME localFileTime;
	SYSTEMTIME sysTime;

	GetProcessTimes(this->handle, &createTime, &exitTime, &kernelTime, &userTime);
	FileTimeToLocalFileTime(&createTime, &localFileTime);
	FileTimeToSystemTime(&localFileTime, &sysTime);

	struct tm tmTime = { 0 };
	tmTime.tm_year = sysTime.wYear - 1900;
	tmTime.tm_mon = sysTime.wMonth - 1;
	tmTime.tm_mday = sysTime.wDay;
	tmTime.tm_hour = sysTime.wHour;
	tmTime.tm_min = sysTime.wMinute;
	tmTime.tm_sec = sysTime.wSecond;
	tmTime.tm_wday = 0;
	tmTime.tm_yday = 0;
	tmTime.tm_isdst = -1;

	this->createTime = tmTime;
}

HWND Process::getHwndFromPid()
{
	HWND hWnd = FindWindow(NULL, NULL);
	while (hWnd != NULL)
	{
		if (GetParent(hWnd) == NULL) {
			DWORD dwProcId;
			GetWindowThreadProcessId(hWnd, &dwProcId);

			if (this->pid == dwProcId)
				return hWnd;
		}
		hWnd = GetWindow(hWnd, GW_HWNDNEXT);
	}
	return NULL;
}

// When you are finished with the handle, be sure to close it using the CloseHandle function.
HANDLE Process::getHandleFromPid()
{
	HANDLE handle;
	if ((handle = OpenProcess(MAXIMUM_ALLOWED, false, this->pid)) == NULL)
		return NULL;

	return handle;
}

DWORD Process::getPid()
{
	return this->pid;
}

TCHAR * Process::getName()
{
	if (this->name)
		return this->name;
	else
		return "";
}

TCHAR * Process::getPath()
{
	if (this->path)
		return this->path;
	else
		return "";
}

TCHAR * Process::getCommandLine()
{
	if (this->commandLine)
		return this->commandLine;
	else
		return "";
}

TCHAR * Process::getOwner()
{
	if (this->owner)
		return this->owner;
	else
		return "";
}

HICON Process::getIcon(BOOLEAN LargeIcon)
{
	/*
		Get High Resolution ICON
		Vista and higer, 256 * 256
		lower 48 * 48
	*/

	SHFILEINFO sfi;
	if (!SHGetFileInfo(this->path, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX))
		return NULL;

	// Retrieve the system image list.
	// To get the 48x48 icons, use SHIL_EXTRALARGE
	// To get the 256x256 icons (Vista only), use SHIL_JUMBO
	HIMAGELIST* imageList;
	if (SHGetImageList(SHIL_JUMBO, IID_IImageList, (void**)&imageList) != S_OK)
		return NULL;

	// Get the icon we need from the list. Note that the HIMAGELIST we retrieved
	// earlier needs to be casted to the IImageList interface before use.
	HICON hIcon;
	HRESULT hResult = ((IImageList*)imageList)->GetIcon(sfi.iIcon, ILD_TRANSPARENT, &hIcon);

	if (hResult == S_OK)
		return hIcon;

	return NULL;
}

BOOLEAN Process::isRunning()
{
	DWORD_PTR dw = 0;
	HWND hWnd = getHwndFromPid();

	// TimeOut 2sec
	if (SendMessageTimeout(hWnd, NULL, NULL, NULL, SMTO_NORMAL, 2000, &dw))
	{
		return TRUE; // process is running
	}
	else
	{
		if (GetLastError() == ERROR_TIMEOUT) {
			return FALSE; // process is not responsed
		}
	}
	return TRUE;
}

int Process::getHandleCount(DWORD &val)
{
	DWORD pCount;

	if (GetProcessHandleCount(this->handle, &pCount) == 0)
		return 0;

	val = pCount;

	return 1;
}

int Process::getNetworkUsage(double &val)
{
	// TODO :
	return 1;
}

/*
	val = kbyte
	Not working properly in operate on 64bit system
*/
int Process::getMemoryUsage(DWORD &val)
{
	/*#if _WIN32 || _WIN64
	#if _WIN64
		// TODO : 64Bit Compile
	#else
		// TODO : 32Bit Compile
	#endif
	#endif*/

	DWORD workingSetPages[1024 * 128]; // 512KB
	DWORD pageSize = 0x1000;

	DWORD sharedPages = 0;
	DWORD privatePages = 0;
	DWORD pageTablePages = 0;

	if (this->handle == NULL)
		return -1;

	if (!QueryWorkingSet(this->handle, workingSetPages, sizeof(workingSetPages)))
		return -2;

	DWORD pages = workingSetPages[0];
	qsort(&workingSetPages[1], pages, sizeof(DWORD), Compare);

	for (DWORD i = 1; i <= pageSize; i++)
	{
		DWORD currentPageStatus = 0;
		DWORD currentPageAddress;
		DWORD nextPageAddress;
		DWORD nextPageFlags;
		ULONGLONG pageAddress = workingSetPages[i] & 0xFFFFF000;
		ULONGLONG pageFlags = workingSetPages[i] & 0x00000FFF;

		while (i <= pages) // iterate all pages
		{
			currentPageStatus++;

			if (i == pages) //if last page
				break;

			currentPageAddress = workingSetPages[i] & 0xFFFFF000;
			nextPageAddress = workingSetPages[i + 1] & 0xFFFFF000;
			nextPageFlags = workingSetPages[i + 1] & 0x00000FFF;

			//decide whether iterate further or exit
			//(this is non-contiguous page or have different flags)
			if ((nextPageAddress == (currentPageAddress + pageSize)) && (nextPageFlags == pageFlags))
				i++;
			else
				break;
		}

		if ((pageAddress < 0xC0000000) || (pageAddress > 0xE0000000))
		{
			if (pageFlags & 0x100) // this is shared one
				sharedPages += currentPageStatus;

			else // private one
				privatePages += currentPageStatus;
		}
		else
			pageTablePages += currentPageStatus; //page table region
	}

	DWORD totalMemory = pages * 4;
	DWORD sharedMemory = sharedPages * 4;
	DWORD privateMemory = totalMemory - sharedMemory;

	val = privateMemory; //ref

	return 1;
}

int Process::getCpuUsage(double &val)
{
	int nResult = 1;

	ULONGLONG LastCycleTime = NULL;
	LARGE_INTEGER LastPCounter;
	LastPCounter.QuadPart = 0; // LARGE_INTEGER Init

							   // cpu get core number
	SYSTEM_INFO sysInfo;
	GetSystemInfo(&sysInfo);
	int numProcessors = sysInfo.dwNumberOfProcessors;

	int count = 0;
	while (true)
	{
		ULONG64	CycleTime;
		LARGE_INTEGER qpcLastInt;

		if (!QueryProcessCycleTime(this->handle, &CycleTime))
			nResult = 0;

		ULONG64 cycle = CycleTime - LastCycleTime;

		if (!QueryPerformanceCounter(&qpcLastInt))
			nResult = 0;

		double Usage = cycle / ((double)(qpcLastInt.QuadPart - LastPCounter.QuadPart));

		// Scaling
		Usage *= 1.0 / numProcessors;
		Usage *= 0.1;

		LastPCounter = qpcLastInt;
		LastCycleTime = CycleTime;

		if (count >= 2)
		{
			val = Usage;
			break;
		}

		Util::microDelay(30); // QueryPerformanceCounter Function Resolution is 1 microsecond

		count++;
	}

	return nResult;
}

int Compare(const void * val1, const void * val2)
{
	if (*(PDWORD)val1 == *(PDWORD)val2)
		return 0;

	return *(PDWORD)val1 > *(PDWORD)val2 ? 1 : -1;
}<|endoftext|>


<commit_before>#ifndef MJOLNIR_POTENTIAL_GLOBAL_3SPN2_COMMON_HPP
#define MJOLNIR_POTENTIAL_GLOBAL_3SPN2_COMMON_HPP
#include <cstdint>

namespace mjolnir
{
namespace parameter_3SPN2
{
enum class bead_kind: std::uint8_t
{
    Phosphate, Sugar, BaseA, BaseT, BaseG, BaseC, Unknown
};

// X is for default parameter
enum class base_kind       : std::uint8_t {A=0, T=1, G=2, C=3,  X};
enum class base_pair_kind  : std::uint8_t {AT, TA, GC, CG};
enum class base_stack_kind : std::uint8_t
{
    AA =  0, AT =  1, AG =  2, AC =  3,
    TA =  4, TT =  5, TG =  6, TC =  7,
    GA =  8, GT =  9, GG = 10, GC = 11,
    CA = 12, CT = 13, CG = 14, CC = 15
};
enum class cross_stack_kind: std::uint8_t
{
    //       Si   Bi   Bj   Sj
    //  5'    o -- o===o -- o     3'
    //  ^    /      \ /      \    |
    //  | P o        x        o P |
    //  |    \      / \      /    v
    //  3'    o -- o===o -- o     5'
    //           Bi3   Bj5
    //
    // sense 5 -- antisense 5 (Bi - Bj5)
    AA5 =  0, AT5 =  1, AG5 =  2, AC5 =  3,
    TA5 =  4, TT5 =  5, TG5 =  6, TC5 =  7,
    GA5 =  8, GT5 =  9, GG5 = 10, GC5 = 11,
    CA5 = 12, CT5 = 13, CG5 = 14, CC5 = 15,
    // sense 3 -- antisense 3 (Bj - Bi3)
    AA3 = 16, AT3 = 17, AG3 = 18, AC3 = 19,
    TA3 = 20, TT3 = 21, TG3 = 22, TC3 = 23,
    GA3 = 24, GT3 = 25, GG3 = 26, GC3 = 27,
    CA3 = 28, CT3 = 29, CG3 = 30, CC3 = 31
};

} // 3SPN2
} // mjolnir
#endif// MJOLNIR_POTENTIAL_GLOBAL_3SPN2_COMMON_HPP
<commit_msg>feat: enable to output enums for logging<commit_after>#ifndef MJOLNIR_POTENTIAL_GLOBAL_3SPN2_COMMON_HPP
#define MJOLNIR_POTENTIAL_GLOBAL_3SPN2_COMMON_HPP
#include <cstdint>

namespace mjolnir
{
namespace parameter_3SPN2
{

enum class bead_kind: std::uint8_t
{
    Phosphate, Sugar, BaseA, BaseT, BaseG, BaseC, Unknown
};

// X is for default parameter
enum class base_kind       : std::uint8_t {A=0, T=1, G=2, C=3, X};
enum class base_pair_kind  : std::uint8_t {AT, TA, GC, CG};
enum class base_stack_kind : std::uint8_t
{
    AA =  0, AT =  1, AG =  2, AC =  3,
    TA =  4, TT =  5, TG =  6, TC =  7,
    GA =  8, GT =  9, GG = 10, GC = 11,
    CA = 12, CT = 13, CG = 14, CC = 15
};
enum class cross_stack_kind: std::uint8_t
{
    //       Si   Bi   Bj   Sj
    //  5'    o -- o===o -- o     3'
    //  ^    /      \ /      \    |
    //  | P o        x        o P |
    //  |    \      / \      /    v
    //  3'    o -- o===o -- o     5'
    //           Bi3   Bj5
    //
    // sense 5 -- antisense 5 (Bi - Bj5)
    AA5 =  0, AT5 =  1, AG5 =  2, AC5 =  3,
    TA5 =  4, TT5 =  5, TG5 =  6, TC5 =  7,
    GA5 =  8, GT5 =  9, GG5 = 10, GC5 = 11,
    CA5 = 12, CT5 = 13, CG5 = 14, CC5 = 15,
    // sense 3 -- antisense 3 (Bj - Bi3)
    AA3 = 16, AT3 = 17, AG3 = 18, AC3 = 19,
    TA3 = 20, TT3 = 21, TG3 = 22, TC3 = 23,
    GA3 = 24, GT3 = 25, GG3 = 26, GC3 = 27,
    CA3 = 28, CT3 = 29, CG3 = 30, CC3 = 31
};

template<typename charT, typename traitsT>
std::basic_ostream<charT, traitsT>&
operator<<(std::basic_ostream<charT, traitsT>& os, const bead_kind bk)
{
    switch(bk)
    {
        case bead_kind::Phosphate: {os << "Phosphate"; return os;}
        case bead_kind::Sugar:     {os << "Sugar"    ; return os;}
        case bead_kind::BaseA:     {os << "BaseA"    ; return os;}
        case bead_kind::BaseT:     {os << "BaseT"    ; return os;}
        case bead_kind::BaseG:     {os << "BaseG"    ; return os;}
        case bead_kind::BaseC:     {os << "BaseC"    ; return os;}
        case bead_kind::Unknown:   {os << "Unknown"  ; return os;}
        default:        {os << "invalid"  ; return os;}
    }
}
template<typename charT, typename traitsT>
std::basic_ostream<charT, traitsT>&
operator<<(std::basic_ostream<charT, traitsT>& os, const base_kind bk)
{
    switch(bk)
    {
        case base_kind::A: {os << "A"; return os;}
        case base_kind::T: {os << "T"; return os;}
        case base_kind::G: {os << "G"; return os;}
        case base_kind::C: {os << "C"; return os;}
        case base_kind::X: {os << "X"; return os;}
        default:{os << "invalid"; return os;}
    }
}
template<typename charT, typename traitsT>
std::basic_ostream<charT, traitsT>&
operator<<(std::basic_ostream<charT, traitsT>& os, const base_pair_kind bk)
{
    switch(bk)
    {
        case base_pair_kind::AT: {os << "AT"; return os;}
        case base_pair_kind::TA: {os << "TA"; return os;}
        case base_pair_kind::GC: {os << "GC"; return os;}
        case base_pair_kind::CG: {os << "CG"; return os;}
        default: {os << "invalid"; return os;}
    }
}
template<typename charT, typename traitsT>
std::basic_ostream<charT, traitsT>&
operator<<(std::basic_ostream<charT, traitsT>& os, const base_stack_kind bs)
{
    switch(bs)
    {
        case base_stack_kind::AA: {os << "AA"; return os;}
        case base_stack_kind::AT: {os << "AT"; return os;}
        case base_stack_kind::AG: {os << "AG"; return os;}
        case base_stack_kind::AC: {os << "AC"; return os;}

        case base_stack_kind::TA: {os << "TA"; return os;}
        case base_stack_kind::TT: {os << "TT"; return os;}
        case base_stack_kind::TG: {os << "TG"; return os;}
        case base_stack_kind::TC: {os << "TC"; return os;}

        case base_stack_kind::GA: {os << "GA"; return os;}
        case base_stack_kind::GT: {os << "GT"; return os;}
        case base_stack_kind::GG: {os << "GG"; return os;}
        case base_stack_kind::GC: {os << "GC"; return os;}

        case base_stack_kind::CA: {os << "CA"; return os;}
        case base_stack_kind::CT: {os << "CT"; return os;}
        case base_stack_kind::CG: {os << "CG"; return os;}
        case base_stack_kind::CC: {os << "CC"; return os;}

        default: {os << "invalid"; return os;}
    }
}
template<typename charT, typename traitsT>
std::basic_ostream<charT, traitsT>&
operator<<(std::basic_ostream<charT, traitsT>& os, const cross_stack_kind cs)
{
    switch(cs)
    {
        case cross_stack_kind::AA5: {os << "AA5"; return os;}
        case cross_stack_kind::AT5: {os << "AT5"; return os;}
        case cross_stack_kind::AG5: {os << "AG5"; return os;}
        case cross_stack_kind::AC5: {os << "AC5"; return os;}

        case cross_stack_kind::TA5: {os << "TA5"; return os;}
        case cross_stack_kind::TT5: {os << "TT5"; return os;}
        case cross_stack_kind::TG5: {os << "TG5"; return os;}
        case cross_stack_kind::TC5: {os << "TC5"; return os;}

        case cross_stack_kind::GA5: {os << "GA5"; return os;}
        case cross_stack_kind::GT5: {os << "GT5"; return os;}
        case cross_stack_kind::GG5: {os << "GG5"; return os;}
        case cross_stack_kind::GC5: {os << "GC5"; return os;}

        case cross_stack_kind::CA5: {os << "CA5"; return os;}
        case cross_stack_kind::CT5: {os << "CT5"; return os;}
        case cross_stack_kind::CG5: {os << "CG5"; return os;}
        case cross_stack_kind::CC5: {os << "CC5"; return os;}

        case cross_stack_kind::AA3: {os << "AA3"; return os;}
        case cross_stack_kind::AT3: {os << "AT3"; return os;}
        case cross_stack_kind::AG3: {os << "AG3"; return os;}
        case cross_stack_kind::AC3: {os << "AC3"; return os;}

        case cross_stack_kind::TA3: {os << "TA3"; return os;}
        case cross_stack_kind::TT3: {os << "TT3"; return os;}
        case cross_stack_kind::TG3: {os << "TG3"; return os;}
        case cross_stack_kind::TC3: {os << "TC3"; return os;}

        case cross_stack_kind::GA3: {os << "GA3"; return os;}
        case cross_stack_kind::GT3: {os << "GT3"; return os;}
        case cross_stack_kind::GG3: {os << "GG3"; return os;}
        case cross_stack_kind::GC3: {os << "GC3"; return os;}

        case cross_stack_kind::CA3: {os << "CA3"; return os;}
        case cross_stack_kind::CT3: {os << "CT3"; return os;}
        case cross_stack_kind::CG3: {os << "CG3"; return os;}
        case cross_stack_kind::CC3: {os << "CC3"; return os;}

        default: {os << "invalid"; return os;}
    }
}

} // 3SPN2
} // mjolnir
#endif// MJOLNIR_POTENTIAL_GLOBAL_3SPN2_COMMON_HPP
<|endoftext|>


<commit_before>#ifndef SERVICE_QUERY_STATE_HH
#define SERVICE_QUERY_STATE_HH

namespace service {

class query_state {
    // FIXME: stub
};

}

#endif
<commit_msg>service: Implement query_state:: get_client_state() and get_timestamp()<commit_after>#ifndef SERVICE_QUERY_STATE_HH
#define SERVICE_QUERY_STATE_HH

#include "service/client_state.hh"

namespace service {

class query_state final {
private:
    client_state& _client_state;
public:
    query_state(client_state& client_state_) : _client_state(client_state_) {}
    client_state& get_client_state() const {
        return _client_state;
    }
    api::timestamp_type get_timestamp() {
        return _client_state.get_timestamp();
    }
};

}

#endif
<|endoftext|>


<commit_before>/****************************************************************/
/*             DO NOT MODIFY OR REMOVE THIS HEADER              */
/*          FALCON - Fracturing And Liquid CONvection           */
/*                                                              */
/*       (c)     2012 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Baseline dependencies (do NOT touch)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#include "Moose.h"
#include "FalconApp.h"
#include "AppFactory.h"
#include "ActionFactory.h"
#include "Syntax.h"

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Actions
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AuxKernels
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#include "PTDarcyFluxAux.h"
#include "PTFluidVelocityAux.h"
#include "VariableGradientAux.h"

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
BCs
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#include "PTEnergyInFlowBC.h"
#include "PTEnergyOutFlowBC.h"

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DGKernels
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DiracKernels
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#include "PTEnergyPointSource.h"
#include "PTMassPointSource.h"

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ICs
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Kernels
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

// pressure & temperature based single-phase flow and heat
#include "PTEnergyResidual.h"
#include "PTEnergyTimeDerivative.h"
#include "PTMassResidual.h"
#include "PTMassTimeDerivative.h"

// solid mechanics

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Materials
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#include "PTGeothermal.h"

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
PostProcessors
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
UserObjects
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MOOSE physics modules
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#include "PhaseFieldApp.h"

/*******************************************************************************
Input template (do NOT touch)
*******************************************************************************/
template<>
InputParameters validParams<FalconApp>()
{
  InputParameters params = validParams<MooseApp>();
  return params;
}

/*******************************************************************************
Routine: FalconApp -- constructor
*******************************************************************************/
FalconApp::FalconApp(InputParameters parameters) :
    MooseApp(parameters)
{
  srand(processor_id());

  Moose::registerObjects(_factory);
  PhaseFieldApp::registerObjects(_factory);
  FalconApp::registerObjects(_factory);

  Moose::associateSyntax(_syntax, _action_factory);
  PhaseFieldApp::associateSyntax(_syntax, _action_factory);
  FalconApp::associateSyntax(_syntax, _action_factory);
}

/*******************************************************************************
Routine: registerApps (no NOT touch)
*******************************************************************************/
extern "C" void FalconApp__registerApps() { FalconApp::registerApps(); }
void
FalconApp::registerApps()
{
#undef  registerApp
#define registerApp(name) AppFactory::instance().reg<name>(#name)

  registerApp(FalconApp);

#undef  registerApp
#define registerApp(name) AppFactory::instance().regLegacy<name>(#name)
}

/*******************************************************************************
Routine: registerObjects
*******************************************************************************/
void
FalconApp::registerObjects(Factory & factory)
{
#undef registerObject
#define registerObject(name) factory.reg<name>(stringifyName(name))

  /* AuxKernels */

  registerAux(PTDarcyFluxAux);
  registerAux(PTFluidVelocityAux);
  registerAux(VariableGradientAux);

  /* BCs */

  registerBoundaryCondition(PTEnergyInFlowBC);
  registerBoundaryCondition(PTEnergyOutFlowBC);

  /* DGKernels */

  /* DiracKernels */
  registerDiracKernel(PTEnergyPointSource);
  registerDiracKernel(PTMassPointSource);

  /* ICs */

  /* Kernel */

  // pressure & temperature based single-phase flow and heat
  registerKernel(PTEnergyResidual);
  registerKernel(PTEnergyTimeDerivative);
  registerKernel(PTMassResidual);
  registerKernel(PTMassTimeDerivative);

  // solid mechanics

  /* Materials */

  registerMaterial(PTGeothermal);

  /* PostProcessors */

  /* UserObjects */
#undef registerObject
#define registerObject(name) factory.regLegacy<name>(stringifyName(name))
}

/*******************************************************************************
Routine: registerApps
*******************************************************************************/
void
FalconApp::associateSyntax(Syntax & syntax, ActionFactory & action_factory)
{}
<commit_msg>Updates for new constructors<commit_after>/****************************************************************/
/*             DO NOT MODIFY OR REMOVE THIS HEADER              */
/*          FALCON - Fracturing And Liquid CONvection           */
/*                                                              */
/*       (c)     2012 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Baseline dependencies (do NOT touch)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#include "Moose.h"
#include "FalconApp.h"
#include "AppFactory.h"
#include "ActionFactory.h"
#include "Syntax.h"

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Actions
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AuxKernels
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#include "PTDarcyFluxAux.h"
#include "PTFluidVelocityAux.h"
#include "VariableGradientAux.h"

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
BCs
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#include "PTEnergyInFlowBC.h"
#include "PTEnergyOutFlowBC.h"

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DGKernels
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DiracKernels
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#include "PTEnergyPointSource.h"
#include "PTMassPointSource.h"

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ICs
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Kernels
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

// pressure & temperature based single-phase flow and heat
#include "PTEnergyResidual.h"
#include "PTEnergyTimeDerivative.h"
#include "PTMassResidual.h"
#include "PTMassTimeDerivative.h"

// solid mechanics

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Materials
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#include "PTGeothermal.h"

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
PostProcessors
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
UserObjects
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MOOSE physics modules
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#include "PhaseFieldApp.h"

/*******************************************************************************
Input template (do NOT touch)
*******************************************************************************/
template<>
InputParameters validParams<FalconApp>()
{
  InputParameters params = validParams<MooseApp>();
  return params;
}

/*******************************************************************************
Routine: FalconApp -- constructor
*******************************************************************************/
FalconApp::FalconApp(InputParameters parameters) :
    MooseApp(parameters)
{
  Moose::registerObjects(_factory);
  PhaseFieldApp::registerObjects(_factory);
  FalconApp::registerObjects(_factory);

  Moose::associateSyntax(_syntax, _action_factory);
  PhaseFieldApp::associateSyntax(_syntax, _action_factory);
  FalconApp::associateSyntax(_syntax, _action_factory);
}

/*******************************************************************************
Routine: registerApps (no NOT touch)
*******************************************************************************/
extern "C" void FalconApp__registerApps() { FalconApp::registerApps(); }
void
FalconApp::registerApps()
{
  registerApp(FalconApp);
}

/*******************************************************************************
Routine: registerObjects
*******************************************************************************/
void
FalconApp::registerObjects(Factory & factory)
{
  /* AuxKernels */

  registerAux(PTDarcyFluxAux);
  registerAux(PTFluidVelocityAux);
  registerAux(VariableGradientAux);

  /* BCs */

  registerBoundaryCondition(PTEnergyInFlowBC);
  registerBoundaryCondition(PTEnergyOutFlowBC);

  /* DGKernels */

  /* DiracKernels */
  registerDiracKernel(PTEnergyPointSource);
  registerDiracKernel(PTMassPointSource);

  /* ICs */

  /* Kernel */

  // pressure & temperature based single-phase flow and heat
  registerKernel(PTEnergyResidual);
  registerKernel(PTEnergyTimeDerivative);
  registerKernel(PTMassResidual);
  registerKernel(PTMassTimeDerivative);

  // solid mechanics

  /* Materials */

  registerMaterial(PTGeothermal);

  /* PostProcessors */

  /* UserObjects */
}

/*******************************************************************************
Routine: registerApps
*******************************************************************************/
void
FalconApp::associateSyntax(Syntax & syntax, ActionFactory & action_factory)
{}
<|endoftext|>


<commit_before>
#include "base/UIPanel.h"
#include "base/Mesh.h"
#include "base/Geometry.h"
#include "base/Font.h"
#include "material/DefaultMaterials.h"
#include "base/StringHash.h"
#include "util/GeometryHelper.h"

#include <cassert>

namespace three {

  uint32_t UIPanel::Type = StringHash("UIPanel").hash;

  static const int BUTTON_HEIGHT = 20;
  static const int SLIDER_HEIGHT = 20;
  static const int SLIDER_MARKER_WIDTH = 10;
  static const int CHECK_SIZE = 8;
  static const int DEFAULT_SPACING = 4;
  static const int TEXT_HEIGHT = 8;
  static const int SCROLL_AREA_PADDING = 6;
  static const int INDENT_SIZE = 16;
  static const int AREA_HEADER = 28;

  static void updateInput(UIPanel::State & state, Vector2 const& mousePos, bool mouseDown, float mouseScroll)
  {
    state.mousePos = mousePos;
    state.mousePressed = !state.mouseDown && mouseDown;
    state.mouseReleased = state.mouseDown && !mouseDown;
    state.mouseDown = mouseDown;
    state.mouseScroll = mouseScroll;
  }

  static void clearInput(UIPanel::State & state)
  {
    state.mousePressed = false;
    state.mouseReleased = false;
    state.mouseScroll = 0;
  }

  UIPanel::UIPanel(Font * font_)
    : Object(),
      size(200, 400),
      font(font_),
      _faceMesh(0),
      _fontMesh(0)
  {
    assert(font);

    MeshBasicMaterial * faceMat = new MeshBasicMaterial();
    faceMat->useVertexColor = true;
    faceMat->diffuse = Color(1, 1, 1);
    faceMat->depthTest = false;
    faceMat->depthWrite = false;
    faceMat->transparent = true;

    MeshBasicMaterial * fontMat = new MeshBasicMaterial();
    fontMat->useTextureMap = true;
    fontMat->useVertexColor = true;
    fontMat->map = font->texture;
    fontMat->diffuse = Color(1, 1, 1);
    fontMat->depthTest = false;
    fontMat->depthWrite = false;
    fontMat->transparent = true;

    _faceMesh = new Mesh(new Geometry(), faceMat);
    _faceMesh->geometry->dynamic = true;

    _fontMesh = new Mesh(new Geometry(), fontMat);
    _fontMesh->geometry->dynamic = true;

    add(_faceMesh);
    add(_fontMesh);
  }

  void UIPanel::begin(Vector2 const& mousePos, bool mouseDown, float mouseScroll)
  {
    _faceMesh->geometry->clear();
    _fontMesh->geometry->clear();

    // Update input with panel normalized mouse coords
    updateInput(_state, mousePos - Vector2(position.x, position.y), mouseDown, mouseScroll);

    _state.hot = _state.toBeHot;
    _state.toBeHot = 0;

    _state.wentActive = false;
    _state.isActive = false;
    _state.isHot = false;

    _state.widgetX = SCROLL_AREA_PADDING;
    _state.widgetY = 0;
    _state.widgetW = size.x - SCROLL_AREA_PADDING * 4;

    _state.areaId = 1;
    _state.widgetId = 1;

    // Change to rounded rect
    addRectangle(_faceMesh->geometry, Vector2(0, 0), Vector2(size.x, size.y), Color(0, 0, 0, 0.75));
  }

  void UIPanel::end()
  {
    clearInput(_state);
  }

  void UIPanel::label(const char * str)
  {
    assert(font);

    float x = _state.widgetX;
    float y = _state.widgetY + BUTTON_HEIGHT;
    _state.widgetY += BUTTON_HEIGHT;

    font->buildTextGeometry(str, Vector2(x, y), _fontMesh->geometry, Color(1, 1, 1));
  }

  void UIPanel::indent()
  {
    _state.widgetX += INDENT_SIZE;
    _state.widgetW -= INDENT_SIZE;
  }

  void UIPanel::unindent()
  {
    _state.widgetX -= INDENT_SIZE;
    _state.widgetW += INDENT_SIZE;
  }

  void UIPanel::separator()
  {
    _state.widgetY += DEFAULT_SPACING * 3;
  }

  void UIPanel::separatorLine()
  {
    int x = _state.widgetX;
    int y = _state.widgetY + DEFAULT_SPACING * 2;
    int w = _state.widgetW;
    int h = 1;
    _state.widgetY += DEFAULT_SPACING * 4;

    addRectangle(_faceMesh->geometry, Vector2(x, y), Vector2(w, h), Color(1, 1, 1, 0.12));
  }
}

<commit_msg>Text should always be positioned above the face mesh<commit_after>
#include "base/UIPanel.h"
#include "base/Mesh.h"
#include "base/Geometry.h"
#include "base/Font.h"
#include "material/DefaultMaterials.h"
#include "base/StringHash.h"
#include "util/GeometryHelper.h"

#include <cassert>

namespace three {

  uint32_t UIPanel::Type = StringHash("UIPanel").hash;

  static const int BUTTON_HEIGHT = 20;
  static const int SLIDER_HEIGHT = 20;
  static const int SLIDER_MARKER_WIDTH = 10;
  static const int CHECK_SIZE = 8;
  static const int DEFAULT_SPACING = 4;
  static const int TEXT_HEIGHT = 8;
  static const int SCROLL_AREA_PADDING = 6;
  static const int INDENT_SIZE = 16;
  static const int AREA_HEADER = 28;

  static void updateInput(UIPanel::State & state, Vector2 const& mousePos, bool mouseDown, float mouseScroll)
  {
    state.mousePos = mousePos;
    state.mousePressed = !state.mouseDown && mouseDown;
    state.mouseReleased = state.mouseDown && !mouseDown;
    state.mouseDown = mouseDown;
    state.mouseScroll = mouseScroll;
  }

  static void clearInput(UIPanel::State & state)
  {
    state.mousePressed = false;
    state.mouseReleased = false;
    state.mouseScroll = 0;
  }

  UIPanel::UIPanel(Font * font_)
    : Object(),
      size(250, 350),
      font(font_),
      _faceMesh(0),
      _fontMesh(0)
  {
    assert(font);

    MeshBasicMaterial * faceMat = new MeshBasicMaterial();
    faceMat->useVertexColor = true;
    faceMat->diffuse = Color(1, 1, 1);
    faceMat->depthTest = false;
    faceMat->depthWrite = false;
    faceMat->transparent = true;

    MeshBasicMaterial * fontMat = new MeshBasicMaterial();
    fontMat->useTextureMap = true;
    fontMat->useVertexColor = true;
    fontMat->map = font->texture;
    fontMat->diffuse = Color(1, 1, 1);
    fontMat->depthTest = false;
    fontMat->depthWrite = false;
    fontMat->transparent = true;

    _faceMesh = new Mesh(new Geometry(), faceMat);
    _faceMesh->geometry->dynamic = true;

    // Create text mesh, this is always slightly above the face mesh
    _fontMesh = new Mesh(new Geometry(), fontMat);
    _fontMesh->position.z = -0.1;
    _fontMesh->geometry->dynamic = true;

    add(_faceMesh);
    add(_fontMesh);
  }

  void UIPanel::begin(Vector2 const& mousePos, bool mouseDown, float mouseScroll)
  {
    _faceMesh->geometry->clear();
    _fontMesh->geometry->clear();

    // Update input with panel normalized mouse coords
    updateInput(_state, mousePos - Vector2(position.x, position.y), mouseDown, mouseScroll);

    _state.hot = _state.toBeHot;
    _state.toBeHot = 0;

    _state.wentActive = false;
    _state.isActive = false;
    _state.isHot = false;

    _state.widgetX = SCROLL_AREA_PADDING;
    _state.widgetY = 0;
    _state.widgetW = size.x - SCROLL_AREA_PADDING * 4;

    _state.areaId = 1;
    _state.widgetId = 1;

    // Change to rounded rect
    addRectangle(_faceMesh->geometry, Vector2(0, 0), Vector2(size.x, size.y), Color(0, 0, 0, 0.75));
  }

  void UIPanel::end()
  {
    clearInput(_state);
  }

  void UIPanel::label(const char * str)
  {
    assert(font);

    float x = _state.widgetX;
    float y = _state.widgetY + BUTTON_HEIGHT;
    _state.widgetY += BUTTON_HEIGHT;

    font->buildTextGeometry(str, Vector2(x, y), _fontMesh->geometry, Color(1, 1, 1));
  }

  void UIPanel::indent()
  {
    _state.widgetX += INDENT_SIZE;
    _state.widgetW -= INDENT_SIZE;
  }

  void UIPanel::unindent()
  {
    _state.widgetX -= INDENT_SIZE;
    _state.widgetW += INDENT_SIZE;
  }

  void UIPanel::separator()
  {
    _state.widgetY += DEFAULT_SPACING * 3;
  }

  void UIPanel::separatorLine()
  {
    int x = _state.widgetX;
    int y = _state.widgetY + DEFAULT_SPACING * 2;
    int w = _state.widgetW;
    int h = 1;
    _state.widgetY += DEFAULT_SPACING * 4;

    addRectangle(_faceMesh->geometry, Vector2(x, y), Vector2(w, h), Color(1, 1, 1, 0.12));
  }
}

<|endoftext|>