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

#include <OdaCommon.h>
#include <OdString.h>

#include <toString.h>
#include <DgLevelTableRecord.h>

#include "geometry_dumper.h"
#include "../../../../core/model/bson/repo_bson_factory.h"
using namespace repo::manipulator::modelconvertor::odaHelper;

void GeometryDumper::triangleOut(const OdInt32* p3Vertices, const OdGeVector3d* pNormal)
{
	const OdGePoint3d*  pVertexDataList = vertexDataList();
	const OdGeVector3d* pNormals = NULL;

	if ((pVertexDataList + p3Vertices[0]) != (pVertexDataList + p3Vertices[1]) &&
		(pVertexDataList + p3Vertices[0]) != (pVertexDataList + p3Vertices[2]) &&
		(pVertexDataList + p3Vertices[1]) != (pVertexDataList + p3Vertices[2]))
	{
		std::vector<repo::lib::RepoVector3D64> vertices;
		for (int i = 0; i < 3; ++i)
		{
			vertices.push_back({ pVertexDataList[p3Vertices[i]].x , pVertexDataList[p3Vertices[i]].y, pVertexDataList[p3Vertices[i]].z });
		}
		collector->addFace(vertices);
	}
}

double GeometryDumper::deviation(
	const OdGiDeviationType deviationType,
	const OdGePoint3d& pointOnCurve) const {
	return 0;
}

VectoriseDevice* GeometryDumper::device()
{
	return static_cast<VectoriseDevice*>(OdGsBaseVectorizeView::device());
}

bool GeometryDumper::doDraw(OdUInt32 i, const OdGiDrawable* pDrawable)
{
	OdDgElementPtr pElm = OdDgElement::cast(pDrawable);

	OdString sClassName = toString(pElm->isA());
	OdString sHandle = pElm->isDBRO() ? toString(pElm->elementId().getHandle()) : toString(OD_T("non-DbResident"));

	std::stringstream ss;
	ss << sHandle;
	collector->setNextMeshName(ss.str());

	OdGiSubEntityTraitsData traits = effectiveTraits();
	OdDgElementId idLevel = traits.layer();
	if (!idLevel.isNull())
	{
		OdDgLevelTableRecordPtr pLevel = idLevel.openObject(OdDg::kForRead);
		OdUInt32 iLevelEntry = pLevel->getEntryId();

		std::stringstream ss;
		ss << pLevel->getName().c_str();
		auto layerName = ss.str();
		collector->setLayer(layerName);
	}
	return OdGsBaseMaterialView::doDraw(i, pDrawable);
}

OdCmEntityColor GeometryDumper::fixByACI(const ODCOLORREF *ids, const OdCmEntityColor &color)
{
	if (color.isByACI() || color.isByDgnIndex())
	{
		return OdCmEntityColor(ODGETRED(ids[color.colorIndex()]), ODGETGREEN(ids[color.colorIndex()]), ODGETBLUE(ids[color.colorIndex()]));
	}
	else if (!color.isByColor())
	{
		return OdCmEntityColor(0, 0, 0);
	}
	return color;
}

OdGiMaterialItemPtr GeometryDumper::fillMaterialCache(
	OdGiMaterialItemPtr prevCache,
	OdDbStub* materialId,
	const OdGiMaterialTraitsData & materialData
) {

	auto id = (OdUInt64)(OdIntPtr)materialId;

	OdGiMaterialColor diffuseColor; OdGiMaterialMap diffuseMap;
	OdGiMaterialColor ambientColor;
	OdGiMaterialColor specularColor; OdGiMaterialMap specularMap; double glossFactor;
	double opacityPercentage; OdGiMaterialMap opacityMap;
	double refrIndex; OdGiMaterialMap refrMap;

	materialData.diffuse(diffuseColor, diffuseMap);
	materialData.ambient(ambientColor);
	materialData.specular(specularColor, specularMap, glossFactor);
	materialData.opacity(opacityPercentage, opacityMap);
	materialData.refraction(refrIndex, refrMap);

	OdGiMaterialMap bumpMap;
	materialData.bump(bumpMap);

	ODCOLORREF colorDiffuse(0), colorAmbient(0), colorSpecular(0);
	if (diffuseColor.color().colorMethod() == OdCmEntityColor::kByColor)
	{
		colorDiffuse = ODTOCOLORREF(diffuseColor.color());
	}
	else if (diffuseColor.color().colorMethod() == OdCmEntityColor::kByACI)
	{
		colorDiffuse = OdCmEntityColor::lookUpRGB((OdUInt8)diffuseColor.color().colorIndex());
	}
	if (ambientColor.color().colorMethod() == OdCmEntityColor::kByColor)
	{
		colorAmbient = ODTOCOLORREF(ambientColor.color());
	}
	else if (ambientColor.color().colorMethod() == OdCmEntityColor::kByACI)
	{
		colorAmbient = OdCmEntityColor::lookUpRGB((OdUInt8)ambientColor.color().colorIndex());
	}
	if (specularColor.color().colorMethod() == OdCmEntityColor::kByColor)
	{
		colorSpecular = ODTOCOLORREF(specularColor.color());
	}
	else if (specularColor.color().colorMethod() == OdCmEntityColor::kByACI)
	{
		colorSpecular = OdCmEntityColor::lookUpRGB((OdUInt8)specularColor.color().colorIndex());
	}

	OdCmEntityColor color = fixByACI(this->device()->getPalette(), effectiveTraits().trueColor());
	repo_material_t material;
	// diffuse
	if (diffuseColor.method() == OdGiMaterialColor::kOverride)
		material.diffuse = { ODGETRED(colorDiffuse) / 255.0f, ODGETGREEN(colorDiffuse) / 255.0f, ODGETBLUE(colorDiffuse) / 255.0f, 1.0f };
	else
		material.diffuse = { color.red() / 255.0f, color.green() / 255.0f, color.blue() / 255.0f, 1.0f };
	/*
	TODO: texture support
	mData.bDiffuseChannelEnabled = (GETBIT(materialData.channelFlags(), OdGiMaterialTraits::kUseDiffuse)) ? true : false;
	if (mData.bDiffuseChannelEnabled && diffuseMap.source() == OdGiMaterialMap::kFile && !diffuseMap.sourceFileName().isEmpty())
	{
	mData.bDiffuseHasTexture = true;
	mData.sDiffuseFileSource = diffuseMap.sourceFileName();
	}*/

	// specular
	if (specularColor.method() == OdGiMaterialColor::kOverride)
		material.specular = { ODGETRED(colorSpecular) / 255.0f, ODGETGREEN(colorSpecular) / 255.0f, ODGETBLUE(colorSpecular) / 255.0f, 1.0f };
	else
		material.specular = { color.red() / 255.0f, color.green() / 255.0f, color.blue() / 255.0f, 1.0f };

	material.shininessStrength = 1 - glossFactor;
	material.shininess = materialData.reflectivity();

	// opacity
	material.opacity = opacityPercentage;

	// refraction
	/*mData.bRefractionChannelEnabled = (GETBIT(materialData.channelFlags(), OdGiMaterialTraits::kUseRefraction)) ? 1 : 0;
	mData.dRefractionIndex = materialData.reflectivity();*/

	// transclucence
	//mData.dTranslucence = materialData.translucence();

	collector->setCurrentMaterial(material);
	collector->stopMeshEntry();
	collector->startMeshEntry();

	return OdGiMaterialItemPtr();
}

void GeometryDumper::init(GeometryCollector *const geoCollector) {
	collector = geoCollector;
}

void GeometryDumper::beginViewVectorization()
{
	OdGsBaseMaterialView::beginViewVectorization();
	setEyeToOutputTransform(getEyeToWorldTransform());

	OdGiGeometrySimplifier::setDrawContext(OdGsBaseMaterialView::drawContext());
	output().setDestGeometry((OdGiGeometrySimplifier&)*this);
}

void GeometryDumper::endViewVectorization()
{
	collector->stopMeshEntry();
	OdGsBaseMaterialView::endViewVectorization();
}

void GeometryDumper::setMode(OdGsView::RenderMode mode)
{
	OdGsBaseVectorizeView::m_renderMode = kGouraudShaded;
	m_regenerationType = kOdGiRenderCommand;
	OdGiGeometrySimplifier::m_renderMode = OdGsBaseVectorizeView::m_renderMode;
}<commit_msg>ISSUE #271 try fix travis via char conversion 2<commit_after>/**
*  Copyright (C) 2018 3D Repo Ltd
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU Affero General Public License as
*  published by the Free Software Foundation, either version 3 of the
*  License, or (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Affero General Public License for more details.
*
*  You should have received a copy of the GNU Affero General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <OdaCommon.h>
#include <OdString.h>

#include <toString.h>
#include <DgLevelTableRecord.h>

#include "geometry_dumper.h"
#include "../../../../core/model/bson/repo_bson_factory.h"
using namespace repo::manipulator::modelconvertor::odaHelper;

void GeometryDumper::triangleOut(const OdInt32* p3Vertices, const OdGeVector3d* pNormal)
{
	const OdGePoint3d*  pVertexDataList = vertexDataList();
	const OdGeVector3d* pNormals = NULL;

	if ((pVertexDataList + p3Vertices[0]) != (pVertexDataList + p3Vertices[1]) &&
		(pVertexDataList + p3Vertices[0]) != (pVertexDataList + p3Vertices[2]) &&
		(pVertexDataList + p3Vertices[1]) != (pVertexDataList + p3Vertices[2]))
	{
		std::vector<repo::lib::RepoVector3D64> vertices;
		for (int i = 0; i < 3; ++i)
		{
			vertices.push_back({ pVertexDataList[p3Vertices[i]].x , pVertexDataList[p3Vertices[i]].y, pVertexDataList[p3Vertices[i]].z });
		}
		collector->addFace(vertices);
	}
}

double GeometryDumper::deviation(
	const OdGiDeviationType deviationType,
	const OdGePoint3d& pointOnCurve) const {
	return 0;
}

VectoriseDevice* GeometryDumper::device()
{
	return static_cast<VectoriseDevice*>(OdGsBaseVectorizeView::device());
}

bool GeometryDumper::doDraw(OdUInt32 i, const OdGiDrawable* pDrawable)
{
	OdDgElementPtr pElm = OdDgElement::cast(pDrawable);

	OdString sClassName = toString(pElm->isA());
	OdString sHandle = pElm->isDBRO() ? toString(pElm->elementId().getHandle()) : toString(OD_T("non-DbResident"));

	std::stringstream ss;
	ss << sHandle.c_str();
	collector->setNextMeshName(ss.str());

	OdGiSubEntityTraitsData traits = effectiveTraits();
	OdDgElementId idLevel = traits.layer();
	if (!idLevel.isNull())
	{
		OdDgLevelTableRecordPtr pLevel = idLevel.openObject(OdDg::kForRead);
		OdUInt32 iLevelEntry = pLevel->getEntryId();

		std::stringstream ss;
		ss << pLevel->getName().c_str();
		auto layerName = ss.str();
		collector->setLayer(layerName);
	}
	return OdGsBaseMaterialView::doDraw(i, pDrawable);
}

OdCmEntityColor GeometryDumper::fixByACI(const ODCOLORREF *ids, const OdCmEntityColor &color)
{
	if (color.isByACI() || color.isByDgnIndex())
	{
		return OdCmEntityColor(ODGETRED(ids[color.colorIndex()]), ODGETGREEN(ids[color.colorIndex()]), ODGETBLUE(ids[color.colorIndex()]));
	}
	else if (!color.isByColor())
	{
		return OdCmEntityColor(0, 0, 0);
	}
	return color;
}

OdGiMaterialItemPtr GeometryDumper::fillMaterialCache(
	OdGiMaterialItemPtr prevCache,
	OdDbStub* materialId,
	const OdGiMaterialTraitsData & materialData
) {

	auto id = (OdUInt64)(OdIntPtr)materialId;

	OdGiMaterialColor diffuseColor; OdGiMaterialMap diffuseMap;
	OdGiMaterialColor ambientColor;
	OdGiMaterialColor specularColor; OdGiMaterialMap specularMap; double glossFactor;
	double opacityPercentage; OdGiMaterialMap opacityMap;
	double refrIndex; OdGiMaterialMap refrMap;

	materialData.diffuse(diffuseColor, diffuseMap);
	materialData.ambient(ambientColor);
	materialData.specular(specularColor, specularMap, glossFactor);
	materialData.opacity(opacityPercentage, opacityMap);
	materialData.refraction(refrIndex, refrMap);

	OdGiMaterialMap bumpMap;
	materialData.bump(bumpMap);

	ODCOLORREF colorDiffuse(0), colorAmbient(0), colorSpecular(0);
	if (diffuseColor.color().colorMethod() == OdCmEntityColor::kByColor)
	{
		colorDiffuse = ODTOCOLORREF(diffuseColor.color());
	}
	else if (diffuseColor.color().colorMethod() == OdCmEntityColor::kByACI)
	{
		colorDiffuse = OdCmEntityColor::lookUpRGB((OdUInt8)diffuseColor.color().colorIndex());
	}
	if (ambientColor.color().colorMethod() == OdCmEntityColor::kByColor)
	{
		colorAmbient = ODTOCOLORREF(ambientColor.color());
	}
	else if (ambientColor.color().colorMethod() == OdCmEntityColor::kByACI)
	{
		colorAmbient = OdCmEntityColor::lookUpRGB((OdUInt8)ambientColor.color().colorIndex());
	}
	if (specularColor.color().colorMethod() == OdCmEntityColor::kByColor)
	{
		colorSpecular = ODTOCOLORREF(specularColor.color());
	}
	else if (specularColor.color().colorMethod() == OdCmEntityColor::kByACI)
	{
		colorSpecular = OdCmEntityColor::lookUpRGB((OdUInt8)specularColor.color().colorIndex());
	}

	OdCmEntityColor color = fixByACI(this->device()->getPalette(), effectiveTraits().trueColor());
	repo_material_t material;
	// diffuse
	if (diffuseColor.method() == OdGiMaterialColor::kOverride)
		material.diffuse = { ODGETRED(colorDiffuse) / 255.0f, ODGETGREEN(colorDiffuse) / 255.0f, ODGETBLUE(colorDiffuse) / 255.0f, 1.0f };
	else
		material.diffuse = { color.red() / 255.0f, color.green() / 255.0f, color.blue() / 255.0f, 1.0f };
	/*
	TODO: texture support
	mData.bDiffuseChannelEnabled = (GETBIT(materialData.channelFlags(), OdGiMaterialTraits::kUseDiffuse)) ? true : false;
	if (mData.bDiffuseChannelEnabled && diffuseMap.source() == OdGiMaterialMap::kFile && !diffuseMap.sourceFileName().isEmpty())
	{
	mData.bDiffuseHasTexture = true;
	mData.sDiffuseFileSource = diffuseMap.sourceFileName();
	}*/

	// specular
	if (specularColor.method() == OdGiMaterialColor::kOverride)
		material.specular = { ODGETRED(colorSpecular) / 255.0f, ODGETGREEN(colorSpecular) / 255.0f, ODGETBLUE(colorSpecular) / 255.0f, 1.0f };
	else
		material.specular = { color.red() / 255.0f, color.green() / 255.0f, color.blue() / 255.0f, 1.0f };

	material.shininessStrength = 1 - glossFactor;
	material.shininess = materialData.reflectivity();

	// opacity
	material.opacity = opacityPercentage;

	// refraction
	/*mData.bRefractionChannelEnabled = (GETBIT(materialData.channelFlags(), OdGiMaterialTraits::kUseRefraction)) ? 1 : 0;
	mData.dRefractionIndex = materialData.reflectivity();*/

	// transclucence
	//mData.dTranslucence = materialData.translucence();

	collector->setCurrentMaterial(material);
	collector->stopMeshEntry();
	collector->startMeshEntry();

	return OdGiMaterialItemPtr();
}

void GeometryDumper::init(GeometryCollector *const geoCollector) {
	collector = geoCollector;
}

void GeometryDumper::beginViewVectorization()
{
	OdGsBaseMaterialView::beginViewVectorization();
	setEyeToOutputTransform(getEyeToWorldTransform());

	OdGiGeometrySimplifier::setDrawContext(OdGsBaseMaterialView::drawContext());
	output().setDestGeometry((OdGiGeometrySimplifier&)*this);
}

void GeometryDumper::endViewVectorization()
{
	collector->stopMeshEntry();
	OdGsBaseMaterialView::endViewVectorization();
}

void GeometryDumper::setMode(OdGsView::RenderMode mode)
{
	OdGsBaseVectorizeView::m_renderMode = kGouraudShaded;
	m_regenerationType = kOdGiRenderCommand;
	OdGiGeometrySimplifier::m_renderMode = OdGsBaseVectorizeView::m_renderMode;
}<|endoftext|>


<commit_before>#include <iostream>
using namespace std;

enum CPU_Rank {P1=1,P2,P3,P4,P5,P6,P7};
class CPU{
private:
	CPU_Rank rank;
	int frequency;
	float voltage;
public:
	CPU(CPU_Rank r,int f, float v){
		rank = r;
		frequency = f;
		voltage = v;
		cout<<"构造了一个CPU!"<<endl;
	}
	~CPU() {cout<<"析构了一个CPU!"<<endl;}
	CPU_Rank getrank() const {return rank;}
	int getfrequency() const {return frequency;}
	float getvoltage() const {return voltage;}

	void setrank(CPU_Rank r){rank = r;}
	void setfrequency(int f){frequency = f;}
	void setvoltage(float v){voltage = v;}

	void Run(){cout<<"CPU 开始运行！"<<endl;}
	void Stop(){cout<<"CPU 停止运行！"<<endl;}
};

int main(){
	CPU a(P6,300,2.8);
	a.Run();
	a.Stop();

	return 0;
}<commit_msg>new practice.<commit_after>#include <iostream>
using namespace std;

enum CPU_Rank {P1=1,P2,P3,P4,P5,P6,P7};
class CPU{
private:
	CPU_Rank rank;
	int frequency;
	float voltage;
public:
	CPU(CPU_Rank r,int f, float v){
		rank = r;
		frequency = f;
		voltage = v;
		cout<<"构造了一个CPU!"<<endl;
	}
	~CPU() {cout<<"析构了一个CPU!"<<endl;}
	CPU_Rank getrank() const {return rank;}
	int getfrequency() const {return frequency;}
	float getvoltage() const {return voltage;}

	void setrank(CPU_Rank r){rank = r;}
	void setfrequency(int f){frequency = f;}
	void setvoltage(float v){voltage = v;}

	void Run(){cout<<"CPU 开始运行！"<<endl;}
	void Stop(){cout<<"CPU 停止运行！"<<endl;}
};

enum  RAM_Type {DDR2=2,DDR3,DDR4};
class RAM{
private:
	enum RAM_Type type;
	unsigned int frequency;
	unsigned int size;
public:
	RAM(RAM_Type t, unsigned int f, unsigned int s){
		type = t;
		frequency = f;
		size = s;
		cout<<"构造了一个RAM!"<<endl;
	}
	~RAM() {cout<<"析构了一个RAM!"<<endl;}

	RAM_Type getType() const {return type;}
	unsigned int getFrequency() const {return frequency;}
	unsigned int getSize() const {return size;}

	void setType(RAM_Type t) {type = t;}
	void setFrequency(unsigned int f) {frequency = f;}
	void setSize(unsigned int s) {size = s;}

	void Run() {cout<<"RAM 开始运行！"<<endl;}
	void Stop() {cout<<"RAM 停止运行！"<<endl;}

};

enum CDROM_Interface {SATA, USB};
enum CDROM_Install_type {external, built_in};
class CDROM{
private:
	enum CDROM_Interface interface_type;
	unsigned int cache_size;
	enum CDROM_Install_type install_type;

public:
	CDROM(CDROM_Interface i, unsigned int s, CDROM_Install_type it){
		interface_type = i;
		cache_size = s;
		install_type = it;
		cout<<"构造了一个CDROM!"<<endl;
	}
	~CDROM() {cout<<"析构了一个CDROM!"<<endl;}

	CDROM_Interface getInterfaceType() {return interface_type;}
	unsigned int getCacheSize() {return cache_size;}
	CDROM_Install_type getInstallType() {return install_type;}

	void setInterfaceType(CDROM_Interface i) {interface_type = i;}
	void setCacheSize(unsigned int s) {cache_size = s;}
	void setInstallType(CDROM_Install_type it) {install_type = it;}

	void Run() {cout<<"CDROM 开始运行！"<<endl;}
	void Stop() {cout<<"CDROM 停止运行！"<<endl;}
};

class COMPUTER{
private:
	CPU my_cpu;
	RAM my_ram;
	CDROM my_cdrom;
	unsigned int storage_size;
	unsigned int bandwidth;

public:
	COMPUTER(CPU c, RAM r, CDROM cd, unsigned int s, unsigned int b);
	~COMPUTER() {cout<<"析构了一个COMPUTER!"<<endl;}

	void Run(){
		my_cpu.Run();
		my_ram.Run();
		my_cdrom.Run();
		cout<<"COMPUTER 开始运行！"<<endl;
	}
	void Stop(){
		my_cpu.Stop();
		my_ram.Stop();
		my_cdrom.Stop();
		cout<<"COMPUTER 停止运行！"<<endl;
	}
};

COMPUTER::COMPUTER(CPU c, RAM r, CDROM cd, unsigned int s, unsigned int b):my_cpu(c),my_ram(r),my_cdrom(cd){
	storage_size = s;
	bandwidth = b;
	cout<<"构造了一个COMPUTER!"<<endl;
};

int main(){
	CPU a(P6,300,2.8);
	a.Run();
	a.Stop();
	cout<<"*********************\n";

	RAM b(DDR3,1600,8);
	b.Run();
	b.Stop();
	cout<<"*********************\n";

	CDROM c(SATA,2,built_in);
	c.Run();
	c.Stop();
	cout<<"*********************\n";

	COMPUTER my_computer(a,b,c,128,10);
	cout<<"*********************\n";

	my_computer.Run();
	my_computer.Stop();
	cout<<"*********************\n";

	return 0;
}<|endoftext|>


<commit_before>#include "btree/get.hpp"

#include "errors.hpp"
#include <boost/shared_ptr.hpp>

#include "btree/delete_expired.hpp"
#include "btree/btree_data_provider.hpp"
#include "btree/internal_node.hpp"
#include "btree/leaf_node.hpp"
#include "btree/operations.hpp"
#include "buffer_cache/buf_lock.hpp"
#include "store.hpp"

get_result_t btree_get(const store_key_t &store_key, btree_slice_t *slice, order_token_t token) {
    btree_key_buffer_t kbuffer(store_key);
    btree_key_t *key = kbuffer.key();

    slice->assert_thread();
    on_thread_t mover(slice->home_thread());

    got_superblock_t got;
    get_btree_superblock(slice, rwi_read, token, &got);

    memcached_value_sizer_t sizer(slice->cache()->get_block_size());
    keyvalue_location_t kv_location;
    find_keyvalue_location_for_read(&sizer, &got, key, &kv_location);

    if (!kv_location.value) {
        return get_result_t();
    }

    const btree_value_t *value = reinterpret_cast<const btree_value_t *>(kv_location.value.get());
    if (value->expired()) {
        // If the value is expired, delete it in the background.
        btree_delete_expired(store_key, slice);
        return get_result_t();
    }

    boost::shared_ptr<value_data_provider_t> dp(value_data_provider_t::create(value, kv_location.txn.get()));

    return get_result_t(dp, value->mcflags(), 0);
}
<commit_msg>Removed on_thread_t usage in get.cc that was asserted against anyway.<commit_after>#include "btree/get.hpp"

#include "errors.hpp"
#include <boost/shared_ptr.hpp>

#include "btree/delete_expired.hpp"
#include "btree/btree_data_provider.hpp"
#include "btree/internal_node.hpp"
#include "btree/leaf_node.hpp"
#include "btree/operations.hpp"
#include "buffer_cache/buf_lock.hpp"
#include "store.hpp"

get_result_t btree_get(const store_key_t &store_key, btree_slice_t *slice, order_token_t token) {
    btree_key_buffer_t kbuffer(store_key);
    btree_key_t *key = kbuffer.key();

    slice->assert_thread();

    got_superblock_t got;
    get_btree_superblock(slice, rwi_read, token, &got);

    memcached_value_sizer_t sizer(slice->cache()->get_block_size());
    keyvalue_location_t kv_location;
    find_keyvalue_location_for_read(&sizer, &got, key, &kv_location);

    if (!kv_location.value) {
        return get_result_t();
    }

    const btree_value_t *value = reinterpret_cast<const btree_value_t *>(kv_location.value.get());
    if (value->expired()) {
        // If the value is expired, delete it in the background.
        btree_delete_expired(store_key, slice);
        return get_result_t();
    }

    boost::shared_ptr<value_data_provider_t> dp(value_data_provider_t::create(value, kv_location.txn.get()));

    return get_result_t(dp, value->mcflags(), 0);
}
<|endoftext|>


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

// +build ignore

#include "exec.h"

#include <stdio.h>
#include <stdlib.h>

#include <memory>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#include "dep.h"
#include "eval.h"
#include "fileutil.h"
#include "log.h"
#include "string_piece.h"
#include "strutil.h"
#include "value.h"
#include "var.h"

namespace {

class Executor;

class AutoVar : public Var {
 public:
  virtual const char* Flavor() const override {
    return "undefined";
  }
  virtual const char* Origin() const override {
    return "automatic";
  }

  virtual void AppendVar(Evaluator*, Value*) override { CHECK(false); }

  virtual StringPiece String() const override {
    ERROR("$(value %s) is not implemented yet", sym_);
    return "";
  }

  virtual string DebugString() const override {
    return string("AutoVar(") + sym_ + ")";
  }

 protected:
  AutoVar(Executor* ex, const char* sym) : ex_(ex), sym_(sym) {}
  virtual ~AutoVar() = default;

  Executor* ex_;
  const char* sym_;
};

#define DECLARE_AUTO_VAR_CLASS(name)                            \
  class name : public AutoVar {                                 \
   public:                                                      \
   name(Executor* ex, const char* sym)                          \
       : AutoVar(ex, sym) {}                                    \
   virtual ~name() = default;                                   \
   virtual void Eval(Evaluator* ev, string* s) const override;  \
  }

DECLARE_AUTO_VAR_CLASS(AutoAtVar);
DECLARE_AUTO_VAR_CLASS(AutoLessVar);
DECLARE_AUTO_VAR_CLASS(AutoHatVar);
DECLARE_AUTO_VAR_CLASS(AutoPlusVar);
DECLARE_AUTO_VAR_CLASS(AutoStarVar);

class AutoSuffixDVar : public AutoVar {
 public:
  AutoSuffixDVar(Executor* ex, const char* sym, Var* wrapped)
      : AutoVar(ex, sym), wrapped_(wrapped) {
  }
  virtual ~AutoSuffixDVar() = default;
  virtual void Eval(Evaluator* ev, string* s) const override;

 private:
  Var* wrapped_;
};

class AutoSuffixFVar : public AutoVar {
 public:
  AutoSuffixFVar(Executor* ex, const char* sym, Var* wrapped)
      : AutoVar(ex, sym), wrapped_(wrapped) {}
  virtual ~AutoSuffixFVar() = default;
  virtual void Eval(Evaluator* ev, string* s) const override;

 private:
  Var* wrapped_;
};

struct Runner {
  Runner()
      : echo(true), ignore_error(false) {
  }
  StringPiece output;
  shared_ptr<string> cmd;
  bool echo;
  bool ignore_error;
  //StringPiece shell;
};

class Executor {
 public:
  explicit Executor(Evaluator* ev)
      : ev_(ev) {
    Vars* vars = ev_->mutable_vars();
#define INSERT_AUTO_VAR(name, sym) do {                                 \
      Var* v = new name(this, sym);                                     \
      (*vars)[STRING_PIECE(sym)] = v;                                   \
      (*vars)[STRING_PIECE(sym"D")] = new AutoSuffixDVar(this, sym"D", v); \
      (*vars)[STRING_PIECE(sym"F")] = new AutoSuffixFVar(this, sym"F", v); \
    } while (0)
    INSERT_AUTO_VAR(AutoAtVar, "@");
    INSERT_AUTO_VAR(AutoLessVar, "<");
    INSERT_AUTO_VAR(AutoHatVar, "^");
    INSERT_AUTO_VAR(AutoPlusVar, "+");
    INSERT_AUTO_VAR(AutoStarVar, "*");
  }

  void ExecNode(DepNode* n, DepNode* needed_by) {
    if (done_[n->output])
      return;
    done_[n->output] = true;

    LOG("ExecNode: %s for %s",
        n->output.as_string().c_str(),
        needed_by ? needed_by->output.as_string().c_str() : "(null)");

    for (DepNode* d : n->deps) {
      if (d->is_order_only && Exists(d->output)) {
        continue;
      }
      // TODO: Check the timestamp.
      if (Exists(d->output)) {
        continue;
      }
      ExecNode(d, n);
    }

    vector<Runner*> runners;
    CreateRunners(n, &runners);
    for (Runner* runner : runners) {
      if (runner->echo) {
        printf("%s\n", runner->cmd->c_str());
        fflush(stdout);
      }
      system(runner->cmd->c_str());
      delete runner;
    }
  }

  void CreateRunners(DepNode* n, vector<Runner*>* runners) {
    ev_->set_current_scope(n->rule_vars);
    current_dep_node_ = n;
    for (Value* v : n->cmds) {
      shared_ptr<string> cmd = v->Eval(ev_);
      while (true) {
        size_t index = cmd->find('\n');
        if (index == string::npos)
          break;

        Runner* runner = new Runner;
        runner->output = n->output;
        runner->cmd = make_shared<string>(cmd->substr(0, index));
        runners->push_back(runner);
        cmd = make_shared<string>(cmd->substr(index + 1));
      }
      Runner* runner = new Runner;
      runner->output = n->output;
      runner->cmd = cmd;
      runners->push_back(runner);
      continue;
    }
    ev_->set_current_scope(NULL);
  }

  const DepNode* current_dep_node() const { return current_dep_node_; }

 private:
  Vars* vars_;
  Evaluator* ev_;
  unordered_map<StringPiece, bool> done_;
  DepNode* current_dep_node_;
};

void AutoAtVar::Eval(Evaluator*, string* s) const {
  AppendString(ex_->current_dep_node()->output, s);
}

void AutoLessVar::Eval(Evaluator*, string* s) const {
  auto& ai = ex_->current_dep_node()->actual_inputs;
  if (!ai.empty())
    AppendString(ai[0], s);
}

void AutoHatVar::Eval(Evaluator*, string* s) const {
  unordered_set<StringPiece> seen;
  WordWriter ww(s);
  for (StringPiece ai : ex_->current_dep_node()->actual_inputs) {
    if (seen.insert(ai).second)
      ww.Write(ai);
  }
}

void AutoPlusVar::Eval(Evaluator*, string* s) const {
  WordWriter ww(s);
  for (StringPiece ai : ex_->current_dep_node()->actual_inputs) {
    ww.Write(ai);
  }
}

void AutoStarVar::Eval(Evaluator*, string* s) const {
  AppendString(StripExt(ex_->current_dep_node()->output), s);
}

void AutoSuffixDVar::Eval(Evaluator* ev, string* s) const {
  string buf;
  wrapped_->Eval(ev, &buf);
  WordWriter ww(s);
  for (StringPiece tok : WordScanner(buf)) {
    ww.Write(Dirname(tok));
  }
}

void AutoSuffixFVar::Eval(Evaluator* ev, string* s) const {
  string buf;
  wrapped_->Eval(ev, &buf);
  WordWriter ww(s);
  for (StringPiece tok : WordScanner(buf)) {
    ww.Write(Basename(tok));
  }
}

}  // namespace

void Exec(const vector<DepNode*>& roots, Evaluator* ev) {
  unique_ptr<Executor> executor(new Executor(ev));
  for (DepNode* root : roots) {
    executor->ExecNode(root, NULL);
  }
}
<commit_msg>[C++] Skip empty command<commit_after>// Copyright 2015 Google Inc. All rights reserved
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// +build ignore

#include "exec.h"

#include <stdio.h>
#include <stdlib.h>

#include <memory>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#include "dep.h"
#include "eval.h"
#include "fileutil.h"
#include "log.h"
#include "string_piece.h"
#include "strutil.h"
#include "value.h"
#include "var.h"

namespace {

class Executor;

class AutoVar : public Var {
 public:
  virtual const char* Flavor() const override {
    return "undefined";
  }
  virtual const char* Origin() const override {
    return "automatic";
  }

  virtual void AppendVar(Evaluator*, Value*) override { CHECK(false); }

  virtual StringPiece String() const override {
    ERROR("$(value %s) is not implemented yet", sym_);
    return "";
  }

  virtual string DebugString() const override {
    return string("AutoVar(") + sym_ + ")";
  }

 protected:
  AutoVar(Executor* ex, const char* sym) : ex_(ex), sym_(sym) {}
  virtual ~AutoVar() = default;

  Executor* ex_;
  const char* sym_;
};

#define DECLARE_AUTO_VAR_CLASS(name)                            \
  class name : public AutoVar {                                 \
   public:                                                      \
   name(Executor* ex, const char* sym)                          \
       : AutoVar(ex, sym) {}                                    \
   virtual ~name() = default;                                   \
   virtual void Eval(Evaluator* ev, string* s) const override;  \
  }

DECLARE_AUTO_VAR_CLASS(AutoAtVar);
DECLARE_AUTO_VAR_CLASS(AutoLessVar);
DECLARE_AUTO_VAR_CLASS(AutoHatVar);
DECLARE_AUTO_VAR_CLASS(AutoPlusVar);
DECLARE_AUTO_VAR_CLASS(AutoStarVar);

class AutoSuffixDVar : public AutoVar {
 public:
  AutoSuffixDVar(Executor* ex, const char* sym, Var* wrapped)
      : AutoVar(ex, sym), wrapped_(wrapped) {
  }
  virtual ~AutoSuffixDVar() = default;
  virtual void Eval(Evaluator* ev, string* s) const override;

 private:
  Var* wrapped_;
};

class AutoSuffixFVar : public AutoVar {
 public:
  AutoSuffixFVar(Executor* ex, const char* sym, Var* wrapped)
      : AutoVar(ex, sym), wrapped_(wrapped) {}
  virtual ~AutoSuffixFVar() = default;
  virtual void Eval(Evaluator* ev, string* s) const override;

 private:
  Var* wrapped_;
};

struct Runner {
  Runner()
      : echo(true), ignore_error(false) {
  }
  StringPiece output;
  shared_ptr<string> cmd;
  bool echo;
  bool ignore_error;
  //StringPiece shell;
};

class Executor {
 public:
  explicit Executor(Evaluator* ev)
      : ev_(ev) {
    Vars* vars = ev_->mutable_vars();
#define INSERT_AUTO_VAR(name, sym) do {                                 \
      Var* v = new name(this, sym);                                     \
      (*vars)[STRING_PIECE(sym)] = v;                                   \
      (*vars)[STRING_PIECE(sym"D")] = new AutoSuffixDVar(this, sym"D", v); \
      (*vars)[STRING_PIECE(sym"F")] = new AutoSuffixFVar(this, sym"F", v); \
    } while (0)
    INSERT_AUTO_VAR(AutoAtVar, "@");
    INSERT_AUTO_VAR(AutoLessVar, "<");
    INSERT_AUTO_VAR(AutoHatVar, "^");
    INSERT_AUTO_VAR(AutoPlusVar, "+");
    INSERT_AUTO_VAR(AutoStarVar, "*");
  }

  void ExecNode(DepNode* n, DepNode* needed_by) {
    if (done_[n->output])
      return;
    done_[n->output] = true;

    LOG("ExecNode: %s for %s",
        n->output.as_string().c_str(),
        needed_by ? needed_by->output.as_string().c_str() : "(null)");

    for (DepNode* d : n->deps) {
      if (d->is_order_only && Exists(d->output)) {
        continue;
      }
      // TODO: Check the timestamp.
      if (Exists(d->output)) {
        continue;
      }
      ExecNode(d, n);
    }

    vector<Runner*> runners;
    CreateRunners(n, &runners);
    for (Runner* runner : runners) {
      if (runner->echo) {
        printf("%s\n", runner->cmd->c_str());
        fflush(stdout);
      }
      system(runner->cmd->c_str());
      delete runner;
    }
  }

  void CreateRunners(DepNode* n, vector<Runner*>* runners) {
    ev_->set_current_scope(n->rule_vars);
    current_dep_node_ = n;
    for (Value* v : n->cmds) {
      shared_ptr<string> cmd = v->Eval(ev_);
      if (TrimSpace(*cmd) == "")
        continue;
      while (true) {
        size_t index = cmd->find('\n');
        if (index == string::npos)
          break;

        Runner* runner = new Runner;
        runner->output = n->output;
        runner->cmd = make_shared<string>(cmd->substr(0, index));
        runners->push_back(runner);
        cmd = make_shared<string>(cmd->substr(index + 1));
      }
      Runner* runner = new Runner;
      runner->output = n->output;
      runner->cmd = cmd;
      runners->push_back(runner);
      continue;
    }
    ev_->set_current_scope(NULL);
  }

  const DepNode* current_dep_node() const { return current_dep_node_; }

 private:
  Vars* vars_;
  Evaluator* ev_;
  unordered_map<StringPiece, bool> done_;
  DepNode* current_dep_node_;
};

void AutoAtVar::Eval(Evaluator*, string* s) const {
  AppendString(ex_->current_dep_node()->output, s);
}

void AutoLessVar::Eval(Evaluator*, string* s) const {
  auto& ai = ex_->current_dep_node()->actual_inputs;
  if (!ai.empty())
    AppendString(ai[0], s);
}

void AutoHatVar::Eval(Evaluator*, string* s) const {
  unordered_set<StringPiece> seen;
  WordWriter ww(s);
  for (StringPiece ai : ex_->current_dep_node()->actual_inputs) {
    if (seen.insert(ai).second)
      ww.Write(ai);
  }
}

void AutoPlusVar::Eval(Evaluator*, string* s) const {
  WordWriter ww(s);
  for (StringPiece ai : ex_->current_dep_node()->actual_inputs) {
    ww.Write(ai);
  }
}

void AutoStarVar::Eval(Evaluator*, string* s) const {
  AppendString(StripExt(ex_->current_dep_node()->output), s);
}

void AutoSuffixDVar::Eval(Evaluator* ev, string* s) const {
  string buf;
  wrapped_->Eval(ev, &buf);
  WordWriter ww(s);
  for (StringPiece tok : WordScanner(buf)) {
    ww.Write(Dirname(tok));
  }
}

void AutoSuffixFVar::Eval(Evaluator* ev, string* s) const {
  string buf;
  wrapped_->Eval(ev, &buf);
  WordWriter ww(s);
  for (StringPiece tok : WordScanner(buf)) {
    ww.Write(Basename(tok));
  }
}

}  // namespace

void Exec(const vector<DepNode*>& roots, Evaluator* ev) {
  unique_ptr<Executor> executor(new Executor(ev));
  for (DepNode* root : roots) {
    executor->ExecNode(root, NULL);
  }
}
<|endoftext|>


<commit_before>#include <turbo/memory/alignment.hpp>
#include <cstdint>
#include <gtest/gtest.h>

namespace tme = turbo::memory;

TEST(alignment_test, align_single_element)
{
    std::uint8_t buffer[64];
    std::uint8_t* pointer1 = &buffer[0];
    if ((reinterpret_cast<std::uintptr_t>(pointer1) % 2U) == 0)
    {
	++pointer1;
    }
    std::uint8_t* expected1 = pointer1 + 1;
    std::size_t size1 = sizeof(buffer);
    void* tmp1 = static_cast<void*>(pointer1);
    tme::align(sizeof(std::uint16_t), sizeof(std::uint16_t), tmp1, size1);
    pointer1 = static_cast<std::uint8_t*>(tmp1);
    EXPECT_EQ(expected1, pointer1) << "Pointer is not aligned";
}
<commit_msg>added more test cases<commit_after>#include <turbo/memory/alignment.hpp>
#include <cstdint>
#include <gtest/gtest.h>

namespace tme = turbo::memory;

TEST(alignment_test, align_single_element)
{
    std::uint8_t buffer1[64];
    std::uint8_t* actual_ptr1 = &buffer1[0];
    std::size_t actual_size1 = sizeof(buffer1);
    if ((reinterpret_cast<std::uintptr_t>(actual_ptr1) % 2U) == 0)
    {
	++actual_ptr1;
    }
    std::uint8_t* expected_ptr1 = actual_ptr1 + 1;
    std::size_t expected_size1 = actual_size1 - 1;
    void* tmp1 = static_cast<void*>(actual_ptr1);
    tme::align(sizeof(std::uint16_t), sizeof(std::uint16_t), tmp1, actual_size1);
    actual_ptr1 = static_cast<std::uint8_t*>(tmp1);
    EXPECT_EQ(expected_ptr1, actual_ptr1) << "Pointer is not aligned";
    EXPECT_EQ(expected_size1, actual_size1) << "Incorrect available space";

    std::uint8_t buffer2[64];
    std::uint8_t* actual_ptr2 = &buffer2[0];
    std::size_t actual_size2 = sizeof(buffer2);
    if ((reinterpret_cast<std::uintptr_t>(actual_ptr2) % 2U) == 0)
    {
	++actual_ptr2;
    }
    std::uint8_t* expected_ptr2 = actual_ptr2 + 7;
    std::size_t expected_size2 = actual_size2 - 7;
    void* tmp2 = static_cast<void*>(actual_ptr2);
    tme::align(sizeof(std::uint64_t), sizeof(std::uint64_t), tmp2, actual_size2);
    actual_ptr2 = static_cast<std::uint8_t*>(tmp2);
    EXPECT_EQ(expected_ptr2, actual_ptr2) << "Pointer is not aligned";
    EXPECT_EQ(expected_size2, actual_size2) << "Incorrect available space";
}

TEST(alignment_test, align_multiple_element)
{
    std::uint8_t buffer1[64];
    std::uint8_t* actual_ptr1 = &buffer1[0];
    std::size_t actual_size1 = sizeof(buffer1);
    if ((reinterpret_cast<std::uintptr_t>(actual_ptr1) % 2U) == 0)
    {
	++actual_ptr1;
    }
    std::uint8_t* expected_ptr1 = actual_ptr1 + 3;
    std::size_t expected_size1 = actual_size1 - 3;
    void* tmp1 = static_cast<void*>(actual_ptr1);
    tme::align(sizeof(std::uint32_t), sizeof(std::uint16_t), tmp1, actual_size1);
    actual_ptr1 = static_cast<std::uint8_t*>(tmp1);
    EXPECT_EQ(expected_ptr1, actual_ptr1) << "Pointer is not aligned";
    EXPECT_EQ(expected_size1, actual_size1) << "Incorrect available space";
}
<|endoftext|>


<commit_before>// Test that a module constructor can not map memory over the MSan heap
// (without MAP_FIXED, of course). Current implementation ensures this by
// mapping the heap early, in __msan_init.
//
// RUN: %clangxx_msan -O0 %s -o %t_1
// RUN: %clangxx_msan -O0 -DHEAP_ADDRESS=$(%run %t_1) %s -o %t_2 && %run %t_2

#include <assert.h>
#include <stdio.h>
#include <sys/mman.h>
#include <stdlib.h>

#ifdef HEAP_ADDRESS
struct A {
  A() {
    void *const hint = reinterpret_cast<void *>(HEAP_ADDRESS);
    void *p = mmap(hint, 4096, PROT_READ | PROT_WRITE,
                   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    // This address must be already mapped. Check that mmap() succeeds, but at a
    // different address.
    assert(p != reinterpret_cast<void *>(-1));
    assert(p != hint);
  }
} a;
#endif

int main() {
  void *p = malloc(10);
  printf("0x%zx\n", reinterpret_cast<size_t>(p) & (~0xfff));
  free(p);
}
<commit_msg>[msan] Disable allocator_mapping test on mips64 and aarch64.<commit_after>// Test that a module constructor can not map memory over the MSan heap
// (without MAP_FIXED, of course). Current implementation ensures this by
// mapping the heap early, in __msan_init.
//
// RUN: %clangxx_msan -O0 %s -o %t_1
// RUN: %clangxx_msan -O0 -DHEAP_ADDRESS=$(%run %t_1) %s -o %t_2 && %run %t_2
//
// This test only makes sense for the 64-bit allocator. The 32-bit allocator
// does not have a fixed mapping. Exclude platforms that use the 32-bit
// allocator.
// UNSUPPORTED: mips64,aarch64

#include <assert.h>
#include <stdio.h>
#include <sys/mman.h>
#include <stdlib.h>

#ifdef HEAP_ADDRESS
struct A {
  A() {
    void *const hint = reinterpret_cast<void *>(HEAP_ADDRESS);
    void *p = mmap(hint, 4096, PROT_READ | PROT_WRITE,
                   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    // This address must be already mapped. Check that mmap() succeeds, but at a
    // different address.
    assert(p != reinterpret_cast<void *>(-1));
    assert(p != hint);
  }
} a;
#endif

int main() {
  void *p = malloc(10);
  printf("0x%zx\n", reinterpret_cast<size_t>(p) & (~0xfff));
  free(p);
}
<|endoftext|>


<commit_before>// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: nadavs@google.com <Nadav Samet>
//         Jin Qing (http://blog.csdn.net/jq0123)

#include <iostream>
#include <boost/optional/optional.hpp>
#include <boost/thread/thread.hpp>
#include <glog/logging.h>
#include <gtest/gtest.h>
#include <zmq.hpp>

#include "rpcz/application.hpp"
#include "rpcz/connection.hpp"
#include "rpcz/connection_manager.hpp"
#include "rpcz/connection_manager_ptr.hpp"
#include "rpcz/replier.hpp"
#include "rpcz/rpc_channel.hpp"
#include "rpcz/server.hpp"
#include "rpcz/sync_event.hpp"

#include "proto/search.pb.h"
#include "proto/search.rpcz.h"

using namespace std;

namespace rpcz {

class SearchServiceImpl : public SearchService {
 public:
  SearchServiceImpl() {
  }

  ~SearchServiceImpl() {
  }

  virtual void Search(
      const SearchRequest& request,
      replier replier_copy) {
    if (request.query() == "timeout") {
      // We "lose" the request.
      return;
    }

    SearchResponse response;
    response.add_results("The search for " + request.query());
    response.add_results("is great");
    replier_copy.send(response);
  }
};

class server_test : public ::testing::Test {
 public:
  server_test() :
      context_(new zmq::context_t(1)) /* scoped_ptr */ {
    EXPECT_TRUE(connection_manager::is_destroyed());
    application::set_zmq_context(context_.get());
    application::set_connection_manager_threads(10);
    connection_.reset(new connection);
    server_.reset(new server);
    start_server();
  }

  ~server_test() {
    // terminate the context, which will cause the thread to quit.
    application::terminate();
    server_.reset();
    service_.reset();
    connection_.reset();

    EXPECT_TRUE(connection_manager::is_destroyed());
    context_.reset();
  }

  void start_server() {
    rpcz::connection_manager_ptr cm = rpcz::connection_manager::get();
    service_.reset(new SearchServiceImpl);
    server_->register_singleton_service(*service_);
    server_->bind("inproc://myserver.frontend");
    *connection_ = cm->connect("inproc://myserver.frontend");
  }

protected:
  // destruct in reversed order
  scoped_ptr<zmq::context_t> context_;  // destruct last
  scoped_ptr<connection> connection_;
  scoped_ptr<SearchServiceImpl> service_;
  // Server must destruct before service. (Or unregister services before destruct.)
  scoped_ptr<server> server_;
};

struct handler {
  rpcz::sync_event sync;
  SearchResponse response;
  boost::optional<rpc_error> error;

  void operator()(const rpc_error* e, const SearchResponse& resp)
  {
    if (e) {
      error.reset(*e);
    } else {
      response = resp;
    }
    sync.signal();
  }
};

/*
Test all kinds of request interfaces.
. Sync or async
. Explicit deadline or implicit default deadline
. Return response or use output parameter (only for sync)
. Explicit error handler or implicit default error handler (only for async)
There are 4 sync interfaces and 4 async interfaces.

Ordered as the declaration in search.rpcz.h.
*/

// Async interfaces:

TEST_F(server_test, AsyncRequestWithTimeout) {
  SearchService_Stub stub(rpc_channel::create(*connection_), true);
  SearchRequest request;
  request.set_query("timeout");
  handler hdl;
  stub.async_Search(request,
      boost::ref(hdl),
      1/*ms*/);
  hdl.sync.wait();
  ASSERT_TRUE(hdl.error);
  ASSERT_EQ(rpc_response_header::DEADLINE_EXCEEDED, hdl.error->get_status());
}

TEST_F(server_test, AsyncRequest) {
  SearchService_Stub stub(rpc_channel::create(*connection_), true);
  SearchRequest request;
  request.set_query("stone");
  handler hdl;
  stub.async_Search(request, boost::ref(hdl));
  hdl.sync.wait();

  ASSERT_FALSE(hdl.error);
  ASSERT_EQ(2, hdl.response.results_size());
  ASSERT_EQ("The search for stone", hdl.response.results(0));
}

TEST_F(server_test, AsyncOnewayRequest) {
  SearchService_Stub stub(rpc_channel::create(*connection_), true);
  SearchRequest request;
  request.set_query("rocket");
  // XXX fix crash on reset...
  //stub.async_Search(request, 0/*ms*/);
  //stub.async_Search(request, 1/*ms*/);
  //stub.async_Search(request, 10/*ms*/);
  //stub.async_Search(request, 1000/*ms*/);
  //stub.async_Search(request, 10000/*ms*/);
  //stub.async_Search(request, -1/*ms*/);
}

TEST_F(server_test, AsyncOnewayRequestDefaultMs) {
  SearchService_Stub stub(rpc_channel::create(*connection_), true);
  SearchRequest request;
  request.set_query("robot");
  // XXX fix crash on reset...
  //stub.async_Search(request);
}

// Sync interfaces:

TEST_F(server_test, SyncRequest) {
  SearchService_Stub stub(rpc_channel::create(*connection_), true);
  SearchRequest request;
  request.set_query("student");
  SearchResponse response;
  stub.Search(request, 5000/*ms*/, &response);
  ASSERT_EQ(2, response.results_size());
  ASSERT_EQ("The search for student", response.results(0));
}

TEST_F(server_test, SyncRequestDefaultMs) {
  SearchService_Stub stub(rpc_channel::create(*connection_), true);
  SearchRequest request;
  request.set_query("stupid");
  SearchResponse response;
  stub.Search(request, &response);
  ASSERT_EQ(2, response.results_size());
  ASSERT_EQ("The search for stupid", response.results(0));
}

TEST_F(server_test, SyncRequestReturn) {
  SearchService_Stub stub(rpc_channel::create(*connection_), true);
  SearchRequest request;
  request.set_query("spool");
  SearchResponse response = stub.Search(request, 5000/*ms*/);
  ASSERT_EQ(2, response.results_size());
  ASSERT_EQ("The search for spool", response.results(0));
}

TEST_F(server_test, SyncRequestReturnDefaultMs) {
  SearchService_Stub stub(rpc_channel::create(*connection_), true);
  SearchRequest request;
  request.set_query("star");
  SearchResponse response = stub.Search(request);
  ASSERT_EQ(2, response.results_size());
  ASSERT_EQ("The search for star", response.results(0));
}

// Other interfaces:

TEST_F(server_test, SetDefaulDeadlineMs) {
  SearchService_Stub stub(rpc_channel::create(*connection_), true);
  SearchRequest request;
  SearchResponse response;
  request.set_query("timeout");
  stub.set_default_deadline_ms(1);
  try {
    stub.Search(request, &response);
    ASSERT_TRUE(false);
  } catch (const rpc_error& error) {
    ASSERT_EQ(status::DEADLINE_EXCEEDED, error.get_status());
    return;
  }
  ASSERT_TRUE(false);
}

}  // namespace
<commit_msg>fix test<commit_after>// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: nadavs@google.com <Nadav Samet>
//         Jin Qing (http://blog.csdn.net/jq0123)

#include <iostream>
#include <boost/optional/optional.hpp>
#include <boost/thread/thread.hpp>
#include <glog/logging.h>
#include <gtest/gtest.h>
#include <zmq.hpp>

#include "rpcz/application.hpp"
#include "rpcz/connection.hpp"
#include "rpcz/connection_manager.hpp"
#include "rpcz/connection_manager_ptr.hpp"
#include "rpcz/replier.hpp"
#include "rpcz/rpc_channel.hpp"
#include "rpcz/server.hpp"
#include "rpcz/sync_event.hpp"

#include "proto/search.pb.h"
#include "proto/search.rpcz.h"

using namespace std;

namespace rpcz {

class SearchServiceImpl : public SearchService {
 public:
  SearchServiceImpl() {
  }

  ~SearchServiceImpl() {
  }

  virtual void Search(
      const SearchRequest& request,
      replier replier_copy) {
    if (request.query() == "timeout") {
      // We "lose" the request.
      return;
    }

    SearchResponse response;
    response.add_results("The search for " + request.query());
    response.add_results("is great");
    replier_copy.send(response);
  }
};

class server_test : public ::testing::Test {
 public:
  server_test() :
      context_(new zmq::context_t(1)) /* scoped_ptr */ {
    EXPECT_TRUE(connection_manager::is_destroyed());
    application::set_zmq_context(context_.get());
    application::set_connection_manager_threads(10);
    connection_.reset(new connection);
    server_.reset(new server);
    start_server();
  }

  ~server_test() {
    // terminate the context, which will cause the thread to quit.
    application::terminate();
    server_.reset();
    service_.reset();
    connection_.reset();

    EXPECT_TRUE(connection_manager::is_destroyed());
    context_.reset();
  }

  void start_server() {
    rpcz::connection_manager_ptr cm = rpcz::connection_manager::get();
    service_.reset(new SearchServiceImpl);
    server_->register_singleton_service(*service_);
    server_->bind("inproc://myserver.frontend");
    *connection_ = cm->connect("inproc://myserver.frontend");
  }

protected:
  // destruct in reversed order
  scoped_ptr<zmq::context_t> context_;  // destruct last
  scoped_ptr<connection> connection_;
  scoped_ptr<SearchServiceImpl> service_;
  // Server must destruct before service. (Or unregister services before destruct.)
  scoped_ptr<server> server_;
};

struct handler {
  rpcz::sync_event sync;
  SearchResponse response;
  boost::optional<rpc_error> error;

  void operator()(const rpc_error* e, const SearchResponse& resp)
  {
    if (e) {
      error.reset(*e);
    } else {
      response = resp;
    }
    sync.signal();
  }
};

/*
Test all kinds of request interfaces.
. Sync or async
. Explicit deadline or implicit default deadline
. Return response or use output parameter (only for sync)
. Explicit error handler or implicit default error handler (only for async)
There are 4 sync interfaces and 4 async interfaces.

Ordered as the declaration in search.rpcz.h.
*/

// Async interfaces:

TEST_F(server_test, AsyncRequestWithTimeout) {
  SearchService_Stub stub(rpc_channel::create(*connection_), true);
  SearchRequest request;
  request.set_query("timeout");
  handler hdl;
  stub.async_Search(request,
      boost::ref(hdl),
      1/*ms*/);
  hdl.sync.wait();
  ASSERT_TRUE(hdl.error);
  ASSERT_EQ(rpc_response_header::DEADLINE_EXCEEDED, hdl.error->get_status());
}

TEST_F(server_test, AsyncRequest) {
  SearchService_Stub stub(rpc_channel::create(*connection_), true);
  SearchRequest request;
  request.set_query("stone");
  handler hdl;
  stub.async_Search(request, boost::ref(hdl));
  hdl.sync.wait();

  ASSERT_FALSE(hdl.error);
  ASSERT_EQ(2, hdl.response.results_size());
  ASSERT_EQ("The search for stone", hdl.response.results(0));
}

TEST_F(server_test, AsyncOnewayRequest) {
  SearchService_Stub stub(rpc_channel::create(*connection_), true);
  SearchRequest request;
  request.set_query("rocket");
  stub.async_Search(request, 0/*ms*/);
  stub.async_Search(request, 1/*ms*/);
  stub.async_Search(request, 10/*ms*/);
  stub.async_Search(request, 1000/*ms*/);
  stub.async_Search(request, 10000/*ms*/);
  stub.async_Search(request, -1/*ms*/);

  // Sync request to end. Crash on reset if not.
  (void)stub.Search(request);
}

TEST_F(server_test, AsyncOnewayRequestDefaultMs) {
  SearchService_Stub stub(rpc_channel::create(*connection_), true);
  SearchRequest request;
  request.set_query("robot");
  stub.async_Search(request);

  // Sync request to end. Crash on reset if not.
  (void)stub.Search(request);
}

// Sync interfaces:

TEST_F(server_test, SyncRequest) {
  SearchService_Stub stub(rpc_channel::create(*connection_), true);
  SearchRequest request;
  request.set_query("student");
  SearchResponse response;
  stub.Search(request, 5000/*ms*/, &response);
  ASSERT_EQ(2, response.results_size());
  ASSERT_EQ("The search for student", response.results(0));
}

TEST_F(server_test, SyncRequestDefaultMs) {
  SearchService_Stub stub(rpc_channel::create(*connection_), true);
  SearchRequest request;
  request.set_query("stupid");
  SearchResponse response;
  stub.Search(request, &response);
  ASSERT_EQ(2, response.results_size());
  ASSERT_EQ("The search for stupid", response.results(0));
}

TEST_F(server_test, SyncRequestReturn) {
  SearchService_Stub stub(rpc_channel::create(*connection_), true);
  SearchRequest request;
  request.set_query("spool");
  SearchResponse response = stub.Search(request, 5000/*ms*/);
  ASSERT_EQ(2, response.results_size());
  ASSERT_EQ("The search for spool", response.results(0));
}

TEST_F(server_test, SyncRequestReturnDefaultMs) {
  SearchService_Stub stub(rpc_channel::create(*connection_), true);
  SearchRequest request;
  request.set_query("star");
  SearchResponse response = stub.Search(request);
  ASSERT_EQ(2, response.results_size());
  ASSERT_EQ("The search for star", response.results(0));
}

// Other interfaces:

TEST_F(server_test, SetDefaulDeadlineMs) {
  SearchService_Stub stub(rpc_channel::create(*connection_), true);
  SearchRequest request;
  SearchResponse response;
  request.set_query("timeout");
  stub.set_default_deadline_ms(1);
  try {
    stub.Search(request, &response);
    ASSERT_TRUE(false);
  } catch (const rpc_error& error) {
    ASSERT_EQ(status::DEADLINE_EXCEEDED, error.get_status());
    return;
  }
  ASSERT_TRUE(false);
}

}  // namespace
<|endoftext|>


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

#include "itkParameterFileParser.h"

#include <itksys/SystemTools.hxx>
#include <itksys/RegularExpression.hxx>

#include <fstream>

namespace itk
{

/**
 * **************** Constructor ***************
 */

ParameterFileParser::ParameterFileParser() = default;

/**
 * **************** Destructor ***************
 */

ParameterFileParser ::~ParameterFileParser() = default;

/**
 * **************** GetParameterMap ***************
 */

const ParameterFileParser::ParameterMapType &
ParameterFileParser::GetParameterMap(void) const
{
  return this->m_ParameterMap;

} // end GetParameterMap()

/**
 * **************** ReadParameterFile ***************
 */

void
ParameterFileParser::ReadParameterFile(void)
{
  /** Perform some basic checks. */
  this->BasicFileChecking();

  /** Open the parameter file for reading. */
  std::ifstream parameterFile(this->m_ParameterFileName);

  /** Check if it opened. */
  if (!parameterFile.is_open())
  {
    itkExceptionMacro(<< "ERROR: could not open " << this->m_ParameterFileName << " for reading.");
  }

  /** Clear the map. */
  this->m_ParameterMap.clear();

  /** Loop over the parameter file, line by line. */
  std::string lineIn;
  std::string lineOut;
  while (parameterFile.good())
  {
    /** Extract a line. */
    itksys::SystemTools::GetLineFromStream(parameterFile, lineIn);

    /** Check this line. */
    const bool validLine = this->CheckLine(lineIn, lineOut);

    if (validLine)
    {
      /** Get the parameter name from this line and store it. */
      this->GetParameterFromLine(lineIn, lineOut);
    }
    // Otherwise, we simply ignore this line
  }

} // end ReadParameterFile()

/**
 * **************** BasicFileChecking ***************
 */

void
ParameterFileParser::BasicFileChecking(void) const
{
  /** Check if the file name is given. */
  if (this->m_ParameterFileName.empty())
  {
    itkExceptionMacro(<< "ERROR: FileName has not been set.");
  }

  /** Basic error checking: existence. */
  const bool exists = itksys::SystemTools::FileExists(this->m_ParameterFileName);
  if (!exists)
  {
    itkExceptionMacro(<< "ERROR: the file " << this->m_ParameterFileName << " does not exist.");
  }

  /** Basic error checking: file or directory. */
  const bool isDir = itksys::SystemTools::FileIsDirectory(this->m_ParameterFileName);
  if (isDir)
  {
    itkExceptionMacro(<< "ERROR: the file " << this->m_ParameterFileName << " is a directory.");
  }

  /** Check the extension. */
  const std::string ext = itksys::SystemTools::GetFilenameLastExtension(this->m_ParameterFileName);
  if (ext != ".txt")
  {
    itkExceptionMacro(<< "ERROR: the file " << this->m_ParameterFileName << " should be a text file (*.txt).");
  }

} // end BasicFileChecking()

/**
 * **************** CheckLine ***************
 */

bool
ParameterFileParser::CheckLine(const std::string & lineIn, std::string & lineOut) const
{
  /** Preprocessing of lineIn:
   * 1) Replace tabs with spaces
   * 2) Remove everything after comment sign //
   * 3) Remove leading spaces
   * 4) Remove trailing spaces
   */
  lineOut = lineIn;
  itksys::SystemTools::ReplaceString(lineOut, "\t", " ");

  itksys::RegularExpression commentPart("//");
  if (commentPart.find(lineOut))
  {
    lineOut = lineOut.substr(0, commentPart.start());
  }

  itksys::RegularExpression leadingSpaces("^[ ]*(.*)");
  leadingSpaces.find(lineOut);
  lineOut = leadingSpaces.match(1);

  itksys::RegularExpression trailingSpaces("[ \t]+$");
  if (trailingSpaces.find(lineOut))
  {
    lineOut = lineOut.substr(0, trailingSpaces.start());
  }

  /**
   * Checks:
   * 1. Empty line -> false
   * 2. Comment (line starts with "//") -> false
   * 3. Line is not between brackets (...) -> exception
   * 4. Line contains less than two words -> exception
   *
   * Otherwise return true.
   */

  /** 1. Check for non-empty lines. */
  itksys::RegularExpression reNonEmptyLine("[^ ]+");
  const bool                match1 = reNonEmptyLine.find(lineOut);
  if (!match1)
  {
    return false;
  }

  /** 2. Check for comments. */
  itksys::RegularExpression reComment("^//");
  const bool                match2 = reComment.find(lineOut);
  if (match2)
  {
    return false;
  }

  /** 3. Check if line is between brackets. */
  if (!itksys::SystemTools::StringStartsWith(lineOut, "(") || !itksys::SystemTools::StringEndsWith(lineOut, ")"))
  {
    const std::string hint = "Line is not between brackets: \"(...)\".";
    this->ThrowException(lineIn, hint);
  }

  /** Remove brackets. */
  lineOut = lineOut.substr(1, lineOut.size() - 2);

  /** 4. Check: the line should contain at least two words. */
  itksys::RegularExpression reTwoWords("([ ]+)([^ ]+)");
  const bool                match4 = reTwoWords.find(lineOut);
  if (!match4)
  {
    const std::string hint = "Line does not contain a parameter name and value.";
    this->ThrowException(lineIn, hint);
  }

  /** At this point we know its at least a line containing a parameter.
   * However, this line can still be invalid, for example:
   * (string &^%^*)
   * This will be checked later.
   */

  return true;

} // end CheckLine()

/**
 * **************** GetParameterFromLine ***************
 */

void
ParameterFileParser::GetParameterFromLine(const std::string & fullLine, const std::string & line)
{
  /** A line has a parameter name followed by one or more parameters.
   * They are all separated by one or more spaces (all tabs have been
   * removed previously) or by quotes in case of strings. So,
   * 1) we split the line at the spaces or quotes
   * 2) the first one is the parameter name
   * 3) the other strings that are not a series of spaces, are parameter values
   */

  /** 1) Split the line. */
  std::vector<std::string> splittedLine;
  this->SplitLine(fullLine, line, splittedLine);

  /** 2) Get the parameter name. */
  std::string parameterName = splittedLine[0];
  itksys::SystemTools::ReplaceString(parameterName, " ", "");
  splittedLine.erase(splittedLine.begin());

  /** 3) Get the parameter values. */
  std::vector<std::string> parameterValues;
  for (const auto & value : splittedLine)
  {
    if (!value.empty())
    {
      parameterValues.push_back(value);
    }
  }

  /** 4) Perform some checks on the parameter name. */
  itksys::RegularExpression reInvalidCharacters1("[.,:;!@#$%^&-+|<>?]");
  const bool                match = reInvalidCharacters1.find(parameterName);
  if (match)
  {
    const std::string hint = "The parameter \"" + parameterName + "\" contains invalid characters (.,:;!@#$%^&-+|<>?).";
    this->ThrowException(fullLine, hint);
  }

  /** 5) Perform checks on the parameter values. */
  itksys::RegularExpression reInvalidCharacters2("[,;!@#$%&|<>?]");
  for (const auto & parameterValue : parameterValues)
  {
    /** For all entries some characters are not allowed. */
    if (reInvalidCharacters2.find(parameterValue))
    {
      const std::string hint =
        "The parameter value \"" + parameterValue + "\" contains invalid characters (,;!@#$%&|<>?).";
      this->ThrowException(fullLine, hint);
    }
  }

  /** 6) Insert this combination in the parameter map. */
  if (this->m_ParameterMap.count(parameterName))
  {
    const std::string hint = "The parameter \"" + parameterName + "\" is specified more than once.";
    this->ThrowException(fullLine, hint);
  }
  else
  {
    this->m_ParameterMap.insert(make_pair(parameterName, parameterValues));
  }

} // end GetParameterFromLine()

/**
 * **************** SplitLine ***************
 */

void
ParameterFileParser::SplitLine(const std::string &        fullLine,
                               const std::string &        line,
                               std::vector<std::string> & splittedLine) const
{
  splittedLine.clear();
  splittedLine.resize(1);

  /** Count the number of quotes in the line. If it is an odd value, the
   * line contains an error; strings should start and end with a quote, so
   * the total number of quotes is even.
   */
  std::size_t numQuotes = itksys::SystemTools::CountChar(line.c_str(), '"');
  if (numQuotes % 2 == 1)
  {
    /** An invalid parameter line. */
    const std::string hint = "This line has an odd number of quotes (\").";
    this->ThrowException(fullLine, hint);
  }

  /** Loop over the line. */
  unsigned int index = 0;
  numQuotes = 0;
  for (const char currentChar : line)
  {
    if (currentChar == '"')
    {
      /** Start a new element. */
      splittedLine.push_back("");
      index++;
      numQuotes++;
    }
    else if (currentChar == ' ')
    {
      /** Only start a new element if it is not a quote, otherwise just add
       * the space to the string.
       */
      if (numQuotes % 2 == 0)
      {
        splittedLine.push_back("");
        index++;
      }
      else
      {
        splittedLine[index].push_back(currentChar);
      }
    }
    else
    {
      /** Add this character to the element. */
      splittedLine[index].push_back(currentChar);
    }
  }

} // end SplitLine()

/**
 * **************** ThrowException ***************
 */

void
ParameterFileParser::ThrowException(const std::string & line, const std::string & hint) const
{
  /** Construct an error message. */
  const std::string errorMessage = "ERROR: the following line in your parameter file is invalid: \n\"" + line + "\"\n" +
                                   hint + "\nPlease correct you parameter file!";

  /** Throw exception. */
  itkExceptionMacro(<< errorMessage);

} // end ThrowException()

/**
 * **************** ReturnParameterFileAsString ***************
 */

std::string
ParameterFileParser::ReturnParameterFileAsString(void)
{
  /** Perform some basic checks. */
  this->BasicFileChecking();

  /** Open the parameter file for reading. */
  std::ifstream parameterFile(this->m_ParameterFileName);

  /** Check if it opened. */
  if (!parameterFile.is_open())
  {
    itkExceptionMacro(<< "ERROR: could not open " << this->m_ParameterFileName << " for reading.");
  }

  /** Loop over the parameter file, line by line. */
  std::string line;
  std::string output;
  while (parameterFile.good())
  {
    /** Extract a line. */
    itksys::SystemTools::GetLineFromStream(parameterFile, line); // \todo: returns bool

    output += line + "\n";
  }

  /** Return the string. */
  return output;

} // end ReturnParameterFileAsString()

} // end namespace itk
<commit_msg>ENH: Lift ParameterFileParser restrictions on chars of parameter values<commit_after>/*=========================================================================
 *
 *  Copyright UMC Utrecht and contributors
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#include "itkParameterFileParser.h"

#include <itksys/SystemTools.hxx>
#include <itksys/RegularExpression.hxx>

#include <fstream>

namespace itk
{

/**
 * **************** Constructor ***************
 */

ParameterFileParser::ParameterFileParser() = default;

/**
 * **************** Destructor ***************
 */

ParameterFileParser ::~ParameterFileParser() = default;

/**
 * **************** GetParameterMap ***************
 */

const ParameterFileParser::ParameterMapType &
ParameterFileParser::GetParameterMap(void) const
{
  return this->m_ParameterMap;

} // end GetParameterMap()

/**
 * **************** ReadParameterFile ***************
 */

void
ParameterFileParser::ReadParameterFile(void)
{
  /** Perform some basic checks. */
  this->BasicFileChecking();

  /** Open the parameter file for reading. */
  std::ifstream parameterFile(this->m_ParameterFileName);

  /** Check if it opened. */
  if (!parameterFile.is_open())
  {
    itkExceptionMacro(<< "ERROR: could not open " << this->m_ParameterFileName << " for reading.");
  }

  /** Clear the map. */
  this->m_ParameterMap.clear();

  /** Loop over the parameter file, line by line. */
  std::string lineIn;
  std::string lineOut;
  while (parameterFile.good())
  {
    /** Extract a line. */
    itksys::SystemTools::GetLineFromStream(parameterFile, lineIn);

    /** Check this line. */
    const bool validLine = this->CheckLine(lineIn, lineOut);

    if (validLine)
    {
      /** Get the parameter name from this line and store it. */
      this->GetParameterFromLine(lineIn, lineOut);
    }
    // Otherwise, we simply ignore this line
  }

} // end ReadParameterFile()

/**
 * **************** BasicFileChecking ***************
 */

void
ParameterFileParser::BasicFileChecking(void) const
{
  /** Check if the file name is given. */
  if (this->m_ParameterFileName.empty())
  {
    itkExceptionMacro(<< "ERROR: FileName has not been set.");
  }

  /** Basic error checking: existence. */
  const bool exists = itksys::SystemTools::FileExists(this->m_ParameterFileName);
  if (!exists)
  {
    itkExceptionMacro(<< "ERROR: the file " << this->m_ParameterFileName << " does not exist.");
  }

  /** Basic error checking: file or directory. */
  const bool isDir = itksys::SystemTools::FileIsDirectory(this->m_ParameterFileName);
  if (isDir)
  {
    itkExceptionMacro(<< "ERROR: the file " << this->m_ParameterFileName << " is a directory.");
  }

  /** Check the extension. */
  const std::string ext = itksys::SystemTools::GetFilenameLastExtension(this->m_ParameterFileName);
  if (ext != ".txt")
  {
    itkExceptionMacro(<< "ERROR: the file " << this->m_ParameterFileName << " should be a text file (*.txt).");
  }

} // end BasicFileChecking()

/**
 * **************** CheckLine ***************
 */

bool
ParameterFileParser::CheckLine(const std::string & lineIn, std::string & lineOut) const
{
  /** Preprocessing of lineIn:
   * 1) Replace tabs with spaces
   * 2) Remove everything after comment sign //
   * 3) Remove leading spaces
   * 4) Remove trailing spaces
   */
  lineOut = lineIn;
  itksys::SystemTools::ReplaceString(lineOut, "\t", " ");

  itksys::RegularExpression commentPart("//");
  if (commentPart.find(lineOut))
  {
    lineOut = lineOut.substr(0, commentPart.start());
  }

  itksys::RegularExpression leadingSpaces("^[ ]*(.*)");
  leadingSpaces.find(lineOut);
  lineOut = leadingSpaces.match(1);

  itksys::RegularExpression trailingSpaces("[ \t]+$");
  if (trailingSpaces.find(lineOut))
  {
    lineOut = lineOut.substr(0, trailingSpaces.start());
  }

  /**
   * Checks:
   * 1. Empty line -> false
   * 2. Comment (line starts with "//") -> false
   * 3. Line is not between brackets (...) -> exception
   * 4. Line contains less than two words -> exception
   *
   * Otherwise return true.
   */

  /** 1. Check for non-empty lines. */
  itksys::RegularExpression reNonEmptyLine("[^ ]+");
  const bool                match1 = reNonEmptyLine.find(lineOut);
  if (!match1)
  {
    return false;
  }

  /** 2. Check for comments. */
  itksys::RegularExpression reComment("^//");
  const bool                match2 = reComment.find(lineOut);
  if (match2)
  {
    return false;
  }

  /** 3. Check if line is between brackets. */
  if (!itksys::SystemTools::StringStartsWith(lineOut, "(") || !itksys::SystemTools::StringEndsWith(lineOut, ")"))
  {
    const std::string hint = "Line is not between brackets: \"(...)\".";
    this->ThrowException(lineIn, hint);
  }

  /** Remove brackets. */
  lineOut = lineOut.substr(1, lineOut.size() - 2);

  /** 4. Check: the line should contain at least two words. */
  itksys::RegularExpression reTwoWords("([ ]+)([^ ]+)");
  const bool                match4 = reTwoWords.find(lineOut);
  if (!match4)
  {
    const std::string hint = "Line does not contain a parameter name and value.";
    this->ThrowException(lineIn, hint);
  }

  /** At this point we know its at least a line containing a parameter.
   * However, this line can still be invalid, for example:
   * (string &^%^*)
   * This will be checked later.
   */

  return true;

} // end CheckLine()

/**
 * **************** GetParameterFromLine ***************
 */

void
ParameterFileParser::GetParameterFromLine(const std::string & fullLine, const std::string & line)
{
  /** A line has a parameter name followed by one or more parameters.
   * They are all separated by one or more spaces (all tabs have been
   * removed previously) or by quotes in case of strings. So,
   * 1) we split the line at the spaces or quotes
   * 2) the first one is the parameter name
   * 3) the other strings that are not a series of spaces, are parameter values
   */

  /** 1) Split the line. */
  std::vector<std::string> splittedLine;
  this->SplitLine(fullLine, line, splittedLine);

  /** 2) Get the parameter name. */
  std::string parameterName = splittedLine[0];
  itksys::SystemTools::ReplaceString(parameterName, " ", "");
  splittedLine.erase(splittedLine.begin());

  /** 3) Get the parameter values. */
  std::vector<std::string> parameterValues;
  for (const auto & value : splittedLine)
  {
    if (!value.empty())
    {
      parameterValues.push_back(value);
    }
  }

  /** 4) Perform some checks on the parameter name. */
  itksys::RegularExpression reInvalidCharacters1("[.,:;!@#$%^&-+|<>?]");
  const bool                match = reInvalidCharacters1.find(parameterName);
  if (match)
  {
    const std::string hint = "The parameter \"" + parameterName + "\" contains invalid characters (.,:;!@#$%^&-+|<>?).";
    this->ThrowException(fullLine, hint);
  }

  /** 5) Insert this combination in the parameter map. */
  if (this->m_ParameterMap.count(parameterName))
  {
    const std::string hint = "The parameter \"" + parameterName + "\" is specified more than once.";
    this->ThrowException(fullLine, hint);
  }
  else
  {
    this->m_ParameterMap.insert(make_pair(parameterName, parameterValues));
  }

} // end GetParameterFromLine()

/**
 * **************** SplitLine ***************
 */

void
ParameterFileParser::SplitLine(const std::string &        fullLine,
                               const std::string &        line,
                               std::vector<std::string> & splittedLine) const
{
  splittedLine.clear();
  splittedLine.resize(1);

  /** Count the number of quotes in the line. If it is an odd value, the
   * line contains an error; strings should start and end with a quote, so
   * the total number of quotes is even.
   */
  std::size_t numQuotes = itksys::SystemTools::CountChar(line.c_str(), '"');
  if (numQuotes % 2 == 1)
  {
    /** An invalid parameter line. */
    const std::string hint = "This line has an odd number of quotes (\").";
    this->ThrowException(fullLine, hint);
  }

  /** Loop over the line. */
  unsigned int index = 0;
  numQuotes = 0;
  for (const char currentChar : line)
  {
    if (currentChar == '"')
    {
      /** Start a new element. */
      splittedLine.push_back("");
      index++;
      numQuotes++;
    }
    else if (currentChar == ' ')
    {
      /** Only start a new element if it is not a quote, otherwise just add
       * the space to the string.
       */
      if (numQuotes % 2 == 0)
      {
        splittedLine.push_back("");
        index++;
      }
      else
      {
        splittedLine[index].push_back(currentChar);
      }
    }
    else
    {
      /** Add this character to the element. */
      splittedLine[index].push_back(currentChar);
    }
  }

} // end SplitLine()

/**
 * **************** ThrowException ***************
 */

void
ParameterFileParser::ThrowException(const std::string & line, const std::string & hint) const
{
  /** Construct an error message. */
  const std::string errorMessage = "ERROR: the following line in your parameter file is invalid: \n\"" + line + "\"\n" +
                                   hint + "\nPlease correct you parameter file!";

  /** Throw exception. */
  itkExceptionMacro(<< errorMessage);

} // end ThrowException()

/**
 * **************** ReturnParameterFileAsString ***************
 */

std::string
ParameterFileParser::ReturnParameterFileAsString(void)
{
  /** Perform some basic checks. */
  this->BasicFileChecking();

  /** Open the parameter file for reading. */
  std::ifstream parameterFile(this->m_ParameterFileName);

  /** Check if it opened. */
  if (!parameterFile.is_open())
  {
    itkExceptionMacro(<< "ERROR: could not open " << this->m_ParameterFileName << " for reading.");
  }

  /** Loop over the parameter file, line by line. */
  std::string line;
  std::string output;
  while (parameterFile.good())
  {
    /** Extract a line. */
    itksys::SystemTools::GetLineFromStream(parameterFile, line); // \todo: returns bool

    output += line + "\n";
  }

  /** Return the string. */
  return output;

} // end ReturnParameterFileAsString()

} // end namespace itk
<|endoftext|>


<commit_before>#define _CRT_RAND_S // For Windows, rand_s

#include <gtest/gtest.h>
#include <array>
#include <chrono>
#include <future>
#include <random>

#ifdef _WIN32
#include <stdlib.h>
#define rand_r rand_s
#define INC_SRT_WIN_WINTIME // exclude gettimeofday from srt headers
#else
typedef int SOCKET;
#define INVALID_SOCKET ((SOCKET)-1)
#define closesocket close
#endif

#include"platform_sys.h"
#include "srt.h"
#include "netinet_any.h"
#include "api.h"

using namespace std;

class TestConnection
    : public ::testing::Test
{
protected:
    TestConnection()
    {
        // initialization code here
    }

    ~TestConnection()
    {
        // cleanup any pending stuff, but no exceptions allowed
    }

    // It should be as much as possible, but how many sockets can
    // be withstood, depends on the platform. Currently used CI test
    // servers seem not to withstand more than 240.
    static const size_t NSOCK = 60;

protected:
    // SetUp() is run immediately before a test starts.
    void SetUp() override
    {
        ASSERT_EQ(srt_startup(), 0);

        m_sa.sin_family = AF_INET;
        m_sa.sin_addr.s_addr = INADDR_ANY;

        m_server_sock = srt_create_socket();
        ASSERT_NE(m_server_sock, SRT_INVALID_SOCK);

        // Find a port not used by another service.
        int bind_res = 0;
        const sockaddr* psa = reinterpret_cast<const sockaddr*>(&m_sa);
        for (int port = 5000; port <= 5100; ++port)
        {
            m_sa.sin_port = htons(port);

            bind_res = srt_bind(m_server_sock, psa, sizeof m_sa);
            if (bind_res == 0)
            {
                cerr << "Running test on port " << port << "\n";
                break;
            }
        }

        ASSERT_GE(bind_res, 0) << "srt_bind returned " << bind_res << ": " << srt_getlasterror_str();
        ASSERT_EQ(inet_pton(AF_INET, "127.0.0.1", &m_sa.sin_addr), 1);

        // Fill the buffer with random data
        std::random_device rnd_device;
        std::mt19937 gen(rnd_device());
        std::uniform_int_distribution<short> dis(-128, 127);
        std::generate(m_buf.begin(), m_buf.end(), [dis, gen]() mutable { return (char)dis(gen); });

        cout << "Generated: " << static_cast<int>(m_buf[0]) << ", " << static_cast<int>(m_buf[1]) << std::endl;

        ASSERT_NE(srt_listen(m_server_sock, NSOCK), -1);
    }

    void TearDown() override
    {
        srt_cleanup();
    }

    void AcceptLoop()
    {
        for (;;)
        {
            sockaddr_any addr;
            int len = sizeof addr;
            int acp = srt_accept(m_server_sock, addr.get(), &len);
            if (acp == -1)
            {
                cerr << "[T] Accept error at " << m_accepted.size()
                     << "/" << NSOCK << ": " << srt_getlasterror_str() << endl;
                break;
            }
            m_accepted.push_back(acp);
        }

        cerr << "[T] Closing those accepted ones\n";
        m_accept_exit = true;

        for (const auto s : m_accepted)
        {
            srt_close(s);
        }

        cerr << "[T] End Accept Loop\n";
    }

protected:
    sockaddr_in m_sa = sockaddr_in();
    SRTSOCKET m_server_sock = SRT_INVALID_SOCK;
    vector<SRTSOCKET> m_accepted;
    std::array<char, SRT_LIVE_DEF_PLSIZE> m_buf;
    SRTSOCKET m_connections[NSOCK];
    volatile bool m_accept_exit = false;
};

// This test establishes multiple connections to a single SRT listener on a localhost port.
// Packets are submitted for sending to all those connections in a non-blocking mode.
// Then all connections are closed. Some sockets may potentially still have undelivered packets.
// This test tries to reproduce the issue described in #1182, and fixed by #1315.
TEST_F(TestConnection, Multiple)
{
    const sockaddr_in lsa = m_sa;
    const sockaddr* psa = reinterpret_cast<const sockaddr*>(&lsa);

    auto ex = std::async([this] { return AcceptLoop(); });

    cerr << "Opening " << NSOCK << " connections\n";

    for (size_t i = 0; i < NSOCK; i++)
    {
        m_connections[i] = srt_create_socket();
        EXPECT_NE(m_connections[i], SRT_INVALID_SOCK);

        // Give it 60s timeout, many platforms fail to process
        // so many connections in a short time.
        int conntimeo = 60;
        srt_setsockflag(m_connections[i], SRTO_CONNTIMEO, &conntimeo, sizeof conntimeo);

        //cerr << "Connecting #" << i << " to " << sockaddr_any(psa).str() << "...\n";
        //cerr << "Connecting to: " << sockaddr_any(psa).str() << endl;
        ASSERT_NE(srt_connect(m_connections[i], psa, sizeof lsa), SRT_ERROR);

        // Set now async sending so that sending isn't blocked
        int no = 0;
        ASSERT_NE(srt_setsockflag(m_connections[i], SRTO_SNDSYN, &no, sizeof no), -1);
    }

    for (size_t j = 1; j <= 100; j++)
    {
        for (size_t i = 0; i < NSOCK; i++)
        {
            EXPECT_GT(srt_send(m_connections[i], m_buf.data(), (int) m_buf.size()), 0);
        }
    }
    cerr << "Sending finished, closing caller sockets\n";

    for (size_t i = 0; i < NSOCK; i++)
    {
        EXPECT_EQ(srt_close(m_connections[i]), SRT_SUCCESS);
    }

    EXPECT_FALSE(m_accept_exit) << "AcceptLoop already broken for some reason!";
    // Up to this moment the server sock should survive
    cerr << "Closing server socket\n";
    // Close server socket to break the accept loop
    EXPECT_EQ(srt_close(m_server_sock), 0);

    cerr << "Synchronize with the accepting thread\n";
    ex.wait();
}

<commit_msg>[tests] Fixed async launch TestConnection.Multiple<commit_after>#define _CRT_RAND_S // For Windows, rand_s

#include <gtest/gtest.h>
#include <array>
#include <chrono>
#include <future>
#include <random>

#ifdef _WIN32
#include <stdlib.h>
#define rand_r rand_s
#define INC_SRT_WIN_WINTIME // exclude gettimeofday from srt headers
#else
typedef int SOCKET;
#define INVALID_SOCKET ((SOCKET)-1)
#define closesocket close
#endif

#include"platform_sys.h"
#include "srt.h"
#include "netinet_any.h"
#include "api.h"

using namespace std;

class TestConnection
    : public ::testing::Test
{
protected:
    TestConnection()
    {
        // initialization code here
    }

    ~TestConnection()
    {
        // cleanup any pending stuff, but no exceptions allowed
    }

    // It should be as much as possible, but how many sockets can
    // be withstood, depends on the platform. Currently used CI test
    // servers seem not to withstand more than 240.
    static const size_t NSOCK = 60;

protected:
    // SetUp() is run immediately before a test starts.
    void SetUp() override
    {
        ASSERT_EQ(srt_startup(), 0);

        m_sa.sin_family = AF_INET;
        m_sa.sin_addr.s_addr = INADDR_ANY;

        m_server_sock = srt_create_socket();
        ASSERT_NE(m_server_sock, SRT_INVALID_SOCK);

        // Find a port not used by another service.
        int bind_res = 0;
        const sockaddr* psa = reinterpret_cast<const sockaddr*>(&m_sa);
        for (int port = 5000; port <= 5100; ++port)
        {
            m_sa.sin_port = htons(port);

            bind_res = srt_bind(m_server_sock, psa, sizeof m_sa);
            if (bind_res == 0)
            {
                cerr << "Running test on port " << port << "\n";
                break;
            }
        }

        ASSERT_GE(bind_res, 0) << "srt_bind returned " << bind_res << ": " << srt_getlasterror_str();
        ASSERT_EQ(inet_pton(AF_INET, "127.0.0.1", &m_sa.sin_addr), 1);

        // Fill the buffer with random data
        std::random_device rnd_device;
        std::mt19937 gen(rnd_device());
        std::uniform_int_distribution<short> dis(-128, 127);
        std::generate(m_buf.begin(), m_buf.end(), [dis, gen]() mutable { return (char)dis(gen); });

        ASSERT_NE(srt_listen(m_server_sock, NSOCK), -1);
    }

    void TearDown() override
    {
        srt_cleanup();
    }

    void AcceptLoop()
    {
        for (;;)
        {
            sockaddr_any addr;
            int len = sizeof addr;
            int acp = srt_accept(m_server_sock, addr.get(), &len);
            if (acp == -1)
            {
                cerr << "[T] Accept error at " << m_accepted.size()
                     << "/" << NSOCK << ": " << srt_getlasterror_str() << endl;
                break;
            }
            m_accepted.push_back(acp);
        }

        cerr << "[T] Closing those accepted ones\n";
        m_accept_exit = true;

        for (const auto s : m_accepted)
        {
            srt_close(s);
        }

        cerr << "[T] End Accept Loop\n";
    }

protected:
    sockaddr_in m_sa = sockaddr_in();
    SRTSOCKET m_server_sock = SRT_INVALID_SOCK;
    vector<SRTSOCKET> m_accepted;
    std::array<char, SRT_LIVE_DEF_PLSIZE> m_buf;
    SRTSOCKET m_connections[NSOCK];
    volatile bool m_accept_exit = false;
};

// This test establishes multiple connections to a single SRT listener on a localhost port.
// Packets are submitted for sending to all those connections in a non-blocking mode.
// Then all connections are closed. Some sockets may potentially still have undelivered packets.
// This test tries to reproduce the issue described in #1182, and fixed by #1315.
TEST_F(TestConnection, Multiple)
{
    const sockaddr_in lsa = m_sa;
    const sockaddr* psa = reinterpret_cast<const sockaddr*>(&lsa);

    auto ex = std::async(std::launch::async, [this] { return AcceptLoop(); });

    cerr << "Opening " << NSOCK << " connections\n";

    for (size_t i = 0; i < NSOCK; i++)
    {
        m_connections[i] = srt_create_socket();
        EXPECT_NE(m_connections[i], SRT_INVALID_SOCK);

        // Give it 60s timeout, many platforms fail to process
        // so many connections in a short time.
        int conntimeo = 60;
        srt_setsockflag(m_connections[i], SRTO_CONNTIMEO, &conntimeo, sizeof conntimeo);

        //cerr << "Connecting #" << i << " to " << sockaddr_any(psa).str() << "...\n";
        //cerr << "Connecting to: " << sockaddr_any(psa).str() << endl;
        ASSERT_NE(srt_connect(m_connections[i], psa, sizeof lsa), SRT_ERROR);

        // Set now async sending so that sending isn't blocked
        int no = 0;
        ASSERT_NE(srt_setsockflag(m_connections[i], SRTO_SNDSYN, &no, sizeof no), -1);
    }

    for (size_t j = 1; j <= 100; j++)
    {
        for (size_t i = 0; i < NSOCK; i++)
        {
            EXPECT_GT(srt_send(m_connections[i], m_buf.data(), (int) m_buf.size()), 0);
        }
    }
    cerr << "Sending finished, closing caller sockets\n";

    for (size_t i = 0; i < NSOCK; i++)
    {
        EXPECT_EQ(srt_close(m_connections[i]), SRT_SUCCESS);
    }

    EXPECT_FALSE(m_accept_exit) << "AcceptLoop already broken for some reason!";
    // Up to this moment the server sock should survive
    cerr << "Closing server socket\n";
    // Close server socket to break the accept loop
    EXPECT_EQ(srt_close(m_server_sock), 0);

    cerr << "Synchronize with the accepting thread\n";
    ex.wait();
    cerr << "Synchronization done\n";
}

<|endoftext|>