<commit_before>#include "Game.hpp"

Game::Game(std::string nickname, std::string address):
	mOgreRoot(0),
	mOgreResourcesCfg(Ogre::StringUtil::BLANK),
	mOgrePluginsCfg(Ogre::StringUtil::BLANK),
	mSceneMgr(0),
	mCameraManager(0),
	mGameWindow(0),
	mInput(0),
	mNickname(nickname),
	mLocalPlayer(0),
	mPlayerList(new OgrePlayerList()),
	mBombManager(0),
	mLocalMap(0),
	mAddress(address),
	mPort("1337"),
	mNMFactory(new NetworkMessage::NetworkMessageFactory()),
	mGCListener(0),
	mOnlineMode(false),
	mServerJoined(false),
	mGameSetUp(false),
	mSceneCreated(false),
	mGameRunning(false),
	mGameEnded(false),
	mShutDownFlag(false)
{
	if(mAddress != "")
		mOnlineMode = true;
}

Game::~Game(){

	Ogre::LogManager::getSingletonPtr()->logMessage("Deleting Client Listener");
	delete mGCListener;
	Ogre::LogManager::getSingletonPtr()->logMessage("Deleting Inputs");
	delete mInput;
	Ogre::LogManager::getSingletonPtr()->logMessage("Deleting Camera Manager");
	delete mCameraManager;
	Ogre::LogManager::getSingletonPtr()->logMessage("Deleting Local Map");
	delete mLocalMap;
	Ogre::LogManager::getSingletonPtr()->logMessage("Deleting Players");
	for(unsigned int i = 0; i < mPlayerList->size(); i++)
		delete (*mPlayerList)[i];
	delete mPlayerList;
	Ogre::LogManager::getSingletonPtr()->logMessage("Deleting Game Window");
	delete mGameWindow;
	Ogre::LogManager::getSingletonPtr()->logMessage("Deleting OGRE Root");
	delete mOgreRoot;

}

void Game::go(){

#ifdef _DEBUG
	mOgreResourcesCfg = "resources_d.cfg";
	mOgrePluginsCfg = "plugins_d.cfg";
#else
	mOgreResourcesCfg = "resources.cfg";
	mOgrePluginsCfg = "plugins.cfg";
#endif

	if (!setup())
		return;

	mOgreRoot->startRendering();

	// clean up
	destroyScene();

}

void Game::shutDown(){
	mShutDownFlag = true;
}

bool Game::keyPressed(const OIS::KeyEvent &arg){

	if(arg.key == OIS::KC_ESCAPE)
		mShutDownFlag = true;

	if(arg.key == OIS::KC_P)
		mCameraManager->increaseIPD();

	if(arg.key == OIS::KC_M)
		mCameraManager->decreaseIPD();

	if(mOnlineMode && arg.key == OIS::KC_R)
		mGCListener->sendMessage(
			mNMFactory->buildMessage(NetworkMessage::GAMESTART)
		);

	return true;

}

void Game::injectClientClose(){

	if(!mGameSetUp){
		if(mServerJoined){
			Ogre::LogManager::getSingletonPtr()->logMessage("Lost connection to the server, shutting down");
			shutDown();
		}
		else{
			Ogre::LogManager::getSingletonPtr()->logMessage("Error while joining server, setting up the game as single player");
			offlineSetup();
		}
	}

}

void Game::injectJoinAccept(NetworkMessage::JoinAccept *message){

	mServerJoined = true;

	PlayerList *pl = message->getPlayerList();
	OgrePlayer *tmp;

	mBombManager = new BombManager(mWorld);

	Ogre::LogManager::getSingletonPtr()->logMessage("Creating Local Map");
	mLocalMap = new LocalMap(
		mWorld,
		mPlayerList,
		mBombManager,
		message->getMapHeight(),
		message->getMapWidth(),
		message->getSeed()
	);

	Ogre::LogManager::getSingletonPtr()->logMessage("Filling player list");
	for(unsigned int i = 0; i < pl->size(); i++){
		if((*pl)[i]->getNickname() == mNickname){
			Ogre::LogManager::getSingletonPtr()->logMessage("Creating Local Player");
			mLocalPlayer = new LocalPlayer(mNickname, mWorld, mBombManager, mCameraManager);
			tmp = mLocalPlayer;
		}
		else
			tmp = new RemotePlayer((*pl)[i]->getNickname(), mWorld, mBombManager);

		tmp->setStartingPosition(
			(*pl)[i]->getX(),
			(*pl)[i]->getY(),
			(*pl)[i]->getZ()
		);

		mPlayerList->addPlayer(tmp);

	}

	mLocalPlayer->setPlayerEventListener(this);

	mGameSetUp = true;

}

void Game::injectJoinRefuse(NetworkMessage::JoinRefuse *message){
	shutDown();
}

void Game::injectPlayerJoined(NetworkMessage::PlayerJoined *message){

	if(!mGameRunning){

		Ogre::LogManager::getSingletonPtr()->logMessage("Adding new player");

		RemotePlayer *rp = new RemotePlayer(message->getNickname(), mWorld, mBombManager);
		rp->setStartingPosition(
			message->getX(),
			message->getY(),
			message->getZ()
		);
		mPlayerList->addPlayer(rp);

	}

}

void Game::injectPlayerLeft(NetworkMessage::PlayerLeft *message){

	Ogre::LogManager::getSingletonPtr()->logMessage("Removing player");
	if(mPlayerList->getPlayerByName(message->getNickname()))
		mPlayerList->getPlayerByName(
			message->getNickname()
		)->die();

}

void Game::injectGameStart(NetworkMessage::GameStart *message){
	Ogre::LogManager::getSingletonPtr()->logMessage("Starting game");
	mGameRunning = true;
}

void Game::injectGameEnd(NetworkMessage::GameEnd *message){

	Ogre::LogManager::getSingletonPtr()->logMessage("Ending game");
	mGameEnded = true;

	for(unsigned int i = 0; i < mPlayerList->size(); i++){
		if(!(*mPlayerList)[i]->isDead()){
			(*mPlayerList)[i]->win();
			std::cout << (*mPlayerList)[i]->getNickname() << " wins !" << std::endl;
		}
	}

}

void Game::injectPlayerInput(NetworkMessage::PlayerInput *message){

	std::string nickname = message->getNickname();

	if(nickname != mNickname)
		mPlayerList->getPlayerByName(nickname)->injectPlayerInput(message);

}

void Game::injectPlayerKilled(NetworkMessage::PlayerKilled *message){

	std::string nickname = message->getNickname();

	if(nickname != mNickname)
		mPlayerList->getPlayerByName(nickname)->die();

}

bool Game::playerInput(){

	if(!mOnlineMode || mGCListener->isClosed())
		return false;

	mGCListener->sendMessage(
		mNMFactory->buildMessage(NetworkMessage::PLAYERINPUT, mLocalPlayer)
	);

	return true;

}

bool Game::playerDied(){

	if(!mOnlineMode || mGCListener->isClosed())
		return false;

	mGCListener->sendMessage(
		mNMFactory->buildMessage(NetworkMessage::PLAYERKILLED, mNickname)
	);

	return true;

}

bool Game::setup(){

	mOgreRoot = new Ogre::Root(mOgrePluginsCfg);

	setupResources();

	chooseSceneManager();

	if(!configure())
		return false;

	// Create any resource listeners (for loading screens)
	createResourceListener();
	// Load resources
	loadResources();

	// Create the frame listener
	createFrameListener();

	bulletSetup();

	if(mOnlineMode)
		networkSetup();
	else
		offlineSetup();

	if(mInput->hasOculusRift())
		mGameWindow->setViewMode(OCULUS);
	else
		mGameWindow->setViewMode(SIMPLE);

	return true;

}

void Game::chooseSceneManager(){
	// Get the SceneManager, in this case a generic one
	mSceneMgr = mOgreRoot->createSceneManager(Ogre::ST_GENERIC);
}

bool Game::configure(){

	// Show the configuration dialog and initialise the system
	// You can skip this and use root.restoreConfig() to load configuration
	// settings if you were sure there are valid ones saved in ogre.cfg
	if(mOgreRoot->showConfigDialog()){

		Ogre::LogManager::getSingletonPtr()->logMessage("Creating Camera Manager");
		mCameraManager = new CameraManager(mSceneMgr);

		Ogre::LogManager::getSingletonPtr()->logMessage("Creating Game Window");
		mGameWindow = new GameWindow(
			mCameraManager,
			mOgreRoot->initialise(true, "Game Render Window")
		);

		return true;

	}
	else
		return false;

}

bool Game::networkSetup(){

	Ogre::LogManager::getSingletonPtr()->logMessage("Starting Game Client");
	mGCListener = new GameClient::Listener(mAddress, mPort);
	createNetworkListener();
	mGCListener->start();

	mGCListener->sendMessage(mNMFactory->buildMessage(NetworkMessage::JOIN, mNickname));

	return true;

}

bool Game::offlineSetup(){

	mBombManager = new BombManager(mWorld);

	Ogre::LogManager::getSingletonPtr()->logMessage("Generating Local Map");
	mLocalMap = new LocalMap(mWorld, mPlayerList, mBombManager, 15, 15);

	Ogre::LogManager::getSingletonPtr()->logMessage("Creating Local Player");
	mLocalPlayer = new LocalPlayer(mNickname, mWorld, mBombManager, mCameraManager);
	mPlayerList->addPlayer(mLocalPlayer);

	mLocalMap->setStartingPosition(0, mLocalPlayer);

	mOnlineMode = false;
	mGameSetUp = true;
	mGameRunning = true;

	return true;

}

bool Game::bulletSetup(){

	AxisAlignedBox bounds(
		Ogre::Vector3 (-10000, -10000, -10000),
		Ogre::Vector3 (10000,  10000,  10000)
	);
	Vector3 gravityVector(0,-9.81 * 2,0);

	mWorld = new OgreBulletDynamics::DynamicsWorld(mSceneMgr, bounds, gravityVector);
	debugDrawer = new OgreBulletCollisions::DebugDrawer();
	debugDrawer->setDrawWireframe(true);	// we want to see the Bullet containers

	mWorld->setDebugDrawer(debugDrawer);
	mWorld->setShowDebugShapes(true);		// enable it if you want to see the Bullet containers
	SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode("debugDrawer", Ogre::Vector3::ZERO);
	node->attachObject(static_cast <SimpleRenderable *> (debugDrawer));

	return true;

}

void Game::createNetworkListener(){

	mGCListener->setCallbackClose(boost::bind(&Game::injectClientClose, this));
	mGCListener->setCallbackJoinAccept(
		boost::bind(&Game::injectJoinAccept, this, _1)
	);
	mGCListener->setCallbackJoinRefuse(
		boost::bind(&Game::injectJoinRefuse, this, _1)
	);
	mGCListener->setCallbackPlayerJoined(
		boost::bind(&Game::injectPlayerJoined, this, _1)
	);
	mGCListener->setCallbackPlayerLeft(
		boost::bind(&Game::injectPlayerLeft, this, _1)
	);
	mGCListener->setCallbackGameStart(
		boost::bind(&Game::injectGameStart, this, _1)
	);
	mGCListener->setCallbackGameEnd(
		boost::bind(&Game::injectGameEnd, this, _1)
	);
	mGCListener->setCallbackPlayerInput(
		boost::bind(&Game::injectPlayerInput, this, _1)
	);
	mGCListener->setCallbackPlayerKilled(
		boost::bind(&Game::injectPlayerKilled, this, _1)
	);

}

void Game::createFrameListener(){

	Ogre::LogManager::getSingletonPtr()->logMessage("Creating Input");
	mInput = new Input(mGameWindow->getWindow());

	mInput->addKeyboardPressListener(this);
	mInput->addKeyboardPressListener(mGameWindow);

	mOgreRoot->addFrameListener(this);

}

void Game::createScene(){

	Animation::setDefaultInterpolationMode(Animation::IM_LINEAR);
	Animation::setDefaultRotationInterpolationMode(Animation::RIM_LINEAR);

	Ogre::LogManager::getSingletonPtr()->logMessage("Generating Player Graphics");

	for(unsigned int i = 0; i < mPlayerList->size(); i++)
		(*mPlayerList)[i]->generateGraphics();

	mLocalPlayer->lookAt(mLocalMap->getMapCenter());

	Ogre::LogManager::getSingletonPtr()->logMessage("Generating Local Map");
	mLocalMap->generate();

	// Lights
	mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f, 0.5f, 0.5f));
	mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_STENCIL_ADDITIVE);

	mSceneCreated = true;

}

void Game::destroyScene(){}

void Game::setupResources(){

	// Load resource paths from config file
	Ogre::ConfigFile cf;
	cf.load(mOgreResourcesCfg);

	// Go through all sections & settings in the file
	Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();

	Ogre::String secName, typeName, archName;

	while (seci.hasMoreElements()){

		secName = seci.peekNextKey();
		Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
		Ogre::ConfigFile::SettingsMultiMap::iterator i;

		for (i = settings->begin(); i != settings->end(); ++i){

			typeName = i->first;
			archName = i->second;
			Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
				archName, typeName, secName);

		}

	}

}

void Game::createResourceListener(){}

void Game::loadResources(){
	Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
}

bool Game::frameRenderingQueued(const Ogre::FrameEvent &evt){

	if(mShutDownFlag)
		return false;

	if(mOnlineMode && mGCListener->isClosed())
		return false;

	mInput->capture();

	if(mGameRunning){

		if(!mSceneCreated){

			// Creates the scene.
			createScene();

			// Enables the player's inputs.
			mInput->addMouseMoveListener(mLocalPlayer);
			mInput->addKeyboardPressListener(mLocalPlayer);
			mInput->addKeyboardReleaseListener(mLocalPlayer);
			mInput->addSensorFusionListener(mLocalPlayer);

		}

		for(unsigned int i = 0; i < mPlayerList->size(); i++)
			(*mPlayerList)[i]->frameRenderingQueued(evt);

		mLocalMap->frameRenderingQueued(evt);
		mBombManager->frameRenderingQueued(evt);
		mWorld->stepSimulation(evt.timeSinceLastFrame);

	}

	return true;

}
<commit_msg>added the ability to enable or disable the debug drawer by pressing N<commit_after>#include "Game.hpp"

Game::Game(std::string nickname, std::string address):
	mOgreRoot(0),
	mOgreResourcesCfg(Ogre::StringUtil::BLANK),
	mOgrePluginsCfg(Ogre::StringUtil::BLANK),
	mSceneMgr(0),
	mCameraManager(0),
	mGameWindow(0),
	mInput(0),
	mNickname(nickname),
	mLocalPlayer(0),
	mPlayerList(new OgrePlayerList()),
	mBombManager(0),
	mLocalMap(0),
	mAddress(address),
	mPort("1337"),
	mNMFactory(new NetworkMessage::NetworkMessageFactory()),
	mGCListener(0),
	mOnlineMode(false),
	mServerJoined(false),
	mGameSetUp(false),
	mSceneCreated(false),
	mGameRunning(false),
	mGameEnded(false),
	mShutDownFlag(false)
{
	if(mAddress != "")
		mOnlineMode = true;
}

Game::~Game(){

	Ogre::LogManager::getSingletonPtr()->logMessage("Deleting Client Listener");
	delete mGCListener;
	Ogre::LogManager::getSingletonPtr()->logMessage("Deleting Inputs");
	delete mInput;
	Ogre::LogManager::getSingletonPtr()->logMessage("Deleting Camera Manager");
	delete mCameraManager;
	Ogre::LogManager::getSingletonPtr()->logMessage("Deleting Local Map");
	delete mLocalMap;
	Ogre::LogManager::getSingletonPtr()->logMessage("Deleting Players");
	for(unsigned int i = 0; i < mPlayerList->size(); i++)
		delete (*mPlayerList)[i];
	delete mPlayerList;
	Ogre::LogManager::getSingletonPtr()->logMessage("Deleting Game Window");
	delete mGameWindow;
	Ogre::LogManager::getSingletonPtr()->logMessage("Deleting OGRE Root");
	delete mOgreRoot;

}

void Game::go(){

#ifdef _DEBUG
	mOgreResourcesCfg = "resources_d.cfg";
	mOgrePluginsCfg = "plugins_d.cfg";
#else
	mOgreResourcesCfg = "resources.cfg";
	mOgrePluginsCfg = "plugins.cfg";
#endif

	if (!setup())
		return;

	mOgreRoot->startRendering();

	// clean up
	destroyScene();

}

void Game::shutDown(){
	mShutDownFlag = true;
}

bool Game::keyPressed(const OIS::KeyEvent &arg){

	if(arg.key == OIS::KC_ESCAPE)
		mShutDownFlag = true;

	if(arg.key == OIS::KC_P)
		mCameraManager->increaseIPD();

	if(arg.key == OIS::KC_M)
		mCameraManager->decreaseIPD();

	if(arg.key == OIS::KC_N)
		mWorld->setShowDebugShapes(!mWorld->getShowDebugShapes());

	if(mOnlineMode && arg.key == OIS::KC_R)
		mGCListener->sendMessage(
			mNMFactory->buildMessage(NetworkMessage::GAMESTART)
		);

	return true;

}

void Game::injectClientClose(){

	if(!mGameSetUp){
		if(mServerJoined){
			Ogre::LogManager::getSingletonPtr()->logMessage("Lost connection to the server, shutting down");
			shutDown();
		}
		else{
			Ogre::LogManager::getSingletonPtr()->logMessage("Error while joining server, setting up the game as single player");
			offlineSetup();
		}
	}

}

void Game::injectJoinAccept(NetworkMessage::JoinAccept *message){

	mServerJoined = true;

	PlayerList *pl = message->getPlayerList();
	OgrePlayer *tmp;

	mBombManager = new BombManager(mWorld);

	Ogre::LogManager::getSingletonPtr()->logMessage("Creating Local Map");
	mLocalMap = new LocalMap(
		mWorld,
		mPlayerList,
		mBombManager,
		message->getMapHeight(),
		message->getMapWidth(),
		message->getSeed()
	);

	Ogre::LogManager::getSingletonPtr()->logMessage("Filling player list");
	for(unsigned int i = 0; i < pl->size(); i++){
		if((*pl)[i]->getNickname() == mNickname){
			Ogre::LogManager::getSingletonPtr()->logMessage("Creating Local Player");
			mLocalPlayer = new LocalPlayer(mNickname, mWorld, mBombManager, mCameraManager);
			tmp = mLocalPlayer;
		}
		else
			tmp = new RemotePlayer((*pl)[i]->getNickname(), mWorld, mBombManager);

		tmp->setStartingPosition(
			(*pl)[i]->getX(),
			(*pl)[i]->getY(),
			(*pl)[i]->getZ()
		);

		mPlayerList->addPlayer(tmp);

	}

	mLocalPlayer->setPlayerEventListener(this);

	mGameSetUp = true;

}

void Game::injectJoinRefuse(NetworkMessage::JoinRefuse *message){
	shutDown();
}

void Game::injectPlayerJoined(NetworkMessage::PlayerJoined *message){

	if(!mGameRunning){

		Ogre::LogManager::getSingletonPtr()->logMessage("Adding new player");

		RemotePlayer *rp = new RemotePlayer(message->getNickname(), mWorld, mBombManager);
		rp->setStartingPosition(
			message->getX(),
			message->getY(),
			message->getZ()
		);
		mPlayerList->addPlayer(rp);

	}

}

void Game::injectPlayerLeft(NetworkMessage::PlayerLeft *message){

	Ogre::LogManager::getSingletonPtr()->logMessage("Removing player");
	if(mPlayerList->getPlayerByName(message->getNickname()))
		mPlayerList->getPlayerByName(
			message->getNickname()
		)->die();

}

void Game::injectGameStart(NetworkMessage::GameStart *message){
	Ogre::LogManager::getSingletonPtr()->logMessage("Starting game");
	mGameRunning = true;
}

void Game::injectGameEnd(NetworkMessage::GameEnd *message){

	Ogre::LogManager::getSingletonPtr()->logMessage("Ending game");
	mGameEnded = true;

	for(unsigned int i = 0; i < mPlayerList->size(); i++){
		if(!(*mPlayerList)[i]->isDead()){
			(*mPlayerList)[i]->win();
			std::cout << (*mPlayerList)[i]->getNickname() << " wins !" << std::endl;
		}
	}

}

void Game::injectPlayerInput(NetworkMessage::PlayerInput *message){

	std::string nickname = message->getNickname();

	if(nickname != mNickname)
		mPlayerList->getPlayerByName(nickname)->injectPlayerInput(message);

}

void Game::injectPlayerKilled(NetworkMessage::PlayerKilled *message){

	std::string nickname = message->getNickname();

	if(nickname != mNickname)
		mPlayerList->getPlayerByName(nickname)->die();

}

bool Game::playerInput(){

	if(!mOnlineMode || mGCListener->isClosed())
		return false;

	mGCListener->sendMessage(
		mNMFactory->buildMessage(NetworkMessage::PLAYERINPUT, mLocalPlayer)
	);

	return true;

}

bool Game::playerDied(){

	if(!mOnlineMode || mGCListener->isClosed())
		return false;

	mGCListener->sendMessage(
		mNMFactory->buildMessage(NetworkMessage::PLAYERKILLED, mNickname)
	);

	return true;

}

bool Game::setup(){

	mOgreRoot = new Ogre::Root(mOgrePluginsCfg);

	setupResources();

	chooseSceneManager();

	if(!configure())
		return false;

	// Create any resource listeners (for loading screens)
	createResourceListener();
	// Load resources
	loadResources();

	// Create the frame listener
	createFrameListener();

	bulletSetup();

	if(mOnlineMode)
		networkSetup();
	else
		offlineSetup();

	if(mInput->hasOculusRift())
		mGameWindow->setViewMode(OCULUS);
	else
		mGameWindow->setViewMode(SIMPLE);

	return true;

}

void Game::chooseSceneManager(){
	// Get the SceneManager, in this case a generic one
	mSceneMgr = mOgreRoot->createSceneManager(Ogre::ST_GENERIC);
}

bool Game::configure(){

	// Show the configuration dialog and initialise the system
	// You can skip this and use root.restoreConfig() to load configuration
	// settings if you were sure there are valid ones saved in ogre.cfg
	if(mOgreRoot->showConfigDialog()){

		Ogre::LogManager::getSingletonPtr()->logMessage("Creating Camera Manager");
		mCameraManager = new CameraManager(mSceneMgr);

		Ogre::LogManager::getSingletonPtr()->logMessage("Creating Game Window");
		mGameWindow = new GameWindow(
			mCameraManager,
			mOgreRoot->initialise(true, "Game Render Window")
		);

		return true;

	}
	else
		return false;

}

bool Game::networkSetup(){

	Ogre::LogManager::getSingletonPtr()->logMessage("Starting Game Client");
	mGCListener = new GameClient::Listener(mAddress, mPort);
	createNetworkListener();
	mGCListener->start();

	mGCListener->sendMessage(mNMFactory->buildMessage(NetworkMessage::JOIN, mNickname));

	return true;

}

bool Game::offlineSetup(){

	mBombManager = new BombManager(mWorld);

	Ogre::LogManager::getSingletonPtr()->logMessage("Generating Local Map");
	mLocalMap = new LocalMap(mWorld, mPlayerList, mBombManager, 15, 15);

	Ogre::LogManager::getSingletonPtr()->logMessage("Creating Local Player");
	mLocalPlayer = new LocalPlayer(mNickname, mWorld, mBombManager, mCameraManager);
	mPlayerList->addPlayer(mLocalPlayer);

	mLocalMap->setStartingPosition(0, mLocalPlayer);

	mOnlineMode = false;
	mGameSetUp = true;
	mGameRunning = true;

	return true;

}

bool Game::bulletSetup(){

	AxisAlignedBox bounds(
		Ogre::Vector3 (-10000, -10000, -10000),
		Ogre::Vector3 (10000,  10000,  10000)
	);
	Vector3 gravityVector(0,-9.81 * 2,0);

	mWorld = new OgreBulletDynamics::DynamicsWorld(mSceneMgr, bounds, gravityVector);
	debugDrawer = new OgreBulletCollisions::DebugDrawer();
	debugDrawer->setDrawWireframe(true);	// we want to see the Bullet containers

	mWorld->setDebugDrawer(debugDrawer);
	mWorld->setShowDebugShapes(false);
	SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode("debugDrawer", Ogre::Vector3::ZERO);
	node->attachObject(static_cast <SimpleRenderable *> (debugDrawer));

	return true;

}

void Game::createNetworkListener(){

	mGCListener->setCallbackClose(boost::bind(&Game::injectClientClose, this));
	mGCListener->setCallbackJoinAccept(
		boost::bind(&Game::injectJoinAccept, this, _1)
	);
	mGCListener->setCallbackJoinRefuse(
		boost::bind(&Game::injectJoinRefuse, this, _1)
	);
	mGCListener->setCallbackPlayerJoined(
		boost::bind(&Game::injectPlayerJoined, this, _1)
	);
	mGCListener->setCallbackPlayerLeft(
		boost::bind(&Game::injectPlayerLeft, this, _1)
	);
	mGCListener->setCallbackGameStart(
		boost::bind(&Game::injectGameStart, this, _1)
	);
	mGCListener->setCallbackGameEnd(
		boost::bind(&Game::injectGameEnd, this, _1)
	);
	mGCListener->setCallbackPlayerInput(
		boost::bind(&Game::injectPlayerInput, this, _1)
	);
	mGCListener->setCallbackPlayerKilled(
		boost::bind(&Game::injectPlayerKilled, this, _1)
	);

}

void Game::createFrameListener(){

	Ogre::LogManager::getSingletonPtr()->logMessage("Creating Input");
	mInput = new Input(mGameWindow->getWindow());

	mInput->addKeyboardPressListener(this);
	mInput->addKeyboardPressListener(mGameWindow);

	mOgreRoot->addFrameListener(this);

}

void Game::createScene(){

	Animation::setDefaultInterpolationMode(Animation::IM_LINEAR);
	Animation::setDefaultRotationInterpolationMode(Animation::RIM_LINEAR);

	Ogre::LogManager::getSingletonPtr()->logMessage("Generating Player Graphics");

	for(unsigned int i = 0; i < mPlayerList->size(); i++)
		(*mPlayerList)[i]->generateGraphics();

	mLocalPlayer->lookAt(mLocalMap->getMapCenter());

	Ogre::LogManager::getSingletonPtr()->logMessage("Generating Local Map");
	mLocalMap->generate();

	// Lights
	mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f, 0.5f, 0.5f));
	mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_STENCIL_ADDITIVE);

	mSceneCreated = true;

}

void Game::destroyScene(){}

void Game::setupResources(){

	// Load resource paths from config file
	Ogre::ConfigFile cf;
	cf.load(mOgreResourcesCfg);

	// Go through all sections & settings in the file
	Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();

	Ogre::String secName, typeName, archName;

	while (seci.hasMoreElements()){

		secName = seci.peekNextKey();
		Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
		Ogre::ConfigFile::SettingsMultiMap::iterator i;

		for (i = settings->begin(); i != settings->end(); ++i){

			typeName = i->first;
			archName = i->second;
			Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
				archName, typeName, secName);

		}

	}

}

void Game::createResourceListener(){}

void Game::loadResources(){
	Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
}

bool Game::frameRenderingQueued(const Ogre::FrameEvent &evt){

	if(mShutDownFlag)
		return false;

	if(mOnlineMode && mGCListener->isClosed())
		return false;

	mInput->capture();

	if(mGameRunning){

		if(!mSceneCreated){

			// Creates the scene.
			createScene();

			// Enables the player's inputs.
			mInput->addMouseMoveListener(mLocalPlayer);
			mInput->addKeyboardPressListener(mLocalPlayer);
			mInput->addKeyboardReleaseListener(mLocalPlayer);
			mInput->addSensorFusionListener(mLocalPlayer);

		}

		for(unsigned int i = 0; i < mPlayerList->size(); i++)
			(*mPlayerList)[i]->frameRenderingQueued(evt);

		mLocalMap->frameRenderingQueued(evt);
		mBombManager->frameRenderingQueued(evt);
		mWorld->stepSimulation(evt.timeSinceLastFrame);

	}

	return true;

}
<|endoftext|>


<commit_before>// Time:  O(n)
// Space: O(n)

// Manacher's Algorithm.
class Solution {
public:
    string longestPalindrome(string s) {
        string T = preProcess(s);
        const int n = T.length();
        vector<int> P(n);
        int C = 0, R = 0;
        for (int i = 1; i < n - 1; ++i) {
            int i_mirror = 2 * C - i; // equals to i' = C - (i-C)

            P[i] = (R > i) ? min(R - i, P[i_mirror]) : 0;

            // Attempt to expand palindrome centered at i
            while (T[i + 1 + P[i]] == T[i - 1 - P[i]]) {
                ++P[i];
            }

            // If palindrome centered at i expand past R,
            // adjust center based on expanded palindrome.
            if (i + P[i] > R) {
                C = i;
                R = i + P[i];
            }
        }

        // Find the maximum element in P.
        int max_len = 0, center_index = 0;
        for (int i = 1; i < n - 1; ++i) {
            if (P[i] > max_len) {
                max_len = P[i];
                center_index = i;
            }
        }

        return s.substr((center_index - 1 - max_len) / 2, max_len);
    }

private:
    string preProcess(const string& s) {
        if (s.empty()) {
            return "^$";
        }
        string ret = "^";
        for (int i = 0; i < s.length(); ++i) {
            ret += "#" + s.substr(i, 1);
        }
        ret += "#$";
        return ret;
    }
};
<commit_msg>Update longest-palindromic-substring.cpp<commit_after>// Time:  O(n)
// Space: O(n)

// Manacher's Algorithm.
class Solution {
public:
    string longestPalindrome(string s) {
        string T = preProcess(s);
        const int n = T.length();
        vector<int> P(n);
        int C = 0, R = 0;
        for (int i = 1; i < n - 1; ++i) {
            int i_mirror = 2 * C - i; // equals to i' = C - (i-C)

            P[i] = (R > i) ? min(R - i, P[i_mirror]) : 0;

            // Attempt to expand palindrome centered at i
            while (T[i + 1 + P[i]] == T[i - 1 - P[i]]) {
                ++P[i];
            }

            // If palindrome centered at i expands the past R,
            // adjust center based on expanded palindrome.
            if (i + P[i] > R) {
                C = i;
                R = i + P[i];
            }
        }

        // Find the maximum element in P.
        int max_len = 0, center_index = 0;
        for (int i = 1; i < n - 1; ++i) {
            if (P[i] > max_len) {
                max_len = P[i];
                center_index = i;
            }
        }

        return s.substr((center_index - 1 - max_len) / 2, max_len);
    }

private:
    string preProcess(const string& s) {
        if (s.empty()) {
            return "^$";
        }
        string ret = "^";
        for (int i = 0; i < s.length(); ++i) {
            ret += "#" + s.substr(i, 1);
        }
        ret += "#$";
        return ret;
    }
};
<|endoftext|>


<commit_before>// Time:  O(n)
// Space: O(n)

// Manacher's Algorithm.
class Solution {
public:
    string longestPalindrome(string s) {
        string T = preProcess(s);
        int n = T.length();
        vector<int> P(n);
        int C = 0, R = 0;
        for (int i = 1; i < n - 1; ++i) {
            int i_mirror = 2 * C - i; // equals to i' = C - (i-C)

            P[i] = (R > i) ? min(R - i, P[i_mirror]) : 0;

            // Attempt to expand palindrome centered at i
            while (T[i + 1 + P[i]] == T[i - 1 - P[i]]) {
                ++P[i];
            }

            // If palindrome centered at i expand past R,
            // adjust center based on expanded palindrome.
            if (i + P[i] > R) {
                C = i;
                R = i + P[i];
            }
        }

        // Find the maximum element in P.
        int max_len = 0, center_index = 0;
        for (int i = 1; i < n - 1; ++i) {
            if (P[i] > max_len) {
                max_len = P[i];
                center_index = i;
            }
        }

        return s.substr((center_index - 1 - max_len) / 2, max_len);
    }
private:
    string preProcess(const string& s) {
        if (s.empty()) {
            return "^$";
        }
        string ret = "^";
        for (int i = 0; i < s.length(); ++i) {
            ret += "#" + s.substr(i, 1);
        }

        ret += "#$";
        return ret;
    }
};
<commit_msg>Update longest-palindromic-substring.cpp<commit_after>// Time:  O(n)
// Space: O(n)

// Manacher's Algorithm.
class Solution {
public:
    string longestPalindrome(string s) {
        string T = preProcess(s);
        int n = T.length();
        vector<int> P(n);
        int C = 0, R = 0;
        for (int i = 1; i < n - 1; ++i) {
            int i_mirror = 2 * C - i; // equals to i' = C - (i-C)

            P[i] = (R > i) ? min(R - i, P[i_mirror]) : 0;

            // Attempt to expand palindrome centered at i
            while (T[i + 1 + P[i]] == T[i - 1 - P[i]]) {
                ++P[i];
            }

            // If palindrome centered at i expand past R,
            // adjust center based on expanded palindrome.
            if (i + P[i] > R) {
                C = i;
                R = i + P[i];
            }
        }

        // Find the maximum element in P.
        int max_len = 0, center_index = 0;
        for (int i = 1; i < n - 1; ++i) {
            if (P[i] > max_len) {
                max_len = P[i];
                center_index = i;
            }
        }

        return s.substr((center_index - 1 - max_len) / 2, max_len);
    }

private:
    string preProcess(const string& s) {
        if (s.empty()) {
            return "^$";
        }
        string ret = "^";
        for (int i = 0; i < s.length(); ++i) {
            ret += "#" + s.substr(i, 1);
        }
        ret += "#$";
        return ret;
    }
};
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/initfiles/p9_fbc_ioe_dl_scom.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#include "p9_fbc_ioe_dl_scom.H"
#include <stdint.h>
#include <stddef.h>
#include <fapi2.H>

using namespace fapi2;

constexpr auto literal_0xFFFFFFFFFFFFFFFF = 0xFFFFFFFFFFFFFFFF;
constexpr auto literal_0xE00 = 0xE00;
constexpr auto literal_0x0000 = 0x0000;
constexpr auto literal_0x0 = 0x0;
constexpr auto literal_0b11 = 0b11;

fapi2::ReturnCode p9_fbc_ioe_dl_scom(const fapi2::Target<fapi2::TARGET_TYPE_XBUS>& TGT0)
{
    {
        fapi2::buffer<uint64_t> l_scom_buffer;
        {
            FAPI_TRY(fapi2::getScom( TGT0, 0x6011803ull, l_scom_buffer ));

            l_scom_buffer.insert<uint64_t> (literal_0xFFFFFFFFFFFFFFFF, 0, 64, 0 );
            FAPI_TRY(fapi2::putScom(TGT0, 0x6011803ull, l_scom_buffer));
        }
        {
            FAPI_TRY(fapi2::getScom( TGT0, 0x601180aull, l_scom_buffer ));

            constexpr auto l_PB_IOE_LL1_CONFIG_LINK_PAIR_ON = 0x1;
            l_scom_buffer.insert<uint64_t> (l_PB_IOE_LL1_CONFIG_LINK_PAIR_ON, 0, 1, 63 );
            constexpr auto l_PB_IOE_LL1_CONFIG_CRC_LANE_ID_ON = 0x1;
            l_scom_buffer.insert<uint64_t> (l_PB_IOE_LL1_CONFIG_CRC_LANE_ID_ON, 2, 1, 63 );
            FAPI_TRY(fapi2::putScom(TGT0, 0x601180aull, l_scom_buffer));
        }
        {
            FAPI_TRY(fapi2::getScom( TGT0, 0x6011818ull, l_scom_buffer ));

            l_scom_buffer.insert<uint64_t> (literal_0xE00, 8, 3, 61 );
            l_scom_buffer.insert<uint64_t> (literal_0x0000, 32, 16, 48 );
            l_scom_buffer.insert<uint64_t> (literal_0x0000, 48, 16, 48 );
            l_scom_buffer.insert<uint64_t> (literal_0x0, 4, 4, 60 );
            l_scom_buffer.insert<uint64_t> (literal_0x0, 0, 4, 60 );
            FAPI_TRY(fapi2::putScom(TGT0, 0x6011818ull, l_scom_buffer));
        }
        {
            FAPI_TRY(fapi2::getScom( TGT0, 0x6011819ull, l_scom_buffer ));

            l_scom_buffer.insert<uint64_t> (literal_0b11, 8, 2, 62 );
            l_scom_buffer.insert<uint64_t> (literal_0x0000, 32, 16, 48 );
            l_scom_buffer.insert<uint64_t> (literal_0x0000, 48, 16, 48 );
            l_scom_buffer.insert<uint64_t> (literal_0x0, 4, 4, 60 );
            l_scom_buffer.insert<uint64_t> (literal_0x0, 0, 4, 60 );
            FAPI_TRY(fapi2::putScom(TGT0, 0x6011819ull, l_scom_buffer));
        }

    };
fapi_try_exit:
    return fapi2::current_err;
}
<commit_msg>Modify initCompiler to use template version of buffer insert<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/initfiles/p9_fbc_ioe_dl_scom.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#include "p9_fbc_ioe_dl_scom.H"
#include <stdint.h>
#include <stddef.h>
#include <fapi2.H>

using namespace fapi2;

constexpr uint64_t literal_0xFFFFFFFFFFFFFFFF = 0xFFFFFFFFFFFFFFFF;
constexpr uint64_t literal_0xE00 = 0xE00;
constexpr uint64_t literal_0x0000 = 0x0000;
constexpr uint64_t literal_0x0 = 0x0;
constexpr uint64_t literal_0b11 = 0b11;

fapi2::ReturnCode p9_fbc_ioe_dl_scom(const fapi2::Target<fapi2::TARGET_TYPE_XBUS>& TGT0)
{
    {
        fapi2::buffer<uint64_t> l_scom_buffer;
        {
            FAPI_TRY(fapi2::getScom( TGT0, 0x6011803ull, l_scom_buffer ));

            l_scom_buffer.insert<0, 64, 0, uint64_t>(literal_0xFFFFFFFFFFFFFFFF );
            FAPI_TRY(fapi2::putScom(TGT0, 0x6011803ull, l_scom_buffer));
        }
        {
            FAPI_TRY(fapi2::getScom( TGT0, 0x601180aull, l_scom_buffer ));

            constexpr auto l_PB_IOE_LL1_CONFIG_LINK_PAIR_ON = 0x1;
            l_scom_buffer.insert<0, 1, 63, uint64_t>(l_PB_IOE_LL1_CONFIG_LINK_PAIR_ON );
            constexpr auto l_PB_IOE_LL1_CONFIG_CRC_LANE_ID_ON = 0x1;
            l_scom_buffer.insert<2, 1, 63, uint64_t>(l_PB_IOE_LL1_CONFIG_CRC_LANE_ID_ON );
            FAPI_TRY(fapi2::putScom(TGT0, 0x601180aull, l_scom_buffer));
        }
        {
            FAPI_TRY(fapi2::getScom( TGT0, 0x6011818ull, l_scom_buffer ));

            l_scom_buffer.insert<8, 3, 61, uint64_t>(literal_0xE00 );
            l_scom_buffer.insert<32, 16, 48, uint64_t>(literal_0x0000 );
            l_scom_buffer.insert<48, 16, 48, uint64_t>(literal_0x0000 );
            l_scom_buffer.insert<4, 4, 60, uint64_t>(literal_0x0 );
            l_scom_buffer.insert<0, 4, 60, uint64_t>(literal_0x0 );
            FAPI_TRY(fapi2::putScom(TGT0, 0x6011818ull, l_scom_buffer));
        }
        {
            FAPI_TRY(fapi2::getScom( TGT0, 0x6011819ull, l_scom_buffer ));

            l_scom_buffer.insert<8, 2, 62, uint64_t>(literal_0b11 );
            l_scom_buffer.insert<32, 16, 48, uint64_t>(literal_0x0000 );
            l_scom_buffer.insert<48, 16, 48, uint64_t>(literal_0x0000 );
            l_scom_buffer.insert<4, 4, 60, uint64_t>(literal_0x0 );
            l_scom_buffer.insert<0, 4, 60, uint64_t>(literal_0x0 );
            FAPI_TRY(fapi2::putScom(TGT0, 0x6011819ull, l_scom_buffer));
        }

    };
fapi_try_exit:
    return fapi2::current_err;
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2004-present, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */
#include "UnresolvedNhopsProber.h"
#include "fboss/agent/NexthopToRouteCount.h"
#include "fboss/agent/state/SwitchState.h"
#include "fboss/agent/state/RouteForwardInfo.h"
#include "fboss/agent/state/Interface.h"
#include "fboss/agent/state/Vlan.h"
#include "fboss/agent/state/VlanMap.h"
#include "fboss/agent/state/ArpTable.h"
#include "fboss/agent/state/NdpTable.h"
#include "fboss/agent/ArpHandler.h"
#include "fboss/agent/IPv6Handler.h"

namespace facebook { namespace fboss {

void UnresolvedNhopsProber::timeoutExpired() noexcept {
  std::lock_guard<std::mutex> g(lock_);
  auto state = sw_->getState();
  for (const auto& ridAndNhopsRefCounts : nhops2RouteCount_) {
    for (const auto& nhopAndRefCount : ridAndNhopsRefCounts.second) {
      const auto& nhop = nhopAndRefCount.first;
      auto intf = state->getInterfaces()->getInterfaceIf(nhop.intf);
      if (!intf) {
        continue; // interface got unconfigured
      }
      // Probe all nexthops for which either don't have a L2 entry
      // or the entry is not resolved (port == 0). Note that we do
      // not exclude pending entries here since in case of recursive
      // routes we might get packets with destination set to prefix
      // that needs to be resolved recursively. In ARP and NDP code
      // we do not do route lookup when deciding to send ARP/NDP requests.
      // So we would only try to ARP/NDP for the destination if it
      // is in one of the interface subnets (which it won't be else
      // we won't have needed recursive resolution). So ARP/NDP for
      // all unresolved next hops. We could also consider doing route
      // lookups in ARP/NDP code, but by probing all unresolved next
      // hops we effectively do the same thing, since the next hops
      // probed come from after the route was (recursively) resolved.
      auto vlan = state->getVlans()->getVlanIf(intf->getVlanID());
      CHECK(vlan); // must have vlan for configrued inteface
      if (nhop.nexthop.isV4()) {
        auto nhop4 = nhop.nexthop.asV4();
        auto arpEntry = vlan->getArpTable()->getEntryIf(nhop4);
        if (!arpEntry || arpEntry->getPort() == 0) {
          VLOG(2) <<" Sending probe for unresolved next hop: " << nhop4;
          ArpHandler::sendArpRequest(sw_, vlan, nhop4);
        }
      } else {
        auto nhop6 = nhop.nexthop.asV6();
        auto ndpEntry = vlan->getNdpTable()->getEntryIf(nhop6);
        if (!ndpEntry || ndpEntry->getPort() == 0) {
          VLOG(2) <<" Sending probe for unresolved next hop: " << nhop6;
          IPv6Handler::sendNeighborSolicitation(sw_, nhop6, vlan);
        }
      }
    }
  }
  scheduleTimeout(interval_);
}

}} // facebook::fboss
<commit_msg>temporarily drop log level of UnresolvedNhopsProber<commit_after>/*
 *  Copyright (c) 2004-present, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */
#include "UnresolvedNhopsProber.h"
#include "fboss/agent/NexthopToRouteCount.h"
#include "fboss/agent/state/SwitchState.h"
#include "fboss/agent/state/RouteForwardInfo.h"
#include "fboss/agent/state/Interface.h"
#include "fboss/agent/state/Vlan.h"
#include "fboss/agent/state/VlanMap.h"
#include "fboss/agent/state/ArpTable.h"
#include "fboss/agent/state/NdpTable.h"
#include "fboss/agent/ArpHandler.h"
#include "fboss/agent/IPv6Handler.h"

namespace facebook { namespace fboss {

void UnresolvedNhopsProber::timeoutExpired() noexcept {
  std::lock_guard<std::mutex> g(lock_);
  auto state = sw_->getState();
  for (const auto& ridAndNhopsRefCounts : nhops2RouteCount_) {
    for (const auto& nhopAndRefCount : ridAndNhopsRefCounts.second) {
      const auto& nhop = nhopAndRefCount.first;
      auto intf = state->getInterfaces()->getInterfaceIf(nhop.intf);
      if (!intf) {
        continue; // interface got unconfigured
      }
      // Probe all nexthops for which either don't have a L2 entry
      // or the entry is not resolved (port == 0). Note that we do
      // not exclude pending entries here since in case of recursive
      // routes we might get packets with destination set to prefix
      // that needs to be resolved recursively. In ARP and NDP code
      // we do not do route lookup when deciding to send ARP/NDP requests.
      // So we would only try to ARP/NDP for the destination if it
      // is in one of the interface subnets (which it won't be else
      // we won't have needed recursive resolution). So ARP/NDP for
      // all unresolved next hops. We could also consider doing route
      // lookups in ARP/NDP code, but by probing all unresolved next
      // hops we effectively do the same thing, since the next hops
      // probed come from after the route was (recursively) resolved.
      auto vlan = state->getVlans()->getVlanIf(intf->getVlanID());
      CHECK(vlan); // must have vlan for configrued inteface
      if (nhop.nexthop.isV4()) {
        auto nhop4 = nhop.nexthop.asV4();
        auto arpEntry = vlan->getArpTable()->getEntryIf(nhop4);
        if (!arpEntry || arpEntry->getPort() == 0) {
          VLOG(3) <<" Sending probe for unresolved next hop: " << nhop4;
          ArpHandler::sendArpRequest(sw_, vlan, nhop4);
        }
      } else {
        auto nhop6 = nhop.nexthop.asV6();
        auto ndpEntry = vlan->getNdpTable()->getEntryIf(nhop6);
        if (!ndpEntry || ndpEntry->getPort() == 0) {
          VLOG(3) <<" Sending probe for unresolved next hop: " << nhop6;
          IPv6Handler::sendNeighborSolicitation(sw_, nhop6, vlan);
        }
      }
    }
  }
  scheduleTimeout(interval_);
}

}} // facebook::fboss
<|endoftext|>


<commit_before>#include <windows.h>

#include <gl\gl.h>

#ifdef _MSC_VER
#define _USE_MATH_DEFINES
#endif
#include <math.h>

#include "Window.h"
#include "Body.h"
#include "Error.h"
#include "Info.h"

#define NAME_FONT_NAME "Arial"
#define NAME_FONT_SIZE_AT_H600 24
#define NAME_FONT_SIZE (NAME_FONT_SIZE_AT_H600*scrheight/600)

#define NAME_TEXT_COLOR_R 1.00f
#define NAME_TEXT_COLOR_G 1.00f
#define NAME_TEXT_COLOR_B 1.00f
#define NAME_TEXT_COLOR_A 0.50f

#define INFO_FONT_NAME "Arial"
#define INFO_FONT_SIZE_AT_H600 16
#define INFO_FONT_SIZE (INFO_FONT_SIZE_AT_H600*scrheight/600)

#define INFO_TEXT_COLOR_R 1.00f
#define INFO_TEXT_COLOR_G 1.00f
#define INFO_TEXT_COLOR_B 1.00f
#define INFO_TEXT_COLOR_A 0.50f

#define SPACING_COEF 1.125f
#define LINES_AFTER_NAME 1.00f

#define WINDOW_COLOR_R 0.50f
#define WINDOW_COLOR_G 0.50f
#define WINDOW_COLOR_B 0.50f
#define WINDOW_COLOR_A 0.25f

#define MAX_FADE_TIME 3.0f
#define FADE_TIME_RATIO 0.10f
#define FADE_TIME(totaltime) min(MAX_FADE_TIME, (totaltime)*FADE_TIME_RATIO)

#define WINDOW_BORDER_REL 0.0125f
#define WINDOW_BORDER (WINDOW_BORDER_REL*scrheight)
#define WINDOW_WIDTH_REL_Y (0.3075f*4.0f/3.0f)
#define WINDOW_WIDTH (WINDOW_WIDTH_REL_Y*scrheight)
#define WINDOW_HEIGHT_REL 0.2575f
#define WINDOW_HEIGHT (WINDOW_HEIGHT_REL*scrheight)

#define WINDOW_POS_X1 (WINDOW_BORDER)
#define WINDOW_POS_Y1 (WINDOW_BORDER)
#define WINDOW_POS_X2 (WINDOW_POS_X1+WINDOW_WIDTH)
#define WINDOW_POS_Y2 (WINDOW_POS_Y1+WINDOW_HEIGHT)

#define MARGIN_TOP_REL 0.100f
#define MARGIN_LEFT_REL 0.075f
#define MARGIN_WIDTH (WINDOW_WIDTH*MARGIN_LEFT_REL)
#define MARGIN_HEIGHT (WINDOW_HEIGHT*MARGIN_TOP_REL)

CInfo::CInfo()
{
	Init();
}

CInfo::~CInfo()
{
	Free();
}

void CInfo::Init()
{
	loaded=false;
	scrwidth=0;
	scrheight=0;
	winlist=0;
	namelist=infolist=0;
	time=0;
	starttime=endtime=0;
	fadetime=1;
	alpha=0;
}

void CInfo::Free()
{
	nametext.Free();
	infotext.Free();
	if (winlist)
	{
		if (glIsList(winlist))
			glDeleteLists(winlist,3);
	}
	Init();
}

bool CInfo::Load()
{
	Free();

	scrwidth=(float)CWindow::GetWidth();
	scrheight=(float)CWindow::GetHeight();

	winlist=glGenLists(3);
	if (!winlist)
	{
		CError::LogError(WARNING_CODE,"Unable to load planet info - failed to generate display lists.");
		Free();
		return false;
	}
	namelist=winlist+1;
	infolist=namelist+1;

	MakeWindow(winlist);

	loaded=true;
	loaded&=nametext.BuildFTFont(NAME_FONT_NAME,(int)NAME_FONT_SIZE);
	loaded&=infotext.BuildFTFont(INFO_FONT_NAME,(int)INFO_FONT_SIZE);
	if (!loaded)
	{
		CError::LogError(WARNING_CODE,"Unable to load planet info - failed to load font.");
		Free();
	}

	return loaded;
}

void CInfo::MakeWindow(int list)
{
	glNewList(list,GL_COMPILE);
	{
		int l=(int)WINDOW_POS_X1;
		int r=(int)WINDOW_POS_X2;
		int b=(int)WINDOW_POS_Y1;
		int t=(int)WINDOW_POS_Y2;
		glDisable(GL_TEXTURE_2D);
		glLoadIdentity();
		glBegin(GL_QUADS);
		{
			glVertex2f((float)l,(float)b);
			glVertex2f((float)r,(float)b);
			glVertex2f((float)r,(float)t);
			glVertex2f((float)l,(float)t);
		}
		glEnd();
	}
	glEndList();
}

void CInfo::GetNameCoords(const char *text, float *x, float *y)
{
	float tw;
	nametext.GetTextSize(text,&tw,NULL);
	int th=(int)NAME_FONT_SIZE;
	if (x) *x=WINDOW_POS_X1+(WINDOW_WIDTH-tw)*0.5f;
	if (y) *y=WINDOW_POS_Y2-MARGIN_HEIGHT-(float)th;
}

void CInfo::GetInfoCoords(int linenum, float *x, float *y)
{
	float namey;
	GetNameCoords(" ",NULL,&namey);
	float nameadd;
	nametext.GetTextSize(" ",NULL,&nameadd);
	nameadd*=(SPACING_COEF*LINES_AFTER_NAME);

	float th;
	infotext.GetTextSize(" ",NULL,&th);
	th*=SPACING_COEF*(float)(linenum-1);

	if (x) *x=WINDOW_POS_X1+MARGIN_WIDTH;
	if (y) *y=namey-nameadd-th;
}

void CInfo::MakeName(int list, char *targetname)
{
	if (!targetname) return;
	if (*targetname==' ') targetname++;
	float x,y;
	GetNameCoords(targetname,&x,&y);
	int xi=(int)x,yi=(int)y;
	glNewList(list,GL_COMPILE);
	{
		glEnable(GL_TEXTURE_2D);
		glLoadIdentity();
		glTranslatef((float)xi,(float)yi,0);
		nametext.Print(targetname);
	}
	glEndList();
}

void CInfo::MakeInfoLine(int linenum, char *line)
{
	float x,y;
	GetInfoCoords(linenum,&x,&y);
	int xi=(int)x,yi=(int)y;
	glPushMatrix();
	glTranslatef((float)xi,(float)yi,0);
	infotext.Print(line);
	glPopMatrix();
}

void CInfo::MakeInfo(int list, CBody *targetbody)
{
	bool star=(targetbody==NULL);
	if (star) targetbody=CBody::bodycache[0];
	glNewList(list,GL_COMPILE);
	{
		int n=0;
		glEnable(GL_TEXTURE_2D);
		glLoadIdentity();
		if (star)
		{
			char line[64];
			n++;
			sprintf(line,"star name: %s",targetbody->name);
			MakeInfoLine(n,line);
		}
		for (int i=0;i<targetbody->info.numlines;i++)
		{
			if (targetbody->info.textlines[i][0]=='/') continue;
			n++;
			MakeInfoLine(n,targetbody->info.textlines[i]);
		}
	}
	glEndList();
}

void CInfo::Start(float seconds, float duration, char *targetname, CBody *targetbody)
{
	if (!loaded)
		return;
	char name[32];
	strcpy(name,targetname);
	int l=strlen(name);
	for (int i=0;i<l;i++)
		if (name[i]=='_')
			name[i]=' ';
	starttime=seconds;
	endtime=starttime+duration;
	fadetime=FADE_TIME(duration);
	MakeName(namelist,name);
	MakeInfo(infolist,targetbody);
}

void CInfo::Update(float seconds)
{
	time=seconds;
	if (time<(endtime-fadetime))
		alpha=min(1,(time-starttime)/fadetime);
	else
		alpha=max(0,(endtime-time)/fadetime);
}

void CInfo::Restart()
{
	starttime-=time;
	endtime-=time;
	time=0;
}

void CInfo::Draw()
{
	if (!alpha || !loaded)
		return;

	glDisable(GL_LIGHTING);
	glDisable(GL_DEPTH_TEST);
	glDisable(GL_CULL_FACE);
	glEnable(GL_BLEND);

	glColor4f(WINDOW_COLOR_R,WINDOW_COLOR_G,WINDOW_COLOR_B,WINDOW_COLOR_A*alpha);
	glCallList(winlist);

	glColor4f(NAME_TEXT_COLOR_R,NAME_TEXT_COLOR_G,NAME_TEXT_COLOR_B,NAME_TEXT_COLOR_A*alpha);
	glCallList(namelist);

	glColor4f(INFO_TEXT_COLOR_R,INFO_TEXT_COLOR_G,INFO_TEXT_COLOR_B,INFO_TEXT_COLOR_A*alpha);
	glCallList(infolist);
}
<commit_msg>Adjusted the info line spacing.<commit_after>#include <windows.h>

#include <gl\gl.h>

#ifdef _MSC_VER
#define _USE_MATH_DEFINES
#endif
#include <math.h>

#include "Window.h"
#include "Body.h"
#include "Error.h"
#include "Info.h"

#define NAME_FONT_NAME "Arial"
#define NAME_FONT_SIZE_AT_H600 24
#define NAME_FONT_SIZE (NAME_FONT_SIZE_AT_H600*scrheight/600)

#define NAME_TEXT_COLOR_R 1.00f
#define NAME_TEXT_COLOR_G 1.00f
#define NAME_TEXT_COLOR_B 1.00f
#define NAME_TEXT_COLOR_A 0.50f

#define INFO_FONT_NAME "Arial"
#define INFO_FONT_SIZE_AT_H600 16
#define INFO_FONT_SIZE (INFO_FONT_SIZE_AT_H600*scrheight/600)

#define INFO_TEXT_COLOR_R 1.00f
#define INFO_TEXT_COLOR_G 1.00f
#define INFO_TEXT_COLOR_B 1.00f
#define INFO_TEXT_COLOR_A 0.50f

#define SPACING_COEF 1.13f
#define LINES_AFTER_NAME 1.00f

#define WINDOW_COLOR_R 0.50f
#define WINDOW_COLOR_G 0.50f
#define WINDOW_COLOR_B 0.50f
#define WINDOW_COLOR_A 0.25f

#define MAX_FADE_TIME 3.0f
#define FADE_TIME_RATIO 0.10f
#define FADE_TIME(totaltime) min(MAX_FADE_TIME, (totaltime)*FADE_TIME_RATIO)

#define WINDOW_BORDER_REL 0.0125f
#define WINDOW_BORDER (WINDOW_BORDER_REL*scrheight)
#define WINDOW_WIDTH_REL_Y (0.3075f*4.0f/3.0f)
#define WINDOW_WIDTH (WINDOW_WIDTH_REL_Y*scrheight)
#define WINDOW_HEIGHT_REL 0.2575f
#define WINDOW_HEIGHT (WINDOW_HEIGHT_REL*scrheight)

#define WINDOW_POS_X1 (WINDOW_BORDER)
#define WINDOW_POS_Y1 (WINDOW_BORDER)
#define WINDOW_POS_X2 (WINDOW_POS_X1+WINDOW_WIDTH)
#define WINDOW_POS_Y2 (WINDOW_POS_Y1+WINDOW_HEIGHT)

#define MARGIN_TOP_REL 0.100f
#define MARGIN_LEFT_REL 0.075f
#define MARGIN_WIDTH (WINDOW_WIDTH*MARGIN_LEFT_REL)
#define MARGIN_HEIGHT (WINDOW_HEIGHT*MARGIN_TOP_REL)

CInfo::CInfo()
{
	Init();
}

CInfo::~CInfo()
{
	Free();
}

void CInfo::Init()
{
	loaded=false;
	scrwidth=0;
	scrheight=0;
	winlist=0;
	namelist=infolist=0;
	time=0;
	starttime=endtime=0;
	fadetime=1;
	alpha=0;
}

void CInfo::Free()
{
	nametext.Free();
	infotext.Free();
	if (winlist)
	{
		if (glIsList(winlist))
			glDeleteLists(winlist,3);
	}
	Init();
}

bool CInfo::Load()
{
	Free();

	scrwidth=(float)CWindow::GetWidth();
	scrheight=(float)CWindow::GetHeight();

	winlist=glGenLists(3);
	if (!winlist)
	{
		CError::LogError(WARNING_CODE,"Unable to load planet info - failed to generate display lists.");
		Free();
		return false;
	}
	namelist=winlist+1;
	infolist=namelist+1;

	MakeWindow(winlist);

	loaded=true;
	loaded&=nametext.BuildFTFont(NAME_FONT_NAME,(int)NAME_FONT_SIZE);
	loaded&=infotext.BuildFTFont(INFO_FONT_NAME,(int)INFO_FONT_SIZE);
	if (!loaded)
	{
		CError::LogError(WARNING_CODE,"Unable to load planet info - failed to load font.");
		Free();
	}

	return loaded;
}

void CInfo::MakeWindow(int list)
{
	glNewList(list,GL_COMPILE);
	{
		int l=(int)WINDOW_POS_X1;
		int r=(int)WINDOW_POS_X2;
		int b=(int)WINDOW_POS_Y1;
		int t=(int)WINDOW_POS_Y2;
		glDisable(GL_TEXTURE_2D);
		glLoadIdentity();
		glBegin(GL_QUADS);
		{
			glVertex2f((float)l,(float)b);
			glVertex2f((float)r,(float)b);
			glVertex2f((float)r,(float)t);
			glVertex2f((float)l,(float)t);
		}
		glEnd();
	}
	glEndList();
}

void CInfo::GetNameCoords(const char *text, float *x, float *y)
{
	float tw;
	nametext.GetTextSize(text,&tw,NULL);
	int th=(int)NAME_FONT_SIZE;
	if (x) *x=WINDOW_POS_X1+(WINDOW_WIDTH-tw)*0.5f;
	if (y) *y=WINDOW_POS_Y2-MARGIN_HEIGHT-(float)th;
}

void CInfo::GetInfoCoords(int linenum, float *x, float *y)
{
	float namey;
	GetNameCoords(" ",NULL,&namey);
	float nameadd;
	nametext.GetTextSize(" ",NULL,&nameadd);
	nameadd*=(SPACING_COEF*LINES_AFTER_NAME);

	float th;
	infotext.GetTextSize(" ",NULL,&th);
	th*=SPACING_COEF*(float)(linenum-1);

	if (x) *x=WINDOW_POS_X1+MARGIN_WIDTH;
	if (y) *y=namey-nameadd-th;
}

void CInfo::MakeName(int list, char *targetname)
{
	if (!targetname) return;
	if (*targetname==' ') targetname++;
	float x,y;
	GetNameCoords(targetname,&x,&y);
	int xi=(int)x,yi=(int)y;
	glNewList(list,GL_COMPILE);
	{
		glEnable(GL_TEXTURE_2D);
		glLoadIdentity();
		glTranslatef((float)xi,(float)yi,0);
		nametext.Print(targetname);
	}
	glEndList();
}

void CInfo::MakeInfoLine(int linenum, char *line)
{
	float x,y;
	GetInfoCoords(linenum,&x,&y);
	int xi=(int)x,yi=(int)y;
	glPushMatrix();
	glTranslatef((float)xi,(float)yi,0);
	infotext.Print(line);
	glPopMatrix();
}

void CInfo::MakeInfo(int list, CBody *targetbody)
{
	bool star=(targetbody==NULL);
	if (star) targetbody=CBody::bodycache[0];
	glNewList(list,GL_COMPILE);
	{
		int n=0;
		glEnable(GL_TEXTURE_2D);
		glLoadIdentity();
		if (star)
		{
			char line[64];
			n++;
			sprintf(line,"star name: %s",targetbody->name);
			MakeInfoLine(n,line);
		}
		for (int i=0;i<targetbody->info.numlines;i++)
		{
			if (targetbody->info.textlines[i][0]=='/') continue;
			n++;
			MakeInfoLine(n,targetbody->info.textlines[i]);
		}
	}
	glEndList();
}

void CInfo::Start(float seconds, float duration, char *targetname, CBody *targetbody)
{
	if (!loaded)
		return;
	char name[32];
	strcpy(name,targetname);
	int l=strlen(name);
	for (int i=0;i<l;i++)
		if (name[i]=='_')
			name[i]=' ';
	starttime=seconds;
	endtime=starttime+duration;
	fadetime=FADE_TIME(duration);
	MakeName(namelist,name);
	MakeInfo(infolist,targetbody);
}

void CInfo::Update(float seconds)
{
	time=seconds;
	if (time<(endtime-fadetime))
		alpha=min(1,(time-starttime)/fadetime);
	else
		alpha=max(0,(endtime-time)/fadetime);
}

void CInfo::Restart()
{
	starttime-=time;
	endtime-=time;
	time=0;
}

void CInfo::Draw()
{
	if (!alpha || !loaded)
		return;

	glDisable(GL_LIGHTING);
	glDisable(GL_DEPTH_TEST);
	glDisable(GL_CULL_FACE);
	glEnable(GL_BLEND);

	glColor4f(WINDOW_COLOR_R,WINDOW_COLOR_G,WINDOW_COLOR_B,WINDOW_COLOR_A*alpha);
	glCallList(winlist);

	glColor4f(NAME_TEXT_COLOR_R,NAME_TEXT_COLOR_G,NAME_TEXT_COLOR_B,NAME_TEXT_COLOR_A*alpha);
	glCallList(namelist);

	glColor4f(INFO_TEXT_COLOR_R,INFO_TEXT_COLOR_G,INFO_TEXT_COLOR_B,INFO_TEXT_COLOR_A*alpha);
	glCallList(infolist);
}
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 <algorithm>

#include <process/defer.hpp>
#include <process/delay.hpp>
#include <process/timer.hpp>

#include <stout/foreach.hpp>

#include "logging/logging.hpp"

#include "master/dominant_share_allocator.hpp"

using std::sort;
using std::string;
using std::vector;

namespace mesos {
namespace internal {
namespace master {

// Used to represent "filters" for resources unused in offers.
class Filter
{
public:
  virtual ~Filter() {}
  virtual bool filter(const SlaveID& slaveId, const Resources& resources) = 0;
};

class RefusedFilter : public Filter
{
public:
  RefusedFilter(const SlaveID& _slaveId,
                const Resources& _resources,
                const Timeout& _timeout)
    : slaveId(_slaveId),
      resources(_resources),
      timeout(_timeout) {}

  virtual bool filter(const SlaveID& slaveId, const Resources& resources)
  {
    return slaveId == this->slaveId &&
      resources <= this->resources &&
      timeout.remaining() < 0.0;
  }

  const SlaveID slaveId;
  const Resources resources;
  const Timeout timeout;
};

struct DominantShareComparator
{
  DominantShareComparator(const Resources& _resources,
                          const hashmap<FrameworkID, Resources>& _allocated)
    : resources(_resources),
      allocated(_allocated)
  {}

  bool operator () (const FrameworkID& frameworkId1,
                    const FrameworkID& frameworkId2)
  {
    double share1 = 0;
    double share2 = 0;

    // TODO(benh): This implementaion of "dominant resource fairness"
    // currently does not take into account resources that are not
    // scalars.

    foreach (const Resource& resource, resources) {
      if (resource.type() == Value::SCALAR) {
        double total = resource.scalar().value();

        if (total > 0) {
          Value::Scalar none;
          const Value::Scalar& scalar1 =
            allocated[frameworkId1].get(resource.name(), none);
          const Value::Scalar& scalar2 =
            allocated[frameworkId2].get(resource.name(), none);
          share1 = std::max(share1, scalar1.value() / total);
          share2 = std::max(share2, scalar2.value() / total);
        }
      }
    }

    if (share1 == share2) {
      // Make the sort deterministic for unit testing.
      return frameworkId1 < frameworkId2;
    } else {
      return share1 < share2;
    }
  }

  const Resources resources;
  hashmap<FrameworkID, Resources> allocated; // Not const for the '[]' operator.
};

void DominantShareAllocator::initialize(const process::PID<Master>& _master)
{
  master = _master;
  initialized = true;

  // TODO(benh): Consider running periodic allocations. This will
  // definitely be necessary for frameworks that hoard resources (in
  // offers), since otherwise we'll just sit waiting.
  // delay(1.0, self(), &DominantShareAllocator::allocate);
}

void DominantShareAllocator::frameworkAdded(
    const FrameworkID& frameworkId,
    const FrameworkInfo& frameworkInfo,
    const Resources& used)
{
  CHECK(initialized);

  // Either a framework is being added for the first time or it's
  // being "re-added" (e.g., due to failover). If it's being added for
  // the first time it's possible that it has some resources already
  // allocated to it (e.g., because it just registered with a new
  // master even though the slaves have already registered).
  if (!frameworks.contains(frameworkId)) {
    CHECK(!allocated.contains(frameworkId));
    allocated[frameworkId] = used;
  }

  // We always update the framework info, even if we already had some
  // state about the framework. TODO(benh): Consider adding a check
  // which confirms that the resources used are a subset or equal to
  // the resources allocated (a subset because the allocator might
  // have just asked the master to offer some more resources).
  frameworks[frameworkId] = frameworkInfo;

  LOG(INFO) << "Added framework " << frameworkId;

  allocate();
}

void DominantShareAllocator::frameworkDeactivated(
    const FrameworkID& frameworkId)
{
  CHECK(initialized);

  frameworks.erase(frameworkId);

  LOG(INFO) << "Deactivated framework " << frameworkId;
}

void DominantShareAllocator::frameworkRemoved(const FrameworkID& frameworkId)
{
  CHECK(initialized);

  // Might not be in 'frameworks' because it was previously
  // deactivated and never re-added.

  frameworks.erase(frameworkId);

  allocated.erase(frameworkId);

  foreach (Filter* filter, filters.get(frameworkId)) {
    filters.remove(frameworkId, filter);
    delete filter;
  }

  filters.remove(frameworkId);

  LOG(INFO) << "Removed framework " << frameworkId;

  allocate();
}

void DominantShareAllocator::slaveAdded(
    const SlaveID& slaveId,
    const SlaveInfo& slaveInfo,
    const hashmap<FrameworkID, Resources>& used)
{
  CHECK(initialized);

  CHECK(!slaves.contains(slaveId));

  slaves[slaveId] = slaveInfo;

  resources += slaveInfo.resources();

  Resources unused = slaveInfo.resources();

  foreachpair (const FrameworkID& frameworkId, const Resources& resources, used) {
    if (frameworks.contains(frameworkId)) {
      allocated[frameworkId] += resources;
    }
    unused -= resources; // Only want to allocate resources that are not used!
  }

  allocatable[slaveId] = unused;

  LOG(INFO) << "Added slave " << slaveId << " (" << slaveInfo.hostname()
            << ") with " << slaveInfo.resources()
            << " (and " << unused << " available)";

  allocate(slaveId);
}

void DominantShareAllocator::slaveRemoved(const SlaveID& slaveId)
{
  CHECK(initialized);

  CHECK(slaves.contains(slaveId));

  resources -= slaves[slaveId].resources();

  slaves.erase(slaveId);

  allocatable.erase(slaveId);

  // Note that we DO NOT actually delete any filters associated with
  // this slave, that will occur when the delayed
  // DominantShareAllocator::expire gets invoked (or the framework
  // that applied the filters gets removed).

  LOG(INFO) << "Removed slave " << slaveId;
}

void DominantShareAllocator::updateWhitelist(
    const Option<hashset<string> >& _whitelist)
{
  CHECK(initialized);

  whitelist = _whitelist;

  if (whitelist.isSome()) {
    LOG(INFO) << "Updated slave white list:";
    foreach (const string& hostname, whitelist.get()) {
      LOG(INFO) << "\t" << hostname;
    }
  }
}

void DominantShareAllocator::resourcesRequested(
    const FrameworkID& frameworkId,
    const vector<Request>& requests)
{
  CHECK(initialized);

  LOG(INFO) << "Received resource request from framework " << frameworkId;
}

void DominantShareAllocator::resourcesUnused(
    const FrameworkID& frameworkId,
    const SlaveID& slaveId,
    const Resources& resources,
    const Option<Filters>& filters)
{
  CHECK(initialized);

  if (resources.allocatable().size() == 0) {
    return;
  }

  VLOG(1) << "Framework " << frameworkId
          << " left " << resources.allocatable()
          << " unused on slave " << slaveId;

  // Updated resources allocated to framework.
  CHECK(allocated.contains(frameworkId));
  allocated[frameworkId] -= resources;

  // Update resources allocatable on slave.
  CHECK(allocatable.contains(slaveId));
  allocatable[slaveId] += resources;

  // Create a refused resources filter.
  double timeout = filters.isSome()
    ? filters.get().refuse_seconds()
    : Filters().refuse_seconds();

  if (timeout != 0.0) {
    LOG(INFO) << "Framework " << frameworkId
	      << " filtered slave " << slaveId
	      << " for " << timeout << " seconds";

    // Create a new filter and delay it's expiration.
    Filter* filter = new RefusedFilter(slaveId, resources, timeout);
    this->filters.put(frameworkId, filter);

    // TODO(benh): Use 'this' and '&This::' as appropriate.
    delay(timeout, PID<DominantShareAllocator>(this), &DominantShareAllocator::expire,
	  frameworkId, filter);
  }

  allocate(slaveId);
}

void DominantShareAllocator::resourcesRecovered(
    const FrameworkID& frameworkId,
    const SlaveID& slaveId,
    const Resources& resources)
{
  CHECK(initialized);

  if (resources.allocatable().size() == 0) {
    return;
  }

  // Updated resources allocated to framework (if framework still
  // exists, which it might not in the event that we dispatched
  // Master::offer before we received Allocator::frameworkRemoved or
  // Allocator::frameworkDeactivated).
  if (allocated.contains(frameworkId)) {
    allocated[frameworkId] -= resources;
  }

  // Update resources allocatable on slave (if slave still exists,
  // which it might not in the event that we dispatched Master::offer
  // before we received Allocator::slaveRemoved).
  if (allocatable.contains(slaveId)) {
    allocatable[slaveId] += resources;

    VLOG(1) << "Recovered " << resources.allocatable()
            << " on slave " << slaveId
            << " from framework " << frameworkId;

    allocate(slaveId);
  }
}

void DominantShareAllocator::offersRevived(const FrameworkID& frameworkId)
{
  CHECK(initialized);

  // TODO(benh): We don't actually delete each Filter right now
  // because that should happen when DominantShareAllocator::expire
  // gets invoked. If we delete the Filter here it's possible that the
  // same Filter (i.e., same address) could get reused and
  // DominantShareAllocator::expire would expire that filter too
  // soon. Note that this only works right now because ALL Filter
  // types "expire".

  foreach (Filter* filter, filters.get(frameworkId)) {
    filters.remove(frameworkId, filter);
    delete filter;
  }

  filters.remove(frameworkId);

  LOG(INFO) << "Removed filters for framework " << frameworkId;

  allocate();
}

void DominantShareAllocator::allocate()
{
  CHECK(initialized);

  allocate(slaves.keys());
}

void DominantShareAllocator::allocate(const SlaveID& slaveId)
{
  CHECK(initialized);

  hashset<SlaveID> slaveIds;
  slaveIds.insert(slaveId);

  allocate(slaveIds);
}

void DominantShareAllocator::allocate(const hashset<SlaveID>& slaveIds)
{
  CHECK(initialized);

  // Order frameworks by dominant resource fairness.
  if (frameworks.size() == 0) {
    VLOG(1) << "No frameworks to allocate resources!";
    return;
  }

  vector<FrameworkID> frameworkIds;

  foreachkey (const FrameworkID& frameworkId, frameworks) {
    frameworkIds.push_back(frameworkId);
  }

  DominantShareComparator comparator(resources, allocated);
  sort(frameworkIds.begin(), frameworkIds.end(), comparator);

  // Get out only "available" resources (i.e., resources that are
  // allocatable and above a certain threshold, see below).
  hashmap<SlaveID, Resources> available;
  foreachpair (const SlaveID& slaveId, Resources resources, allocatable) {
    if (isWhitelisted(slaveId)) {
      resources = resources.allocatable(); // Make sure they're allocatable.

      // TODO(benh): For now, only make offers when there is some cpu
      // and memory left. This is an artifact of the original code
      // that only offered when there was at least 1 cpu "unit"
      // available, and without doing this a framework might get
      // offered resources with only memory available (which it
      // obviously will decline) and then end up waiting the default
      // Filters::refuse_seconds (unless the framework set it to
      // something different).

      Value::Scalar none;
      Value::Scalar cpus = resources.get("cpus", none);
      Value::Scalar mem = resources.get("mem", none);

      if (cpus.value() >= MIN_CPUS && mem.value() > MIN_MEM) {
        VLOG(1) << "Found available resources: " << resources
                << " on slave " << slaveId;
        available[slaveId] = resources;
      }
    }
  }

  if (available.size() == 0) {
    VLOG(1) << "No resources available to allocate!";
    return;
  }

  foreach (const FrameworkID& frameworkId, frameworkIds) {
    // Check if we should offer resources to this framework.
    hashmap<SlaveID, Resources> offerable;
    foreachpair (const SlaveID& slaveId, const Resources& resources, available) {
      // Check whether or not this framework filters this slave.
      bool filtered = false;

      foreach (Filter* filter, filters.get(frameworkId)) {
        if (filter->filter(slaveId, resources)) {
          VLOG(1) << "Filtered " << resources
                  << " on slave " << slaveId
                  << " for framework " << frameworkId;
          filtered = true;
          break;
        }
      }

      if (!filtered) {
        VLOG(1) << "Offering " << resources
                << " on slave " << slaveId
                << " to framework " << frameworkId;
        offerable[slaveId] = resources;

        // Update framework and slave resources.
        allocated[frameworkId] += resources;
        allocatable[slaveId] -= resources;
      }
    }

    if (offerable.size() > 0) {
      foreachkey (const SlaveID& slaveId, offerable) {
        available.erase(slaveId);
      }
      dispatch(master, &Master::offer, frameworkId, offerable);
    }
  }
}

void DominantShareAllocator::expire(
    const FrameworkID& frameworkId,
    Filter* filter)
{
  // Framework might have been removed, in which case it's filters
  // should also already have been deleted.
  if (frameworks.contains(frameworkId)) {
    // Check and see if the filter was already removed in
    // DominantShareAllocator::offersRevived (but not deleted).
    if (filters.contains(frameworkId, filter)) {
      filters.remove(frameworkId, filter);
      delete filter;
      allocate();
    } else {
      delete filter;
    }
  }
}

bool DominantShareAllocator::isWhitelisted(const SlaveID& slaveId)
{
  CHECK(initialized);

  CHECK(slaves.contains(slaveId));

  return whitelist.isNone() ||
    whitelist.get().contains(slaves[slaveId].hostname());
}

} // namespace master {
} // namespace internal {
} // namespace mesos {
<commit_msg>Fixes a bug with the refused filter (https://reviews.apache.org/r/6045).<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 <algorithm>

#include <process/defer.hpp>
#include <process/delay.hpp>
#include <process/timer.hpp>

#include <stout/foreach.hpp>

#include "logging/logging.hpp"

#include "master/dominant_share_allocator.hpp"

using std::sort;
using std::string;
using std::vector;

namespace mesos {
namespace internal {
namespace master {

// Used to represent "filters" for resources unused in offers.
class Filter
{
public:
  virtual ~Filter() {}
  virtual bool filter(const SlaveID& slaveId, const Resources& resources) = 0;
};

class RefusedFilter : public Filter
{
public:
  RefusedFilter(const SlaveID& _slaveId,
                const Resources& _resources,
                const Timeout& _timeout)
    : slaveId(_slaveId),
      resources(_resources),
      timeout(_timeout) {}

  virtual bool filter(const SlaveID& slaveId, const Resources& resources)
  {
    return slaveId == this->slaveId &&
      resources <= this->resources && // Refused resources are superset.
      timeout.remaining() > 0.0;
  }

  const SlaveID slaveId;
  const Resources resources;
  const Timeout timeout;
};

struct DominantShareComparator
{
  DominantShareComparator(const Resources& _resources,
                          const hashmap<FrameworkID, Resources>& _allocated)
    : resources(_resources),
      allocated(_allocated)
  {}

  bool operator () (const FrameworkID& frameworkId1,
                    const FrameworkID& frameworkId2)
  {
    double share1 = 0;
    double share2 = 0;

    // TODO(benh): This implementaion of "dominant resource fairness"
    // currently does not take into account resources that are not
    // scalars.

    foreach (const Resource& resource, resources) {
      if (resource.type() == Value::SCALAR) {
        double total = resource.scalar().value();

        if (total > 0) {
          Value::Scalar none;
          const Value::Scalar& scalar1 =
            allocated[frameworkId1].get(resource.name(), none);
          const Value::Scalar& scalar2 =
            allocated[frameworkId2].get(resource.name(), none);
          share1 = std::max(share1, scalar1.value() / total);
          share2 = std::max(share2, scalar2.value() / total);
        }
      }
    }

    if (share1 == share2) {
      // Make the sort deterministic for unit testing.
      return frameworkId1 < frameworkId2;
    } else {
      return share1 < share2;
    }
  }

  const Resources resources;
  hashmap<FrameworkID, Resources> allocated; // Not const for the '[]' operator.
};

void DominantShareAllocator::initialize(const process::PID<Master>& _master)
{
  master = _master;
  initialized = true;

  // TODO(benh): Consider running periodic allocations. This will
  // definitely be necessary for frameworks that hoard resources (in
  // offers), since otherwise we'll just sit waiting.
  // delay(1.0, self(), &DominantShareAllocator::allocate);
}

void DominantShareAllocator::frameworkAdded(
    const FrameworkID& frameworkId,
    const FrameworkInfo& frameworkInfo,
    const Resources& used)
{
  CHECK(initialized);

  // Either a framework is being added for the first time or it's
  // being "re-added" (e.g., due to failover). If it's being added for
  // the first time it's possible that it has some resources already
  // allocated to it (e.g., because it just registered with a new
  // master even though the slaves have already registered).
  if (!frameworks.contains(frameworkId)) {
    CHECK(!allocated.contains(frameworkId));
    allocated[frameworkId] = used;
  }

  // We always update the framework info, even if we already had some
  // state about the framework. TODO(benh): Consider adding a check
  // which confirms that the resources used are a subset or equal to
  // the resources allocated (a subset because the allocator might
  // have just asked the master to offer some more resources).
  frameworks[frameworkId] = frameworkInfo;

  LOG(INFO) << "Added framework " << frameworkId;

  allocate();
}

void DominantShareAllocator::frameworkDeactivated(
    const FrameworkID& frameworkId)
{
  CHECK(initialized);

  frameworks.erase(frameworkId);

  LOG(INFO) << "Deactivated framework " << frameworkId;
}

void DominantShareAllocator::frameworkRemoved(const FrameworkID& frameworkId)
{
  CHECK(initialized);

  // Might not be in 'frameworks' because it was previously
  // deactivated and never re-added.

  frameworks.erase(frameworkId);

  allocated.erase(frameworkId);

  foreach (Filter* filter, filters.get(frameworkId)) {
    filters.remove(frameworkId, filter);
    // We *must* delete filter because DominantShareAllocator::expire
    // will have an invalid FrameworkID and won't delete.
    delete filter;
  }

  filters.remove(frameworkId);

  LOG(INFO) << "Removed framework " << frameworkId;

  allocate();
}

void DominantShareAllocator::slaveAdded(
    const SlaveID& slaveId,
    const SlaveInfo& slaveInfo,
    const hashmap<FrameworkID, Resources>& used)
{
  CHECK(initialized);

  CHECK(!slaves.contains(slaveId));

  slaves[slaveId] = slaveInfo;

  resources += slaveInfo.resources();

  Resources unused = slaveInfo.resources();

  foreachpair (const FrameworkID& frameworkId, const Resources& resources, used) {
    if (frameworks.contains(frameworkId)) {
      allocated[frameworkId] += resources;
    }
    unused -= resources; // Only want to allocate resources that are not used!
  }

  allocatable[slaveId] = unused;

  LOG(INFO) << "Added slave " << slaveId << " (" << slaveInfo.hostname()
            << ") with " << slaveInfo.resources()
            << " (and " << unused << " available)";

  allocate(slaveId);
}

void DominantShareAllocator::slaveRemoved(const SlaveID& slaveId)
{
  CHECK(initialized);

  CHECK(slaves.contains(slaveId));

  resources -= slaves[slaveId].resources();

  slaves.erase(slaveId);

  allocatable.erase(slaveId);

  // Note that we DO NOT actually delete any filters associated with
  // this slave, that will occur when the delayed
  // DominantShareAllocator::expire gets invoked (or the framework
  // that applied the filters gets removed).

  LOG(INFO) << "Removed slave " << slaveId;
}

void DominantShareAllocator::updateWhitelist(
    const Option<hashset<string> >& _whitelist)
{
  CHECK(initialized);

  whitelist = _whitelist;

  if (whitelist.isSome()) {
    LOG(INFO) << "Updated slave white list:";
    foreach (const string& hostname, whitelist.get()) {
      LOG(INFO) << "\t" << hostname;
    }
  }
}

void DominantShareAllocator::resourcesRequested(
    const FrameworkID& frameworkId,
    const vector<Request>& requests)
{
  CHECK(initialized);

  LOG(INFO) << "Received resource request from framework " << frameworkId;
}

void DominantShareAllocator::resourcesUnused(
    const FrameworkID& frameworkId,
    const SlaveID& slaveId,
    const Resources& resources,
    const Option<Filters>& filters)
{
  CHECK(initialized);

  if (resources.allocatable().size() == 0) {
    return;
  }

  VLOG(1) << "Framework " << frameworkId
          << " left " << resources.allocatable()
          << " unused on slave " << slaveId;

  // Updated resources allocated to framework.
  CHECK(allocated.contains(frameworkId));
  allocated[frameworkId] -= resources;

  // Update resources allocatable on slave.
  CHECK(allocatable.contains(slaveId));
  allocatable[slaveId] += resources;

  // Create a refused resources filter.
  double timeout = filters.isSome()
    ? filters.get().refuse_seconds()
    : Filters().refuse_seconds();

  if (timeout != 0.0) {
    LOG(INFO) << "Framework " << frameworkId
	      << " filtered slave " << slaveId
	      << " for " << timeout << " seconds";

    // Create a new filter and delay it's expiration.
    Filter* filter = new RefusedFilter(slaveId, resources, timeout);
    this->filters.put(frameworkId, filter);

    // TODO(benh): Use 'this' and '&This::' as appropriate.
    delay(timeout, PID<DominantShareAllocator>(this), &DominantShareAllocator::expire,
	  frameworkId, filter);
  }

  allocate(slaveId);
}

void DominantShareAllocator::resourcesRecovered(
    const FrameworkID& frameworkId,
    const SlaveID& slaveId,
    const Resources& resources)
{
  CHECK(initialized);

  if (resources.allocatable().size() == 0) {
    return;
  }

  // Updated resources allocated to framework (if framework still
  // exists, which it might not in the event that we dispatched
  // Master::offer before we received Allocator::frameworkRemoved or
  // Allocator::frameworkDeactivated).
  if (allocated.contains(frameworkId)) {
    allocated[frameworkId] -= resources;
  }

  // Update resources allocatable on slave (if slave still exists,
  // which it might not in the event that we dispatched Master::offer
  // before we received Allocator::slaveRemoved).
  if (allocatable.contains(slaveId)) {
    allocatable[slaveId] += resources;

    VLOG(1) << "Recovered " << resources.allocatable()
            << " on slave " << slaveId
            << " from framework " << frameworkId;

    allocate(slaveId);
  }
}

void DominantShareAllocator::offersRevived(const FrameworkID& frameworkId)
{
  CHECK(initialized);

  foreach (Filter* filter, filters.get(frameworkId)) {
    filters.remove(frameworkId, filter);

    // TODO(benh): We don't actually delete each Filter right now
    // because that should happen when DominantShareAllocator::expire
    // gets invoked. If we delete the Filter here it's possible that
    // the same Filter (i.e., same address) could get reused and
    // DominantShareAllocator::expire would expire that filter too
    // soon. Note that this only works right now because ALL Filter
    // types "expire".
  }

  filters.remove(frameworkId);

  LOG(INFO) << "Removed filters for framework " << frameworkId;

  allocate();
}

void DominantShareAllocator::allocate()
{
  CHECK(initialized);

  allocate(slaves.keys());
}

void DominantShareAllocator::allocate(const SlaveID& slaveId)
{
  CHECK(initialized);

  hashset<SlaveID> slaveIds;
  slaveIds.insert(slaveId);

  allocate(slaveIds);
}

void DominantShareAllocator::allocate(const hashset<SlaveID>& slaveIds)
{
  CHECK(initialized);

  // Order frameworks by dominant resource fairness.
  if (frameworks.size() == 0) {
    VLOG(1) << "No frameworks to allocate resources!";
    return;
  }

  vector<FrameworkID> frameworkIds;

  foreachkey (const FrameworkID& frameworkId, frameworks) {
    frameworkIds.push_back(frameworkId);
  }

  DominantShareComparator comparator(resources, allocated);
  sort(frameworkIds.begin(), frameworkIds.end(), comparator);

  // Get out only "available" resources (i.e., resources that are
  // allocatable and above a certain threshold, see below).
  hashmap<SlaveID, Resources> available;
  foreachpair (const SlaveID& slaveId, Resources resources, allocatable) {
    if (isWhitelisted(slaveId)) {
      resources = resources.allocatable(); // Make sure they're allocatable.

      // TODO(benh): For now, only make offers when there is some cpu
      // and memory left. This is an artifact of the original code
      // that only offered when there was at least 1 cpu "unit"
      // available, and without doing this a framework might get
      // offered resources with only memory available (which it
      // obviously will decline) and then end up waiting the default
      // Filters::refuse_seconds (unless the framework set it to
      // something different).

      Value::Scalar none;
      Value::Scalar cpus = resources.get("cpus", none);
      Value::Scalar mem = resources.get("mem", none);

      if (cpus.value() >= MIN_CPUS && mem.value() > MIN_MEM) {
        VLOG(1) << "Found available resources: " << resources
                << " on slave " << slaveId;
        available[slaveId] = resources;
      }
    }
  }

  if (available.size() == 0) {
    VLOG(1) << "No resources available to allocate!";
    return;
  }

  foreach (const FrameworkID& frameworkId, frameworkIds) {
    // Check if we should offer resources to this framework.
    hashmap<SlaveID, Resources> offerable;
    foreachpair (const SlaveID& slaveId, const Resources& resources, available) {
      // Check whether or not this framework filters this slave.
      bool filtered = false;

      foreach (Filter* filter, filters.get(frameworkId)) {
        if (filter->filter(slaveId, resources)) {
          VLOG(1) << "Filtered " << resources
                  << " on slave " << slaveId
                  << " for framework " << frameworkId;
          filtered = true;
          break;
        }
      }

      if (!filtered) {
        VLOG(1) << "Offering " << resources
                << " on slave " << slaveId
                << " to framework " << frameworkId;
        offerable[slaveId] = resources;

        // Update framework and slave resources.
        allocated[frameworkId] += resources;
        allocatable[slaveId] -= resources;
      }
    }

    if (offerable.size() > 0) {
      foreachkey (const SlaveID& slaveId, offerable) {
        available.erase(slaveId);
      }
      dispatch(master, &Master::offer, frameworkId, offerable);
    }
  }
}

void DominantShareAllocator::expire(
    const FrameworkID& frameworkId,
    Filter* filter)
{
  // Framework might have been removed, in which case it's filters
  // should also already have been deleted.
  if (frameworks.contains(frameworkId)) {
    // Check and see if the filter was already removed in
    // DominantShareAllocator::offersRevived (but not deleted).
    if (filters.contains(frameworkId, filter)) {
      filters.remove(frameworkId, filter);
      delete filter;
      allocate();
    } else {
      delete filter;
    }
  }
}

bool DominantShareAllocator::isWhitelisted(const SlaveID& slaveId)
{
  CHECK(initialized);

  CHECK(slaves.contains(slaveId));

  return whitelist.isNone() ||
    whitelist.get().contains(slaves[slaveId].hostname());
}

} // namespace master {
} // namespace internal {
} // namespace mesos {
<|endoftext|>