<commit_before>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/utilities/CDirEntry.cpp,v $
   $Revision: 1.4 $
   $Name:  $
   $Author: shoops $
   $Date: 2005/05/13 17:27:50 $
   End CVS Header */

#include <sys/types.h>
#include <sys/stat.h>

#ifdef WIN32
# include <io.h>
# include <direct.h>
# define stat _stat
# define S_IFREG _S_IFREG
# define S_IFDIR _S_IFDIR
# define access _access
# define mkdir _mkdir
# define rmdir _rmdir
#else
# include <dirent.h>
# include <unistd.h>
#endif // WIN32

#include "copasi.h"

#include "CDirEntry.h"

bool CDirEntry::isFile(const std::string & path)
{
  struct stat st;
  if (stat(path.c_str(), & st) == -1) return false;

#ifdef WIN32
  return ((st.st_mode & S_IFREG) == S_IFREG);
#else
  return S_ISREG(st.st_mode);
#endif
}

bool CDirEntry::isDir(const std::string & path)
{
  struct stat st;
  if (stat(path.c_str(), & st) == -1) return false;

#ifdef WIN32
  return ((st.st_mode & S_IFDIR) == S_IFDIR);
#else
  return S_ISDIR(st.st_mode);
#endif
}

bool CDirEntry::exist(const std::string & path)
{
  struct stat st;
  if (stat(path.c_str(), & st) == -1) return false;

#ifdef WIN32
  return ((st.st_mode & S_IFREG) == S_IFREG ||
          (st.st_mode & S_IFDIR) == S_IFDIR);
#else
  return (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode));
#endif
}

bool CDirEntry::isReadable(const std::string & path)
{return (access(path.c_str(), 0x4) == 0);}

bool CDirEntry::isWritable(const std::string & path)
{return (access(path.c_str(), 0x2) == 0);}

bool CDirEntry::createDir(const std::string & dir,
                          const std::string & parent)
{
  std::string Separator;
#ifdef WIN32
  Separator = "\\";
#else
  Separator = "/";
#endif

  std::string Dir;
  if (parent != "") Dir = parent + Separator;
  Dir += dir;

  // Check whether the directory already exists and is writable.
  if (isDir(Dir) && isWritable(Dir)) return true;

  // Check whether the parent directory exists and is writable.
  if (!isDir(parent) || !isWritable(parent)) return false;

#ifdef WIN32
  return (mkdir(Dir.c_str()) == 0);
#else
  return (mkdir(Dir.c_str(), 0) == 0);
#endif
}

bool CDirEntry::remove(const std::string & path)
{
  if (isDir(path))
    return (rmdir(path.c_str()) == 0);
  else if (isFile(path))
    return (::remove(path.c_str()) == 0);

  return false;
}

bool CDirEntry::removeFiles(const std::string & pattern,
                            const std::string & path)
{
  bool success = true;

  // :TODO:
#ifdef WIN32

  // Append to the "path" mask for all files in directory
  std::string FilePattern = path + "\\" + pattern;

  // Open directory stream and try read info about first entry
  struct _finddata_t Entry;
  C_INT32 hList = _findfirst(FilePattern.c_str(), &Entry);

  if (hList == -1) return success;

  if (Entry.attrib | _A_NORMAL)
    {
      if (::remove((path + "\\" + Entry.name).c_str()) != 0) success = false;
    }
  else
    {
      if (rmdir((path + "\\" + Entry.name).c_str()) != 0) success = false;
    }

  while (_findnext(hList, &Entry) == 0)
    if (Entry.attrib | _A_NORMAL)
      {
        if (::remove((path + "\\" + Entry.name).c_str()) != 0) success = false;
      }
    else
      {
        if (rmdir((path + "\\" + Entry.name).c_str()) != 0) success = false;
      }

  _findclose(hList);

#else

  DIR * pDir = opendir(path.c_str());
  if (!pDir) return false;

  struct dirent * pEntry;

  while ((pEntry = readdir(pDir)) != NULL)
    {
      // Match pattern.

      if (isDir(pEntry->d_name))
        {
          if (rmdir((path + "/" + pEntry->d_name).c_str()) != 0)
            success = false;
        }
      else
        {
          if (::remove((path + "/" + pEntry->d_name).c_str()) != 0)
            success = false;
        }

      pEntry = readdir(pDir);
    }

  closedir(pDir);

#endif // WIN32

  return success;
}
<commit_msg>Simplified removeFiles for WIN32 platform.<commit_after>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/utilities/CDirEntry.cpp,v $
   $Revision: 1.5 $
   $Name:  $
   $Author: shoops $
   $Date: 2005/05/13 18:21:34 $
   End CVS Header */

#include <sys/types.h>
#include <sys/stat.h>

#ifdef WIN32
# include <io.h>
# include <direct.h>
# define stat _stat
# define S_IFREG _S_IFREG
# define S_IFDIR _S_IFDIR
# define access _access
# define mkdir _mkdir
# define rmdir _rmdir
#else
# include <dirent.h>
# include <unistd.h>
#endif // WIN32

#include "copasi.h"

#include "CDirEntry.h"

bool CDirEntry::isFile(const std::string & path)
{
  struct stat st;
  if (stat(path.c_str(), & st) == -1) return false;

#ifdef WIN32
  return ((st.st_mode & S_IFREG) == S_IFREG);
#else
  return S_ISREG(st.st_mode);
#endif
}

bool CDirEntry::isDir(const std::string & path)
{
  struct stat st;
  if (stat(path.c_str(), & st) == -1) return false;

#ifdef WIN32
  return ((st.st_mode & S_IFDIR) == S_IFDIR);
#else
  return S_ISDIR(st.st_mode);
#endif
}

bool CDirEntry::exist(const std::string & path)
{
  struct stat st;
  if (stat(path.c_str(), & st) == -1) return false;

#ifdef WIN32
  return ((st.st_mode & S_IFREG) == S_IFREG ||
          (st.st_mode & S_IFDIR) == S_IFDIR);
#else
  return (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode));
#endif
}

bool CDirEntry::isReadable(const std::string & path)
{return (access(path.c_str(), 0x4) == 0);}

bool CDirEntry::isWritable(const std::string & path)
{return (access(path.c_str(), 0x2) == 0);}

bool CDirEntry::createDir(const std::string & dir,
                          const std::string & parent)
{
  std::string Separator;
#ifdef WIN32
  Separator = "\\";
#else
  Separator = "/";
#endif

  std::string Dir;
  if (parent != "") Dir = parent + Separator;
  Dir += dir;

  // Check whether the directory already exists and is writable.
  if (isDir(Dir) && isWritable(Dir)) return true;

  // Check whether the parent directory exists and is writable.
  if (!isDir(parent) || !isWritable(parent)) return false;

#ifdef WIN32
  return (mkdir(Dir.c_str()) == 0);
#else
  return (mkdir(Dir.c_str(), 0) == 0);
#endif
}

bool CDirEntry::remove(const std::string & path)
{
  if (isDir(path))
    return (rmdir(path.c_str()) == 0);
  else if (isFile(path))
    return (::remove(path.c_str()) == 0);

  return false;
}

bool CDirEntry::removeFiles(const std::string & pattern,
                            const std::string & path)
{
  bool success = true;

  // :TODO:
#ifdef WIN32

  // Append to the "path" mask for all files in directory
  std::string FilePattern = path + "\\" + pattern;

  // Open directory stream and try read info about first entry
  struct _finddata_t Entry;
  C_INT32 hList = _findfirst(FilePattern.c_str(), &Entry);

  if (hList == -1) return success;

  do
    {
      if (Entry.attrib | _A_NORMAL)
        {
          if (::remove((path + "\\" + Entry.name).c_str()) != 0) success = false;
        }
      else
        {
          if (rmdir((path + "\\" + Entry.name).c_str()) != 0) success = false;
        }
    }
  while (_findnext(hList, &Entry) == 0);

  _findclose(hList);

#else

  DIR * pDir = opendir(path.c_str());
  if (!pDir) return false;

  struct dirent * pEntry;

  while ((pEntry = readdir(pDir)) != NULL)
    {
      // Match pattern.

      if (isDir(pEntry->d_name))
        {
          if (rmdir((path + "/" + pEntry->d_name).c_str()) != 0)
            success = false;
        }
      else
        {
          if (::remove((path + "/" + pEntry->d_name).c_str()) != 0)
            success = false;
        }

      pEntry = readdir(pDir);
    }

  closedir(pDir);

#endif // WIN32

  return success;
}
<|endoftext|>


<commit_before><commit_msg>we're not using this header here<commit_after><|endoftext|>


<commit_before>#include <iostream>
#include "bots.h"
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>

using boost::asio::ip::tcp;

void async_send(tcp::socket &socket, const std::string & str)
{
    boost::asio::async_write(socket, boost::asio::buffer(str + "\n"), boost::asio::transfer_all());
}

void pinta_escenario( bots mis_bots, int paso, int cols, int filas)
{
	std::cout << "Paso : " << paso << std::endl;

	for ( int col = 0; col < cols + 2; col++ ) // Primera fila de X
        	std::cout << 'X';
	std::cout << std::endl;
	for ( int fila = 0; fila < filas; fila++ ) //! Recorre toda la altura
        {
		std::cout << 'X'; // Primera X de la fila
		for ( int col = 0; col < cols; col++ ) // Espacios en blanco
		{
			bot * pos_bot = mis_bots.find_at( { col, fila} );
			if ( pos_bot == nullptr )
                        	std::cout << ' ';
			else
				std::cout << pos_bot->get_team();
		}
		std::cout << 'X'; //! Espacios de 1a altura - fila
                std::cout << std::endl;
        }
	for ( int col = 0; col < cols + 2; col++ ) // Primera fila de X
                        std::cout << 'X';
	std::cout << std::endl;
}

int main (int argc, char* argv[])
{
	boost::asio::io_service io_service; // Inicia comunicaciones
	tcp::resolver resolver(io_service); // Resuelve la comunicación
	auto endpoint_iterator = resolver.resolve({ argv[1], argv[2] }); // Iterador hacia puerto y dirección
	std::shared_ptr<tcp::socket> socket(new tcp::socket(io_service)); // Puntero compartido hacia el socket
	boost::asio::connect(*socket, endpoint_iterator); // Conexión

	io_service.run();

	int paso = 0;

	// Variables de comunicacion
	boost::mutex state_mutex;
	bool gameover = false;
	bool connected = false;
	bot::team_id id = 6666;
	bot::field_size field_width;
	bot::field_size field_height;
	int win_width = 500;
	int win_height = 500;
	// Mi instancia de la clase bots
	bots mi_bots = bots(field_width, field_height); // Tamaño del campo 10x10, usa la pila
	//Lee el bufer de comunicaciones
	boost::asio::streambuf buf;
	read_until(*socket, buf, "\n");
	std::string data;
	std::istream is(&buf);
	std::getline(is, data);
	std::istringstream mi_stream(data);
	// Lee la primer palabra
	std::string command;
	mi_stream >> command;
	// Lee la información inicial
	if(command == "welcome")
	{
        mi_stream >> id;
        std::cout << "team id: " << id << std::endl;
        //ai.set_team(id);
        mi_stream >> field_width;
        mi_stream >> field_height;
        mi_bots.set_size(field_width, field_height);
        std::cout << "setting field: " << field_width << " x " << field_height << std::endl;
    }

	while (!gameover)
	{
		{
			read_until(*socket, buf, "\n"); //Leo el bufer
			std::istream is2(&buf); // Input Stream (lectura) a la clase buf
			std::getline(is2, data); // Convierte a String y guarda en data
			std::istringstream mi_stream2(data); // Input Stream (letura) al string data
			mi_stream2 >> command;

			//Lee el estado del escenario
			if(command == "state")
			{
				std::stringstream state;

				while(!mi_stream2.eof()) {
					std::string a;
					mi_stream2 >> a;
					state << a << " ";
				}
				std::cout << state.str() << std::endl;

				boost::archive::text_iarchive ia(state);
				{
					boost::mutex::scoped_lock lock(state_mutex);
					ia >> mi_bots;
					paso++;
					std::cout << "\x1B[2J\x1B[H"; // Limpia pantalla
					pinta_escenario(mi_bots, paso, field_width, field_height);
				}
			}
			else
			{
				std::cout << "GAME OVER " << command << std::endl;
			}

		}

		mi_bots.for_each_bot([&] ( bot & b ) {
		std::stringstream stream;
		// Envia movimeinte del bot
        stream << "move " << b.get_x() << " " << b.get_y() << " " << bot::W;
        async_send(*socket, stream.str());

		});

		//while ( std::cin.get() != ' ' ); // Espera entrada espacio
	}
	return 0;
}
<commit_msg>Asinc comms OK!<commit_after>#include <iostream>
#include "bots.h"
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>

using boost::asio::ip::tcp;

void pinta_escenario( bots & mis_bots, bot::field_size cols, bot::field_size filas)
{
	std::cout << "\x1B[2J\x1B[H"; // Despeja la pantalla del terminal
	for ( int col = 0; col < cols + 2; col++ ) // Primera fila de X
        	std::cout << 'X';
	std::cout << std::endl;
	for ( int fila = 0; fila < filas; fila++ ) //! Recorre toda la altura
        {
		std::cout << 'X'; // Primera X de la fila
		for ( int col = 0; col < cols; col++ ) // Espacios en blanco
		{
			bot * pos_bot = mis_bots.find_at( { col, fila} );
			if ( pos_bot == nullptr )
                        	std::cout << ' ';
			else
				std::cout << pos_bot->get_team();
		}
		std::cout << 'X'; //! Espacios de 1a altura - fila
                std::cout << std::endl;
        }
	for ( int col = 0; col < cols + 2; col++ ) // Primera fila de X
                        std::cout << 'X';
	std::cout << std::endl;
}

class client_bot
{
private:
	tcp::resolver _resolver;
	tcp::socket _socket;
	boost::asio::streambuf _packetToSend;
	boost::asio::streambuf _receiver;
	bots & _bots;
	boost::mutex & _state_mutex;
	bot::team_id & _id;
	bot::field_size _field_width;
	bot::field_size _field_height;

public:
 client_bot(boost::asio::io_service& io_service, const std::string& server,
   const std::string& port, bots & bts, boost::mutex & sm, bot::team_id & id)
 : _resolver(io_service),
   _socket(io_service),
   _bots(bts),
   _state_mutex(sm),
   _id(id)
 {
 // Start an asynchronous resolve to translate the server and service names
 // into a list of endpoints.
 std::cout << "Resolving..." << std::endl;
 tcp::resolver::query query(server, port);
 _resolver.async_resolve(query,
  boost::bind(&client_bot::handle_resolve, this,
  boost::asio::placeholders::error,
  boost::asio::placeholders::iterator));
 }

private:
 void handle_resolve(const boost::system::error_code& err,
   tcp::resolver::iterator endpoint_iterator)
 {
  if (!err)
  {
   // Attempt a connection to the first endpoint in the list. Each endpoint
   // will be tried until we successfully establish a connection.
   std::cout << "Connecting to " << endpoint_iterator->host_name() << std::endl;
   tcp::endpoint endpoint = *endpoint_iterator;
   _socket.async_connect(endpoint,
    boost::bind(&client_bot::handle_connect, this,
    boost::asio::placeholders::error, ++endpoint_iterator));
  }
  else
  {
   std::cout << "Error resolving: " << err.message() << "\n";
  }
 }

 void handle_connect(const boost::system::error_code& err,
   tcp::resolver::iterator endpoint_iterator)
 {
  if (!err)
  {

   // The connection was successful. Send the request.
   std::cout << "Retrieving..." << std::endl;
   // Read the response status line.
   boost::asio::async_read_until(_socket, _receiver, "\n",
    boost::bind(&client_bot::handle_read_command, this,
    boost::asio::placeholders::error));
  }
  else if (endpoint_iterator != tcp::resolver::iterator())
  {
   // The connection failed. Try the next endpoint in the list.
   _socket.close();
   tcp::endpoint endpoint = *endpoint_iterator;
   _socket.async_connect(endpoint,
    boost::bind(&client_bot::handle_connect, this,
    boost::asio::placeholders::error, ++endpoint_iterator));
  }
  else
  {
   std::cout << "Error: " << err.message() << "\n";
  }
 }

 void handle_read_command(const boost::system::error_code& err)
 {
  if (!err)
  {
   // Check that response is OK.
   std::string data;
   std::istream _receiverstream(&_receiver);
   std::getline(_receiverstream, data);

   std::istringstream stream(data);
   std::string command;
   stream >> command;

   // Read the response headers, which are terminated by a blank line.
   if(command == "welcome") {
    stream >> _id;
    stream >> _field_width;
    stream >> _field_height;
    std::cout << data << std::endl;
    //ai.set_team(id);
    while(!stream.eof()) {
     std::string a;
     stream >> a;
     //state << a << " ";
    }
   }
   else if(command == "state") {

    std::stringstream state;
    while(!stream.eof()) {
     std::string a;
     stream >> a;
     state << a << " ";
    }
    boost::archive::text_iarchive ia(state);
    {
     // mutex:
     // segfaults if it draws during a state update (drawing +
     // incomplete state is fatal)
     boost::mutex::scoped_lock lock(_state_mutex);
     ia >> _bots;
    }
    std::cout << "State updated" << std::endl;
    pinta_escenario(_bots, _field_width, _field_height);
   }

         for(auto b : _bots.team_bots(_id)) {
          std::ostream _packetToSendstream(&_packetToSend);
          _packetToSendstream << "move " << b->get_x() << " " << b->get_y() << " 3\n";

          boost::asio::async_write(_socket, _packetToSend,
     boost::bind(&client_bot::handle_write_request, this,
     boost::asio::placeholders::error));
         }
   boost::asio::async_read_until(_socket, _receiver, "\n",
    boost::bind(&client_bot::handle_read_command, this,
    boost::asio::placeholders::error));
  }
  else
  {
   std::cout << "Error reading command: " << err << "\n";
  }
 }

 void handle_write_request(const boost::system::error_code& err)
 {
     if (!err)
     {

     }
     else
     {
      std::cout << "Error writing: " << err.message() << "\n";
     }
 }
};

int main (int argc, char* argv[])
{
	// Mi instancia de la clase bots
	bots mi_bots;
	bot::team_id id = 1001;

	boost::asio::io_service io_service; // Inicia comunicaciones
	boost::mutex state_mutex;
	client_bot mi_cliente_bot(io_service, argv[1], argv[2], mi_bots, state_mutex, id);
	io_service.run();

	return(0);
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2014, Project OSRM, Dennis Luxen, others
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef LRUCACHE_HPP
#define LRUCACHE_HPP

#include <list>
#include <unordered_map>

template <typename KeyT, typename ValueT> class LRUCache
{
  private:
    struct CacheEntry
    {
        CacheEntry(KeyT k, ValueT v) : key(k), value(v) {}
        KeyT key;
        ValueT value;
    };
    unsigned capacity;
    std::list<CacheEntry> itemsInCache;
    std::unordered_map<KeyT, typename std::list<CacheEntry>::iterator> positionMap;

  public:
    explicit LRUCache(unsigned c) : capacity(c) {}

    bool Holds(KeyT key)
    {
        if (positionMap.find(key) != positionMap.end())
        {
            return true;
        }
        return false;
    }

    void Insert(const KeyT key, ValueT &value)
    {
        itemsInCache.push_front(CacheEntry(key, value));
        positionMap.insert(std::make_pair(key, itemsInCache.begin()));
        if (itemsInCache.size() > capacity)
        {
            positionMap.erase(itemsInCache.back().key);
            itemsInCache.pop_back();
        }
    }

    void Insert(const KeyT key, ValueT value)
    {
        itemsInCache.push_front(CacheEntry(key, value));
        positionMap.insert(std::make_pair(key, itemsInCache.begin()));
        if (itemsInCache.size() > capacity)
        {
            positionMap.erase(itemsInCache.back().key);
            itemsInCache.pop_back();
        }
    }

    bool Fetch(const KeyT key, ValueT &result)
    {
        if (Holds(key))
        {
            CacheEntry e = *(positionMap.find(key)->second);
            result = e.value;

            // move to front
            itemsInCache.splice(positionMap.find(key)->second, itemsInCache, itemsInCache.begin());
            positionMap.find(key)->second = itemsInCache.begin();
            return true;
        }
        return false;
    }
    unsigned Size() const { return itemsInCache.size(); }
};
#endif // LRUCACHE_HPP
<commit_msg>Fix std::list splice usage error<commit_after>/*

Copyright (c) 2014, Project OSRM, Dennis Luxen, others
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef LRUCACHE_HPP
#define LRUCACHE_HPP

#include <list>
#include <unordered_map>

template <typename KeyT, typename ValueT> class LRUCache
{
  private:
    struct CacheEntry
    {
        CacheEntry(KeyT k, ValueT v) : key(k), value(v) {}
        KeyT key;
        ValueT value;
    };
    unsigned capacity;
    std::list<CacheEntry> itemsInCache;
    std::unordered_map<KeyT, typename std::list<CacheEntry>::iterator> positionMap;

  public:
    explicit LRUCache(unsigned c) : capacity(c) {}

    bool Holds(KeyT key)
    {
        if (positionMap.find(key) != positionMap.end())
        {
            return true;
        }
        return false;
    }

    void Insert(const KeyT key, ValueT &value)
    {
        itemsInCache.push_front(CacheEntry(key, value));
        positionMap.insert(std::make_pair(key, itemsInCache.begin()));
        if (itemsInCache.size() > capacity)
        {
            positionMap.erase(itemsInCache.back().key);
            itemsInCache.pop_back();
        }
    }

    void Insert(const KeyT key, ValueT value)
    {
        itemsInCache.push_front(CacheEntry(key, value));
        positionMap.insert(std::make_pair(key, itemsInCache.begin()));
        if (itemsInCache.size() > capacity)
        {
            positionMap.erase(itemsInCache.back().key);
            itemsInCache.pop_back();
        }
    }

    bool Fetch(const KeyT key, ValueT &result)
    {
        if (Holds(key))
        {
            CacheEntry e = *(positionMap.find(key)->second);
            result = e.value;

            // move to front
            itemsInCache.splice(itemsInCache.begin(), itemsInCache, positionMap.find(key)->second);
            positionMap.find(key)->second = itemsInCache.begin();
            return true;
        }
        return false;
    }
    unsigned Size() const { return itemsInCache.size(); }
};
#endif // LRUCACHE_HPP
<|endoftext|>


<commit_before>namespace iox
{
template <uint64_t Capacity, typename ValueType>
IndexQueue<Capacity, ValueType>::IndexQueue(ConstructEmpty_t)
    : m_readPosition(Index(Capacity))
    , m_writePosition(Index(Capacity))
{
}

template <uint64_t Capacity, typename ValueType>
IndexQueue<Capacity, ValueType>::IndexQueue(ConstructFull_t)
    : m_readPosition(Index(0))
    , m_writePosition(Index(Capacity))
{
    for (uint64_t i = 0; i < Capacity; ++i)
    {
        m_cells[i].store(Index(i));
    }
}

template <uint64_t Capacity, typename ValueType>
constexpr uint64_t IndexQueue<Capacity, ValueType>::capacity()
{
    return Capacity;
}

template <uint64_t Capacity, typename ValueType>
void IndexQueue<Capacity, ValueType>::push(ValueType index)
{
    // we need the CAS loop here since we may fail due to concurrent push operations
    // note that we are always able to succeed to publish since we have
    // enough capacity for all unique indices used

    // case analyis
    // (1) loaded value is exactly one cycle behind:
    //     value is from the last cycle
    //     we can try to publish
    // (2) loaded value has the same cycle:
    //     some other push has published but not updated the write position
    //     help updating the write position
    // (3) loaded value is more than one cycle behind:
    //     this should only happen due to wrap around when push is interrupted for a long time
    //     reload write position and try again
    //     note that a complete wraparound can lead to a false detection of 1) (ABA problem)
    //     but this is very unlikely with e.g. a 64 bit value type
    // (4) loaded value is some cycle ahead:
    //     write position is outdated, there must have been other pushes concurrently
    //     reload write position and try again

    constexpr bool notPublished = true;
    auto writePosition = loadNextWritePosition();
    do
    {
        auto oldValue = loadValueAt(writePosition);

        auto isFreeToPublish = [&]() { return oldValue.isOneCycleBehind(writePosition); };

        if (isFreeToPublish())
        {
            // case (1)
            Index newValue(index, writePosition.getCycle());

            // if publish fails, another thread has published before us
            if (tryToPublishAt(writePosition, oldValue, newValue))
            {
                break;
            }
        }

        // even if we are not able to publish, we check whether some other push has already updated the writePosition
        // before trying again to publish
        auto writePositionWasNotUpdated = [&]() { return oldValue.getCycle() == writePosition.getCycle(); };

        if (writePositionWasNotUpdated())
        {
            // case (2)
            // the writePosition was not updated yet by another push but the value was already written
            // help with the update
            updateNextWritePosition(writePosition);
        }
        else
        {
            // case (3) and (4)
            // note: we do not call updateNextWritePosition here, the CAS is bound to fail anyway
            // (our value of writePosition is not up to date so needs to be loaded again)
            writePosition = loadNextWritePosition();
        }

    } while (notPublished);

    updateNextWritePosition(writePosition);
}

template <uint64_t Capacity, typename ValueType>
bool IndexQueue<Capacity, ValueType>::pop(ValueType& index)
{
    // we need the CAS loop here since we may fail due to concurrent pop operations
    // we leave when we detect an empty queue, otherwise we retry the pop operation

    // case analyis
    // (1) loaded value has the same cycle:
    //     value was not popped before
    //     try to get ownership
    // (2) loaded value is exactly one cycle behind:
    //     value is from the last cycle which means the queue is empty
    //     return false
    // (3) loaded value is more than one cycle behind:
    //     this should only happen due to wrap around when push is interrupted for a long time
    //     reload read position and try again
    // (4) loaded value is some cycle ahead:
    //     read position is outdated, there must have been pushes concurrently
    //     reload read position and try again

    constexpr bool ownerShipGained = true;
    Index value;
    auto readPosition = loadNextReadPosition();
    do
    {
        value = loadValueAt(readPosition);

        // we only dequeue if value and readPosition are in the same cycle
        auto isValidToRead = [&]() { return readPosition.getCycle() == value.getCycle(); };
        // readPosition is ahead by one cycle, queue was empty at loadValueAt(..)
        auto isEmpty = [&]() { return value.isOneCycleBehind(readPosition); };

        if (isValidToRead())
        {
            // case (1)
            if (tryToGainOwnershipAt(readPosition))
            {
                break; // pop successful
            }
            else
            {
                // retry, readPosition was already updated via CAS in tryToGainOwnershipAt
                // todo: maybe refactor to eliminate the continue but still skip the reload of
                // readPosition
                continue;
            }
        }
        else if (isEmpty())
        {
            // case (2)
            return false;
        }
        // else readPosition is outdated, retry operation

        // case (3) and (4)

        readPosition = loadNextReadPosition();

    } while (!ownerShipGained); // we leave if we gain ownership of readPosition

    index = value.getIndex();
    return true;
}

template <uint64_t Capacity, typename ValueType>
bool IndexQueue<Capacity, ValueType>::popIfFull(ValueType& index)
{
    // we do NOT need a CAS loop here since if we detect that the queue is not full
    // someone else popped an element and we do not retry to check whether it was filled AGAIN
    // concurrently (which will usually not be the case and then we would return false anyway)
    // if it is filled again we can (and will) retry popIfFull from the call site

    // the queue is full if and only if write position and read position are the same but read position is
    // one cycle behind write position
    // unfortunately it seems impossible in this design to check this condition without loading
    // write posiion and read position (which causes more contention)

    auto writePosition = loadNextWritePosition();
    auto readPosition = loadNextReadPosition();
    auto value = loadValueAt(readPosition);

    auto isFull = [&]() {
        return writePosition.getIndex() == readPosition.getIndex() && readPosition.isOneCycleBehind(writePosition);
    };

    if (isFull())
    {
        if (tryToGainOwnershipAt(readPosition))
        {
            index = value.getIndex();
            return true;
        }
    } // else someone else has popped an index
    return false;
}

template <uint64_t Capacity, typename ValueType>
bool IndexQueue<Capacity, ValueType>::empty()
{
    auto oldReadIndex = m_readPosition.load(std::memory_order_relaxed);
    auto value = m_cells[oldReadIndex.getIndex()].load(std::memory_order_relaxed);

    // if m_readPosition is ahead by one cycle compared to the value stored at head,
    // the queue was empty at the time of the loads above (but might not be anymore!)
    return value.isOneCycleBehind(oldReadIndex);
}

template <uint64_t Capacity, typename ValueType>
typename IndexQueue<Capacity, ValueType>::Index IndexQueue<Capacity, ValueType>::loadNextReadPosition() const
{
    return m_readPosition.load(std::memory_order_relaxed);
}

template <uint64_t Capacity, typename ValueType>
typename IndexQueue<Capacity, ValueType>::Index IndexQueue<Capacity, ValueType>::loadNextWritePosition() const
{
    return m_writePosition.load(std::memory_order_relaxed);
}

template <uint64_t Capacity, typename ValueType>
typename IndexQueue<Capacity, ValueType>::Index
IndexQueue<Capacity, ValueType>::loadValueAt(typename IndexQueue<Capacity, ValueType>::Index position) const
{
    return m_cells[position.getIndex()].load(std::memory_order_relaxed);
}

template <uint64_t Capacity, typename ValueType>
bool IndexQueue<Capacity, ValueType>::tryToPublishAt(typename IndexQueue<Capacity, ValueType>::Index writePosition,
                                                     Index& oldValue,
                                                     Index newValue)
{
    return m_cells[writePosition.getIndex()].compare_exchange_strong(
        oldValue, newValue, std::memory_order_relaxed, std::memory_order_relaxed);
}

template <uint64_t Capacity, typename ValueType>
void IndexQueue<Capacity, ValueType>::updateNextWritePosition(Index& writePosition)
{
    // compare_exchange updates writePosition if NOT successful
    Index newWritePosition(writePosition + 1);
    auto updateSucceeded = m_writePosition.compare_exchange_strong(
        writePosition, newWritePosition, std::memory_order_relaxed, std::memory_order_relaxed);

    // not needed in the successful case, we do not retry
    // if (updateSucceeded)
    // {
    //     writePosition = newWritePosition;
    // }
}

template <uint64_t Capacity, typename ValueType>
bool IndexQueue<Capacity, ValueType>::tryToGainOwnershipAt(Index& oldReadPosition)
{
    Index newReadPosition(oldReadPosition + 1);
    return m_readPosition.compare_exchange_strong(
        oldReadPosition, newReadPosition, std::memory_order_relaxed, std::memory_order_relaxed);
}

template <uint64_t Capacity, typename ValueType>
void IndexQueue<Capacity, ValueType>::push(const UniqueIndex& index)
{
    push(*index);
}

template <uint64_t Capacity, typename ValueType>
typename IndexQueue<Capacity, ValueType>::UniqueIndex IndexQueue<Capacity, ValueType>::pop()
{
    ValueType value;
    if (pop(value))
    {
        return UniqueIndex(value);
    }
    return UniqueIndex::invalid;
}

template <uint64_t Capacity, typename ValueType>
typename IndexQueue<Capacity, ValueType>::UniqueIndex IndexQueue<Capacity, ValueType>::popIfFull()
{
    ValueType value;
    if (popIfFull(value))
    {
        return UniqueIndex(value);
    }
    return UniqueIndex::invalid;
}

} // namespace iox<commit_msg>refactor code in index queue for comprehensibility<commit_after>namespace iox
{
template <uint64_t Capacity, typename ValueType>
IndexQueue<Capacity, ValueType>::IndexQueue(ConstructEmpty_t)
    : m_readPosition(Index(Capacity))
    , m_writePosition(Index(Capacity))
{
}

template <uint64_t Capacity, typename ValueType>
IndexQueue<Capacity, ValueType>::IndexQueue(ConstructFull_t)
    : m_readPosition(Index(0))
    , m_writePosition(Index(Capacity))
{
    for (uint64_t i = 0; i < Capacity; ++i)
    {
        m_cells[i].store(Index(i));
    }
}

template <uint64_t Capacity, typename ValueType>
constexpr uint64_t IndexQueue<Capacity, ValueType>::capacity()
{
    return Capacity;
}

template <uint64_t Capacity, typename ValueType>
void IndexQueue<Capacity, ValueType>::push(ValueType index)
{
    // we need the CAS loop here since we may fail due to concurrent push operations
    // note that we are always able to succeed to publish since we have
    // enough capacity for all unique indices used

    // case analyis
    // (1) loaded value is exactly one cycle behind:
    //     value is from the last cycle
    //     we can try to publish
    // (2) loaded value has the same cycle:
    //     some other push has published but not updated the write position
    //     help updating the write position
    // (3) loaded value is more than one cycle behind:
    //     this should only happen due to wrap around when push is interrupted for a long time
    //     reload write position and try again
    //     note that a complete wraparound can lead to a false detection of 1) (ABA problem)
    //     but this is very unlikely with e.g. a 64 bit value type
    // (4) loaded value is some cycle ahead:
    //     write position is outdated, there must have been other pushes concurrently
    //     reload write position and try again

    constexpr bool notPublished = true;
    auto writePosition = loadNextWritePosition();
    do
    {
        auto oldValue = loadValueAt(writePosition);

        auto cellIsFree = oldValue.isOneCycleBehind(writePosition);

        if (cellIsFree)
        {
            // case (1)
            Index newValue(index, writePosition.getCycle());

            // if publish fails, another thread has published before us
            if (tryToPublishAt(writePosition, oldValue, newValue))
            {
                break;
            }
        }

        // even if we are not able to publish, we check whether some other push has already updated the writePosition
        // before trying again to publish
        auto writePositionRequiresUpdate = oldValue.getCycle() == writePosition.getCycle();

        if (writePositionRequiresUpdate)
        {
            // case (2)
            // the writePosition was not updated yet by another push but the value was already written
            // help with the update
            updateNextWritePosition(writePosition);
        }
        else
        {
            // case (3) and (4)
            // note: we do not call updateNextWritePosition here, the CAS is bound to fail anyway
            // (since our value of writePosition is not up to date so needs to be loaded again)
            writePosition = loadNextWritePosition();
        }

    } while (notPublished);

    updateNextWritePosition(writePosition);
}

template <uint64_t Capacity, typename ValueType>
bool IndexQueue<Capacity, ValueType>::pop(ValueType& index)
{
    // we need the CAS loop here since we may fail due to concurrent pop operations
    // we leave when we detect an empty queue, otherwise we retry the pop operation

    // case analyis
    // (1) loaded value has the same cycle:
    //     value was not popped before
    //     try to get ownership
    // (2) loaded value is exactly one cycle behind:
    //     value is from the last cycle which means the queue is empty
    //     return false
    // (3) loaded value is more than one cycle behind:
    //     this should only happen due to wrap around when push is interrupted for a long time
    //     reload read position and try again
    // (4) loaded value is some cycle ahead:
    //     read position is outdated, there must have been pushes concurrently
    //     reload read position and try again

    constexpr bool ownerShipGained = true;
    Index value;
    auto readPosition = loadNextReadPosition();
    do
    {
        value = loadValueAt(readPosition);

        // we only dequeue if value and readPosition are in the same cycle
        auto cellIsValidToRead = readPosition.getCycle() == value.getCycle();

        if (cellIsValidToRead)
        {
            // case (1)
            if (tryToGainOwnershipAt(readPosition))
            {
                break; // pop successful
            }
            // retry, readPosition was already updated via CAS in tryToGainOwnershipAt
        }
        else
        {
            // readPosition is ahead by one cycle, queue was empty at loadValueAt(..)
            auto isEmpty = value.isOneCycleBehind(readPosition);

            if (isEmpty)
            {
                // case (2)
                return false;
            }

            // case (3) and (4) requires loading readPosition again
            readPosition = loadNextReadPosition();
        }

        // readPosition is outdated, retry operation

    } while (!ownerShipGained); // we leave if we gain ownership of readPosition

    index = value.getIndex();
    return true;
}

template <uint64_t Capacity, typename ValueType>
bool IndexQueue<Capacity, ValueType>::popIfFull(ValueType& index)
{
    // we do NOT need a CAS loop here since if we detect that the queue is not full
    // someone else popped an element and we do not retry to check whether it was filled AGAIN
    // concurrently (which will usually not be the case and then we would return false anyway)
    // if it is filled again we can (and will) retry popIfFull from the call site

    // the queue is full if and only if write position and read position are the same but read position is
    // one cycle behind write position
    // unfortunately it seems impossible in this design to check this condition without loading
    // write posiion and read position (which causes more contention)

    auto writePosition = loadNextWritePosition();
    auto readPosition = loadNextReadPosition();
    auto value = loadValueAt(readPosition);

    auto isFull = writePosition.getIndex() == readPosition.getIndex() && readPosition.isOneCycleBehind(writePosition);

    if (isFull)
    {
        if (tryToGainOwnershipAt(readPosition))
        {
            index = value.getIndex();
            return true;
        }
    }

    // otherwise someone else has dequeued an index and the queue was not full at the start of this popIfFull
    return false;
}

template <uint64_t Capacity, typename ValueType>
bool IndexQueue<Capacity, ValueType>::empty()
{
    auto oldReadIndex = m_readPosition.load(std::memory_order_relaxed);
    auto value = m_cells[oldReadIndex.getIndex()].load(std::memory_order_relaxed);

    // if m_readPosition is ahead by one cycle compared to the value stored at head,
    // the queue was empty at the time of the loads above (but might not be anymore!)
    return value.isOneCycleBehind(oldReadIndex);
}

template <uint64_t Capacity, typename ValueType>
typename IndexQueue<Capacity, ValueType>::Index IndexQueue<Capacity, ValueType>::loadNextReadPosition() const
{
    return m_readPosition.load(std::memory_order_relaxed);
}

template <uint64_t Capacity, typename ValueType>
typename IndexQueue<Capacity, ValueType>::Index IndexQueue<Capacity, ValueType>::loadNextWritePosition() const
{
    return m_writePosition.load(std::memory_order_relaxed);
}

template <uint64_t Capacity, typename ValueType>
typename IndexQueue<Capacity, ValueType>::Index
IndexQueue<Capacity, ValueType>::loadValueAt(typename IndexQueue<Capacity, ValueType>::Index position) const
{
    return m_cells[position.getIndex()].load(std::memory_order_relaxed);
}

template <uint64_t Capacity, typename ValueType>
bool IndexQueue<Capacity, ValueType>::tryToPublishAt(typename IndexQueue<Capacity, ValueType>::Index writePosition,
                                                     Index& oldValue,
                                                     Index newValue)
{
    return m_cells[writePosition.getIndex()].compare_exchange_strong(
        oldValue, newValue, std::memory_order_relaxed, std::memory_order_relaxed);
}

template <uint64_t Capacity, typename ValueType>
void IndexQueue<Capacity, ValueType>::updateNextWritePosition(Index& writePosition)
{
    // compare_exchange updates writePosition if NOT successful
    Index newWritePosition(writePosition + 1);
    auto updateSucceeded = m_writePosition.compare_exchange_strong(
        writePosition, newWritePosition, std::memory_order_relaxed, std::memory_order_relaxed);
}

template <uint64_t Capacity, typename ValueType>
bool IndexQueue<Capacity, ValueType>::tryToGainOwnershipAt(Index& oldReadPosition)
{
    Index newReadPosition(oldReadPosition + 1);
    return m_readPosition.compare_exchange_strong(
        oldReadPosition, newReadPosition, std::memory_order_relaxed, std::memory_order_relaxed);
}

template <uint64_t Capacity, typename ValueType>
void IndexQueue<Capacity, ValueType>::push(const UniqueIndex& index)
{
    push(*index);
}

template <uint64_t Capacity, typename ValueType>
typename IndexQueue<Capacity, ValueType>::UniqueIndex IndexQueue<Capacity, ValueType>::pop()
{
    ValueType value;
    if (pop(value))
    {
        return UniqueIndex(value);
    }
    return UniqueIndex::invalid;
}

template <uint64_t Capacity, typename ValueType>
typename IndexQueue<Capacity, ValueType>::UniqueIndex IndexQueue<Capacity, ValueType>::popIfFull()
{
    ValueType value;
    if (popIfFull(value))
    {
        return UniqueIndex(value);
    }
    return UniqueIndex::invalid;
}

} // namespace iox<|endoftext|>


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

/* $Id$ */

// ---
// Macro for MUON alignment using physics tracks. The macro uses AliMUONAlignment
// class to calculate the alignment parameters.
// An array for the alignment parameters is created and can be filled with
// initial values that will be used as starting values by the alignment
// algorithm.
// Ny default the macro run over galice.root in the working directory. If a file list
// of galice.root is provided as third argument the macro will run over all files.
// The macro loop over the files, events and tracks. For each track
// AliMUONAlignment::ProcessTrack(AliMUONTrack * track) and then
// AliMUONAlignment::LocalFit(Int_t iTrack, Double_t *lTrackParam, Int_t
// lSingleFit) are called. After all tracks have been procesed and fitted
// AliMUONAlignment::GlobalFit(Double_t *parameters,Double_t *errors,Double_t *pulls)
// is called. The array parameters contains the obatained misalignement parameters.
// A realigned geometry is generated in a local CDB.
//
// Authors: B. Becker and J. Castillo
// ---

#if !defined(__CINT__) || defined(__MAKECINT__)

#include "AliMUONAlignment.h"
#include "AliMUONTrack.h"
#include "AliMUONTrackExtrap.h"
#include "AliMUONTrackParam.h"
#include "AliMUONGeometryTransformer.h"
#include "AliMUONDataInterface.h"

#include "AliMagFMaps.h"
#include "AliTracker.h"
#include "AliCDBManager.h"
#include "AliCDBMetaData.h"
#include "AliCDBId.h"

#include <TString.h>
#include <TGeoManager.h>
#include <TError.h>
#include <TH1.h>
#include <TGraphErrors.h>
#include <TFile.h>
#include <TClonesArray.h>
#include <Riostream.h>

#include <fstream>

#endif

void MUONAlignment(Int_t nEvents = 100000, char* geoFilename = "geometry.root", TString fileName = "galice.root", TString fileList = "")
{

  // Import TGeo geometry (needed by AliMUONTrackExtrap::ExtrapToVertex)
  if (!gGeoManager) {
    TGeoManager::Import(geoFilename);
    if (!gGeoManager) {
      Error("MUONmass_ESD", "getting geometry from file %s failed", geoFilename);
      return;
    }
  }

  // set  mag field
  // waiting for mag field in CDB
  printf("Loading field map...\n");
  AliMagFMaps* field = new AliMagFMaps("Maps","Maps", 1, 1., 10., AliMagFMaps::k5kG);
  AliTracker::SetFieldMap(field, kFALSE);
  // set the magnetic field for track extrapolations
  AliMUONTrackExtrap::SetField(AliTracker::GetFieldMap());

  Double_t parameters[3*156];
  Double_t errors[3*156];
  Double_t pulls[3*156];
  for(Int_t k=0;k<3*156;k++) {
    parameters[k]=0.;
    errors[k]=0.;
    pulls[k]=0.;
  }

  Double_t trackParams[8] = {0.,0.,0.,0.,0.,0.,0.,0.};

  // Set initial values here, good guess may help convergence
  // St 1
  //  Int_t iPar = 0;
  //  parameters[iPar++] =  0.010300 ;  parameters[iPar++] =  0.010600 ;  parameters[iPar++] =  0.000396 ;

  bool bLoop = kFALSE;
  ifstream sFileList;
  if (fileList.Contains(".list")) {
    cout << "Reading file list: " << fileList.Data() << endl;
    bLoop = kTRUE;

    TString fullListName(".");
    fullListName +="/";
    fullListName +=fileList;
    sFileList.open(fileList.Data());
  }

  TH1F *fInvBenMom = new TH1F("fInvBenMom","fInvBenMom",200,-0.1,0.1);
  TH1F *fBenMom = new TH1F("fBenMom","fBenMom",200,-40,40);

  AliMUONAlignment* alig = new AliMUONAlignment();
  alig->InitGlobalParameters(parameters);

  AliMUONGeometryTransformer *transform = new AliMUONGeometryTransformer(true);
  transform->ReadGeometryData("volpath.dat", gGeoManager);
  alig->SetGeometryTransformer(transform);

  // Set tracking station to use
  Bool_t bStOnOff[5] = {kTRUE,kTRUE,kTRUE,kTRUE,kTRUE};

  // Fix parameters or add constraints here
  for (Int_t iSt=0; iSt<5; iSt++)
    if (!bStOnOff[iSt]) alig->FixStation(iSt+1);

  // Left and right sides of the detector are independent, one can choose to align
  // only one side
  Bool_t bSpecLROnOff[2] = {kTRUE,kTRUE};
  alig->FixHalfSpectrometer(bStOnOff,bSpecLROnOff);

  // Set predifined global constrains: X, Y, P, XvsZ, YvsZ, PvsZ, XvsY, YvsY, PvsY
  Bool_t bVarXYT[9] = {kTRUE,kTRUE,kTRUE,kTRUE,kTRUE,kTRUE,kTRUE,kTRUE,kTRUE};
  Bool_t bDetTLBR[4] = {kFALSE,kTRUE,kFALSE,kTRUE};
  alig->AddConstraints(bStOnOff,bVarXYT,bDetTLBR,bSpecLROnOff);

  char cFileName[100];
  AliMUONDataInterface amdi;

  Int_t lMaxFile = 1000;
  Int_t iFile = 0;
  Int_t iEvent = 0;
  bool bKeepLoop = kTRUE;
  Int_t iTrackTot=0;
  Int_t iTrackOk=0;

  while(bKeepLoop && iFile<lMaxFile){
    iFile++;
    if (bLoop) {
      sFileList.getline(cFileName,100);
      if (sFileList.eof()) bKeepLoop = kFALSE;
    }
    else {
      sprintf(cFileName,fileName.Data());
      bKeepLoop = kFALSE;
    }
    if (!strstr(cFileName,"galice.root")) continue;
    cout << "Using file: " << cFileName << endl;
    amdi.SetFile(cFileName);
    Int_t nevents = amdi.NumberOfEvents();
    cout << "... with " << nevents << endl;
    for(Int_t event = 0; event < nevents; event++) {
      amdi.GetEvent(event);
      if (iEvent >= nEvents){
	bKeepLoop = kFALSE;
	break;
      }
      iEvent++;

      Int_t ntracks = amdi.NumberOfRecTracks();
      if (!event%100)
	cout << " there are " << ntracks << " tracks in event " << event << endl;
      Int_t iTrack=0;
      AliMUONTrack* track = amdi.RecTrack(iTrack);
      while(track) {
	AliMUONTrackParam trackParam(*((AliMUONTrackParam*)(track->GetTrackParamAtHit()->First())));
	AliMUONTrackExtrap::ExtrapToVertex(&trackParam,0.,0.,0.);
	Double_t invBenMom = trackParam.GetInverseBendingMomentum();
	fInvBenMom->Fill(invBenMom);
	fBenMom->Fill(1./invBenMom);
	if (TMath::Abs(invBenMom)<=1.04) {
	  alig->ProcessTrack(track);
	  alig->LocalFit(iTrackOk++,trackParams,0);
	}
	iTrack++;
	iTrackTot++;
	track = amdi.RecTrack(iTrack);
      }
    }
    cout << "Processed " << iTrackTot << " Tracks so far." << endl;
  }
  alig->GlobalFit(parameters,errors,pulls);

  cout << "Done with GlobalFit " << endl;

  // Store results
  Double_t DEid[156] = {0};
  Double_t MSDEx[156] = {0};
  Double_t MSDEy[156] = {0};
  Double_t MSDExt[156] = {0};
  Double_t MSDEyt[156] = {0};
  Double_t DEidErr[156] = {0};
  Double_t MSDExErr[156] = {0};
  Double_t MSDEyErr[156] = {0};
  Double_t MSDExtErr[156] = {0};
  Double_t MSDEytErr[156] = {0};
  Int_t lNDetElem = 4*2+4*2+18*2+26*2+26*2;
  Int_t lNDetElemCh[10] = {4,4,4,4,18,18,26,26,26,26};
  // Int_t lSNDetElemCh[10] = {4,8,12,16,34,52,78,104,130,156};
  Int_t idOffset = 0; // 400
  Int_t lSDetElemCh = 0;
  for(Int_t iDE=0; iDE<lNDetElem; iDE++){
    DEidErr[iDE] = 0.;
    DEid[iDE] = idOffset+100;
    DEid[iDE] += iDE;
    lSDetElemCh = 0;
    for(Int_t iCh=0; iCh<9; iCh++){
      lSDetElemCh += lNDetElemCh[iCh];
      if (iDE>=lSDetElemCh) {
	DEid[iDE] += 100;
	DEid[iDE] -= lNDetElemCh[iCh];
      }
    }
    MSDEx[iDE]=parameters[3*iDE+0];
    MSDEy[iDE]=parameters[3*iDE+1];
    MSDExt[iDE]=parameters[3*iDE+2];
    MSDEyt[iDE]=parameters[3*iDE+2];
    MSDExErr[iDE]=(Double_t)alig->GetParError(3*iDE+0);
    MSDEyErr[iDE]=(Double_t)alig->GetParError(3*iDE+1);
    MSDExtErr[iDE]=(Double_t)alig->GetParError(3*iDE+2);
    MSDEytErr[iDE]=(Double_t)alig->GetParError(3*iDE+2);
  }

  cout << "Let's create graphs ...  " << endl;

  TGraphErrors *gMSDEx = new TGraphErrors(lNDetElem,DEid,MSDEx,DEidErr,MSDExErr);
  TGraphErrors *gMSDEy = new TGraphErrors(lNDetElem,DEid,MSDEy,DEidErr,MSDEyErr);
  TGraphErrors *gMSDExt = new TGraphErrors(lNDetElem,DEid,MSDExt,DEidErr,MSDExtErr);
  TGraphErrors *gMSDEyt = new TGraphErrors(lNDetElem,DEid,MSDEyt,DEidErr,MSDEytErr);

  cout << "... graphs created, open file ...  " << endl;

  TFile *hFile = new TFile("measShifts.root","RECREATE");

  cout << "... file opened ...  " << endl;

  gMSDEx->Write("gMSDEx");
  gMSDEy->Write("gMSDEy");
  gMSDExt->Write("gMSDExt");
  gMSDEyt->Write("gMSDEyt");
  fInvBenMom->Write();
  fBenMom->Write();
  hFile->Close();

  cout << "... and closed!" << endl;
  // Re Align
  AliMUONGeometryTransformer *newTransform = alig->ReAlign(transform,parameters,true);
  newTransform->WriteTransformations("transform2ReAlign.dat");

  // Generate realigned data in local cdb
  const TClonesArray* array = newTransform->GetMisAlignmentData();

  // CDB manager
  AliCDBManager* cdbManager = AliCDBManager::Instance();
  cdbManager->SetDefaultStorage("local://ReAlignCDB");

  AliCDBMetaData* cdbData = new AliCDBMetaData();
  cdbData->SetResponsible("Dimuon Offline project");
  cdbData->SetComment("MUON alignment objects with residual misalignment");
  AliCDBId id("MUON/Align/Data", 0, 0);
  cdbManager->Put(const_cast<TClonesArray*>(array), id, cdbData);

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

/* $Id$ */

// ---
// Macro for MUON alignment using physics tracks. The macro uses AliMUONAlignment
// class to calculate the alignment parameters.
// An array for the alignment parameters is created and can be filled with
// initial values that will be used as starting values by the alignment
// algorithm.
// Ny default the macro run over galice.root in the working directory. If a file list
// of galice.root is provided as third argument the macro will run over all files.
// The macro loop over the files, events and tracks. For each track
// AliMUONAlignment::ProcessTrack(AliMUONTrack * track) and then
// AliMUONAlignment::LocalFit(Int_t iTrack, Double_t *lTrackParam, Int_t
// lSingleFit) are called. After all tracks have been procesed and fitted
// AliMUONAlignment::GlobalFit(Double_t *parameters,Double_t *errors,Double_t *pulls)
// is called. The array parameters contains the obatained misalignement parameters.
// A realigned geometry is generated in a local CDB.
//
// Authors: B. Becker and J. Castillo
// ---

#if !defined(__CINT__) || defined(__MAKECINT__)

#include "AliMUONAlignment.h"
#include "AliMUONTrack.h"
#include "AliMUONTrackExtrap.h"
#include "AliMUONTrackParam.h"
#include "AliMUONGeometryTransformer.h"
#include "AliMUONDataInterface.h"

#include "AliMagFMaps.h"
#include "AliTracker.h"
#include "AliCDBManager.h"
#include "AliCDBMetaData.h"
#include "AliCDBId.h"
#include "AliGeomManager.h"

#include <TString.h>
#include <TError.h>
#include <TH1.h>
#include <TGraphErrors.h>
#include <TFile.h>
#include <TClonesArray.h>
#include <Riostream.h>

#include <fstream>

#endif

void MUONAlignment(Int_t nEvents = 100000, char* geoFilename = "geometry.root", TString fileName = "galice.root", TString fileList = "")
{

  // Import TGeo geometry (needed by AliMUONTrackExtrap::ExtrapToVertex)
  if ( ! AliGeomManager::GetGeometry() ) {
    AliGeomManager::LoadGeometry(geoFilename);
    if (! AliGeomManager::GetGeometry() ) {
      Error("MUONAlignment", "getting geometry from file %s failed", geoFilename);
      return;
    }
  }

  // set  mag field
  // waiting for mag field in CDB
  printf("Loading field map...\n");
  AliMagFMaps* field = new AliMagFMaps("Maps","Maps", 1, 1., 10., AliMagFMaps::k5kG);
  AliTracker::SetFieldMap(field, kFALSE);
  // set the magnetic field for track extrapolations
  AliMUONTrackExtrap::SetField(AliTracker::GetFieldMap());

  Double_t parameters[3*156];
  Double_t errors[3*156];
  Double_t pulls[3*156];
  for(Int_t k=0;k<3*156;k++) {
    parameters[k]=0.;
    errors[k]=0.;
    pulls[k]=0.;
  }

  Double_t trackParams[8] = {0.,0.,0.,0.,0.,0.,0.,0.};

  // Set initial values here, good guess may help convergence
  // St 1
  //  Int_t iPar = 0;
  //  parameters[iPar++] =  0.010300 ;  parameters[iPar++] =  0.010600 ;  parameters[iPar++] =  0.000396 ;

  bool bLoop = kFALSE;
  ifstream sFileList;
  if (fileList.Contains(".list")) {
    cout << "Reading file list: " << fileList.Data() << endl;
    bLoop = kTRUE;

    TString fullListName(".");
    fullListName +="/";
    fullListName +=fileList;
    sFileList.open(fileList.Data());
  }

  TH1F *fInvBenMom = new TH1F("fInvBenMom","fInvBenMom",200,-0.1,0.1);
  TH1F *fBenMom = new TH1F("fBenMom","fBenMom",200,-40,40);

  AliMUONAlignment* alig = new AliMUONAlignment();
  alig->InitGlobalParameters(parameters);

  AliMUONGeometryTransformer *transform = new AliMUONGeometryTransformer();
  transform->LoadGeometryData();
  alig->SetGeometryTransformer(transform);

  // Set tracking station to use
  Bool_t bStOnOff[5] = {kTRUE,kTRUE,kTRUE,kTRUE,kTRUE};

  // Fix parameters or add constraints here
  for (Int_t iSt=0; iSt<5; iSt++)
    if (!bStOnOff[iSt]) alig->FixStation(iSt+1);

  // Left and right sides of the detector are independent, one can choose to align
  // only one side
  Bool_t bSpecLROnOff[2] = {kTRUE,kTRUE};
  alig->FixHalfSpectrometer(bStOnOff,bSpecLROnOff);

  // Set predifined global constrains: X, Y, P, XvsZ, YvsZ, PvsZ, XvsY, YvsY, PvsY
  Bool_t bVarXYT[9] = {kTRUE,kTRUE,kTRUE,kTRUE,kTRUE,kTRUE,kTRUE,kTRUE,kTRUE};
  Bool_t bDetTLBR[4] = {kFALSE,kTRUE,kFALSE,kTRUE};
  alig->AddConstraints(bStOnOff,bVarXYT,bDetTLBR,bSpecLROnOff);

  char cFileName[100];
  AliMUONDataInterface amdi;

  Int_t lMaxFile = 1000;
  Int_t iFile = 0;
  Int_t iEvent = 0;
  bool bKeepLoop = kTRUE;
  Int_t iTrackTot=0;
  Int_t iTrackOk=0;

  while(bKeepLoop && iFile<lMaxFile){
    iFile++;
    if (bLoop) {
      sFileList.getline(cFileName,100);
      if (sFileList.eof()) bKeepLoop = kFALSE;
    }
    else {
      sprintf(cFileName,fileName.Data());
      bKeepLoop = kFALSE;
    }
    if (!strstr(cFileName,"galice.root")) continue;
    cout << "Using file: " << cFileName << endl;
    amdi.SetFile(cFileName);
    Int_t nevents = amdi.NumberOfEvents();
    cout << "... with " << nevents << endl;
    for(Int_t event = 0; event < nevents; event++) {
      amdi.GetEvent(event);
      if (iEvent >= nEvents){
	bKeepLoop = kFALSE;
	break;
      }
      iEvent++;

      Int_t ntracks = amdi.NumberOfRecTracks();
      if (!event%100)
	cout << " there are " << ntracks << " tracks in event " << event << endl;
      Int_t iTrack=0;
      AliMUONTrack* track = amdi.RecTrack(iTrack);
      while(track) {
	AliMUONTrackParam trackParam(*((AliMUONTrackParam*)(track->GetTrackParamAtHit()->First())));
	AliMUONTrackExtrap::ExtrapToVertex(&trackParam,0.,0.,0.);
	Double_t invBenMom = trackParam.GetInverseBendingMomentum();
	fInvBenMom->Fill(invBenMom);
	fBenMom->Fill(1./invBenMom);
	if (TMath::Abs(invBenMom)<=1.04) {
	  alig->ProcessTrack(track);
	  alig->LocalFit(iTrackOk++,trackParams,0);
	}
	iTrack++;
	iTrackTot++;
	track = amdi.RecTrack(iTrack);
      }
    }
    cout << "Processed " << iTrackTot << " Tracks so far." << endl;
  }
  alig->GlobalFit(parameters,errors,pulls);

  cout << "Done with GlobalFit " << endl;

  // Store results
  Double_t DEid[156] = {0};
  Double_t MSDEx[156] = {0};
  Double_t MSDEy[156] = {0};
  Double_t MSDExt[156] = {0};
  Double_t MSDEyt[156] = {0};
  Double_t DEidErr[156] = {0};
  Double_t MSDExErr[156] = {0};
  Double_t MSDEyErr[156] = {0};
  Double_t MSDExtErr[156] = {0};
  Double_t MSDEytErr[156] = {0};
  Int_t lNDetElem = 4*2+4*2+18*2+26*2+26*2;
  Int_t lNDetElemCh[10] = {4,4,4,4,18,18,26,26,26,26};
  // Int_t lSNDetElemCh[10] = {4,8,12,16,34,52,78,104,130,156};
  Int_t idOffset = 0; // 400
  Int_t lSDetElemCh = 0;
  for(Int_t iDE=0; iDE<lNDetElem; iDE++){
    DEidErr[iDE] = 0.;
    DEid[iDE] = idOffset+100;
    DEid[iDE] += iDE;
    lSDetElemCh = 0;
    for(Int_t iCh=0; iCh<9; iCh++){
      lSDetElemCh += lNDetElemCh[iCh];
      if (iDE>=lSDetElemCh) {
	DEid[iDE] += 100;
	DEid[iDE] -= lNDetElemCh[iCh];
      }
    }
    MSDEx[iDE]=parameters[3*iDE+0];
    MSDEy[iDE]=parameters[3*iDE+1];
    MSDExt[iDE]=parameters[3*iDE+2];
    MSDEyt[iDE]=parameters[3*iDE+2];
    MSDExErr[iDE]=(Double_t)alig->GetParError(3*iDE+0);
    MSDEyErr[iDE]=(Double_t)alig->GetParError(3*iDE+1);
    MSDExtErr[iDE]=(Double_t)alig->GetParError(3*iDE+2);
    MSDEytErr[iDE]=(Double_t)alig->GetParError(3*iDE+2);
  }

  cout << "Let's create graphs ...  " << endl;

  TGraphErrors *gMSDEx = new TGraphErrors(lNDetElem,DEid,MSDEx,DEidErr,MSDExErr);
  TGraphErrors *gMSDEy = new TGraphErrors(lNDetElem,DEid,MSDEy,DEidErr,MSDEyErr);
  TGraphErrors *gMSDExt = new TGraphErrors(lNDetElem,DEid,MSDExt,DEidErr,MSDExtErr);
  TGraphErrors *gMSDEyt = new TGraphErrors(lNDetElem,DEid,MSDEyt,DEidErr,MSDEytErr);

  cout << "... graphs created, open file ...  " << endl;

  TFile *hFile = new TFile("measShifts.root","RECREATE");

  cout << "... file opened ...  " << endl;

  gMSDEx->Write("gMSDEx");
  gMSDEy->Write("gMSDEy");
  gMSDExt->Write("gMSDExt");
  gMSDEyt->Write("gMSDEyt");
  fInvBenMom->Write();
  fBenMom->Write();
  hFile->Close();

  cout << "... and closed!" << endl;
  // Re Align
  AliMUONGeometryTransformer *newTransform = alig->ReAlign(transform,parameters,true);
  newTransform->WriteTransformations("transform2ReAlign.dat");

  // Generate realigned data in local cdb
  const TClonesArray* array = newTransform->GetMisAlignmentData();

  // CDB manager
  AliCDBManager* cdbManager = AliCDBManager::Instance();
  cdbManager->SetDefaultStorage("local://ReAlignCDB");

  AliCDBMetaData* cdbData = new AliCDBMetaData();
  cdbData->SetResponsible("Dimuon Offline project");
  cdbData->SetComment("MUON alignment objects with residual misalignment");
  AliCDBId id("MUON/Align/Data", 0, 0);
  cdbManager->Put(const_cast<TClonesArray*>(array), id, cdbData);

}
<|endoftext|>


<commit_before>#include "win32/AcceleratorTableGenerator.h"

using namespace Framework::Win32;

CAcceleratorTableGenerator::CAcceleratorTableGenerator()
{

}

CAcceleratorTableGenerator::~CAcceleratorTableGenerator()
{

}

void CAcceleratorTableGenerator::Insert(unsigned int cmd, unsigned int key, unsigned int virt)
{
	ACCEL accel;
    memset(&accel, 0, sizeof(ACCEL));
	accel.cmd	= cmd;
	accel.key	= key;
	accel.fVirt	= virt;
    m_table.push_back(accel);
}

HACCEL CAcceleratorTableGenerator::Create()
{
    return CreateAcceleratorTable(&m_table[0], static_cast<int>(m_table.size()));
}
<commit_msg>Don't crash if we generate an accelerator table with no entries.<commit_after>#include "win32/AcceleratorTableGenerator.h"

using namespace Framework::Win32;

CAcceleratorTableGenerator::CAcceleratorTableGenerator()
{

}

CAcceleratorTableGenerator::~CAcceleratorTableGenerator()
{

}

void CAcceleratorTableGenerator::Insert(unsigned int cmd, unsigned int key, unsigned int virt)
{
	ACCEL accel;
    memset(&accel, 0, sizeof(ACCEL));
	accel.cmd	= cmd;
	accel.key	= key;
	accel.fVirt	= virt;
    m_table.push_back(accel);
}

HACCEL CAcceleratorTableGenerator::Create()
{
	if(m_table.size() == 0) return NULL;
    return CreateAcceleratorTable(&m_table[0], static_cast<int>(m_table.size()));
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/aura/desktop/desktop_activation_client.h"

#include "base/auto_reset.h"
#include "base/compiler_specific.h"
#include "ui/aura/client/activation_delegate.h"
#include "ui/aura/client/activation_change_observer.h"
#include "ui/aura/focus_manager.h"
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"

namespace {

// Checks to make sure this window is a direct child of the Root Window. We do
// this to mirror ash's more interesting behaviour: it checks to make sure the
// window it's going to activate is a child of one a few container windows.
bool IsChildOfRootWindow(aura::Window* window) {
  return window && window->parent() == window->GetRootWindow();
}

}  // namespace

namespace aura {

DesktopActivationClient::DesktopActivationClient(FocusManager* focus_manager)
    : focus_manager_(focus_manager),
      current_active_(NULL),
      updating_activation_(false),
      ALLOW_THIS_IN_INITIALIZER_LIST(observer_manager_(this)) {
  focus_manager->AddObserver(this);
}

DesktopActivationClient::~DesktopActivationClient() {
  focus_manager_->RemoveObserver(this);
}

void DesktopActivationClient::AddObserver(
    client::ActivationChangeObserver* observer) {
  observers_.AddObserver(observer);
}

void DesktopActivationClient::RemoveObserver(
    client::ActivationChangeObserver* observer) {
  observers_.RemoveObserver(observer);
}

void DesktopActivationClient::ActivateWindow(Window* window) {
  // Prevent recursion when called from focus.
  if (updating_activation_)
    return;

  AutoReset<bool> in_activate_window(&updating_activation_, true);
  // Nothing may actually have changed.
  if (current_active_ == window)
    return;
  // The stacking client may impose rules on what window configurations can be
  // activated or deactivated.
  if (window && !CanActivateWindow(window))
    return;
  // Switch internal focus before we change the activation. Will probably cause
  // recursion.
  if (window &&
      !window->Contains(window->GetFocusManager()->GetFocusedWindow())) {
    window->GetFocusManager()->SetFocusedWindow(window, NULL);
  }

  aura::Window* old_active = current_active_;
  current_active_ = window;
  if (window && !observer_manager_.IsObserving(window))
    observer_manager_.Add(window);

  FOR_EACH_OBSERVER(client::ActivationChangeObserver,
                    observers_,
                    OnWindowActivated(window, old_active));

  // Invoke OnLostActive after we've changed the active window. That way if the
  // delegate queries for active state it doesn't think the window is still
  // active.
  if (old_active && client::GetActivationDelegate(old_active))
    client::GetActivationDelegate(old_active)->OnLostActive();

  // Send an activation event to the new window
  if (window && client::GetActivationDelegate(window))
    client::GetActivationDelegate(window)->OnActivated();
}

void DesktopActivationClient::DeactivateWindow(Window* window) {
  if (window == current_active_)
    current_active_ = NULL;
}

Window* DesktopActivationClient::GetActiveWindow() {
  return current_active_;
}

bool DesktopActivationClient::OnWillFocusWindow(Window* window,
                                                const ui::Event* event) {
  return CanActivateWindow(GetActivatableWindow(window));
}

void DesktopActivationClient::OnWindowDestroying(aura::Window* window) {
  if (current_active_ == window) {
    current_active_ = NULL;
    FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver,
                      observers_,
                      OnWindowActivated(NULL, window));

    // ash::ActivationController will also activate the next window here; we
    // don't do this because that's the desktop environment's job.
  }
  observer_manager_.Remove(window);
}

void DesktopActivationClient::OnWindowFocused(aura::Window* window) {
  ActivateWindow(GetActivatableWindow(window));
}

bool DesktopActivationClient::CanActivateWindow(aura::Window* window) const {
  return window &&
      window->IsVisible() &&
      (!aura::client::GetActivationDelegate(window) ||
        aura::client::GetActivationDelegate(window)->ShouldActivate(NULL));
}

aura::Window* DesktopActivationClient::GetActivatableWindow(
    aura::Window* window) {
  aura::Window* parent = window->parent();
  aura::Window* child = window;
  while (parent) {
    if (CanActivateWindow(child)) {
      if (child->transient_parent())
        child = GetActivatableWindow(child->transient_parent());
      return child;
    }
    // If |child| isn't activatable, but has transient parent, trace
    // that path instead.
    if (child->transient_parent())
      return GetActivatableWindow(child->transient_parent());
    parent = parent->parent();
    child = child->parent();
  }
  return NULL;
}

}  // namespace aura
<commit_msg>linux_aura: Temporarily restore IsChildOfRootWindow() checks on Linux.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/aura/desktop/desktop_activation_client.h"

#include "base/auto_reset.h"
#include "base/compiler_specific.h"
#include "ui/aura/client/activation_delegate.h"
#include "ui/aura/client/activation_change_observer.h"
#include "ui/aura/focus_manager.h"
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"

namespace aura {

DesktopActivationClient::DesktopActivationClient(FocusManager* focus_manager)
    : focus_manager_(focus_manager),
      current_active_(NULL),
      updating_activation_(false),
      ALLOW_THIS_IN_INITIALIZER_LIST(observer_manager_(this)) {
  focus_manager->AddObserver(this);
}

DesktopActivationClient::~DesktopActivationClient() {
  focus_manager_->RemoveObserver(this);
}

void DesktopActivationClient::AddObserver(
    client::ActivationChangeObserver* observer) {
  observers_.AddObserver(observer);
}

void DesktopActivationClient::RemoveObserver(
    client::ActivationChangeObserver* observer) {
  observers_.RemoveObserver(observer);
}

void DesktopActivationClient::ActivateWindow(Window* window) {
  // Prevent recursion when called from focus.
  if (updating_activation_)
    return;

  AutoReset<bool> in_activate_window(&updating_activation_, true);
  // Nothing may actually have changed.
  if (current_active_ == window)
    return;
  // The stacking client may impose rules on what window configurations can be
  // activated or deactivated.
  if (window && !CanActivateWindow(window))
    return;
  // Switch internal focus before we change the activation. Will probably cause
  // recursion.
  if (window &&
      !window->Contains(window->GetFocusManager()->GetFocusedWindow())) {
    window->GetFocusManager()->SetFocusedWindow(window, NULL);
  }

  aura::Window* old_active = current_active_;
  current_active_ = window;
  if (window && !observer_manager_.IsObserving(window))
    observer_manager_.Add(window);

  FOR_EACH_OBSERVER(client::ActivationChangeObserver,
                    observers_,
                    OnWindowActivated(window, old_active));

  // Invoke OnLostActive after we've changed the active window. That way if the
  // delegate queries for active state it doesn't think the window is still
  // active.
  if (old_active && client::GetActivationDelegate(old_active))
    client::GetActivationDelegate(old_active)->OnLostActive();

  // Send an activation event to the new window
  if (window && client::GetActivationDelegate(window))
    client::GetActivationDelegate(window)->OnActivated();
}

void DesktopActivationClient::DeactivateWindow(Window* window) {
  if (window == current_active_)
    current_active_ = NULL;
}

Window* DesktopActivationClient::GetActiveWindow() {
  return current_active_;
}

bool DesktopActivationClient::OnWillFocusWindow(Window* window,
                                                const ui::Event* event) {
  return CanActivateWindow(GetActivatableWindow(window));
}

void DesktopActivationClient::OnWindowDestroying(aura::Window* window) {
  if (current_active_ == window) {
    current_active_ = NULL;
    FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver,
                      observers_,
                      OnWindowActivated(NULL, window));

    // ash::ActivationController will also activate the next window here; we
    // don't do this because that's the desktop environment's job.
  }
  observer_manager_.Remove(window);
}

void DesktopActivationClient::OnWindowFocused(aura::Window* window) {
  ActivateWindow(GetActivatableWindow(window));
}

bool DesktopActivationClient::CanActivateWindow(aura::Window* window) const {
  bool can_activate = window &&
      window->IsVisible() &&
      (!aura::client::GetActivationDelegate(window) ||
       aura::client::GetActivationDelegate(window)->ShouldActivate(NULL));

#if defined(OS_LINUX)
  if (can_activate) {
    // TODO(erg,ananta): Windows behaves differently than Linux; clicking will
    // always send an activation message on windows while on Linux we'll need
    // to emulate that behavior if views is expecting it.
    can_activate = window->parent() == window->GetRootWindow();
  }
#endif

  return can_activate;
}

aura::Window* DesktopActivationClient::GetActivatableWindow(
    aura::Window* window) {
  aura::Window* parent = window->parent();
  aura::Window* child = window;
  while (parent) {
    if (CanActivateWindow(child)) {
      if (child->transient_parent())
        child = GetActivatableWindow(child->transient_parent());
      return child;
    }
    // If |child| isn't activatable, but has transient parent, trace
    // that path instead.
    if (child->transient_parent())
      return GetActivatableWindow(child->transient_parent());
    parent = parent->parent();
    child = child->parent();
  }
  return NULL;
}

}  // namespace aura
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 ScyllaDB
 */

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

#pragma once

#include "leveled_manifest.hh"

namespace sstables {

class leveled_compaction_strategy : public compaction_strategy_impl {
    static constexpr int32_t DEFAULT_MAX_SSTABLE_SIZE_IN_MB = 160;
    const sstring SSTABLE_SIZE_OPTION = "sstable_size_in_mb";

    int32_t _max_sstable_size_in_mb = DEFAULT_MAX_SSTABLE_SIZE_IN_MB;
    stdx::optional<std::vector<stdx::optional<dht::decorated_key>>> _last_compacted_keys;
    std::vector<int> _compaction_counter;
public:
    leveled_compaction_strategy(const std::map<sstring, sstring>& options)
        : compaction_strategy_impl(options)
    {
        using namespace cql3::statements;

        auto tmp_value = compaction_strategy_impl::get_value(options, SSTABLE_SIZE_OPTION);
        _max_sstable_size_in_mb = property_definitions::to_int(SSTABLE_SIZE_OPTION, tmp_value, DEFAULT_MAX_SSTABLE_SIZE_IN_MB);
        if (_max_sstable_size_in_mb >= 1000) {
            leveled_manifest::logger.warn("Max sstable size of {}MB is configured; having a unit of compaction this large is probably a bad idea",
                _max_sstable_size_in_mb);
        } else if (_max_sstable_size_in_mb < 50) {
            leveled_manifest::logger.warn("Max sstable size of {}MB is configured. Testing done for CASSANDRA-5727 indicates that performance" \
                "improves up to 160MB", _max_sstable_size_in_mb);
        }
        _compaction_counter.resize(leveled_manifest::MAX_LEVELS);
    }

    virtual compaction_descriptor get_sstables_for_compaction(column_family& cfs, std::vector<sstables::shared_sstable> candidates) override;

    virtual std::vector<resharding_descriptor> get_resharding_jobs(column_family& cf, std::vector<shared_sstable> candidates) override;

    virtual void notify_completion(const std::vector<lw_shared_ptr<sstable>>& removed, const std::vector<lw_shared_ptr<sstable>>& added) override;

    // for each level > 0, get newest sstable and use its last key as last
    // compacted key for the previous level.
    void generate_last_compacted_keys(leveled_manifest& manifest);

    virtual int64_t estimated_pending_compactions(column_family& cf) const override;

    virtual bool parallel_compaction() const override {
        return false;
    }

    virtual compaction_strategy_type type() const {
        return compaction_strategy_type::leveled;
    }
    virtual std::unique_ptr<sstable_set_impl> make_sstable_set(schema_ptr schema) const override;
};

compaction_descriptor leveled_compaction_strategy::get_sstables_for_compaction(column_family& cfs, std::vector<sstables::shared_sstable> candidates) {
    // NOTE: leveled_manifest creation may be slightly expensive, so later on,
    // we may want to store it in the strategy itself. However, the sstable
    // lists managed by the manifest may become outdated. For example, one
    // sstable in it may be marked for deletion after compacted.
    // Currently, we create a new manifest whenever it's time for compaction.
    leveled_manifest manifest = leveled_manifest::create(cfs, candidates, _max_sstable_size_in_mb);
    if (!_last_compacted_keys) {
        generate_last_compacted_keys(manifest);
    }
    auto candidate = manifest.get_compaction_candidates(*_last_compacted_keys, _compaction_counter);

    if (!candidate.sstables.empty()) {
        leveled_manifest::logger.debug("leveled: Compacting {} out of {} sstables", candidate.sstables.size(), cfs.get_sstables()->size());
        return std::move(candidate);
    }

    // if there is no sstable to compact in standard way, try compacting based on droppable tombstone ratio
    // unlike stcs, lcs can look for sstable with highest droppable tombstone ratio, so as not to choose
    // a sstable which droppable data shadow data in older sstable, by starting from highest levels which
    // theoretically contain oldest non-overlapping data.
    auto gc_before = gc_clock::now() - cfs.schema()->gc_grace_seconds();
    for (auto level = manifest.get_level_count(); level >= 0; level--) {
        auto& sstables = manifest.get_level(level);
        // filter out sstables which droppable tombstone ratio isn't greater than the defined threshold.
        auto e = boost::range::remove_if(sstables, [this, &gc_before] (const sstables::shared_sstable& sst) -> bool {
            return !worth_dropping_tombstones(sst, gc_before);
        });
        sstables.erase(e, sstables.end());
        if (sstables.empty()) {
            continue;
        }
        auto& sst = *std::max_element(sstables.begin(), sstables.end(), [&] (auto& i, auto& j) {
            return i->estimate_droppable_tombstone_ratio(gc_before) < j->estimate_droppable_tombstone_ratio(gc_before);
        });
        return sstables::compaction_descriptor({ sst }, sst->get_sstable_level());
    }
}

std::vector<resharding_descriptor> leveled_compaction_strategy::get_resharding_jobs(column_family& cf, std::vector<shared_sstable> candidates) {
    leveled_manifest manifest = leveled_manifest::create(cf, candidates, _max_sstable_size_in_mb);

    std::vector<resharding_descriptor> descriptors;
    shard_id target_shard = 0;
    auto get_shard = [&target_shard] { return target_shard++ % smp::count; };

    // Basically, we'll iterate through all levels, and for each, we'll sort the
    // sstables by first key because there's a need to reshard together adjacent
    // sstables.
    // The shard at which the job will run is chosen in a round-robin fashion.
    for (auto level = 0U; level <= manifest.get_level_count(); level++) {
        uint64_t max_sstable_size = !level ? std::numeric_limits<uint64_t>::max() : (_max_sstable_size_in_mb*1024*1024);
        auto& sstables = manifest.get_level(level);
        boost::sort(sstables, [] (auto& i, auto& j) {
            return i->compare_by_first_key(*j) < 0;
        });

        resharding_descriptor current_descriptor = resharding_descriptor{{}, max_sstable_size, get_shard(), level};

        for (auto it = sstables.begin(); it != sstables.end(); it++) {
            current_descriptor.sstables.push_back(*it);

            auto next = std::next(it);
            if (current_descriptor.sstables.size() == smp::count || next == sstables.end()) {
                descriptors.push_back(std::move(current_descriptor));
                current_descriptor = resharding_descriptor{{}, max_sstable_size, get_shard(), level};
            }
        }
    }
    return descriptors;
}

void leveled_compaction_strategy::notify_completion(const std::vector<lw_shared_ptr<sstable>>& removed, const std::vector<lw_shared_ptr<sstable>>& added) {
    if (removed.empty() || added.empty()) {
        return;
    }
    auto min_level = std::numeric_limits<uint32_t>::max();
    for (auto& sstable : removed) {
        min_level = std::min(min_level, sstable->get_sstable_level());
    }

    const sstables::sstable *last = nullptr;
    for (auto& candidate : added) {
        if (!last || last->compare_by_first_key(*candidate) < 0) {
            last = &*candidate;
        }
    }
    _last_compacted_keys.value().at(min_level) = last->get_last_decorated_key();
}

void leveled_compaction_strategy::generate_last_compacted_keys(leveled_manifest& manifest) {
    std::vector<stdx::optional<dht::decorated_key>> last_compacted_keys(leveled_manifest::MAX_LEVELS);
    for (auto i = 0; i < leveled_manifest::MAX_LEVELS - 1; i++) {
        if (manifest.get_level(i + 1).empty()) {
            continue;
        }

        const sstables::sstable* sstable_with_last_compacted_key = nullptr;
        stdx::optional<db_clock::time_point> max_creation_time;
        for (auto& sst : manifest.get_level(i + 1)) {
            auto wtime = sst->data_file_write_time();
            if (!max_creation_time || wtime >= *max_creation_time) {
                sstable_with_last_compacted_key = &*sst;
                max_creation_time = wtime;
            }
        }
        last_compacted_keys[i] = sstable_with_last_compacted_key->get_last_decorated_key();
    }
    _last_compacted_keys = std::move(last_compacted_keys);
}

int64_t leveled_compaction_strategy::estimated_pending_compactions(column_family& cf) const {
    std::vector<sstables::shared_sstable> sstables;
    sstables.reserve(cf.sstables_count());
    for (auto& entry : *cf.get_sstables()) {
        sstables.push_back(entry);
    }
    leveled_manifest manifest = leveled_manifest::create(cf, sstables, _max_sstable_size_in_mb);
    return manifest.get_estimated_tasks();
}

}
<commit_msg>compaction: fix return in leveled compaction droppable tombstones loop<commit_after>/*
 * Copyright (C) 2017 ScyllaDB
 */

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

#pragma once

#include "leveled_manifest.hh"

namespace sstables {

class leveled_compaction_strategy : public compaction_strategy_impl {
    static constexpr int32_t DEFAULT_MAX_SSTABLE_SIZE_IN_MB = 160;
    const sstring SSTABLE_SIZE_OPTION = "sstable_size_in_mb";

    int32_t _max_sstable_size_in_mb = DEFAULT_MAX_SSTABLE_SIZE_IN_MB;
    stdx::optional<std::vector<stdx::optional<dht::decorated_key>>> _last_compacted_keys;
    std::vector<int> _compaction_counter;
public:
    leveled_compaction_strategy(const std::map<sstring, sstring>& options)
        : compaction_strategy_impl(options)
    {
        using namespace cql3::statements;

        auto tmp_value = compaction_strategy_impl::get_value(options, SSTABLE_SIZE_OPTION);
        _max_sstable_size_in_mb = property_definitions::to_int(SSTABLE_SIZE_OPTION, tmp_value, DEFAULT_MAX_SSTABLE_SIZE_IN_MB);
        if (_max_sstable_size_in_mb >= 1000) {
            leveled_manifest::logger.warn("Max sstable size of {}MB is configured; having a unit of compaction this large is probably a bad idea",
                _max_sstable_size_in_mb);
        } else if (_max_sstable_size_in_mb < 50) {
            leveled_manifest::logger.warn("Max sstable size of {}MB is configured. Testing done for CASSANDRA-5727 indicates that performance" \
                "improves up to 160MB", _max_sstable_size_in_mb);
        }
        _compaction_counter.resize(leveled_manifest::MAX_LEVELS);
    }

    virtual compaction_descriptor get_sstables_for_compaction(column_family& cfs, std::vector<sstables::shared_sstable> candidates) override;

    virtual std::vector<resharding_descriptor> get_resharding_jobs(column_family& cf, std::vector<shared_sstable> candidates) override;

    virtual void notify_completion(const std::vector<lw_shared_ptr<sstable>>& removed, const std::vector<lw_shared_ptr<sstable>>& added) override;

    // for each level > 0, get newest sstable and use its last key as last
    // compacted key for the previous level.
    void generate_last_compacted_keys(leveled_manifest& manifest);

    virtual int64_t estimated_pending_compactions(column_family& cf) const override;

    virtual bool parallel_compaction() const override {
        return false;
    }

    virtual compaction_strategy_type type() const {
        return compaction_strategy_type::leveled;
    }
    virtual std::unique_ptr<sstable_set_impl> make_sstable_set(schema_ptr schema) const override;
};

compaction_descriptor leveled_compaction_strategy::get_sstables_for_compaction(column_family& cfs, std::vector<sstables::shared_sstable> candidates) {
    // NOTE: leveled_manifest creation may be slightly expensive, so later on,
    // we may want to store it in the strategy itself. However, the sstable
    // lists managed by the manifest may become outdated. For example, one
    // sstable in it may be marked for deletion after compacted.
    // Currently, we create a new manifest whenever it's time for compaction.
    leveled_manifest manifest = leveled_manifest::create(cfs, candidates, _max_sstable_size_in_mb);
    if (!_last_compacted_keys) {
        generate_last_compacted_keys(manifest);
    }
    auto candidate = manifest.get_compaction_candidates(*_last_compacted_keys, _compaction_counter);

    if (!candidate.sstables.empty()) {
        leveled_manifest::logger.debug("leveled: Compacting {} out of {} sstables", candidate.sstables.size(), cfs.get_sstables()->size());
        return std::move(candidate);
    }

    // if there is no sstable to compact in standard way, try compacting based on droppable tombstone ratio
    // unlike stcs, lcs can look for sstable with highest droppable tombstone ratio, so as not to choose
    // a sstable which droppable data shadow data in older sstable, by starting from highest levels which
    // theoretically contain oldest non-overlapping data.
    auto gc_before = gc_clock::now() - cfs.schema()->gc_grace_seconds();
    for (auto level = manifest.get_level_count(); level >= 0; level--) {
        auto& sstables = manifest.get_level(level);
        // filter out sstables which droppable tombstone ratio isn't greater than the defined threshold.
        auto e = boost::range::remove_if(sstables, [this, &gc_before] (const sstables::shared_sstable& sst) -> bool {
            return !worth_dropping_tombstones(sst, gc_before);
        });
        sstables.erase(e, sstables.end());
        if (sstables.empty()) {
            continue;
        }
        auto& sst = *std::max_element(sstables.begin(), sstables.end(), [&] (auto& i, auto& j) {
            return i->estimate_droppable_tombstone_ratio(gc_before) < j->estimate_droppable_tombstone_ratio(gc_before);
        });
        return sstables::compaction_descriptor({ sst }, sst->get_sstable_level());
    }
    return {};
}

std::vector<resharding_descriptor> leveled_compaction_strategy::get_resharding_jobs(column_family& cf, std::vector<shared_sstable> candidates) {
    leveled_manifest manifest = leveled_manifest::create(cf, candidates, _max_sstable_size_in_mb);

    std::vector<resharding_descriptor> descriptors;
    shard_id target_shard = 0;
    auto get_shard = [&target_shard] { return target_shard++ % smp::count; };

    // Basically, we'll iterate through all levels, and for each, we'll sort the
    // sstables by first key because there's a need to reshard together adjacent
    // sstables.
    // The shard at which the job will run is chosen in a round-robin fashion.
    for (auto level = 0U; level <= manifest.get_level_count(); level++) {
        uint64_t max_sstable_size = !level ? std::numeric_limits<uint64_t>::max() : (_max_sstable_size_in_mb*1024*1024);
        auto& sstables = manifest.get_level(level);
        boost::sort(sstables, [] (auto& i, auto& j) {
            return i->compare_by_first_key(*j) < 0;
        });

        resharding_descriptor current_descriptor = resharding_descriptor{{}, max_sstable_size, get_shard(), level};

        for (auto it = sstables.begin(); it != sstables.end(); it++) {
            current_descriptor.sstables.push_back(*it);

            auto next = std::next(it);
            if (current_descriptor.sstables.size() == smp::count || next == sstables.end()) {
                descriptors.push_back(std::move(current_descriptor));
                current_descriptor = resharding_descriptor{{}, max_sstable_size, get_shard(), level};
            }
        }
    }
    return descriptors;
}

void leveled_compaction_strategy::notify_completion(const std::vector<lw_shared_ptr<sstable>>& removed, const std::vector<lw_shared_ptr<sstable>>& added) {
    if (removed.empty() || added.empty()) {
        return;
    }
    auto min_level = std::numeric_limits<uint32_t>::max();
    for (auto& sstable : removed) {
        min_level = std::min(min_level, sstable->get_sstable_level());
    }

    const sstables::sstable *last = nullptr;
    for (auto& candidate : added) {
        if (!last || last->compare_by_first_key(*candidate) < 0) {
            last = &*candidate;
        }
    }
    _last_compacted_keys.value().at(min_level) = last->get_last_decorated_key();
}

void leveled_compaction_strategy::generate_last_compacted_keys(leveled_manifest& manifest) {
    std::vector<stdx::optional<dht::decorated_key>> last_compacted_keys(leveled_manifest::MAX_LEVELS);
    for (auto i = 0; i < leveled_manifest::MAX_LEVELS - 1; i++) {
        if (manifest.get_level(i + 1).empty()) {
            continue;
        }

        const sstables::sstable* sstable_with_last_compacted_key = nullptr;
        stdx::optional<db_clock::time_point> max_creation_time;
        for (auto& sst : manifest.get_level(i + 1)) {
            auto wtime = sst->data_file_write_time();
            if (!max_creation_time || wtime >= *max_creation_time) {
                sstable_with_last_compacted_key = &*sst;
                max_creation_time = wtime;
            }
        }
        last_compacted_keys[i] = sstable_with_last_compacted_key->get_last_decorated_key();
    }
    _last_compacted_keys = std::move(last_compacted_keys);
}

int64_t leveled_compaction_strategy::estimated_pending_compactions(column_family& cf) const {
    std::vector<sstables::shared_sstable> sstables;
    sstables.reserve(cf.sstables_count());
    for (auto& entry : *cf.get_sstables()) {
        sstables.push_back(entry);
    }
    leveled_manifest manifest = leveled_manifest::create(cf, sstables, _max_sstable_size_in_mb);
    return manifest.get_estimated_tasks();
}

}
<|endoftext|>