<commit_before>// Copyright (c) 2014 Dims dev-team
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef ACTION_HANDLER_H
#define ACTION_HANDLER_H

#include <boost/thread.hpp>

#include <map>

#include "connectionProvider.h"
#include "setResponseVisitor.h"
#include "request.h"
#include "requestHandler.h"

#include <exception>
#include <boost/foreach.hpp>

#include "util.h"
#include "action.h"
#include <algorithm>
/*
initially I wanted to make every actionHandler to operate on its own response list
I feared that if  I put everything in the same mpl::list it will be bloated to impossibility,
additionally I thought that it is  obvious that every action  handler  should have distinctive features.

now I doubt
this approach lead me to  situation where I have to drag template parameters like ( NodeResponses, TrackerResponses etc. )everywhere
I didn't expected that my initial choice will have such devastating  result to the code  apperance
I am on the brink of removing separate response lists completely, this will result in removing template  parameter from most places

*/

namespace common
{

template < class _RequestResponses > class CSetResponseVisitor;
template < class _RequestResponses > class CRequestHandler;
template < class _RequestResponses > struct CRequest;

template < class _RequestResponses >
struct LessHandlers : public std::binary_function< CRequestHandler< _RequestResponses >* ,CRequestHandler< _RequestResponses >* ,bool>
{
	bool operator() ( CRequestHandler< _RequestResponses >* const & _handlerLhs, CRequestHandler< _RequestResponses >* const & _handlerRhs) const
	{
		return *_handlerLhs < *_handlerRhs;
	}

	bool operator() ( CRequestHandler< _RequestResponses >* const & _handlerLhs, CMedium< _RequestResponses >* const & _medium) const
	{
		return *_handlerLhs < _medium;
	}
};


template < class _RequestResponses >
class CActionHandler
{
public:
	typedef std::set< CRequestHandler< _RequestResponses > *, LessHandlers< _RequestResponses > > AvailableHandlers;

	typedef std::map< CRequest< _RequestResponses >*, CAction< _RequestResponses >* > RequestToAction;

	typedef std::multimap< CRequest< _RequestResponses >*, CRequestHandler< _RequestResponses > * > RequestToHandlers;
public:
	void loop();
	void shutDown();
	~CActionHandler();
	static CActionHandler* getInstance( );

	void executeAction( CAction< _RequestResponses >* _action );

	void addConnectionProvider( CConnectionProvider< _RequestResponses >* _connectionProvider );
private:
	CActionHandler();

	std::list< CRequestHandler< _RequestResponses > * > provideHandler( CMediumFilter<_RequestResponses> const & _mediumFilter );

	void findAction( CAction< _RequestResponses >* _action ) const;

private:
	static CActionHandler * ms_instance;

	mutable boost::mutex m_mutex;

	std::list< CAction< _RequestResponses >* > m_actions;

	RequestToAction m_reqToAction;

	std::list<CConnectionProvider< _RequestResponses >*> m_connectionProviders;

	//this  will be  multimap one  day, this  should  be  periodically  cleanuped ,  don't  know  how  yet
	AvailableHandlers m_requestHandlers;

	static unsigned int const m_sleepTime;

	RequestToHandlers m_currentlyUsedHandlers;
};

template < class _RequestResponses >
CActionHandler< _RequestResponses >::CActionHandler()
{
}

template < class _RequestResponses >
CActionHandler< _RequestResponses >::~CActionHandler()
{
}

template < class _RequestResponses >
CActionHandler< _RequestResponses >*
CActionHandler< _RequestResponses >::getInstance( )
{
	if ( !ms_instance )
	{
		ms_instance = new CActionHandler();
	};
	return ms_instance;
}

template < class _RequestResponses >
void
CActionHandler< _RequestResponses >::executeAction( CAction< _RequestResponses >* _action )
{
	boost::lock_guard<boost::mutex> lock(m_mutex);
	m_actions.push_back( _action );
}

template < class _RequestResponses >
void
CActionHandler< _RequestResponses >::addConnectionProvider( CConnectionProvider< _RequestResponses >* _connectionProvider )
{
	m_connectionProviders.push_back( _connectionProvider );
}

/* I have  done some drastic simplification here, in case  of problems look how it  was  done before till August 7-8 */
template < class _RequestResponses >
std::list< CRequestHandler< _RequestResponses > * >
CActionHandler< _RequestResponses >::provideHandler( CMediumFilter<_RequestResponses> const & _mediumFilter )
{
	std::list< CRequestHandler< _RequestResponses > * > requestHandelers;

	typename std::list< CConnectionProvider< _RequestResponses >*>::iterator iterator = m_connectionProviders.begin();

	while( iterator != m_connectionProviders.end() )// for now only one provider is allowed to service request so firs is best
	{
		std::list< CMedium< _RequestResponses >*> mediums= (*iterator)->provideConnection( _mediumFilter );

		if ( !mediums.empty() )
		{
			BOOST_FOREACH( CMedium< _RequestResponses > * medium, mediums )
			{
				// here we are counting on medium provider to select properly
				typename AvailableHandlers::iterator iterator = std::lower_bound( m_requestHandlers.begin(), m_requestHandlers.end(), medium, LessHandlers< _RequestResponses >() );
				if ( iterator != m_requestHandlers.end() )
				{
					requestHandelers.push_back( *iterator );
				}
				else
				{
					CRequestHandler< _RequestResponses > * requestHandler = new CRequestHandler< _RequestResponses >( medium );
					m_requestHandlers.insert( requestHandler );
					requestHandelers.push_back( requestHandler );
				}
			}
			return requestHandelers;
		}

		iterator++;
	}
	return std::list< CRequestHandler< _RequestResponses > * >();
}

template < class _RequestResponses >
void
CActionHandler< _RequestResponses >::shutDown()
{
}

template < class _RequestResponses >
void
CActionHandler< _RequestResponses >::loop()
{
	std::set< CRequestHandler< _RequestResponses > * > requestHandlersToExecute;
	while(1)<commit_msg>small fix in action handler<commit_after>// Copyright (c) 2014 Dims dev-team
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef ACTION_HANDLER_H
#define ACTION_HANDLER_H

#include <boost/thread.hpp>

#include <map>

#include "connectionProvider.h"
#include "setResponseVisitor.h"
#include "request.h"
#include "requestHandler.h"

#include <exception>
#include <boost/foreach.hpp>

#include "util.h"
#include "action.h"
#include <algorithm>
/*
initially I wanted to make every actionHandler to operate on its own response list
I feared that if  I put everything in the same mpl::list it will be bloated to impossibility,
additionally I thought that it is  obvious that every action  handler  should have distinctive features.

now I doubt
this approach lead me to  situation where I have to drag template parameters like ( NodeResponses, TrackerResponses etc. )everywhere
I didn't expected that my initial choice will have such devastating  result to the code  apperance
I am on the brink of removing separate response lists completely, this will result in removing template  parameter from most places

*/

namespace common
{

template < class _RequestResponses > class CSetResponseVisitor;
template < class _RequestResponses > class CRequestHandler;
template < class _RequestResponses > struct CRequest;

template < class _RequestResponses >
struct LessHandlers : public std::binary_function< CRequestHandler< _RequestResponses >* ,CRequestHandler< _RequestResponses >* ,bool>
{
	bool operator() ( CRequestHandler< _RequestResponses >* const & _handlerLhs, CRequestHandler< _RequestResponses >* const & _handlerRhs) const
	{
		return *_handlerLhs < *_handlerRhs;
	}

	bool operator() ( CRequestHandler< _RequestResponses >* const & _handlerLhs, CMedium< _RequestResponses >* const & _medium) const
	{
		return *_handlerLhs < _medium;
	}

	bool operator() ( CMedium< _RequestResponses >* const & _medium, CRequestHandler< _RequestResponses >* const & _handlerLhs ) const
	{
		return *_handlerLhs < _medium;
	}
};


template < class _RequestResponses >
class CActionHandler
{
public:
	typedef std::set< CRequestHandler< _RequestResponses > *, LessHandlers< _RequestResponses > > AvailableHandlers;

	typedef std::map< CRequest< _RequestResponses >*, CAction< _RequestResponses >* > RequestToAction;

	typedef std::multimap< CRequest< _RequestResponses >*, CRequestHandler< _RequestResponses > * > RequestToHandlers;
public:
	void loop();
	void shutDown();
	~CActionHandler();
	static CActionHandler* getInstance( );

	void executeAction( CAction< _RequestResponses >* _action );

	void addConnectionProvider( CConnectionProvider< _RequestResponses >* _connectionProvider );
private:
	CActionHandler();

	std::list< CRequestHandler< _RequestResponses > * > provideHandler( CMediumFilter<_RequestResponses> const & _mediumFilter );

	void findAction( CAction< _RequestResponses >* _action ) const;

private:
	static CActionHandler * ms_instance;

	mutable boost::mutex m_mutex;

	std::list< CAction< _RequestResponses >* > m_actions;

	RequestToAction m_reqToAction;

	std::list<CConnectionProvider< _RequestResponses >*> m_connectionProviders;

	//this  will be  multimap one  day, this  should  be  periodically  cleanuped ,  don't  know  how  yet
	AvailableHandlers m_requestHandlers;

	static unsigned int const m_sleepTime;

	RequestToHandlers m_currentlyUsedHandlers;
};

template < class _RequestResponses >
CActionHandler< _RequestResponses >::CActionHandler()
{
}

template < class _RequestResponses >
CActionHandler< _RequestResponses >::~CActionHandler()
{
}

template < class _RequestResponses >
CActionHandler< _RequestResponses >*
CActionHandler< _RequestResponses >::getInstance( )
{
	if ( !ms_instance )
	{
		ms_instance = new CActionHandler();
	};
	return ms_instance;
}

template < class _RequestResponses >
void
CActionHandler< _RequestResponses >::executeAction( CAction< _RequestResponses >* _action )
{
	boost::lock_guard<boost::mutex> lock(m_mutex);
	m_actions.push_back( _action );
}

template < class _RequestResponses >
void
CActionHandler< _RequestResponses >::addConnectionProvider( CConnectionProvider< _RequestResponses >* _connectionProvider )
{
	m_connectionProviders.push_back( _connectionProvider );
}

/* I have  done some drastic simplification here, in case  of problems look how it  was  done before till August 7-8 */
template < class _RequestResponses >
std::list< CRequestHandler< _RequestResponses > * >
CActionHandler< _RequestResponses >::provideHandler( CMediumFilter<_RequestResponses> const & _mediumFilter )
{
	std::list< CRequestHandler< _RequestResponses > * > requestHandelers;

	typename std::list< CConnectionProvider< _RequestResponses >*>::iterator iterator = m_connectionProviders.begin();

	while( iterator != m_connectionProviders.end() )// for now only one provider is allowed to service request so firs is best
	{
		std::list< CMedium< _RequestResponses >*> mediums= (*iterator)->provideConnection( _mediumFilter );

		if ( !mediums.empty() )
		{
			BOOST_FOREACH( CMedium< _RequestResponses > * medium, mediums )
			{
				// here we are counting on medium provider to select properly
				typename AvailableHandlers::iterator iterator = std::lower_bound( m_requestHandlers.begin(), m_requestHandlers.end(), medium, LessHandlers< _RequestResponses >() );
				if ( iterator != std::upper_bound( m_requestHandlers.begin(), m_requestHandlers.end(), medium, LessHandlers< _RequestResponses >() ) )
				{
					requestHandelers.push_back( *iterator );
				}
				else
				{
					CRequestHandler< _RequestResponses > * requestHandler = new CRequestHandler< _RequestResponses >( medium );
					m_requestHandlers.insert( requestHandler );
					requestHandelers.push_back( requestHandler );
				}
			}
			return requestHandelers;
		}

		iterator++;
	}
	return std::list< CRequestHandler< _RequestResponses > * >();
}

template < class _RequestResponses >
void
CActionHandler< _RequestResponses >::shutDown()
{
}

template < class _RequestResponses >
void
CActionHandler< _RequestResponses >::loop()
{
	std::set< CRequestHandler< _RequestResponses > * > requestHandlersToExecute;
	while(1)
{'fraction_non_alphanumeric': 0.09253486464315012, 'fraction_numerical': 0.0014766201804757998, 'mean_word_length': 5.669037199124727, 'pattern_counts': {'":': 0, '<': 157, '<?xml version=': 0, '>': 154, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '634171', 'n_tokens_mistral': 3872, 'n_tokens_neox': 3644, 'n_words': 1012}