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

#include "runtime_support_builder.h"

#include "gc/card_table.h"
#include "ir_builder.h"
#include "monitor.h"
#include "object.h"
#include "thread.h"

#include <llvm/DerivedTypes.h>
#include <llvm/Function.h>
#include <llvm/Module.h>
#include <llvm/Type.h>

using namespace llvm;

namespace art {
namespace compiler_llvm {

using namespace runtime_support;

RuntimeSupportBuilder::RuntimeSupportBuilder(llvm::LLVMContext& context,
                                             llvm::Module& module,
                                             IRBuilder& irb)
    : context_(context), module_(module), irb_(irb)
{
  memset(target_runtime_support_func_, 0, sizeof(target_runtime_support_func_));
#define GET_RUNTIME_SUPPORT_FUNC_DECL(ID, NAME) \
  do { \
    llvm::Function* fn = module_.getFunction(#NAME); \
    DCHECK_NE(fn, (void*)NULL) << "Function not found: " << #NAME; \
    runtime_support_func_decls_[runtime_support::ID] = fn; \
  } while (0);

#include "runtime_support_func_list.h"
  RUNTIME_SUPPORT_FUNC_LIST(GET_RUNTIME_SUPPORT_FUNC_DECL)
#undef RUNTIME_SUPPORT_FUNC_LIST
#undef GET_RUNTIME_SUPPORT_FUNC_DECL
}

/* Thread */

llvm::Value* RuntimeSupportBuilder::EmitGetCurrentThread() {
  Function* func = GetRuntimeSupportFunction(runtime_support::GetCurrentThread);
  CallInst* call_inst = irb_.CreateCall(func);
  call_inst->setOnlyReadsMemory();
  irb_.SetTBAA(call_inst, kTBAAConstJObject);
  return call_inst;
}

llvm::Value* RuntimeSupportBuilder::EmitLoadFromThreadOffset(int64_t offset, llvm::Type* type,
                                                             TBAASpecialType s_ty) {
  Value* thread = EmitGetCurrentThread();
  return irb_.LoadFromObjectOffset(thread, offset, type, s_ty);
}

void RuntimeSupportBuilder::EmitStoreToThreadOffset(int64_t offset, llvm::Value* value,
                                                    TBAASpecialType s_ty) {
  Value* thread = EmitGetCurrentThread();
  irb_.StoreToObjectOffset(thread, offset, value, s_ty);
}

llvm::Value* RuntimeSupportBuilder::EmitSetCurrentThread(llvm::Value* thread) {
  Function* func = GetRuntimeSupportFunction(runtime_support::SetCurrentThread);
  return irb_.CreateCall(func, thread);
}

/* ShadowFrame */

llvm::Value* RuntimeSupportBuilder::EmitPushShadowFrame(llvm::Value* new_shadow_frame,
                                                        llvm::Value* method,
                                                        uint32_t num_vregs) {
  Value* old_shadow_frame = EmitLoadFromThreadOffset(Thread::TopShadowFrameOffset().Int32Value(),
                                                     irb_.getArtFrameTy()->getPointerTo(),
                                                     kTBAARuntimeInfo);
  EmitStoreToThreadOffset(Thread::TopShadowFrameOffset().Int32Value(),
                          new_shadow_frame,
                          kTBAARuntimeInfo);

  // Store the method pointer
  irb_.StoreToObjectOffset(new_shadow_frame,
                           ShadowFrame::MethodOffset(),
                           method,
                           kTBAAShadowFrame);

  // Store the number of vregs
  irb_.StoreToObjectOffset(new_shadow_frame,
                           ShadowFrame::NumberOfVRegsOffset(),
                           irb_.getInt32(num_vregs),
                           kTBAAShadowFrame);

  // Store the link to previous shadow frame
  irb_.StoreToObjectOffset(new_shadow_frame,
                           ShadowFrame::LinkOffset(),
                           old_shadow_frame,
                           kTBAAShadowFrame);

  return old_shadow_frame;
}

llvm::Value*
RuntimeSupportBuilder::EmitPushShadowFrameNoInline(llvm::Value* new_shadow_frame,
                                                   llvm::Value* method,
                                                   uint32_t num_vregs) {
  Function* func = GetRuntimeSupportFunction(runtime_support::PushShadowFrame);
  llvm::CallInst* call_inst =
      irb_.CreateCall4(func,
                       EmitGetCurrentThread(),
                       new_shadow_frame,
                       method,
                       irb_.getInt32(num_vregs));
  irb_.SetTBAA(call_inst, kTBAARuntimeInfo);
  return call_inst;
}

void RuntimeSupportBuilder::EmitPopShadowFrame(llvm::Value* old_shadow_frame) {
  // Store old shadow frame to TopShadowFrame
  EmitStoreToThreadOffset(Thread::TopShadowFrameOffset().Int32Value(),
                          old_shadow_frame,
                          kTBAARuntimeInfo);
}

/* Exception */

llvm::Value* RuntimeSupportBuilder::EmitGetAndClearException() {
  Function* slow_func = GetRuntimeSupportFunction(runtime_support::GetAndClearException);
  return irb_.CreateCall(slow_func, EmitGetCurrentThread());
}

llvm::Value* RuntimeSupportBuilder::EmitIsExceptionPending() {
  Value* exception = EmitLoadFromThreadOffset(Thread::ExceptionOffset().Int32Value(),
                                              irb_.getJObjectTy(),
                                              kTBAARuntimeInfo);
  // If exception not null
  return irb_.CreateIsNotNull(exception);
}

/* Suspend */

void RuntimeSupportBuilder::EmitTestSuspend() {
  Function* slow_func = GetRuntimeSupportFunction(runtime_support::TestSuspend);
  CallInst* call_inst = irb_.CreateCall(slow_func, EmitGetCurrentThread());
  irb_.SetTBAA(call_inst, kTBAAJRuntime);
}

/* Monitor */

void RuntimeSupportBuilder::EmitLockObject(llvm::Value* object) {
  // TODO: Implement a fast path.
  Function* slow_func = GetRuntimeSupportFunction(runtime_support::LockObject);
  irb_.CreateCall2(slow_func, object, EmitGetCurrentThread());
}

void RuntimeSupportBuilder::EmitUnlockObject(llvm::Value* object) {
  Value* lock_id =
      EmitLoadFromThreadOffset(Thread::ThinLockIdOffset().Int32Value(),
                               irb_.getJIntTy(),
                               kTBAARuntimeInfo);
  Value* monitor =
      irb_.LoadFromObjectOffset(object,
                                Object::MonitorOffset().Int32Value(),
                                irb_.getJIntTy(),
                                kTBAARuntimeInfo);

  Value* my_monitor = irb_.CreateShl(lock_id, LW_LOCK_OWNER_SHIFT);
  Value* hash_state = irb_.CreateAnd(monitor, (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));
  Value* real_monitor = irb_.CreateAnd(monitor, ~(LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));

  // Is thin lock, held by us and not recursively acquired
  Value* is_fast_path = irb_.CreateICmpEQ(real_monitor, my_monitor);

  Function* parent_func = irb_.GetInsertBlock()->getParent();
  BasicBlock* bb_fast = BasicBlock::Create(context_, "unlock_fast", parent_func);
  BasicBlock* bb_slow = BasicBlock::Create(context_, "unlock_slow", parent_func);
  BasicBlock* bb_cont = BasicBlock::Create(context_, "unlock_cont", parent_func);
  irb_.CreateCondBr(is_fast_path, bb_fast, bb_slow, kLikely);

  irb_.SetInsertPoint(bb_fast);
  // Set all bits to zero (except hash state)
  irb_.StoreToObjectOffset(object,
                           Object::MonitorOffset().Int32Value(),
                           hash_state,
                           kTBAARuntimeInfo);
  irb_.CreateBr(bb_cont);

  irb_.SetInsertPoint(bb_slow);
  Function* slow_func = GetRuntimeSupportFunction(runtime_support::UnlockObject);
  irb_.CreateCall2(slow_func, object, EmitGetCurrentThread());
  irb_.CreateBr(bb_cont);

  irb_.SetInsertPoint(bb_cont);
}

void RuntimeSupportBuilder::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
  Function* parent_func = irb_.GetInsertBlock()->getParent();
  BasicBlock* bb_mark_gc_card = BasicBlock::Create(context_, "mark_gc_card", parent_func);
  BasicBlock* bb_cont = BasicBlock::Create(context_, "mark_gc_card_cont", parent_func);

  llvm::Value* not_null = irb_.CreateIsNotNull(value);
  irb_.CreateCondBr(not_null, bb_mark_gc_card, bb_cont);

  irb_.SetInsertPoint(bb_mark_gc_card);
  Value* card_table = EmitLoadFromThreadOffset(Thread::CardTableOffset().Int32Value(),
                                               irb_.getInt8Ty()->getPointerTo(),
                                               kTBAAConstJObject);
  Value* target_addr_int = irb_.CreatePtrToInt(target_addr, irb_.getPtrEquivIntTy());
  Value* card_no = irb_.CreateLShr(target_addr_int, irb_.getPtrEquivInt(CardTable::kCardShift));
  Value* card_table_entry = irb_.CreateGEP(card_table, card_no);
  irb_.CreateStore(irb_.getInt8(CardTable::kCardDirty), card_table_entry, kTBAARuntimeInfo);
  irb_.CreateBr(bb_cont);

  irb_.SetInsertPoint(bb_cont);
}

} // namespace compiler_llvm
} // namespace art
<commit_msg>Change LLVM check for pending exception to use thread flags.<commit_after>/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "runtime_support_builder.h"

#include "gc/card_table.h"
#include "ir_builder.h"
#include "monitor.h"
#include "object.h"
#include "thread.h"

#include <llvm/DerivedTypes.h>
#include <llvm/Function.h>
#include <llvm/Module.h>
#include <llvm/Type.h>

using namespace llvm;

namespace art {
namespace compiler_llvm {

using namespace runtime_support;

RuntimeSupportBuilder::RuntimeSupportBuilder(llvm::LLVMContext& context,
                                             llvm::Module& module,
                                             IRBuilder& irb)
    : context_(context), module_(module), irb_(irb)
{
  memset(target_runtime_support_func_, 0, sizeof(target_runtime_support_func_));
#define GET_RUNTIME_SUPPORT_FUNC_DECL(ID, NAME) \
  do { \
    llvm::Function* fn = module_.getFunction(#NAME); \
    DCHECK_NE(fn, (void*)NULL) << "Function not found: " << #NAME; \
    runtime_support_func_decls_[runtime_support::ID] = fn; \
  } while (0);

#include "runtime_support_func_list.h"
  RUNTIME_SUPPORT_FUNC_LIST(GET_RUNTIME_SUPPORT_FUNC_DECL)
#undef RUNTIME_SUPPORT_FUNC_LIST
#undef GET_RUNTIME_SUPPORT_FUNC_DECL
}

/* Thread */

llvm::Value* RuntimeSupportBuilder::EmitGetCurrentThread() {
  Function* func = GetRuntimeSupportFunction(runtime_support::GetCurrentThread);
  CallInst* call_inst = irb_.CreateCall(func);
  call_inst->setOnlyReadsMemory();
  irb_.SetTBAA(call_inst, kTBAAConstJObject);
  return call_inst;
}

llvm::Value* RuntimeSupportBuilder::EmitLoadFromThreadOffset(int64_t offset, llvm::Type* type,
                                                             TBAASpecialType s_ty) {
  Value* thread = EmitGetCurrentThread();
  return irb_.LoadFromObjectOffset(thread, offset, type, s_ty);
}

void RuntimeSupportBuilder::EmitStoreToThreadOffset(int64_t offset, llvm::Value* value,
                                                    TBAASpecialType s_ty) {
  Value* thread = EmitGetCurrentThread();
  irb_.StoreToObjectOffset(thread, offset, value, s_ty);
}

llvm::Value* RuntimeSupportBuilder::EmitSetCurrentThread(llvm::Value* thread) {
  Function* func = GetRuntimeSupportFunction(runtime_support::SetCurrentThread);
  return irb_.CreateCall(func, thread);
}

/* ShadowFrame */

llvm::Value* RuntimeSupportBuilder::EmitPushShadowFrame(llvm::Value* new_shadow_frame,
                                                        llvm::Value* method,
                                                        uint32_t num_vregs) {
  Value* old_shadow_frame = EmitLoadFromThreadOffset(Thread::TopShadowFrameOffset().Int32Value(),
                                                     irb_.getArtFrameTy()->getPointerTo(),
                                                     kTBAARuntimeInfo);
  EmitStoreToThreadOffset(Thread::TopShadowFrameOffset().Int32Value(),
                          new_shadow_frame,
                          kTBAARuntimeInfo);

  // Store the method pointer
  irb_.StoreToObjectOffset(new_shadow_frame,
                           ShadowFrame::MethodOffset(),
                           method,
                           kTBAAShadowFrame);

  // Store the number of vregs
  irb_.StoreToObjectOffset(new_shadow_frame,
                           ShadowFrame::NumberOfVRegsOffset(),
                           irb_.getInt32(num_vregs),
                           kTBAAShadowFrame);

  // Store the link to previous shadow frame
  irb_.StoreToObjectOffset(new_shadow_frame,
                           ShadowFrame::LinkOffset(),
                           old_shadow_frame,
                           kTBAAShadowFrame);

  return old_shadow_frame;
}

llvm::Value*
RuntimeSupportBuilder::EmitPushShadowFrameNoInline(llvm::Value* new_shadow_frame,
                                                   llvm::Value* method,
                                                   uint32_t num_vregs) {
  Function* func = GetRuntimeSupportFunction(runtime_support::PushShadowFrame);
  llvm::CallInst* call_inst =
      irb_.CreateCall4(func,
                       EmitGetCurrentThread(),
                       new_shadow_frame,
                       method,
                       irb_.getInt32(num_vregs));
  irb_.SetTBAA(call_inst, kTBAARuntimeInfo);
  return call_inst;
}

void RuntimeSupportBuilder::EmitPopShadowFrame(llvm::Value* old_shadow_frame) {
  // Store old shadow frame to TopShadowFrame
  EmitStoreToThreadOffset(Thread::TopShadowFrameOffset().Int32Value(),
                          old_shadow_frame,
                          kTBAARuntimeInfo);
}

/* Exception */

llvm::Value* RuntimeSupportBuilder::EmitGetAndClearException() {
  Function* slow_func = GetRuntimeSupportFunction(runtime_support::GetAndClearException);
  return irb_.CreateCall(slow_func, EmitGetCurrentThread());
}

llvm::Value* RuntimeSupportBuilder::EmitIsExceptionPending() {
  Value* state_and_flags = EmitLoadFromThreadOffset(Thread::ThreadFlagsOffset().Int32Value(),
                                                    irb_.getInt16Ty(),
                                                    kTBAARuntimeInfo);
  // Mask exception pending status and return true if non-zero.
  Value* exception_pending = irb_.CreateAnd(state_and_flags, irb_.getInt16(kExceptionPending));
  return irb_.CreateICmpNE(exception_pending, irb_.getInt16(0));
}

/* Suspend */

void RuntimeSupportBuilder::EmitTestSuspend() {
  Function* slow_func = GetRuntimeSupportFunction(runtime_support::TestSuspend);
  CallInst* call_inst = irb_.CreateCall(slow_func, EmitGetCurrentThread());
  irb_.SetTBAA(call_inst, kTBAAJRuntime);
}

/* Monitor */

void RuntimeSupportBuilder::EmitLockObject(llvm::Value* object) {
  // TODO: Implement a fast path.
  Function* slow_func = GetRuntimeSupportFunction(runtime_support::LockObject);
  irb_.CreateCall2(slow_func, object, EmitGetCurrentThread());
}

void RuntimeSupportBuilder::EmitUnlockObject(llvm::Value* object) {
  Value* lock_id =
      EmitLoadFromThreadOffset(Thread::ThinLockIdOffset().Int32Value(),
                               irb_.getJIntTy(),
                               kTBAARuntimeInfo);
  Value* monitor =
      irb_.LoadFromObjectOffset(object,
                                Object::MonitorOffset().Int32Value(),
                                irb_.getJIntTy(),
                                kTBAARuntimeInfo);

  Value* my_monitor = irb_.CreateShl(lock_id, LW_LOCK_OWNER_SHIFT);
  Value* hash_state = irb_.CreateAnd(monitor, (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));
  Value* real_monitor = irb_.CreateAnd(monitor, ~(LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));

  // Is thin lock, held by us and not recursively acquired
  Value* is_fast_path = irb_.CreateICmpEQ(real_monitor, my_monitor);

  Function* parent_func = irb_.GetInsertBlock()->getParent();
  BasicBlock* bb_fast = BasicBlock::Create(context_, "unlock_fast", parent_func);
  BasicBlock* bb_slow = BasicBlock::Create(context_, "unlock_slow", parent_func);
  BasicBlock* bb_cont = BasicBlock::Create(context_, "unlock_cont", parent_func);
  irb_.CreateCondBr(is_fast_path, bb_fast, bb_slow, kLikely);

  irb_.SetInsertPoint(bb_fast);
  // Set all bits to zero (except hash state)
  irb_.StoreToObjectOffset(object,
                           Object::MonitorOffset().Int32Value(),
                           hash_state,
                           kTBAARuntimeInfo);
  irb_.CreateBr(bb_cont);

  irb_.SetInsertPoint(bb_slow);
  Function* slow_func = GetRuntimeSupportFunction(runtime_support::UnlockObject);
  irb_.CreateCall2(slow_func, object, EmitGetCurrentThread());
  irb_.CreateBr(bb_cont);

  irb_.SetInsertPoint(bb_cont);
}

void RuntimeSupportBuilder::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
  Function* parent_func = irb_.GetInsertBlock()->getParent();
  BasicBlock* bb_mark_gc_card = BasicBlock::Create(context_, "mark_gc_card", parent_func);
  BasicBlock* bb_cont = BasicBlock::Create(context_, "mark_gc_card_cont", parent_func);

  llvm::Value* not_null = irb_.CreateIsNotNull(value);
  irb_.CreateCondBr(not_null, bb_mark_gc_card, bb_cont);

  irb_.SetInsertPoint(bb_mark_gc_card);
  Value* card_table = EmitLoadFromThreadOffset(Thread::CardTableOffset().Int32Value(),
                                               irb_.getInt8Ty()->getPointerTo(),
                                               kTBAAConstJObject);
  Value* target_addr_int = irb_.CreatePtrToInt(target_addr, irb_.getPtrEquivIntTy());
  Value* card_no = irb_.CreateLShr(target_addr_int, irb_.getPtrEquivInt(CardTable::kCardShift));
  Value* card_table_entry = irb_.CreateGEP(card_table, card_no);
  irb_.CreateStore(irb_.getInt8(CardTable::kCardDirty), card_table_entry, kTBAARuntimeInfo);
  irb_.CreateBr(bb_cont);

  irb_.SetInsertPoint(bb_cont);
}

} // namespace compiler_llvm
} // namespace art
<|endoftext|>


<commit_before>#include "AssetManager.hpp"

namespace swift
{
	AssetManager::AssetManager()
	{
		smooth = false;
		sf::err().rdbuf(nullptr);	// redirect sfml errors to nothing, we want to handle errors on our own
	}

	AssetManager::~AssetManager()
	{
		for(auto& a : animTextures)
			delete a.second;

		for(auto& t : textures)
			delete t.second;

		for(auto& s : soundBuffers)
			delete s.second;

		for(auto& m : music)
			delete m.second;

		for(auto& f : fonts)
			delete f.second;

		for(auto& s : scripts)
			delete s.second;
	}

	bool AssetManager::loadResourceFolder(const std::string& folder)
	{
		DIR* dir = nullptr;
		struct dirent* entry = nullptr;

		dir = opendir(folder.c_str());

		// error handling
		if(dir == nullptr)
		{
			log << "Unable to open resource folder: " << folder << "\n";
			return false;
		}

		while((entry = readdir(dir)))
		{
			if(entry == nullptr)
			{
				log << "Unable to read resource folder: " << folder << "\n";
				return false;
			}

			// if the entry is a directory, but is not the current or parent directory
			if(entry->d_type == DT_DIR && !(std::string(entry->d_name).compare(".") == 0 || std::string(entry->d_name).compare("..") == 0))
			{
				loadResourceFolder(folder + '/' + std::string(entry->d_name));	// recursive on child directory
			}
			// entry is a file
			else if(entry->d_type == DT_REG)
			{
				loadResource(folder + '/' + std::string(entry->d_name));
			}
		}

		closedir(dir);

		return true;
	}

	bool AssetManager::loadMod(const Mod& mod)
	{
		bool returnVar = true;

		for(auto &f : mod.getFiles())
		{
			bool temp = true;
			temp = loadResource(f);
			if(temp == false)
			{
				log << "ERROR: In " << mod.getName() << ", could not load " << f << '\n';
				returnVar = false;
			}
		}

		return returnVar;
	}

	void AssetManager::clean()
	{
		for(auto& a : animTextures)
			delete a.second;

		for(auto& b : batches)
			delete b.second;

		for(auto& t : textures)
			delete t.second;

		for(auto& s : soundBuffers)
			delete s.second;

		for(auto& m : music)
			delete m.second;

		for(auto& f : fonts)
			delete f.second;

		for(auto& s : scripts)
			delete s.second;

		animTextures.clear();
		batches.clear();
		textures.clear();
		soundBuffers.clear();
		music.clear();
		fonts.clear();
		scripts.clear();
	}

	void AssetManager::setSmooth(bool s)
	{
		smooth = s;
		for(auto &t : textures)
		{
			t.second->setSmooth(smooth);
		}
	}

	bool AssetManager::newSpriteBatch(const std::string& t, unsigned int s)
	{
		if(batches.find(t) == batches.end())
		{
			sf::Texture* texture = getTexture(t);

			if(texture)
			{
				batches[t] = new SpriteBatch(*texture, s);
				return true;
			}
			else
				return false;
		}
		else
			return false;
	}

	AnimTexture* AssetManager::getAnimTexture(const std::string& n)
	{
		if(animTextures.find(n) != animTextures.end())
			return animTextures.find(n)->second;
		else
			log << "No \"" << n << "\" anim file exists\n";

		return nullptr;
	}

	SpriteBatch* AssetManager::getBatch(const std::string& n)
	{
		if(batches.find(n) != batches.end())
			return batches.find(n)->second;
		else
			log << "No\"" << n << "\" batch exists\n";

		return nullptr;
	}

	sf::Texture* AssetManager::getTexture(const std::string& n)
	{
		if(textures.find(n) != textures.end())
			return textures.find(n)->second;
		else
			log << "No \"" << n << "\" texture file exists\n";

		return nullptr;
	}

	sf::SoundBuffer* AssetManager::getSoundBuffer(const std::string& n)
	{
		if(soundBuffers.find(n) != soundBuffers.end())
			return soundBuffers.find(n)->second;
		else
			log << "No \"" << n << "\" sound buffer file exists\n";

		return nullptr;
	}

	sf::Music* AssetManager::getSong(const std::string& n)
	{
		if(music.find(n) != music.end())
			return music.find(n)->second;
		else
			log << "No \"" << n << "\" music file exists\n";

		return nullptr;
	}

	sf::Font* AssetManager::getFont(const std::string& n)
	{
		if(fonts.find(n) != fonts.end())
			return fonts.find(n)->second;
		else
			log << "No \"" << n << "\" font file exists\n";

		return nullptr;
	}

	Script* AssetManager::getScript(const std::string& n)
	{
		if(scripts.find(n) != scripts.end())
			return scripts.find(n)->second;
		else
			log << "No \"" << n << "\" script file exists\n";

		return nullptr;
	}

	bool AssetManager::loadAnimTexture(const std::string& file)
	{
		animTextures.emplace(file, new AnimTexture());

		if(!animTextures[file]->loadFromFile(file))
		{
			log << "Unable to load " << file << " as an anim\n";

			delete animTextures[file];

			animTextures.erase(file);
			return false;
		}

		log << "Anim:\t" << file << '\n';

		return true;
	}

	bool AssetManager::loadTexture(const std::string& file)
	{
		textures.emplace(file, new sf::Texture());

		if(!textures[file]->loadFromFile(file))
		{
			log << "Unable to load " << file << " as a texture.\n";

			delete textures[file];

			textures.erase(file);
			return false;
		}

		textures[file]->setSmooth(smooth);

		log << "Texture:\t" << file << '\n';

		return true;
	}

	bool AssetManager::loadSound(const std::string& file)
	{
		soundBuffers.emplace(file, new sf::SoundBuffer());

		if(!soundBuffers[file]->loadFromFile(file))
		{
			log << "Unable to load " << file << " as a sound.\n";

			// delete new'd soundbuffer
			auto it = soundBuffers.end();
			it--;
			delete it->second;

			soundBuffers.erase(file);
			return false;
		}

		log << "Sound:\t" << file << '\n';

		return true;
	}

	bool AssetManager::loadSong(const std::string& file)
	{
		music.emplace(file, new sf::Music());

		if(!music[file]->openFromFile(file))
		{
			log << "Unable to open " << file << " as a music file.\n";

			// delete new'd music
			auto it = music.end();
			it--;
			delete it->second;

			music.erase(file);
			return false;
		}

		log << "Music:\t" << file << '\n';

		return true;
	}

	bool AssetManager::loadFont(const std::string& file)
	{
		fonts.emplace(file, new sf::Font());

		if(!fonts[file]->loadFromFile(file))
		{
			log << "Unable to load " << file << " as a font.\n";

			// delete new'd font
			auto it = fonts.end();
			it--;
			delete it->second;

			fonts.erase(file);
			return false;
		}

		log << "Font:\t" << file << '\n';

		return true;
	}

	bool AssetManager::loadScript(const std::string& file)
	{

	}

	bool AssetManager::loadResource(const std::string& file)
	{
		// this if chain checks what folder the file is in
		if(file.find("/anims/") != std::string::npos)
		{
			return loadAnimTexture(file);
		}
		else if(file.find("/textures/") != std::string::npos)
		{
			return loadTexture(file);
		}
		else if(file.find("/sounds/") != std::string::npos)
		{
			return loadSound(file);
		}
		else if(file.find("/music/") != std::string::npos)
		{
			return loadSong(file);
		}
		else if(file.find("/fonts/") != std::string::npos)
		{
			return loadFont(file);
		}
		else if(file.find("/scripts/") != std::string::npos)
		{
			return loadScript(file);
		}
		else if(file.find(".txt") != std::string::npos)
		{
			// ignore *.txt files, but don't throw a warning/error
			log << "Ignoring " << file << '\n';
		}
		else
		{
			log << "WARNING: " << file << " is an unknown resource type.\n";
			return false;
		}
		return true;
	}
}
<commit_msg>Default loadScript now returns false.<commit_after>#include "AssetManager.hpp"

namespace swift
{
	AssetManager::AssetManager()
	{
		smooth = false;
		sf::err().rdbuf(nullptr);	// redirect sfml errors to nothing, we want to handle errors on our own
	}

	AssetManager::~AssetManager()
	{
		for(auto& a : animTextures)
			delete a.second;

		for(auto& t : textures)
			delete t.second;

		for(auto& s : soundBuffers)
			delete s.second;

		for(auto& m : music)
			delete m.second;

		for(auto& f : fonts)
			delete f.second;

		for(auto& s : scripts)
			delete s.second;
	}

	bool AssetManager::loadResourceFolder(const std::string& folder)
	{
		DIR* dir = nullptr;
		struct dirent* entry = nullptr;

		dir = opendir(folder.c_str());

		// error handling
		if(dir == nullptr)
		{
			log << "Unable to open resource folder: " << folder << "\n";
			return false;
		}

		while((entry = readdir(dir)))
		{
			if(entry == nullptr)
			{
				log << "Unable to read resource folder: " << folder << "\n";
				return false;
			}

			// if the entry is a directory, but is not the current or parent directory
			if(entry->d_type == DT_DIR && !(std::string(entry->d_name).compare(".") == 0 || std::string(entry->d_name).compare("..") == 0))
			{
				loadResourceFolder(folder + '/' + std::string(entry->d_name));	// recursive on child directory
			}
			// entry is a file
			else if(entry->d_type == DT_REG)
			{
				loadResource(folder + '/' + std::string(entry->d_name));
			}
		}

		closedir(dir);

		return true;
	}

	bool AssetManager::loadMod(const Mod& mod)
	{
		bool returnVar = true;

		for(auto &f : mod.getFiles())
		{
			bool temp = true;
			temp = loadResource(f);
			if(temp == false)
			{
				log << "ERROR: In " << mod.getName() << ", could not load " << f << '\n';
				returnVar = false;
			}
		}

		return returnVar;
	}

	void AssetManager::clean()
	{
		for(auto& a : animTextures)
			delete a.second;

		for(auto& b : batches)
			delete b.second;

		for(auto& t : textures)
			delete t.second;

		for(auto& s : soundBuffers)
			delete s.second;

		for(auto& m : music)
			delete m.second;

		for(auto& f : fonts)
			delete f.second;

		for(auto& s : scripts)
			delete s.second;

		animTextures.clear();
		batches.clear();
		textures.clear();
		soundBuffers.clear();
		music.clear();
		fonts.clear();
		scripts.clear();
	}

	void AssetManager::setSmooth(bool s)
	{
		smooth = s;
		for(auto &t : textures)
		{
			t.second->setSmooth(smooth);
		}
	}

	bool AssetManager::newSpriteBatch(const std::string& t, unsigned int s)
	{
		if(batches.find(t) == batches.end())
		{
			sf::Texture* texture = getTexture(t);

			if(texture)
			{
				batches[t] = new SpriteBatch(*texture, s);
				return true;
			}
			else
				return false;
		}
		else
			return false;
	}

	AnimTexture* AssetManager::getAnimTexture(const std::string& n)
	{
		if(animTextures.find(n) != animTextures.end())
			return animTextures.find(n)->second;
		else
			log << "No \"" << n << "\" anim file exists\n";

		return nullptr;
	}

	SpriteBatch* AssetManager::getBatch(const std::string& n)
	{
		if(batches.find(n) != batches.end())
			return batches.find(n)->second;
		else
			log << "No\"" << n << "\" batch exists\n";

		return nullptr;
	}

	sf::Texture* AssetManager::getTexture(const std::string& n)
	{
		if(textures.find(n) != textures.end())
			return textures.find(n)->second;
		else
			log << "No \"" << n << "\" texture file exists\n";

		return nullptr;
	}

	sf::SoundBuffer* AssetManager::getSoundBuffer(const std::string& n)
	{
		if(soundBuffers.find(n) != soundBuffers.end())
			return soundBuffers.find(n)->second;
		else
			log << "No \"" << n << "\" sound buffer file exists\n";

		return nullptr;
	}

	sf::Music* AssetManager::getSong(const std::string& n)
	{
		if(music.find(n) != music.end())
			return music.find(n)->second;
		else
			log << "No \"" << n << "\" music file exists\n";

		return nullptr;
	}

	sf::Font* AssetManager::getFont(const std::string& n)
	{
		if(fonts.find(n) != fonts.end())
			return fonts.find(n)->second;
		else
			log << "No \"" << n << "\" font file exists\n";

		return nullptr;
	}

	Script* AssetManager::getScript(const std::string& n)
	{
		if(scripts.find(n) != scripts.end())
			return scripts.find(n)->second;
		else
			log << "No \"" << n << "\" script file exists\n";

		return nullptr;
	}

	bool AssetManager::loadAnimTexture(const std::string& file)
	{
		animTextures.emplace(file, new AnimTexture());

		if(!animTextures[file]->loadFromFile(file))
		{
			log << "Unable to load " << file << " as an anim\n";

			delete animTextures[file];

			animTextures.erase(file);
			return false;
		}

		log << "Anim:\t" << file << '\n';

		return true;
	}

	bool AssetManager::loadTexture(const std::string& file)
	{
		textures.emplace(file, new sf::Texture());

		if(!textures[file]->loadFromFile(file))
		{
			log << "Unable to load " << file << " as a texture.\n";

			delete textures[file];

			textures.erase(file);
			return false;
		}

		textures[file]->setSmooth(smooth);

		log << "Texture:\t" << file << '\n';

		return true;
	}

	bool AssetManager::loadSound(const std::string& file)
	{
		soundBuffers.emplace(file, new sf::SoundBuffer());

		if(!soundBuffers[file]->loadFromFile(file))
		{
			log << "Unable to load " << file << " as a sound.\n";

			// delete new'd soundbuffer
			auto it = soundBuffers.end();
			it--;
			delete it->second;

			soundBuffers.erase(file);
			return false;
		}

		log << "Sound:\t" << file << '\n';

		return true;
	}

	bool AssetManager::loadSong(const std::string& file)
	{
		music.emplace(file, new sf::Music());

		if(!music[file]->openFromFile(file))
		{
			log << "Unable to open " << file << " as a music file.\n";

			// delete new'd music
			auto it = music.end();
			it--;
			delete it->second;

			music.erase(file);
			return false;
		}

		log << "Music:\t" << file << '\n';

		return true;
	}

	bool AssetManager::loadFont(const std::string& file)
	{
		fonts.emplace(file, new sf::Font());

		if(!fonts[file]->loadFromFile(file))
		{
			log << "Unable to load " << file << " as a font.\n";

			// delete new'd font
			auto it = fonts.end();
			it--;
			delete it->second;

			fonts.erase(file);
			return false;
		}

		log << "Font:\t" << file << '\n';

		return true;
	}

	bool AssetManager::loadScript(const std::string&)
	{
		return false;
	}

	bool AssetManager::loadResource(const std::string& file)
	{
		// this if chain checks what folder the file is in
		if(file.find("/anims/") != std::string::npos)
		{
			return loadAnimTexture(file);
		}
		else if(file.find("/textures/") != std::string::npos)
		{
			return loadTexture(file);
		}
		else if(file.find("/sounds/") != std::string::npos)
		{
			return loadSound(file);
		}
		else if(file.find("/music/") != std::string::npos)
		{
			return loadSong(file);
		}
		else if(file.find("/fonts/") != std::string::npos)
		{
			return loadFont(file);
		}
		else if(file.find("/scripts/") != std::string::npos)
		{
			return loadScript(file);
		}
		else if(file.find(".txt") != std::string::npos)
		{
			// ignore *.txt files, but don't throw a warning/error
			log << "Ignoring " << file << '\n';
		}
		else
		{
			log << "WARNING: " << file << " is an unknown resource type.\n";
			return false;
		}
		return true;
	}
}
<|endoftext|>


<commit_before>/*
 * PuckManager.cpp
 *
 *  Created on: 09.06.2017
 *      Author: aca592
 */

#include "PuckManager.h"

#include "logger.h"
#include "logScope.h"

PuckManager::PuckManager(int chid)
	: puckList()
	, nextPuckID(0)
	, chid(chid)
{}

PuckManager::~PuckManager() {
	std::list<PuckContext*>::iterator it = puckList.begin();
	while(it != puckList.end()) {
		LOG_DEBUG <<"[Puck" + std::to_string((*it)->getPuckID()) + "] was deleted \n";
		delete *it;					// delete the puck from memory
		it = puckList.erase(it);	// delete the puck from list
	}
}

PuckManager::ManagerReturn PuckManager::newPuck(PuckSignal::PuckType type) {
	LOG_SCOPE;
	ManagerReturn ret;
	ret.actorFlag = true;
	ret.actorSignal = ActorSignal::ACCEPTED_PUCK;
	addPuck(new PuckContext(chid, type));
	return ret;
}

void PuckManager::addPuck(PuckContext *puck) {
	LOG_SCOPE;
	puck->setPuckID(nextPuckID++);
	puckList.push_back(puck);
}

PuckManager::ManagerReturn PuckManager::process(PuckSignal::Signal signal) {
	LOG_SCOPE;

	ManagerReturn prioReturnVal; // the prioritized return value
	prioReturnVal.speedSignal = PuckSignal::PuckSpeed::FAST;
	prioReturnVal.actorFlag = false;
	prioReturnVal.errorFlag = false;
	prioReturnVal.slideFullFlag = false;
	prioReturnVal.puckType = nullptr;

	int32_t acceptCounter = 0; // count all accepted signals
	int32_t warningCounter = 0; // count all warnings

#if !machine // machine0
	// check for first interrupt signal - puck must be created
	if(	signal.signalType == PuckSignal::SignalType::INTERRUPT_SIGNAL &&
		signal.interruptSignal == interrupts::interruptSignals::INLET_IN) {

		addPuck(new PuckContext(chid));

		std::list<PuckContext*>::iterator it = puckList.begin();
		while(it != puckList.end()) {
			if((*it)->getCurrentSpeed() > prioReturnVal.speedSignal) { // Check for speed prio
				prioReturnVal.speedSignal = (*it)->getCurrentSpeed();
			}
			it++;
		}

		return prioReturnVal;
	}

	// signal can be passed for speed prio -> every puck should return deny
#endif

	if(puckList.empty()) {
		prioReturnVal.speedSignal = PuckSignal::PuckSpeed::STOP;
		prioReturnVal.errorFlag = true;
		prioReturnVal.errorSignal = ErrorSignal::UNEXPECTED_SIGNAL;
		return prioReturnVal;
	}

	// Pass the timer signal to the given puckID
	if(signal.signalType == PuckSignal::SignalType::TIMER_SIGNAL) {
		std::list<PuckContext*>::iterator it = puckList.begin();
		while(it != puckList.end()) {
			if((*it)->getCurrentSpeed() > prioReturnVal.speedSignal) { // Check for speed prio
				prioReturnVal.speedSignal = (*it)->getCurrentSpeed();
			}

			// check for puckID
			uint16_t currentPuckID = (*it)->getPuckID();
			if(currentPuckID == signal.timerSignal.TimerInfo.puckID) {
				// pass the timer signal
				PuckSignal::Return returnVal = (*it)->process(signal);

				// check return value
				if(	returnVal.puckReturn != PuckSignal::PuckReturn::ACCEPT &&
					returnVal.puckReturn != PuckSignal::PuckReturn::ERROR) {
					// puck should be triggered on accept or error -> unexpected otherwise
					prioReturnVal.errorFlag = true;
					prioReturnVal.errorSignal = ErrorSignal::UNEXPECTED_SIGNAL;
				} else if(returnVal.puckReturn == PuckSignal::PuckReturn::ERROR) {
					prioReturnVal.errorFlag = true;
					prioReturnVal.errorSignal = ErrorSignal::PUCK_LOST; //Late Timer expiered
				}
			}

			it++;
		}

		return prioReturnVal;
	}

	if(signal.signalType == PuckSignal::SignalType::SERIAL_SIGNAL && signal.serialSignal == Serial_n::ser_proto_msg::SLIDE_FULL_SER) {
		sort.process(signal.serialSignal);

		std::list<PuckContext*>::iterator it = puckList.begin();
		while(it != puckList.end()) {
			if((*it)->getCurrentSpeed() > prioReturnVal.speedSignal) { // Check for speed prio
				prioReturnVal.speedSignal = (*it)->getCurrentSpeed();
			}
			it++;
		}

		return prioReturnVal;
	}

	// check the signal for every puck in the list
	std::list<PuckContext*>::iterator it = puckList.begin();
	while(it != puckList.end()) {
		PuckSignal::Return returnVal = (*it)->process(signal);

		if(returnVal.puckSpeed > prioReturnVal.speedSignal) { // Check for speed prio
			prioReturnVal.speedSignal = returnVal.puckSpeed;
		}

		switch(returnVal.puckReturn) {
			case PuckSignal::PuckReturn::ACCEPT:
				acceptCounter++;
				break;
			case PuckSignal::PuckReturn::DELETE:
				acceptCounter++;
				LOG_DEBUG <<"[Puck" + std::to_string((*it)->getPuckID()) + "] was deleted \n";
				delete *it;					// delete the puck from memory
				it = puckList.erase(it);	// delete the puck from list
				break;
			case PuckSignal::PuckReturn::SEND:
				acceptCounter++;
				prioReturnVal.puckType = new PuckSignal::PuckType((*it)->getType());
				prioReturnVal.actorFlag = true;
				prioReturnVal.actorSignal = ActorSignal::SEND_PUCK;
				break;
			case PuckSignal::PuckReturn::RECEIVED:
				acceptCounter++;
				prioReturnVal.actorFlag = true;
				prioReturnVal.actorSignal = ActorSignal::RECEIVED_PUCK;
				break;
			case PuckSignal::PuckReturn::EVALUATE:
				acceptCounter++;
				if(!sort.process((*it)->getType())) {
					prioReturnVal.actorFlag = true;
					prioReturnVal.actorSignal = ActorSignal::OPEN_SWITCH;
				}
				break;
			case PuckSignal::PuckReturn::START_HEIGHT:
				acceptCounter++;
				prioReturnVal.actorFlag = true;
				prioReturnVal.actorSignal = ActorSignal::START_MEASUREMENT;
				break;
			case PuckSignal::PuckReturn::STOP_HEIGHT:
				acceptCounter++;
				prioReturnVal.actorFlag = true;
				prioReturnVal.actorSignal = ActorSignal::STOP_MEASUREMENT;
				break;
			case PuckSignal::PuckReturn::SLIDE_FULL:
				acceptCounter++;

				sort.process(returnVal.puckReturn);

				prioReturnVal.slideFullFlag = true;
				LOG_DEBUG <<"[Puck" + std::to_string((*it)->getPuckID()) + "] was deleted \n";
				delete *it;					// delete the puck from memory
				it = puckList.erase(it);	// delete the puck from list
				break;
			//
			case PuckSignal::PuckReturn::WARNING:
				warningCounter++;
				break;
			case PuckSignal::PuckReturn::DENY:
				break;
			case PuckSignal::PuckReturn::ERROR:
				prioReturnVal.errorFlag = true;
				prioReturnVal.errorSignal = ErrorSignal::PUCK_LOST;
				break;
			default:
				prioReturnVal.errorFlag = true;
				prioReturnVal.errorSignal = ErrorSignal::UNEXPECTED_SIGNAL;
				return prioReturnVal;
		}

		if(		returnVal.puckReturn != PuckSignal::PuckReturn::DELETE ||
				returnVal.puckReturn != PuckSignal::PuckReturn::SLIDE_FULL) {
			++it;
		}
	}

	if(!prioReturnVal.errorFlag) {
		if(acceptCounter > 1 || acceptCounter < 0) {
			prioReturnVal.errorFlag = true;
			prioReturnVal.errorSignal = ErrorSignal::MULTIPLE_ACCEPT;
			return prioReturnVal;
		}

		if(acceptCounter == 0) {
			prioReturnVal.errorFlag = true;
			prioReturnVal.errorSignal = ErrorSignal::UNEXPECTED_SIGNAL;
			return prioReturnVal;
		}

		// acceptCounter == 1
		if(warningCounter > 1 || warningCounter < 0) {
			prioReturnVal.errorFlag = true;
			prioReturnVal.errorSignal = ErrorSignal::MULTIPLE_WARNING;
			return prioReturnVal;
		}

		// warning can be ignored
	}

	if(puckList.empty()) {
		prioReturnVal.speedSignal = PuckSignal::PuckSpeed::STOP;
	}

	// everything OK
	return prioReturnVal;
}
<commit_msg>metal detect hotfix<commit_after>/*
 * PuckManager.cpp
 *
 *  Created on: 09.06.2017
 *      Author: aca592
 */

#include "PuckManager.h"

#include "logger.h"
#include "logScope.h"

PuckManager::PuckManager(int chid)
	: puckList()
	, nextPuckID(0)
	, chid(chid)
{}

PuckManager::~PuckManager() {
	std::list<PuckContext*>::iterator it = puckList.begin();
	while(it != puckList.end()) {
		LOG_DEBUG <<"[Puck" + std::to_string((*it)->getPuckID()) + "] was deleted \n";
		delete *it;					// delete the puck from memory
		it = puckList.erase(it);	// delete the puck from list
	}
}

PuckManager::ManagerReturn PuckManager::newPuck(PuckSignal::PuckType type) {
	LOG_SCOPE;
	ManagerReturn ret;
	ret.actorFlag = true;
	ret.actorSignal = ActorSignal::ACCEPTED_PUCK;
	addPuck(new PuckContext(chid, type));
	return ret;
}

void PuckManager::addPuck(PuckContext *puck) {
	LOG_SCOPE;
	puck->setPuckID(nextPuckID++);
	puckList.push_back(puck);
}

PuckManager::ManagerReturn PuckManager::process(PuckSignal::Signal signal) {
	LOG_SCOPE;

	ManagerReturn prioReturnVal; // the prioritized return value
	prioReturnVal.speedSignal = PuckSignal::PuckSpeed::FAST;
	prioReturnVal.actorFlag = false;
	prioReturnVal.errorFlag = false;
	prioReturnVal.slideFullFlag = false;
	prioReturnVal.puckType = nullptr;

	int32_t acceptCounter = 0; // count all accepted signals
	int32_t warningCounter = 0; // count all warnings

#if !machine // machine0
	// check for first interrupt signal - puck must be created
	if(	signal.signalType == PuckSignal::SignalType::INTERRUPT_SIGNAL &&
		signal.interruptSignal == interrupts::interruptSignals::INLET_IN) {

		addPuck(new PuckContext(chid));

		std::list<PuckContext*>::iterator it = puckList.begin();
		while(it != puckList.end()) {
			if((*it)->getCurrentSpeed() > prioReturnVal.speedSignal) { // Check for speed prio
				prioReturnVal.speedSignal = (*it)->getCurrentSpeed();
			}
			it++;
		}

		return prioReturnVal;
	}

	// signal can be passed for speed prio -> every puck should return deny
#endif

	if(puckList.empty()) {
		prioReturnVal.speedSignal = PuckSignal::PuckSpeed::STOP;
		prioReturnVal.errorFlag = true;
		prioReturnVal.errorSignal = ErrorSignal::UNEXPECTED_SIGNAL;
		return prioReturnVal;
	}

	// Pass the timer signal to the given puckID
	if(signal.signalType == PuckSignal::SignalType::TIMER_SIGNAL) {
		std::list<PuckContext*>::iterator it = puckList.begin();
		while(it != puckList.end()) {
			if((*it)->getCurrentSpeed() > prioReturnVal.speedSignal) { // Check for speed prio
				prioReturnVal.speedSignal = (*it)->getCurrentSpeed();
			}

			// check for puckID
			uint16_t currentPuckID = (*it)->getPuckID();
			if(currentPuckID == signal.timerSignal.TimerInfo.puckID) {
				// pass the timer signal
				PuckSignal::Return returnVal = (*it)->process(signal);

				// check return value
				if(	returnVal.puckReturn != PuckSignal::PuckReturn::ACCEPT &&
					returnVal.puckReturn != PuckSignal::PuckReturn::ERROR) {
					// puck should be triggered on accept or error -> unexpected otherwise
					prioReturnVal.errorFlag = true;
					prioReturnVal.errorSignal = ErrorSignal::UNEXPECTED_SIGNAL;
				} else if(returnVal.puckReturn == PuckSignal::PuckReturn::ERROR) {
					prioReturnVal.errorFlag = true;
					prioReturnVal.errorSignal = ErrorSignal::PUCK_LOST; //Late Timer expiered
				}
			}

			it++;
		}

		return prioReturnVal;
	}

	if(signal.signalType == PuckSignal::SignalType::SERIAL_SIGNAL && signal.serialSignal == Serial_n::ser_proto_msg::SLIDE_FULL_SER) {
		sort.process(signal.serialSignal);

		std::list<PuckContext*>::iterator it = puckList.begin();
		while(it != puckList.end()) {
			if((*it)->getCurrentSpeed() > prioReturnVal.speedSignal) { // Check for speed prio
				prioReturnVal.speedSignal = (*it)->getCurrentSpeed();
			}
			it++;
		}

		return prioReturnVal;
	}

	// check the signal for every puck in the list
	std::list<PuckContext*>::iterator it = puckList.begin();
	while(it != puckList.end()) {
		PuckSignal::Return returnVal = (*it)->process(signal);

		if(returnVal.puckSpeed > prioReturnVal.speedSignal) { // Check for speed prio
			prioReturnVal.speedSignal = returnVal.puckSpeed;
		}

		switch(returnVal.puckReturn) {
			case PuckSignal::PuckReturn::ACCEPT:
				acceptCounter++;
				break;
			case PuckSignal::PuckReturn::DELETE:
				acceptCounter++;
				LOG_DEBUG <<"[Puck" + std::to_string((*it)->getPuckID()) + "] was deleted \n";
				delete *it;					// delete the puck from memory
				it = puckList.erase(it);	// delete the puck from list
				break;
			case PuckSignal::PuckReturn::SEND:
				acceptCounter++;
				prioReturnVal.puckType = new PuckSignal::PuckType((*it)->getType());
				prioReturnVal.actorFlag = true;
				prioReturnVal.actorSignal = ActorSignal::SEND_PUCK;
				break;
			case PuckSignal::PuckReturn::RECEIVED:
				acceptCounter++;
				prioReturnVal.actorFlag = true;
				prioReturnVal.actorSignal = ActorSignal::RECEIVED_PUCK;
				break;
			case PuckSignal::PuckReturn::EVALUATE:
				acceptCounter++;
				if(!sort.process((*it)->getType())) {
					prioReturnVal.actorFlag = true;
					prioReturnVal.actorSignal = ActorSignal::OPEN_SWITCH;
				}
				break;
			case PuckSignal::PuckReturn::START_HEIGHT:
				acceptCounter++;
				prioReturnVal.actorFlag = true;
				prioReturnVal.actorSignal = ActorSignal::START_MEASUREMENT;
				break;
			case PuckSignal::PuckReturn::STOP_HEIGHT:
				acceptCounter++;
				prioReturnVal.actorFlag = true;
				prioReturnVal.actorSignal = ActorSignal::STOP_MEASUREMENT;
				break;
			case PuckSignal::PuckReturn::SLIDE_FULL:
				acceptCounter++;

				sort.process(returnVal.puckReturn);

				prioReturnVal.slideFullFlag = true;
				LOG_DEBUG <<"[Puck" + std::to_string((*it)->getPuckID()) + "] was deleted \n";
				delete *it;					// delete the puck from memory
				it = puckList.erase(it);	// delete the puck from list
				break;
			//
			case PuckSignal::PuckReturn::WARNING:
				warningCounter++;
				break;
			case PuckSignal::PuckReturn::DENY:
				break;
			case PuckSignal::PuckReturn::ERROR:
				prioReturnVal.errorFlag = true;
				prioReturnVal.errorSignal = ErrorSignal::PUCK_LOST;
				break;
			default:
				prioReturnVal.errorFlag = true;
				prioReturnVal.errorSignal = ErrorSignal::UNEXPECTED_SIGNAL;
				return prioReturnVal;
		}

		if(		returnVal.puckReturn != PuckSignal::PuckReturn::DELETE ||
				returnVal.puckReturn != PuckSignal::PuckReturn::SLIDE_FULL) {
			++it;
		}
	}

	// metal detect hot fix
	if(signal.signalType == PuckSignal::SignalType::INTERRUPT_SIGNAL
			&& signal.interruptSignal == interrupts::interruptSignals::METAL_DETECT
			&& acceptCounter == 0) {
		acceptCounter++;
	}

	if(!prioReturnVal.errorFlag) {
		if(acceptCounter > 1 || acceptCounter < 0) {
			prioReturnVal.errorFlag = true;
			prioReturnVal.errorSignal = ErrorSignal::MULTIPLE_ACCEPT;
			return prioReturnVal;
		}

		if(acceptCounter == 0) {
			prioReturnVal.errorFlag = true;
			prioReturnVal.errorSignal = ErrorSignal::UNEXPECTED_SIGNAL;
			return prioReturnVal;
		}

		// acceptCounter == 1
		if(warningCounter > 1 || warningCounter < 0) {
			prioReturnVal.errorFlag = true;
			prioReturnVal.errorSignal = ErrorSignal::MULTIPLE_WARNING;
			return prioReturnVal;
		}

		// warning can be ignored
	}

	if(puckList.empty()) {
		prioReturnVal.speedSignal = PuckSignal::PuckSpeed::STOP;
	}

	// everything OK
	return prioReturnVal;
}
<|endoftext|>


<commit_before>//******************************************************************
//
// Copyright 2014 Intel Mobile Communications GmbH 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.
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

///
///This sample demonstrates the device discovery feature
///The server sets the device related info. which can
///be later retrieved by a client.
///

#include <mutex>
#include <condition_variable>

#include "OCPlatform.h"
#include "OCApi.h"

using namespace OC;

//Set of strings for each of deviceInfo fields
std::string contentType = "myContentType";
std::string dateOfManufacture = "myDateOfManufacture";
std::string deviceName = "myDeviceName";
std::string deviceUUID = "myDeviceUUID";
std::string firmwareVersion = "myFirmwareVersion";
std::string hostName = "myHostName";
std::string manufacturerName = "myManufacturerNa";
std::string manufacturerUrl = "myManufacturerUrl";
std::string modelNumber = "myModelNumber";
std::string platformVersion = "myPlatformVersion";
std::string supportUrl = "mySupportUrl";
std::string version = "myVersion";

//OCDeviceInfo Contains all the device info to be stored
OCDeviceInfo deviceInfo;

void DeleteDeviceInfo()
{
    delete[] deviceInfo.contentType;
    delete[] deviceInfo.dateOfManufacture;
    delete[] deviceInfo.deviceName;
    delete[] deviceInfo.deviceUUID;
    delete[] deviceInfo.firmwareVersion;
    delete[] deviceInfo.hostName;
    delete[] deviceInfo.manufacturerName;
    delete[] deviceInfo.manufacturerUrl;
    delete[] deviceInfo.modelNumber;
    delete[] deviceInfo.platformVersion;
    delete[] deviceInfo.supportUrl;
    delete[] deviceInfo.version;
}

void DuplicateString(char ** targetString, std::string sourceString)
{
    *targetString = new char[sourceString.length() + 1];
    strncpy(*targetString, sourceString.c_str(), (sourceString.length() + 1));
}

OCStackResult SetDeviceInfo(std::string contentType, std::string dateOfManufacture,
                std::string deviceName, std::string deviceUUID, std::string firmwareVersion,
                std::string hostName, std::string manufacturerName, std::string manufacturerUrl,
                std::string modelNumber, std::string platformVersion, std::string supportUrl,
                std::string version)
{
    if(manufacturerName.length() > MAX_MANUFACTURER_NAME_LENGTH)
    {
        return OC_STACK_INVALID_PARAM;

    }

    if(manufacturerUrl.length() > MAX_MANUFACTURER_URL_LENGTH)
    {
        return OC_STACK_INVALID_PARAM;

    }

    try
    {
        DuplicateString(&deviceInfo.contentType, contentType);
        DuplicateString(&deviceInfo.dateOfManufacture, dateOfManufacture);
        DuplicateString(&deviceInfo.deviceName, deviceName);
        DuplicateString(&deviceInfo.deviceUUID, deviceUUID);
        DuplicateString(&deviceInfo.firmwareVersion, firmwareVersion);
        DuplicateString(&deviceInfo.hostName, hostName);
        DuplicateString(&deviceInfo.manufacturerName, manufacturerName);
        DuplicateString(&deviceInfo.manufacturerUrl, manufacturerUrl);
        DuplicateString(&deviceInfo.modelNumber, modelNumber);
        DuplicateString(&deviceInfo.platformVersion, platformVersion);
        DuplicateString(&deviceInfo.supportUrl, supportUrl);
        DuplicateString(&deviceInfo.version, version);
    }catch(exception &e)
    {
        std::cout<<"String Copy failed!!\n";
        return OC_STACK_ERROR;
    }

    return OC_STACK_OK;
}

int main()
{

    // Create PlatformConfig object
    PlatformConfig cfg {
        OC::ServiceType::InProc,
        OC::ModeType::Server,
        "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
        0,         // Uses randomly available port
        OC::QualityOfService::LowQos
    };

    OCPlatform::Configure(cfg);

    std::cout<<"Starting server & setting device info\n";

    OCStackResult result = SetDeviceInfo(contentType, dateOfManufacture, deviceName,
            deviceUUID, firmwareVersion, hostName, manufacturerName, manufacturerUrl,
            modelNumber, platformVersion, supportUrl, version);

    if(result != OC_STACK_OK)
    {
        std::cout << "Device Registration failed\n";
        return -1;
    }

    result = OCPlatform::registerDeviceInfo(deviceInfo);

    if(result != OC_STACK_OK)
    {
        std::cout << "Device Registration failed\n";
        return -1;
    }

    DeleteDeviceInfo();

    // A condition variable will free the mutex it is given, then do a non-
    // intensive block until 'notify' is called on it.  In this case, since we
    // don't ever call cv.notify, this should be a non-processor intensive version
    // of while(true);
    std::mutex blocker;
    std::condition_variable cv;
    std::unique_lock<std::mutex> lock(blocker);
    cv.wait(lock);

    // No explicit call to stop the platform.
    // When OCPlatform::destructor is invoked, internally we do platform cleanup

    return 0;

}

<commit_msg>Guard against spurious wakeups in devicediscoveryserver.cpp<commit_after>//******************************************************************
//
// Copyright 2014 Intel Mobile Communications GmbH 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.
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

///
///This sample demonstrates the device discovery feature
///The server sets the device related info. which can
///be later retrieved by a client.
///

#include <mutex>
#include <condition_variable>

#include "OCPlatform.h"
#include "OCApi.h"

using namespace OC;

//Set of strings for each of deviceInfo fields
std::string contentType = "myContentType";
std::string dateOfManufacture = "myDateOfManufacture";
std::string deviceName = "myDeviceName";
std::string deviceUUID = "myDeviceUUID";
std::string firmwareVersion = "myFirmwareVersion";
std::string hostName = "myHostName";
std::string manufacturerName = "myManufacturerNa";
std::string manufacturerUrl = "myManufacturerUrl";
std::string modelNumber = "myModelNumber";
std::string platformVersion = "myPlatformVersion";
std::string supportUrl = "mySupportUrl";
std::string version = "myVersion";

//OCDeviceInfo Contains all the device info to be stored
OCDeviceInfo deviceInfo;

void DeleteDeviceInfo()
{
    delete[] deviceInfo.contentType;
    delete[] deviceInfo.dateOfManufacture;
    delete[] deviceInfo.deviceName;
    delete[] deviceInfo.deviceUUID;
    delete[] deviceInfo.firmwareVersion;
    delete[] deviceInfo.hostName;
    delete[] deviceInfo.manufacturerName;
    delete[] deviceInfo.manufacturerUrl;
    delete[] deviceInfo.modelNumber;
    delete[] deviceInfo.platformVersion;
    delete[] deviceInfo.supportUrl;
    delete[] deviceInfo.version;
}

void DuplicateString(char ** targetString, std::string sourceString)
{
    *targetString = new char[sourceString.length() + 1];
    strncpy(*targetString, sourceString.c_str(), (sourceString.length() + 1));
}

OCStackResult SetDeviceInfo(std::string contentType, std::string dateOfManufacture,
                std::string deviceName, std::string deviceUUID, std::string firmwareVersion,
                std::string hostName, std::string manufacturerName, std::string manufacturerUrl,
                std::string modelNumber, std::string platformVersion, std::string supportUrl,
                std::string version)
{
    if(manufacturerName.length() > MAX_MANUFACTURER_NAME_LENGTH)
    {
        return OC_STACK_INVALID_PARAM;

    }

    if(manufacturerUrl.length() > MAX_MANUFACTURER_URL_LENGTH)
    {
        return OC_STACK_INVALID_PARAM;

    }

    try
    {
        DuplicateString(&deviceInfo.contentType, contentType);
        DuplicateString(&deviceInfo.dateOfManufacture, dateOfManufacture);
        DuplicateString(&deviceInfo.deviceName, deviceName);
        DuplicateString(&deviceInfo.deviceUUID, deviceUUID);
        DuplicateString(&deviceInfo.firmwareVersion, firmwareVersion);
        DuplicateString(&deviceInfo.hostName, hostName);
        DuplicateString(&deviceInfo.manufacturerName, manufacturerName);
        DuplicateString(&deviceInfo.manufacturerUrl, manufacturerUrl);
        DuplicateString(&deviceInfo.modelNumber, modelNumber);
        DuplicateString(&deviceInfo.platformVersion, platformVersion);
        DuplicateString(&deviceInfo.supportUrl, supportUrl);
        DuplicateString(&deviceInfo.version, version);
    }catch(exception &e)
    {
        std::cout<<"String Copy failed!!\n";
        return OC_STACK_ERROR;
    }

    return OC_STACK_OK;
}

int main()
{

    // Create PlatformConfig object
    PlatformConfig cfg {
        OC::ServiceType::InProc,
        OC::ModeType::Server,
        "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
        0,         // Uses randomly available port
        OC::QualityOfService::LowQos
    };

    OCPlatform::Configure(cfg);

    std::cout<<"Starting server & setting device info\n";

    OCStackResult result = SetDeviceInfo(contentType, dateOfManufacture, deviceName,
            deviceUUID, firmwareVersion, hostName, manufacturerName, manufacturerUrl,
            modelNumber, platformVersion, supportUrl, version);

    if(result != OC_STACK_OK)
    {
        std::cout << "Device Registration failed\n";
        return -1;
    }

    result = OCPlatform::registerDeviceInfo(deviceInfo);

    if(result != OC_STACK_OK)
    {
        std::cout << "Device Registration failed\n";
        return -1;
    }

    DeleteDeviceInfo();

    // A condition variable will free the mutex it is given, then do a non-
    // intensive block until 'notify' is called on it.  In this case, since we
    // don't ever call cv.notify, this should be a non-processor intensive version
    // of while(true);
    std::mutex blocker;
    std::condition_variable cv;
    std::unique_lock<std::mutex> lock(blocker);
    while(true)
    {
        cv.wait(lock);
    }

    // No explicit call to stop the platform.
    // When OCPlatform::destructor is invoked, internally we do platform cleanup

    return 0;

}

<|endoftext|>


<commit_before>/**
 *  @file
 *  @copyright defined in eos/LICENSE.txt
 */
#pragma once
#include <eosio/chain/authority.hpp>

#include "multi_index_includes.hpp"

namespace eosio { namespace chain {
   class permission_object : public chainbase::object<permission_object_type, permission_object> {
      OBJECT_CTOR(permission_object, (auth) )

      id_type           id;
      account_name      owner; ///< the account this permission belongs to
      id_type           parent; ///< parent permission
      permission_name   name; ///< human-readable name for the permission
      shared_authority  auth; ///< authority required to execute this permission
      time_point        last_updated; ///< the last time this authority was updated
      time_point        delay; ///< delay associated with this permission

      /**
       * @brief Checks if this permission is equivalent or greater than other
       * @tparam Index The permission_index
       * @return True if this permission matches, or is a parent of, other; false otherwise
       *
       * Permissions are organized hierarchically such that a parent permission is strictly more powerful than its
       * children/grandchildren. This method checks whether this permission is of greater or equal power (capable of
       * satisfying) permission @ref other. This would be the case if this permission matches, or is some parent of,
       * other.
       */
      template <typename Index>
      bool satisfies(const permission_object& other, const Index& permission_index) const {
         // If the owners are not the same, this permission cannot satisfy other
         if (owner != other.owner)
            return false;
         // If this permission matches other, or is the immediate parent of other, then this permission satisfies other
         if (id == other.id || id == other.parent)
            return true;
         // Walk up other's parent tree, seeing if we find this permission. If so, this permission satisfies other
         const permission_object* parent = &*permission_index.template get<by_id>().find(other.parent);
         while (parent) {
            if (id == parent->parent)
               return true;
            if (parent->parent._id == 0)
               return false;
            parent = &*permission_index.template get<by_id>().find(parent->parent);
         }
         // This permission is not a parent of other, and so does not satisfy other
         return false;
      }
   };

   struct by_parent;
   struct by_owner;
   struct by_name;
   using permission_index = chainbase::shared_multi_index_container<
      permission_object,
      indexed_by<
         ordered_unique<tag<by_id>, member<permission_object, permission_object::id_type, &permission_object::id>>,
         ordered_unique<tag<by_parent>,
            composite_key<permission_object,
               member<permission_object, permission_object::id_type, &permission_object::parent>,
               member<permission_object, permission_object::id_type, &permission_object::id>
            >
         >,
         ordered_unique<tag<by_owner>,
            composite_key<permission_object,
               member<permission_object, account_name, &permission_object::owner>,
               member<permission_object, permission_name, &permission_object::name>
            >
         >,
         ordered_unique<tag<by_name>,
            composite_key<permission_object,
               member<permission_object, permission_name, &permission_object::name>,
               member<permission_object, permission_object::id_type, &permission_object::id>
            >
         >
      >
   >;

   class permission_usage_object : public chainbase::object<permission_usage_object_type, permission_usage_object> {
      OBJECT_CTOR(permission_usage_object)

      id_type           id;
      account_name      account;     ///< the account this permission belongs to
      permission_name   permission;  ///< human-readable name for the permission
      time_point        last_used;   ///< when this permission was last used
   };

   struct by_account_permission;
   using permission_usage_index = chainbase::shared_multi_index_container<
      permission_usage_object,
      indexed_by<
         ordered_unique<tag<by_id>, member<permission_usage_object, permission_usage_object::id_type, &permission_usage_object::id>>,
         ordered_unique<tag<by_account_permission>,
            composite_key<permission_usage_object,
               member<permission_usage_object, account_name, &permission_usage_object::account>,
               member<permission_usage_object, permission_name, &permission_usage_object::permission>,
               member<permission_usage_object, permission_usage_object::id_type, &permission_usage_object::id>
            >
         >
      >
   >;

} } // eosio::chain

CHAINBASE_SET_INDEX_TYPE(eosio::chain::permission_object, eosio::chain::permission_index)
CHAINBASE_SET_INDEX_TYPE(eosio::chain::permission_usage_object, eosio::chain::permission_usage_index)

FC_REFLECT(chainbase::oid<eosio::chain::permission_object>, (_id))
FC_REFLECT(eosio::chain::permission_object, (id)(owner)(parent)(name)(auth)(last_updated)(delay))

FC_REFLECT(chainbase::oid<eosio::chain::permission_usage_object>, (_id))
FC_REFLECT(eosio::chain::permission_usage_object, (id)(account)(permission)(last_used))
<commit_msg>Changed satisfy to accumulate the highest delay found on any of the permissions traversed from other to this permission. GH# 1022<commit_after>/**
 *  @file
 *  @copyright defined in eos/LICENSE.txt
 */
#pragma once
#include <eosio/chain/authority.hpp>

#include "multi_index_includes.hpp"

namespace eosio { namespace chain {
   class permission_object : public chainbase::object<permission_object_type, permission_object> {
      OBJECT_CTOR(permission_object, (auth) )

      id_type           id;
      account_name      owner; ///< the account this permission belongs to
      id_type           parent; ///< parent permission
      permission_name   name; ///< human-readable name for the permission
      shared_authority  auth; ///< authority required to execute this permission
      time_point        last_updated; ///< the last time this authority was updated
      time_point        delay; ///< delay associated with this permission

      /**
       * @brief Checks if this permission is equivalent or greater than other
       * @tparam Index The permission_index
       * @return a time_point set to the maximum delay encountered between this and the permission that is other;
       * empty optional otherwise
       *
       * Permissions are organized hierarchically such that a parent permission is strictly more powerful than its
       * children/grandchildren. This method checks whether this permission is of greater or equal power (capable of
       * satisfying) permission @ref other. The returned value is an optional<time_point> that will indicate the
       * maximum delay encountered walking the hierarchy between this permission and other, if other satisfies this,
       * otherwise an empty optional is returned.
       */
      template <typename Index>
      optional<time_point> satisfies(const permission_object& other, const Index& permission_index) const {
         // If the owners are not the same, this permission cannot satisfy other
         if (owner != other.owner)
            return optional<time_point>();

         // if other satisfies this permission, then other's delay and this delay will have to contribute
         auto max_delay = other.delay > delay ? other.delay : delay;
         // If this permission matches other, or is the immediate parent of other, then this permission satisfies other
         if (id == other.id || id == other.parent)
            return optional<time_point>(max_delay);
         // Walk up other's parent tree, seeing if we find this permission. If so, this permission satisfies other
         const permission_object* parent = &*permission_index.template get<by_id>().find(other.parent);
         while (parent) {
            if (max_delay < parent->delay)
               max_delay = parent->delay;
            if (id == parent->parent)
               return optional<time_point>(max_delay);
            if (parent->parent._id == 0)
               return optional<time_point>();
            parent = &*permission_index.template get<by_id>().find(parent->parent);
         }
         // This permission is not a parent of other, and so does not satisfy other
         return optional<time_point>();
      }
   };

   struct by_parent;
   struct by_owner;
   struct by_name;
   using permission_index = chainbase::shared_multi_index_container<
      permission_object,
      indexed_by<
         ordered_unique<tag<by_id>, member<permission_object, permission_object::id_type, &permission_object::id>>,
         ordered_unique<tag<by_parent>,
            composite_key<permission_object,
               member<permission_object, permission_object::id_type, &permission_object::parent>,
               member<permission_object, permission_object::id_type, &permission_object::id>
            >
         >,
         ordered_unique<tag<by_owner>,
            composite_key<permission_object,
               member<permission_object, account_name, &permission_object::owner>,
               member<permission_object, permission_name, &permission_object::name>
            >
         >,
         ordered_unique<tag<by_name>,
            composite_key<permission_object,
               member<permission_object, permission_name, &permission_object::name>,
               member<permission_object, permission_object::id_type, &permission_object::id>
            >
         >
      >
   >;

   class permission_usage_object : public chainbase::object<permission_usage_object_type, permission_usage_object> {
      OBJECT_CTOR(permission_usage_object)

      id_type           id;
      account_name      account;     ///< the account this permission belongs to
      permission_name   permission;  ///< human-readable name for the permission
      time_point        last_used;   ///< when this permission was last used
   };

   struct by_account_permission;
   using permission_usage_index = chainbase::shared_multi_index_container<
      permission_usage_object,
      indexed_by<
         ordered_unique<tag<by_id>, member<permission_usage_object, permission_usage_object::id_type, &permission_usage_object::id>>,
         ordered_unique<tag<by_account_permission>,
            composite_key<permission_usage_object,
               member<permission_usage_object, account_name, &permission_usage_object::account>,
               member<permission_usage_object, permission_name, &permission_usage_object::permission>,
               member<permission_usage_object, permission_usage_object::id_type, &permission_usage_object::id>
            >
         >
      >
   >;

} } // eosio::chain

CHAINBASE_SET_INDEX_TYPE(eosio::chain::permission_object, eosio::chain::permission_index)
CHAINBASE_SET_INDEX_TYPE(eosio::chain::permission_usage_object, eosio::chain::permission_usage_index)

FC_REFLECT(chainbase::oid<eosio::chain::permission_object>, (_id))
FC_REFLECT(eosio::chain::permission_object, (id)(owner)(parent)(name)(auth)(last_updated)(delay))

FC_REFLECT(chainbase::oid<eosio::chain::permission_usage_object>, (_id))
FC_REFLECT(eosio::chain::permission_usage_object, (id)(account)(permission)(last_used))
<|endoftext|>


<commit_before># pragma once
# include <Siv3D.hpp>

namespace asc
{
	using namespace s3d;

	/// <summary>
	/// 𑗎M\ TCPServer
	/// </summary>
	/// <remarks>
	/// M UTF-8 ōs܂B
	/// </remarks>
	class TCPStringServer : public TCPServer
	{
	private:

		std::string m_buffer;

	public:

		/// <summary>
		/// 1 ǂݍ݂܂B
		/// </summary>
		/// <param name="to">
		/// ǂݍݐ
		/// </param>
		/// <returns>
		/// ǂݍ݂ɐ true
		/// </returns>
		/// <remarks>
		/// {Ȃǂ 1 oCgł͂Ȃ͐܂B
		/// </remarks>
		bool readChar(wchar& to)
		{
			if (m_buffer.length() > 0)
			{
				to = FromUTF8(m_buffer.substr(0, 1))[0];
				m_buffer = m_buffer.substr(1);
			}

			std::string buffer;

			if (!read(buffer[0]))
				return false;

			to = FromUTF8(std::move(buffer))[0];
			return true;
		}

		/// <summary>
		/// w肵ĕǂݍ݂܂B
		/// </summary>
		/// <param name="length">
		/// ǂݍޕ
		/// </param>
		/// <param name="to">
		/// ǂݍݐ
		/// </param>
		/// <returns>
		/// ǂݍ݂ɐ true
		/// </returns>
		/// <remarks>
		/// {Ȃǂ 1 oCgł͂Ȃ͐܂B
		/// </remarks>
		bool readString(size_t length, String& to)
		{
			if (m_buffer.length() >= length)
			{
				to = FromUTF8(m_buffer.substr(0, length));
				m_buffer = m_buffer.substr(length);
				return true;
			}

			for (;;)
			{
				char character;

				if (!read(character))
					return false;

				m_buffer.push_back(character);

				if (m_buffer.length() >= length)
				{
					to = FromUTF8(m_buffer.substr(0, length));
					m_buffer = m_buffer.substr(length);
					return true;
				}
			}

			return false;
		}

		/// <summary>
		/// 1 sǂݍ݂܂B
		/// </summary>
		/// <param name="to">
		/// ǂݍݐ
		/// </param>
		/// <returns>
		/// ǂݍ݂ɐ true
		/// </returns>
		/// <remarks>
		/// {Ȃǂ 1 oCgł͂Ȃ܂B
		/// </remarks>
		bool readLine(String& to)
		{
			return readUntil('\n', to);
		}

		/// <summary>
		/// w肵܂œǂݍ݂܂B
		/// </summary>
		/// <param name="end">
		/// w肷镶
		/// </param>
		/// <param name="to">
		/// ǂݍݐ
		/// </param>
		/// <returns>
		/// ǂݍ݂ɐ true
		/// </returns>
		/// <remarks>
		/// {Ȃǂ 1 oCgł͂Ȃ܂B
		/// </remarks>
		bool readUntil(char end, String& to)
		{
			const auto pos = m_buffer.find(end);

			if (pos != std::string::npos)
			{
				to = FromUTF8(m_buffer.substr(0, pos));
				m_buffer = m_buffer.substr(pos);
				return true;
			}

			for (;;)
			{
				char character;

				if (!read(character))
					return false;

				m_buffer.push_back(character);

				if (character == end)
					break;
			}

			to = FromUTF8(std::move(m_buffer));
			m_buffer.clear();
			return true;
		}

		/// <summary>
		/// \Ȍǂݍ݂܂B
		/// </summary>
		/// <param name="to">
		/// ǂݍݐ
		/// </param>
		/// <returns>
		/// 1 łǂݍ݂ɐ true
		/// </returns>
		/// <remarks>
		/// {Ȃǂ 1 oCgł͂Ȃ܂B
		/// </remarks>
		bool readAll(String& to)
		{
			for (;;)
			{
				char character;

				if (!read(character))
					break;

				m_buffer.push_back(character);
			}

			const auto success = m_buffer.empty();

			if (success)
			{
				to = FromUTF8(std::move(m_buffer));
				m_buffer.clear();
			}

			return success;
		}

		/// <summary>
		/// 𑗐M܂B
		/// </summary>
		/// <param name="data">
		/// M镶
		/// </param>
		/// <returns>
		/// Mɐ true
		/// </returns>
		/// <remarks>
		/// {Ȃǂ 1 oCgł͂Ȃ܂B
		/// </remarks>
		bool sendString(const String& data)
		{
			const auto str = ToUTF8(data);
			return send(str.data(), sizeof(char) * str.length());
		}

		/// <summary>
		/// readUntil֐Ŏgpobt@̒g폜܂B
		/// </summary>
		/// <returns>
		/// 폜obt@̒g
		/// </returns>
		String clearBuffer()
		{
			const auto buffer = FromUTF8(std::move(m_buffer));
			m_buffer.clear();
			return buffer;
		}
	};
}
<commit_msg>Adjust to TCPStringClient.<commit_after># pragma once
# include <Siv3D.hpp>

namespace asc
{
	using namespace s3d;

	/// <summary>
	/// 𑗎M\ TCPServer
	/// </summary>
	/// <remarks>
	/// M UTF-8 ōs܂B
	/// </remarks>
	class TCPStringServer : public TCPServer
	{
	public:

		/// <summary>
		/// 1 ǂݍ݂܂B
		/// </summary>
		/// <param name="to">
		/// ǂݍݐ
		/// </param>
		/// <returns>
		/// ǂݍ݂ɐ true
		/// </returns>
		/// <remarks>
		/// {Ȃǂ 1 oCgł͂Ȃ͐܂B
		/// </remarks>
		bool readChar(wchar& to)
		{
			std::string buffer;

			if (!lookahead(buffer[0]))
				return false;

			skip(sizeof(std::string::value_type));
			to = FromUTF8(std::move(buffer))[0];

			return true;
		}

		/// <summary>
		/// w肵ĕǂݍ݂܂B
		/// </summary>
		/// <param name="length">
		/// ǂݍޕ
		/// </param>
		/// <param name="to">
		/// ǂݍݐ
		/// </param>
		/// <returns>
		/// ǂݍ݂ɐ true
		/// </returns>
		/// <remarks>
		/// {Ȃǂ 1 oCgł͂Ȃ͐܂B
		/// </remarks>
		bool readString(size_t length, String& to)
		{
			std::string buffer;

			buffer.resize(length);

			if (!lookahead(&buffer[0], buffer.size()))
			{
				return false;
			}

			skip(sizeof(std::string::value_type) * buffer.size());
			to = FromUTF8(std::move(buffer));

			return true;
		}

		/// <summary>
		/// 1 sǂݍ݂܂B
		/// </summary>
		/// <param name="to">
		/// ǂݍݐ
		/// </param>
		/// <returns>
		/// ǂݍ݂ɐ true
		/// </returns>
		/// <remarks>
		/// {Ȃǂ 1 oCgł͂Ȃ܂B
		/// </remarks>
		bool readLine(String& to)
		{
			return readUntil('\n', to);
		}

		/// <summary>
		/// w肵܂œǂݍ݂܂B
		/// </summary>
		/// <param name="end">
		/// w肷镶
		/// </param>
		/// <param name="to">
		/// ǂݍݐ
		/// </param>
		/// <returns>
		/// ǂݍ݂ɐ true
		/// </returns>
		/// <remarks>
		/// {Ȃǂ 1 oCgł͂Ȃ܂B
		/// </remarks>
		bool readUntil(char end, String& to)
		{
			std::string buffer;

			buffer.resize(available());

			if (!lookahead(&buffer[0], buffer.size()))
				return false;

			const auto pos = buffer.find(end);

			if (pos == buffer.npos)
				return false;

			buffer.resize(pos + 1);

			skip(sizeof(std::string::value_type) * buffer.size());
			to = FromUTF8(std::move(buffer));

			return true;
		}

		/// <summary>
		/// \Ȍǂݍ݂܂B
		/// </summary>
		/// <param name="to">
		/// ǂݍݐ
		/// </param>
		/// <returns>
		/// 1 łǂݍ݂ɐ true
		/// </returns>
		/// <remarks>
		/// {Ȃǂ 1 oCgł͂Ȃ܂B
		/// </remarks>
		bool readAll(String& to)
		{
			std::string buffer;

			buffer.resize(available());

			if (!lookahead(&buffer[0], buffer.size()))
				return false;

			if (buffer.empty())
				return false;

			skip(sizeof(std::string::value_type) * buffer.size());
			to = FromUTF8(std::move(buffer));

			return true;
		}

		/// <summary>
		/// 𑗐M܂B
		/// </summary>
		/// <param name="data">
		/// M镶
		/// </param>
		/// <returns>
		/// Mɐ true
		/// </returns>
		/// <remarks>
		/// {Ȃǂ 1 oCgł͂Ȃ܂B
		/// </remarks>
		bool sendString(const String& data)
		{
			const auto str = ToUTF8(data);
			return send(str.data(), sizeof(char) * str.length());
		}
	};
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <limits>

#include "logging/rtc_event_log/output/rtc_event_log_output_file.h"
#include "logging/rtc_event_log/rtc_event_log.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "system_wrappers/include/file_wrapper.h"

namespace webrtc {

// Together with the assumption of no single Write() would ever be called on
// an input with length greater-than-or-equal-to (max(size_t) / 2), this
// guarantees no overflow of the check for remaining file capacity in Write().
// This does *not* apply to files with unlimited size.
const size_t RtcEventLogOutputFile::kMaxReasonableFileSize =
    std::numeric_limits<size_t>::max() / 2;

RtcEventLogOutputFile::RtcEventLogOutputFile(const std::string& file_name)
    : RtcEventLogOutputFile(file_name, RtcEventLog::kUnlimitedOutput) {}

RtcEventLogOutputFile::RtcEventLogOutputFile(const std::string& file_name,
                                             size_t max_size_bytes)
    : max_size_bytes_(max_size_bytes), file_(FileWrapper::Create()) {
  RTC_CHECK_LE(max_size_bytes_, kMaxReasonableFileSize);

  if (!file_->OpenFile(file_name.c_str(), false)) {
    LOG(LS_ERROR) << "Can't open file. WebRTC event log not started.";
    file_.reset();
    return;
  }
}

RtcEventLogOutputFile::RtcEventLogOutputFile(rtc::PlatformFile file)
    : RtcEventLogOutputFile(file, RtcEventLog::kUnlimitedOutput) {}

RtcEventLogOutputFile::RtcEventLogOutputFile(rtc::PlatformFile file,
                                             size_t max_size_bytes)
    : max_size_bytes_(max_size_bytes), file_(FileWrapper::Create()) {
  RTC_CHECK_LE(max_size_bytes_, kMaxReasonableFileSize);

  FILE* file_handle = rtc::FdopenPlatformFileForWriting(file);
  if (!file_handle) {
    LOG(LS_ERROR) << "Can't open file. WebRTC event log not started.";
    // Even though we failed to open a FILE*, the file is still open
    // and needs to be closed.
    if (!rtc::ClosePlatformFile(file)) {
      LOG(LS_ERROR) << "Can't close file.";
      file_.reset();
    }
    return;
  }

  if (!file_->OpenFromFileHandle(file_handle)) {
    LOG(LS_ERROR) << "Can't open file. WebRTC event log not started.";
    file_.reset();
    return;
  }
}

RtcEventLogOutputFile::~RtcEventLogOutputFile() {
  if (file_) {
    RTC_DCHECK(IsActiveInternal());
    file_->CloseFile();
    file_.reset();
  }
}

bool RtcEventLogOutputFile::IsActive() const {
  return IsActiveInternal();
}

bool RtcEventLogOutputFile::Write(const std::string& output) {
  RTC_DCHECK(IsActiveInternal());
  // No single write may be so big, that it would risk overflowing the
  // calculation of (written_bytes_ + output.length()).
  RTC_DCHECK_LT(output.length(), kMaxReasonableFileSize);

  bool written = false;
  if (max_size_bytes_ == RtcEventLog::kUnlimitedOutput ||
      written_bytes_ + output.length() <= max_size_bytes_) {
    written = file_->Write(output.c_str(), output.size());
    if (!written) {
      LOG(LS_ERROR) << "FileWrapper failed to write WebRtcEventLog file.";
    }
  } else {
    LOG(LS_VERBOSE) << "Max file size reached.";
  }

  if (written) {
    written_bytes_ += output.size();
  } else {
    file_->CloseFile();
    file_.reset();
  }

  return written;
}

bool RtcEventLogOutputFile::IsActiveInternal() const {
  return file_ && file_->is_open();
}

}  // namespace webrtc
<commit_msg>RtcEventLogOutputFile needs to reset file_ whenever the file is not successfully opened<commit_after>/*
 *  Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <limits>

#include "logging/rtc_event_log/output/rtc_event_log_output_file.h"
#include "logging/rtc_event_log/rtc_event_log.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "system_wrappers/include/file_wrapper.h"

namespace webrtc {

// Together with the assumption of no single Write() would ever be called on
// an input with length greater-than-or-equal-to (max(size_t) / 2), this
// guarantees no overflow of the check for remaining file capacity in Write().
// This does *not* apply to files with unlimited size.
const size_t RtcEventLogOutputFile::kMaxReasonableFileSize =
    std::numeric_limits<size_t>::max() / 2;

RtcEventLogOutputFile::RtcEventLogOutputFile(const std::string& file_name)
    : RtcEventLogOutputFile(file_name, RtcEventLog::kUnlimitedOutput) {}

RtcEventLogOutputFile::RtcEventLogOutputFile(const std::string& file_name,
                                             size_t max_size_bytes)
    : max_size_bytes_(max_size_bytes), file_(FileWrapper::Create()) {
  RTC_CHECK_LE(max_size_bytes_, kMaxReasonableFileSize);

  if (!file_->OpenFile(file_name.c_str(), false)) {
    LOG(LS_ERROR) << "Can't open file. WebRTC event log not started.";
    file_.reset();
    return;
  }
}

RtcEventLogOutputFile::RtcEventLogOutputFile(rtc::PlatformFile file)
    : RtcEventLogOutputFile(file, RtcEventLog::kUnlimitedOutput) {}

RtcEventLogOutputFile::RtcEventLogOutputFile(rtc::PlatformFile file,
                                             size_t max_size_bytes)
    : max_size_bytes_(max_size_bytes), file_(FileWrapper::Create()) {
  RTC_CHECK_LE(max_size_bytes_, kMaxReasonableFileSize);

  FILE* file_handle = rtc::FdopenPlatformFileForWriting(file);
  if (!file_handle) {
    LOG(LS_ERROR) << "Can't open file. WebRTC event log not started.";
    // Even though we failed to open a FILE*, the file is still open
    // and needs to be closed.
    if (!rtc::ClosePlatformFile(file)) {
      LOG(LS_ERROR) << "Can't close file.";
    }
    file_.reset();
    return;
  }

  if (!file_->OpenFromFileHandle(file_handle)) {
    LOG(LS_ERROR) << "Can't open file. WebRTC event log not started.";
    file_.reset();
    return;
  }
}

RtcEventLogOutputFile::~RtcEventLogOutputFile() {
  if (file_) {
    RTC_DCHECK(IsActiveInternal());
    file_->CloseFile();
    file_.reset();
  }
}

bool RtcEventLogOutputFile::IsActive() const {
  return IsActiveInternal();
}

bool RtcEventLogOutputFile::Write(const std::string& output) {
  RTC_DCHECK(IsActiveInternal());
  // No single write may be so big, that it would risk overflowing the
  // calculation of (written_bytes_ + output.length()).
  RTC_DCHECK_LT(output.length(), kMaxReasonableFileSize);

  bool written = false;
  if (max_size_bytes_ == RtcEventLog::kUnlimitedOutput ||
      written_bytes_ + output.length() <= max_size_bytes_) {
    written = file_->Write(output.c_str(), output.size());
    if (!written) {
      LOG(LS_ERROR) << "FileWrapper failed to write WebRtcEventLog file.";
    }
  } else {
    LOG(LS_VERBOSE) << "Max file size reached.";
  }

  if (written) {
    written_bytes_ += output.size();
  } else {
    file_->CloseFile();
    file_.reset();
  }

  return written;
}

bool RtcEventLogOutputFile::IsActiveInternal() const {
  return file_ && file_->is_open();
}

}  // namespace webrtc
<|endoftext|>


<commit_before>#include "pivision_ethterm.h"
#include "jobdispatcher.h"
#include "pivision_events.h"
#include "pivision_threadmodel.h"

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

PiVisionEthTermConnectServiceJob::PiVisionEthTermConnectServiceJob(const uint32_t _serviceNo):
serviceNo(_serviceNo),
serviceDiscoveryHeader("WHERE_IS_"),
multicastGroup("224.1.1.1"),
numAttempts(0u),
serverAddress(""),
serviceFound(false),
socketFd(0)
{
  serviceDiscoverySocket = socket(AF_INET, SOCK_DGRAM, 0);

  struct timeval tv;
  tv.tv_sec = 1;
  tv.tv_usec = 0;
  setsockopt(serviceDiscoverySocket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv));

  JobDispatcher::GetApi()->SubscribeToEvent(PIVISION_EVENT_SERVICE_DISCOVERY_TIMEOUT, this);
}

void PiVisionEthTermConnectServiceJob::TryConnect(void)
{
  std::string serviceDiscoverString = serviceDiscoveryHeader + std::to_string(serviceNo);
  JobDispatcher::GetApi()->Log("serviceDiscoveryString: %s", serviceDiscoverString.c_str());

  struct sockaddr_in addr;

  memset(&addr,0,sizeof(addr));
  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = inet_addr(multicastGroup.c_str());
  addr.sin_port = htons(serviceNo - 1u);

  int numBytesSent = sendto(serviceDiscoverySocket,
                            serviceDiscoverString.c_str(),
                            serviceDiscoverString.length(),
                            0,
                            (struct sockaddr*)&addr,
                            sizeof(addr));
  if(numBytesSent < 0)
  {
    perror("sendto");
    exit(1);
  }

  char serverAddressArray[INET_ADDRSTRLEN];

  int32_t bytesReceived = recv(serviceDiscoverySocket,
                               serverAddressArray,
                               sizeof(serverAddressArray),
                               0);

  if(bytesReceived > 0)
  {
    serverAddressArray[bytesReceived] = '\0';
    serverAddress = std::string(serverAddressArray);
    JobDispatcher::GetApi()->Log("Received service address: %s",
                                 serverAddress.c_str());
    serviceFound = true;
  }
}

int32_t PiVisionEthTermConnectServiceJob::ConnectToServer()
{
  int sockfd;

  struct addrinfo hints;
  struct addrinfo* servinfo;
  struct addrinfo* p;

  memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;

  if (getaddrinfo(serverAddress.c_str(),
                  std::to_string(serviceNo).c_str(),
                  &hints,
                  &servinfo) != 0)
  {
      printf("getddrinfo\n");
      return -1;
  }

  for(p = servinfo; p != 0; p = p->ai_next)
  {
    (void) printf("Finding suitable servinfo\n");
      if ((sockfd = socket(p->ai_family, p->ai_socktype,
                           p->ai_protocol)) == -1)
      {
          continue;
      }

      if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1)
      {
          close(sockfd);
          continue;
      }

      break;
  }

  if (p == 0)
  {
      printf("p==0, errno: %d\n", errno);
      return -1;
  }

  freeaddrinfo(servinfo);

  return sockfd;
}

void PiVisionEthTermConnectServiceJob::Execute()
{
  const uint32_t maxNumAttempts = 5u;
  serviceFound = false;
  while(numAttempts < maxNumAttempts)
  {
    TryConnect();
    if(!serviceFound)
    {
      numAttempts += 1u;

      auto serviceTimeout = std::make_shared<PiVisionServiceDiscoveryTimeout>(serviceNo);
      JobDispatcher::GetApi()->RaiseEventIn(PIVISION_EVENT_SERVICE_DISCOVERY_TIMEOUT, serviceTimeout, 500u);

      std::unique_lock<std::mutex> timeoutLock(timeoutMutex);
      timeoutNotification.wait(timeoutLock);
    }
    else
    {
      numAttempts = maxNumAttempts;
      serviceFound = true;
    }
  }

  std::shared_ptr<PiVisionServiceStatusInd> serviceStatusInd = nullptr;

  if(serviceFound)
  {
    JobDispatcher::GetApi()->Log("Service found");
    if(-1 != (socketFd = ConnectToServer()))
  	{
      PiVisionServiceStatus status = PiVisionServiceStatus::SERVICE_CONNECTED;
      serviceStatusInd = std::make_shared<PiVisionServiceStatusInd>(status, serviceNo);
      JobDispatcher::GetApi()->Log("PiVision connected to camera");
  	}
    else
    {
      JobDispatcher::GetApi()->Log("Failed to connect to service");
      PiVisionServiceStatus status = PiVisionServiceStatus::SERVICE_DISCONNECTED;
      serviceStatusInd = std::make_shared<PiVisionServiceStatusInd>(status, serviceNo);
    }
  }
  else
  {
    JobDispatcher::GetApi()->Log("Service not found");
    PiVisionServiceStatus status = PiVisionServiceStatus::SERVICE_NOT_FOUND;
    serviceStatusInd = std::make_shared<PiVisionServiceStatusInd>(status, serviceNo);
  }

  JobDispatcher::GetApi()->RaiseEvent(PIVISION_EVENT_SERVICE_STATUS_IND, serviceStatusInd);
}

void PiVisionEthTermConnectServiceJob::HandleEvent(const uint32_t eventNo, std::shared_ptr<EventDataBase> dataPtr)
{
  switch(eventNo)
  {
    case PIVISION_EVENT_SERVICE_DISCOVERY_TIMEOUT:
    {
      auto timeoutData = std::static_pointer_cast<PiVisionServiceDiscoveryTimeout>(dataPtr);
      if(timeoutData->serviceNo == serviceNo)
      {
        std::unique_lock<std::mutex> timeoutLock(timeoutMutex);
      	timeoutNotification.notify_one();
      }
      break;
    }
    default:
    break;
  }
}

PiVisionEthTerm::PiVisionEthTerm()
{
  JobDispatcher::GetApi()->SubscribeToEvent(PIVISION_EVENT_CONNECT_TO_SERVICE_REQ, this);
  JobDispatcher::GetApi()->SubscribeToEvent(PIVISION_EVENT_SERVICE_STATUS_IND, this);
}

void PiVisionEthTerm::HandleEvent(const uint32_t eventNo, std::shared_ptr<EventDataBase> dataPtr)
{
  switch(eventNo)
  {
    case PIVISION_EVENT_CONNECT_TO_SERVICE_REQ:
    {
      std::shared_ptr<PiVisionConnectToServiceReq> serviceReq = std::static_pointer_cast<PiVisionConnectToServiceReq>(dataPtr);
      std::shared_ptr<JobBase> serviceReqJob = std::make_shared<PiVisionEthTermConnectServiceJob>(serviceReq->serviceNo);
      JobDispatcher::GetApi()->ExecuteJobInGroup(serviceReqJob, PIVISION_SERVICE_DISCOVERY_THREAD_ID);
      break;
    }
    case PIVISION_EVENT_SERVICE_STATUS_IND:
    {
      std::shared_ptr<PiVisionServiceStatusInd> statusInd = std::static_pointer_cast<PiVisionServiceStatusInd>(dataPtr);
      switch(statusInd->status)
      {
        case PiVisionServiceStatus::SERVICE_NOT_FOUND:
        {
          std::shared_ptr<EventDataBase> connectRej = std::make_shared<PiVisionConnectToServiceRej>(statusInd->serviceNo);
          JobDispatcher::GetApi()->RaiseEvent(PIVISION_EVENT_CONNECT_TO_SERVICE_REJ, connectRej);
          break;
        }
        case PiVisionServiceStatus::SERVICE_CONNECTED:
        {
          std::shared_ptr<EventDataBase> connectCfm = std::make_shared<PiVisionConnectToServiceCfm>(statusInd->serviceNo);
          JobDispatcher::GetApi()->RaiseEvent(PIVISION_EVENT_CONNECT_TO_SERVICE_CFM, connectCfm);
          break;
        }
        default:
        break;
      }
      break;
    }
    default:
      JobDispatcher::GetApi()->Log("PiVisionEthTerm received unexpected event: 0x%x", eventNo);
      break;
  }
}
<commit_msg>Fixed formatting<commit_after>#include "pivision_ethterm.h"
#include "jobdispatcher.h"
#include "pivision_events.h"
#include "pivision_threadmodel.h"

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

PiVisionEthTermConnectServiceJob::PiVisionEthTermConnectServiceJob(const uint32_t _serviceNo):
serviceNo(_serviceNo),
serviceDiscoveryHeader("WHERE_IS_"),
multicastGroup("224.1.1.1"),
numAttempts(0u),
serverAddress(""),
serviceFound(false),
socketFd(0)
{
  serviceDiscoverySocket = socket(AF_INET, SOCK_DGRAM, 0);

  struct timeval tv;
  tv.tv_sec = 1;
  tv.tv_usec = 0;
  setsockopt(serviceDiscoverySocket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv));

  JobDispatcher::GetApi()->SubscribeToEvent(PIVISION_EVENT_SERVICE_DISCOVERY_TIMEOUT, this);
}

void PiVisionEthTermConnectServiceJob::TryConnect(void)
{
  std::string serviceDiscoverString = serviceDiscoveryHeader + std::to_string(serviceNo);
  JobDispatcher::GetApi()->Log("serviceDiscoveryString: %s", serviceDiscoverString.c_str());

  struct sockaddr_in addr;

  memset(&addr,0,sizeof(addr));
  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = inet_addr(multicastGroup.c_str());
  addr.sin_port = htons(serviceNo - 1u);

  int numBytesSent = sendto(serviceDiscoverySocket,
                            serviceDiscoverString.c_str(),
                            serviceDiscoverString.length(),
                            0,
                            (struct sockaddr*)&addr,
                            sizeof(addr));
  if(numBytesSent < 0)
  {
    perror("sendto");
    exit(1);
  }

  char serverAddressArray[INET_ADDRSTRLEN];

  int32_t bytesReceived = recv(serviceDiscoverySocket,
                               serverAddressArray,
                               sizeof(serverAddressArray),
                               0);

  if(bytesReceived > 0)
  {
    serverAddressArray[bytesReceived] = '\0';
    serverAddress = std::string(serverAddressArray);
    JobDispatcher::GetApi()->Log("Received service address: %s",
                                 serverAddress.c_str());
    serviceFound = true;
  }
}

int32_t PiVisionEthTermConnectServiceJob::ConnectToServer()
{
  int sockfd;

  struct addrinfo hints;
  struct addrinfo* servinfo;
  struct addrinfo* p;

  memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;

  if (getaddrinfo(serverAddress.c_str(),
                  std::to_string(serviceNo).c_str(),
                  &hints,
                  &servinfo) != 0)
  {
      printf("getddrinfo\n");
      return -1;
  }

  for(p = servinfo; p != 0; p = p->ai_next)
  {
    (void) printf("Finding suitable servinfo\n");
      if ((sockfd = socket(p->ai_family, p->ai_socktype,
                           p->ai_protocol)) == -1)
      {
          continue;
      }

      if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1)
      {
          close(sockfd);
          continue;
      }

      break;
  }

  if (p == 0)
  {
      printf("p==0, errno: %d\n", errno);
      return -1;
  }

  freeaddrinfo(servinfo);

  return sockfd;
}

void PiVisionEthTermConnectServiceJob::Execute()
{
  const uint32_t maxNumAttempts = 5u;
  serviceFound = false;
  while(numAttempts < maxNumAttempts)
  {
    TryConnect();
    if(!serviceFound)
    {
      numAttempts += 1u;

      auto serviceTimeout = std::make_shared<PiVisionServiceDiscoveryTimeout>(serviceNo);
      JobDispatcher::GetApi()->RaiseEventIn(PIVISION_EVENT_SERVICE_DISCOVERY_TIMEOUT, serviceTimeout, 500u);

      std::unique_lock<std::mutex> timeoutLock(timeoutMutex);
      timeoutNotification.wait(timeoutLock);
    }
    else
    {
      numAttempts = maxNumAttempts;
      serviceFound = true;
    }
  }

  std::shared_ptr<PiVisionServiceStatusInd> serviceStatusInd = nullptr;

  if(serviceFound)
  {
    JobDispatcher::GetApi()->Log("Service found");
    if(-1 != (socketFd = ConnectToServer()))
    {
      PiVisionServiceStatus status = PiVisionServiceStatus::SERVICE_CONNECTED;
      serviceStatusInd = std::make_shared<PiVisionServiceStatusInd>(status, serviceNo);
      JobDispatcher::GetApi()->Log("PiVision connected to camera");
    }
    else
    {
      JobDispatcher::GetApi()->Log("Failed to connect to service");
      PiVisionServiceStatus status = PiVisionServiceStatus::SERVICE_DISCONNECTED;
      serviceStatusInd = std::make_shared<PiVisionServiceStatusInd>(status, serviceNo);
    }
  }
  else
  {
    JobDispatcher::GetApi()->Log("Service not found");
    PiVisionServiceStatus status = PiVisionServiceStatus::SERVICE_NOT_FOUND;
    serviceStatusInd = std::make_shared<PiVisionServiceStatusInd>(status, serviceNo);
  }

  JobDispatcher::GetApi()->RaiseEvent(PIVISION_EVENT_SERVICE_STATUS_IND, serviceStatusInd);
}

void PiVisionEthTermConnectServiceJob::HandleEvent(const uint32_t eventNo, std::shared_ptr<EventDataBase> dataPtr)
{
  switch(eventNo)
  {
    case PIVISION_EVENT_SERVICE_DISCOVERY_TIMEOUT:
    {
      auto timeoutData = std::static_pointer_cast<PiVisionServiceDiscoveryTimeout>(dataPtr);
      if(timeoutData->serviceNo == serviceNo)
      {
        std::unique_lock<std::mutex> timeoutLock(timeoutMutex);
      	timeoutNotification.notify_one();
      }
      break;
    }
    default:
    break;
  }
}

PiVisionEthTerm::PiVisionEthTerm()
{
  JobDispatcher::GetApi()->SubscribeToEvent(PIVISION_EVENT_CONNECT_TO_SERVICE_REQ, this);
  JobDispatcher::GetApi()->SubscribeToEvent(PIVISION_EVENT_SERVICE_STATUS_IND, this);
}

void PiVisionEthTerm::HandleEvent(const uint32_t eventNo, std::shared_ptr<EventDataBase> dataPtr)
{
  switch(eventNo)
  {
    case PIVISION_EVENT_CONNECT_TO_SERVICE_REQ:
    {
      std::shared_ptr<PiVisionConnectToServiceReq> serviceReq = std::static_pointer_cast<PiVisionConnectToServiceReq>(dataPtr);
      std::shared_ptr<JobBase> serviceReqJob = std::make_shared<PiVisionEthTermConnectServiceJob>(serviceReq->serviceNo);
      JobDispatcher::GetApi()->ExecuteJobInGroup(serviceReqJob, PIVISION_SERVICE_DISCOVERY_THREAD_ID);
      break;
    }
    case PIVISION_EVENT_SERVICE_STATUS_IND:
    {
      std::shared_ptr<PiVisionServiceStatusInd> statusInd = std::static_pointer_cast<PiVisionServiceStatusInd>(dataPtr);
      switch(statusInd->status)
      {
        case PiVisionServiceStatus::SERVICE_NOT_FOUND:
        {
          std::shared_ptr<EventDataBase> connectRej = std::make_shared<PiVisionConnectToServiceRej>(statusInd->serviceNo);
          JobDispatcher::GetApi()->RaiseEvent(PIVISION_EVENT_CONNECT_TO_SERVICE_REJ, connectRej);
          break;
        }
        case PiVisionServiceStatus::SERVICE_CONNECTED:
        {
          std::shared_ptr<EventDataBase> connectCfm = std::make_shared<PiVisionConnectToServiceCfm>(statusInd->serviceNo);
          JobDispatcher::GetApi()->RaiseEvent(PIVISION_EVENT_CONNECT_TO_SERVICE_CFM, connectCfm);
          break;
        }
        default:
        break;
      }
      break;
    }
    default:
      JobDispatcher::GetApi()->Log("PiVisionEthTerm received unexpected event: 0x%x", eventNo);
      break;
  }
}
<|endoftext|>